【分析 0x03】《加密与解密》第三版 5.2学习笔记

 

这是一个注册的例子,首先通过查找提示的字符串进而找到程序对输入的name和key的处理函数

这个例子是用的对等函数检查注册码 F1(用户名)=F2(序列号)

 1 00401223   .  83F8 00       cmp eax,0x0
 2 00401226   .^ 74 BE         je short serial.004011E6
 3 00401228   .  68 8E214000   push serial.0040218E                     ;  ASCII "GFFGFGFGFG"
 4 0040122D   .  E8 4C010000   call serial.0040137E                     ;  计算F1用户名
 5 00401232   .  50            push eax
 6 00401233   .  68 7E214000   push serial.0040217E                     ;  ASCII "ggggggggg"
 7 00401238   .  E8 9B010000   call serial.004013D8                     ;  计算F2序列号
 8 0040123D      83C4 04       add esp,0x4
 9 00401240   .  58            pop eax
10 00401241   .  3BC3          cmp eax,ebx                              ;  比较
11 00401243   .  74 07         je short serial.0040124C                 ;  相等 则注册成功
12 00401245   .  E8 18010000   call serial.00401362
13 0040124A   .^ EB 9A         jmp short serial.004011E6

call serial.0040137E

 1 0040137E  /$  8B7424 04     mov esi,dword ptr ss:[esp+0x4]
 2 00401382  |.  56            push esi
 3 00401383  |>  8A06          /mov al,byte ptr ds:[esi]                ;  从字符串中取一个字符
 4 00401385  |.  84C0          |test al,al                              ;  判断取出的字符是否为null
 5 00401387  |.  74 13         |je short serial.0040139C
 6 00401389  |.  3C 41         |cmp al,0x41                             ;  判断取出的字符是否小于'A'
 7 0040138B  |.  72 1F         |jb short serial.004013AC
 8 0040138D  |.  3C 5A         |cmp al,0x5A                             ;  判断字符是否为大写
 9 0040138F  |.  73 03         |jnb short serial.00401394
10 00401391  |.  46            |inc esi
11 00401392  |.^ EB EF         |jmp short serial.00401383
12 00401394  |>  E8 39000000   |call serial.004013D2
13 00401399  |.  46            |inc esi
14 0040139A  |.^ EB E7         \jmp short serial.00401383               ;  开始读取下一个字符
15 0040139C  |>  5E            pop esi                                  ;  esi 再次指向字符串首部
16 0040139D  |.  E8 20000000   call serial.004013C2                     ;  把整个字符串的单个字符依次相加 结果存放在edi中
17 004013A2  |.  81F7 78560000 xor edi,0x5678                           ;  edi | 5678h
18 004013A8  |.  8BC7          mov eax,edi
19 004013AA  |.  EB 15         jmp short serial.004013C1                ;  返回值存放于eax后返回
20 004013AC  |>  5E            pop esi
21 004013AD  |.  6A 30         push 0x30                                ; /Style = MB_OK|MB_ICONEXCLAMATION|MB_APPLMODAL
22 004013AF  |.  68 60214000   push serial.00402160                     ; |Title = "Error!  "
23 004013B4  |.  68 69214000   push serial.00402169                     ; |Text = "Incorrect!,Try Again"
24 004013B9  |.  FF75 08       push [arg.1]                             ; |hOwner
25 004013BC  |.  E8 79000000   call <jmp.&USER32.MessageBoxA>           ; \MessageBoxA
26 004013C1  \>  C3            retn
27 004013C2  /$  33FF          xor edi,edi
28 004013C4  |.  33DB          xor ebx,ebx
29 004013C6  |>  8A1E          /mov bl,byte ptr ds:[esi]
30 004013C8  |.  84DB          |test bl,bl
31 004013CA  |.  74 05         |je short serial.004013D1                ;  判断是否把字符串读结束
32 004013CC  |.  03FB          |add edi,ebx                             ;  读出的字符加到edi中 edi+=字符(小写)ASCII值
33 004013CE  |.  46            |inc esi
34 004013CF  |.^ EB F5         \jmp short serial.004013C6
35 004013D1  \>  C3            retn
36 004013D2  /$  2C 20         sub al,0x20                              ;  小写改为大写
37 004013D4  |.  8806          mov byte ptr ds:[esi],al
38 004013D6  \.  C3            retn

返回值就是把字符串转换为小写在把每个字符相加

call serial.004013D8

 1 004013D8  /$  33C0          xor eax,eax
 2 004013DA  |.  33FF          xor edi,edi
 3 004013DC  |.  33DB          xor ebx,ebx
 4 004013DE  |.  8B7424 04     mov esi,dword ptr ss:[esp+0x4]
 5 004013E2  |>  B0 0A         /mov al,0xA
 6 004013E4  |.  8A1E          |mov bl,byte ptr ds:[esi]
 7 004013E6  |.  84DB          |test bl,bl
 8 004013E8  |.  74 0B         |je short serial.004013F5
 9 004013EA  |.  80EB 30       |sub bl,0x30                             ;  取出的字符c-=30h
10 004013ED  |.  0FAFF8        |imul edi,eax                            ;  edi*Ah
11 004013F0  |.  03FB          |add edi,ebx                             ;  edi+=c
12 004013F2  |.  46            |inc esi
13 004013F3  |.^ EB ED         \jmp short serial.004013E2
14 004013F5  |>  81F7 34120000 xor edi,0x1234                           ;  edi|1234h
15 004013FB  |.  8BDF          mov ebx,edi                              ;  结果放在ebx中
16 004013FD  \.  C3            retn                                     ;  最后返回的 ebx=edi=(c-48)+edi*

设每次读取一个字符c

返回值就是sum = sum * 10 +c-48

这样就可以写出注册程序了

 1 // F2(name) = F1(key)
 2 // key = F1(-1)(F2(name)) = F1(F2(name)) 因为xor (xor A) = A
 3 #include <iostream>
 4 using namespace std;
 5 
 6 int keygen(char *name)
 7 {
 8     int key1=0;
 9     int key2=0;
10     char *pname=name;
11     while(*pname != NULL)
12     {
13         if(*pname>='a'&&*pname<='z')
14             *pname-=32;
15         key1+=*pname;
16         pname++;
17     }
18     key1=key1^0x5678;    //这里利用了 异或是可逆的
19     key2=key1^0x1234;    //xor (xor A) = A
20     return key2;
21 }
22 
23 int main()
24 {
25     char name[20]={0};
26     cin>>name;
27     int key = keygen(name);
28     cout<<key<<endl;
29 }

 

 

posted @ 2016-04-26 18:48  yugan  阅读(431)  评论(0编辑  收藏  举报