Let's see if the third question in this series is a water problem.
Peid, did not find the shell, is still a C + + reverse:
Pseudo Code test:
Also find the text string in OD, navigate to the string location:
None of the three questions were cracker in the position.
So the same work, up to find the function of the head under the breakpoint, F9 run, after the input pseudo-code, F8 for code Analysis:
This is part of the code flow after this:
004014EC |. 8B4D E0 mov ecx,[local.8]004014ef |. 81C1 A0000000 Add Ecx,0xa0004014f5 |. E8 AA030000 call <jmp.&mfc42. #3876 >; Gets the length of the name string 004014FA |. 8945 EC mov [local.5],eax; COSH_3.004014B0004014FD |. 837D EC-CMP [local.5],0x5; ; Judge whether it is greater than 500401501 |. 7F JG Short cosh_3.0040150800401503 |. E9 BB000000 jmp cosh_3.004015c300401508 |> 8b4d E0 mov ecx,[local.8]0040150b | 83C1 Add ecx,0x600040150e |. E8 91030000 call <jmp.&mfc42. #3876 >; ; Gets the length of the user serial string 00401513 |. 8945 E8 mov [local.6],eax; cosh_3.004014b000401516 |. 837D E8 cmp [local.6],0x5; To judge the user Serila length is greater than 50040151A |. 7F JG Short cosh_3.004015210040151c |. E9 A2000000 jmp cosh_3.004015c300401521 |> 8b45 E0 MOV eax,[local.8]00401524 |. E0000000 Add eax,0xe000401529 |. -Push eax; cosh_3.004014b00040152a |. 8B4D E0 mov ecx,[local.8]0040152d |. 81C1 A0000000 Add ecx,0xa000401533 |. E8 66030000 call <jmp.&mfc42. #3874 >00401538 |. 8B4D E0 mov ecx,[local.8]0040153b |. 81C1 E4000000 Add ecx,0xe400401541 |. Wuyi Push ecx00401542 |. 8B4D E0 mov ecx,[local.8]00401545 |. 83C1 Add ecx,0x6000401548 |. E8 51030000 call <jmp.&mfc42. #3874 >0040154d |. 8b55 E0 mov edx,[local.8]00401550 |. 81C2 E0000000 Add edx,0xe000401556 |. Push edx00401557 |. 8D4D E4 Lea ecx,[local.7]0040155a |. E8 39030000 call <jmp.&mfc42. #858 >0040155f |. 8b45 E0 mov eax,[local.8]00401562 |. E4000000 Add eax,0xe400401567 |. -Push eax; cosh_3.004014b000401568 |. 8D4D F0 Lea ecx,[local.4]0040156b |. E8 28030000 call <jmp.&mfc42. #858 >00401570 |. 33c0 XOR Eax,eax; cosh_3.004014b000401572 |. 33DB xor ebx,ebx00401574 |. 33c9 xor ecx,ecx00401576 |. B9 01000000 mov ecx,0x10040157b |. 33d2 XOR Edx,edx
is still judging the length of the input name and serial string.
This is followed by the two loops, the name algorithm and the serial algorithm:
0040157D |. 8B45 E4 mov eax,[local.7]; The algorithm for the name string 00401580 |> 8a18/mov bl,byte ptr ds:[eax]00401582 |. 32d9 |xor bl,cl00401584 |. 8818 |mov byte ptr ds:[eax],bl00401586 |. |inc ecx00401587 |. |inc eax; cosh_3.004014b000401588 |. 8038 |cmp byte ptr ds:[eax],0x00040158b |. ^ F3 \jnz short cosh_3.004015800040158d |. 33c0 XOR Eax,eax; cosh_3.004014b00040158f |. 33DB xor ebx,ebx00401591 |. 33c9 xor ecx,ecx00401593 |. B9 0a000000 mov ecx,0xa00401598 |. 33d2 xor edx,edx0040159a |. 8b45 F0 mov eax,[local.4]0040159d |> 8a18/mov bl,byte ptr ds:[eax]; ; Serial string change Algorithm 0040159F |. 32d9 |xor BL,CL004015A1 |. 8818 |mov byte ptr ds:[eax],bl004015a3 |. 41 |inc ecx004015a4 |. |inc eax; Cosh_3.004014b0004015a5 |. 8038 |cmp byte ptr ds:[eax],0x0
This hex window will be better followed:
It is easy to understand what to do when you are familiar with the assembly cycle, for example: in C language:
int c1=0x1; for(int i=0;i<strlen(name);i++) { name[i]=c1^(int)name[i]; c1++; }
The same operation was done for Seial_false, but the initial value changed:
int c1=0xA; for(int i=0;i<strlen(seial);i++) { serial[i]=c1^(int)serial[i]; c1++; }
After that, analyze the code:
004015A4 |. 40 |inc eax004015A5 |. 8038 00 |cmp byte ptr ds:[eax],0x0004015A8 |.^ 75 F3 \jnz short cosh_3.0040159D004015AA |. 8B45 E4 mov eax,[local.7]004015AD |. 8B55 F0 mov edx,[local.4]004015B0 |> 33C9 /xor ecx,ecx004015B2 |. 8A18 |mov bl,byte ptr ds:[eax]004015B4 |. 8A0A |mov cl,byte ptr ds:[edx]004015B6 |. 3AD9 |cmp bl,cl004015B8 |. 75 09 |jnz short cosh_3.004015C3 ; ;改变后的name字符串与改变后的serial逐位比较,失败就失败004015BA |. 40 |inc eax004015BB |. 42 |inc edx004015BC |. 8038 00 |cmp byte ptr ds:[eax],0x0004015BF |.^ 75 EF \jnz short cosh_3.004015B0004015C1 |. EB 16 jmp short cosh_3.004015D9 ; ;比较成功跳转成功信息
The middle part seems to be much, in fact, the name and serial of each bit are compared:
Here are the two strings generated by the pseudo code I entered:
Obviously not equal, the first comparison will be wrong ...
We thoroughly understand the flow of the algorithm, and note that the two strings are compared to the number of digits of the length of the name string after their respective algorithm transformations.
The algorithm uses the C language to write the inverse algorithm's skill:
#include <iostream>#include <cstring>using namespace std;#define N 100int main(){ char name[N]; char serial_true[N]; char serial_false[N]; cout<<"Please input your name:"<<endl; cin>>name; cout<<"Please input your serial:"<<endl; cin>>serial_false; if(strlen(name)<=5||strlen(serial_false)<=5) { cout<<"Error!"<<endl; return 0; } int c1=0x1; for(int i=0;i<strlen(name);i++) { name[i]=c1^(int)name[i]; c1++; } //for(int i=0;i<strlen(name);i++) //cout<<name[i]; int c2=0xA; for(int i=0;i<strlen(name);i++) { serial_true[i]=c2^name[i]; c2++; } for(int i=0;i<strlen(name);i++) cout<<serial_true[i]; return 0;}
Results test:
Recent life Ah, I am in yongming crackme ...
160 x Crackme 029 cosh.3