这个是从crackme版块下载的,具体是那篇贴记不住了。
Crackme.zip
运行界面如下:
对GetDlgItemTextA下断点,找到注册码算法代码:
00401230 /$ 8B0D BC564000 mov ecx,dword ptr ds:[4056BC]
00401236 |. 83EC 30 sub esp,30
00401239 |. 8D4424 00 lea eax,dword ptr ss:[esp]
0040123D |. 53 push ebx
0040123E |. 56 push esi
0040123F |. 8B35 94404000 mov esi,dword ptr ds:[<&USER32.GetDlgIte>; user32.GetDlgItemTextA
00401245 |. 6A 10 push 10 ; /Count = 10 (16.)
00401247 |. 50 push eax ; |Buffer
00401248 |. 68 E8030000 push 3E8 ; |ControlID = 3E8 (1000.)
0040124D |. 51 push ecx ; |hWnd => 000B0640 (class='#32770',parent=001305B8)
0040124E |. 33DB xor ebx,ebx ; |
00401250 |. FFD6 call esi ; \GetDlgItemTextA 获取用户名
00401252 |. 83F8 03 cmp eax,3 ;如果用户名长度小于3,函数直接返回,注册失败
00401255 |. 73 0B jnb short ncrackme.00401262
00401257 |. 5E pop esi
00401258 |. B8 01000000 mov eax,1
0040125D |. 5B pop ebx
0040125E |. 83C4 30 add esp,30
00401261 |. C3 retn
00401262 |> A1 BC564000 mov eax,dword ptr ds:[4056BC]
00401267 |. 8D5424 28 lea edx,dword ptr ss:[esp+28]
0040126B |. 6A 10 push 10
0040126D |. 52 push edx
0040126E |. 68 E9030000 push 3E9
00401273 |. 50 push eax
00401274 |. FFD6 call esi ;调用GetDlgItemTextA 获取序列号
00401276 |. 0FBE4424 08 movsx eax,byte ptr ss:[esp+8] ;取出用户名的第一和第二个字符
0040127B |. 0FBE4C24 09 movsx ecx,byte ptr ss:[esp+9]
00401280 |. 99 cdq
00401281 |. F7F9 idiv ecx ;用户名第一字符除以用户名第二个字符,取余数。edx保存是除法结果的余数
00401283 |. 8BCA mov ecx,edx
00401285 |. 83C8 FF or eax,FFFFFFFF
00401288 |. 0FBE5424 0A movsx edx,byte ptr ss:[esp+A] ;余数乘以用户名第三个字符,结果再加1
0040128D |. 0FAFCA imul ecx,edx
00401290 |. 41 inc ecx
00401291 |. 33D2 xor edx,edx
00401293 |. F7F1 div ecx ;0xffffffff/上面计算的结果
00401295 |. 50 push eax
00401296 |. E8 A5000000 call ncrackme.00401340 ;跟进这个函数,发现他把计算的结果eax放入一个全局变量(地址:0x004050ac)。取名字g_a
00401340 /$ 8B4424 04 mov eax,dword ptr ss:[esp+4] ;也就是根据用户名钱3个字符初始化一个全局变量
00401344 |. A3 AC504000 mov dword ptr ds:[4050AC],eax
00401349 \. C3 retn
0040129B |. 83C4 04 add esp,4
0040129E |. 33F6 xor esi,esi
004012A0 |> E8 A5000000 /call ncrackme.0040134A ;循环15次调用函数ncrackme.0040134A。跟进函数
0040134A /$ A1 AC504000 mov eax,dword ptr ds:[4050AC] ;取出全局变量g_a中的值
0040134F |. 69C0 FD430300 imul eax,eax,343FD
00401355 |. 05 C39E2600 add eax,269EC3
0040135A |. A3 AC504000 mov dword ptr ds:[4050AC],eax ;g_a=g_a*343fd+269ec3
0040135F |. C1F8 10 sar eax,10 ;返回值:(g_a>>10) & 7fff
00401362 |. 25 FF7F0000 and eax,7FFF
00401367 \. C3 retn
004012A5 |. 99 |cdq
004012A6 |. B9 1A000000 |mov ecx,1A ;把函数返回的结果模26,再加上字符‘A'asscii码0x41
004012AB |. F7F9 |idiv ecx
004012AD |. 80C2 41 |add dl,41
004012B0 |. 885434 18 |mov byte ptr ss:[esp+esi+18],dl ;将得到的一个大写字母保存到[esp+18]中。这个字符串没有被使用。
004012B4 |. 46 |inc esi
004012B5 |. 83FE 0F |cmp esi,0F
004012B8 |.^ 72 E6 \jb short ncrackme.004012A0
004012BA |. 57 push edi
004012BB |. 8D7C24 0C lea edi,dword ptr ss:[esp+C]
004012BF |. 83C9 FF or ecx,FFFFFFFF
004012C2 |. 33C0 xor eax,eax
004012C4 |. 33F6 xor esi,esi
004012C6 |. F2:AE repne scas byte ptr es:[edi]
004012C8 |. F7D1 not ecx
004012CA |. 49 dec ecx
004012CB |. 74 59 je short ncrackme.00401326
004012CD |> 8A4434 0C /mov al,byte ptr ss:[esp+esi+C] ;计算序列号。循环次数为用户名的长度,esi控制循环次数,
004012D1 |. C0F8 05 |sar al,5 ;用户名第一个字符除以32
004012D4 |. 0FBEC0 |movsx eax,al ;a = username[i]/32;
004012D7 |. 8D1480 |lea edx,dword ptr ds:[eax+eax*4] ;很显然下面的代码是算数乘法运算,<加密与解密>整数乘法那节有讲。DWORD b = 5*a;
004012DA |. 8D04D0 |lea eax,dword ptr ds:[eax+edx*8] ;a += b*8;
004012DD |. 8D0440 |lea eax,dword ptr ds:[eax+eax*2] ;a = a*3;
004012E0 |. 85C0 |test eax,eax
004012E2 |. 7E 0A |jle short ncrackme.004012EE ;循环调用a次函数ncrackme.0040134A,记住这个函数要改变全局变量g_a
004012E4 |. 8BF8 |mov edi,eax
004012E6 |> E8 5F000000 |/call ncrackme.0040134A
004012EB |. 4F ||dec edi
004012EC |.^ 75 F8 |\jnz short ncrackme.004012E6
004012EE |> E8 57000000 |call ncrackme.0040134A
004012F3 |. 99 |cdq
004012F4 |. B9 1A000000 |mov ecx,1A
004012F9 |. 8D7C24 0C |lea edi,dword ptr ss:[esp+C]
004012FD |. F7F9 |idiv ecx
004012FF |. 0FBE4C34 2C |movsx ecx,byte ptr ss:[esp+esi+2C] ;这是用户输入的序列号
00401304 |. 80C2 41 |add dl,41
00401307 |. 0FBEC2 |movsx eax,dl
0040130A |. 2BC1 |sub eax,ecx ;输入的序列号-正确的序列号,如果相同的话,结果为0
0040130C |. 885434 1C |mov byte ptr ss:[esp+esi+1C],dl ;次函数ncrackme.0040134A返回值 / 26 + 41,将结果保存在[esp+1c]中,这就是正确序列号
00401310 |. 99 |cdq
00401311 |. 33C2 |xor eax,edx
00401313 |. 83C9 FF |or ecx,FFFFFFFF
00401316 |. 2BC2 |sub eax,edx
00401318 |. 03D8 |add ebx,eax ;将序列号相减的结果保存在ebx中
0040131A |. 33C0 |xor eax,eax
0040131C |. 46 |inc esi
0040131D |. F2:AE |repne scas byte ptr es:[edi] ;计算用户名长度,判断循环结束条件
0040131F |. F7D1 |not ecx
00401321 |. 49 |dec ecx
00401322 |. 3BF1 |cmp esi,ecx
00401324 |.^ 72 A7 \jb short ncrackme.004012CD
00401326 |> 5F pop edi
00401327 |. 8BC3 mov eax,ebx ;ebx作为函数返回值,如果序列号相等,ebx则等于0,返回0表示注册成功。
00401329 |. 5E pop esi
0040132A |. 5B pop ebx
0040132B |. 83C4 30 add esp,30
0040132E \. C3 retn
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!