这是一个注册的例子,首先通过查找提示的字符串进而找到程序对输入的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 }