【文章标题】: 堆栈的计算
【文章作者】: coldpine
【下载地址】: http://www.crackmes.de/users/pickled/crackme0x1/
【编写语言】: c++
【使用工具】: od
【作者声明】: 只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!
--------------------------------------------------------------------------------
【详细过程】
name:heminrui
serial:123456789
00401290 /$ 55 PUSH EBP
00401291 |. 89E5 MOV EBP, ESP
00401293 |. 81EC A8000000 SUB ESP, 0A8
00401299 |. 83E4 F0 AND ESP, FFFFFFF0
0040129C |. B8 00000000 MOV EAX, 0
004012A1 |. 83C0 0F ADD EAX, 0F
004012A4 |. 83C0 0F ADD EAX, 0F
004012A7 |. C1E8 04 SHR EAX, 4
004012AA |. C1E0 04 SHL EAX, 4
004012AD |. 8985 74FFFFFF MOV DWORD PTR SS:[EBP-8C], EAX
004012B3 |. 8B85 74FFFFFF MOV EAX, DWORD PTR SS:[EBP-8C]
004012B9 |. E8 92050000 CALL xtfK1.00401850
004012BE |. E8 2D020000 CALL xtfK1.004014F0
004012C3 |. C70424 002040>MOV DWORD PTR SS:[ESP], xtfK1.004020>; |||||created by: xtfusion\ncrackme: k1\n\nwelcome to my first crackme! (sorry for my lazy coding)\nalso i had no time to test this crackme! but it should\nwork on 95 , 98 , 2000 , xp\ncreate a keygen and make a tut for crackmes.de\nthats all so injoy.\n\n
004012CA |. E8 91060000 CALL <JMP.&msvcrt.printf> ; ||||\printf
004012CF |. C70424 003040>MOV DWORD PTR SS:[ESP], xtfK1.004030>; ||||name:
004012D6 |. E8 85060000 CALL <JMP.&msvcrt.printf> ; |||\printf
004012DB |. 8D45 98 LEA EAX, DWORD PTR SS:[EBP-68] ; |||
004012DE |. 890424 MOV DWORD PTR SS:[ESP], EAX ; |||
004012E1 |. E8 6A060000 CALL <JMP.&msvcrt.gets> ; ||\gets
004012E6 |. C70424 073040>MOV DWORD PTR SS:[ESP], xtfK1.004030>; ||serial:
004012ED |. E8 6E060000 CALL <JMP.&msvcrt.printf> ; |\printf
004012F2 |. 8D85 78FFFFFF LEA EAX, DWORD PTR SS:[EBP-88] ; |
004012F8 |. 890424 MOV DWORD PTR SS:[ESP], EAX ; |
004012FB |. E8 50060000 CALL <JMP.&msvcrt.gets> ; \gets
00401300 |. C745 F4 00000>MOV DWORD PTR SS:[EBP-C], 0
00401307 |> 8D45 98 /LEA EAX, DWORD PTR SS:[EBP-68] ;
0040130A |. 890424 |MOV DWORD PTR SS:[ESP], EAX ; 取得用户名
0040130D |. E8 2E060000 |CALL <JMP.&msvcrt.strlen> ; \strlen
00401312 |. 3945 F4 |CMP DWORD PTR SS:[EBP-C], EAX ;比较,不大于的时候跳走
00401315 |. 73 4B |JNB SHORT xtfK1.00401362
00401317 |. 8D45 F8 |LEA EAX, DWORD PTR SS:[EBP-8]
0040131A |. 0345 F4 |ADD EAX, DWORD PTR SS:[EBP-C]
0040131D |. 83E8 60 |SUB EAX, 60 ;用户名(循环的时候由于[ebp-c]在逐渐加1,所以可以循环取用户名的每个字符)
00401320 |. 0FBE10 |MOVSX EDX, BYTE PTR DS:[EAX] ;取用户名每个字符的ascii码值,设值为x
00401323 |. 89D0 |MOV EAX, EDX ;eax=x,edx=x
00401325 |. C1E0 02 |SHL EAX, 2 ;将x左移两位
00401328 |. 01D0 |ADD EAX, EDX ;再求和
0040132A |. 89C2 |MOV EDX, EAX ;分别将结果保留为两份
0040132C |. C1E2 04 |SHL EDX, 4 ;将其中的一份左移四位
0040132F |. 8D45 EC |LEA EAX, DWORD PTR SS:[EBP-14] ;12c6cc的地址 ;12e74c
00401332 |. 0110 |ADD DWORD PTR DS:[EAX], EDX ;12c6cc+2080=12e74c = y1 ;12e74c+1f90=1306dc =y2
00401334 |. 8B45 EC |MOV EAX, DWORD PTR SS:[EBP-14]
00401337 |. 0345 E8 |ADD EAX, DWORD PTR SS:[EBP-18] ;12e74c+77c0aead=77d395f9 1306dc+77d395cb=77e69ca7
0040133A |. 83F0 32 |XOR EAX, 32 ;将结果异或77d395f9 xor 32=77d395cb 77e69ca7 xor 32 =77e69c95
0040133D |. 8945 E8 |MOV DWORD PTR SS:[EBP-18], EAX [ebp-18]= 77d395cb = y1' [ebp-18]=77e69c95 =y2'
00401340 |. 8B45 E8 |MOV EAX, DWORD PTR SS:[EBP-18]
00401343 |. 8D1485 000000>|LEA EDX, DWORD PTR DS:[EAX*4] ;edx=DF4E572C edx=DF9A7254
0040134A |. 8D45 E4 |LEA EAX, DWORD PTR SS:[EBP-1C] ;ebp-1c存放着8 [ebp-1c]=DF4E5734
0040134D |. 0110 |ADD DWORD PTR DS:[EAX], EDX ;[ebp-1c]=DF4E572C+8=DF4E5734 =z1 [ebp-1c]=DF9A7254+DF4E5734=BEE8C988 =z2
0040134F |. 8B45 E8 |MOV EAX, DWORD PTR SS:[EBP-18] ;[ebp-18]=77d395cb [ebp-18]=77e69c95 并送到eax
00401352 |. 0345 E4 |ADD EAX, DWORD PTR SS:[EBP-1C] ;eax=77d395cb+DF4E5734=5721ECF7 eax=77e69c95+BEE8C988=36CF661D
00401355 |. 0345 EC |ADD EAX, DWORD PTR SS:[EBP-14] ;eax=5721ecf7+12e74c=5734d44b eax=36CF661D+1306dc=36E26CF9
00401358 |. 8945 E0 |MOV DWORD PTR SS:[EBP-20], EAX ;[ebp-20]=5734d44b =z1' [ebp-20]=36E26CF9 =z2'
0040135B |. 8D45 F4 |LEA EAX, DWORD PTR SS:[EBP-C]
0040135E |. FF00 |INC DWORD PTR DS:[EAX] ;22ff6c是一个计数器,计数器加1 计数器再加1,继续第三位跟踪
00401360 |.^ EB A5 \JMP SHORT xtfK1.00401307
00401362 |> 8B45 E0 MOV EAX, DWORD PTR SS:[EBP-20] ; ||
00401365 |. 894424 08 MOV DWORD PTR SS:[ESP+8], EAX ; ||
00401369 |. C74424 04 103>MOV DWORD PTR SS:[ESP+4], xtfK1.0040>; ||%x
00401371 |. 8D45 B8 LEA EAX, DWORD PTR SS:[EBP-48] ; ||
00401374 |. 890424 MOV DWORD PTR SS:[ESP], EAX ; ||
00401377 |. E8 44060000 CALL <JMP.&USER32.wsprintfA> ; |\wsprintfA 将结果7B52F4A1变成字符串"7b52f4a1"(这个就是最终的真注册码)
0040137C |. C745 F0 00000>MOV DWORD PTR SS:[EBP-10], 0 ; |
00401383 |. 80BD 78FFFFFF>CMP BYTE PTR SS:[EBP-88], 0 ; | ;输入的序列号和0比较
0040138A |. 75 0E JNZ SHORT xtfK1.0040139A ; |
0040138C |. C70424 133040>MOV DWORD PTR SS:[ESP], xtfK1.004030>; |serial 2 short!
00401393 |. E8 C8050000 CALL <JMP.&msvcrt.printf> ; \printf
00401398 |. EB 57 JMP SHORT xtfK1.004013F1
0040139A |> 807D 98 00 CMP BYTE PTR SS:[EBP-68], 0 ; |
0040139E |. 75 0E JNZ SHORT xtfK1.004013AE ; |
004013A0 |. C70424 233040>MOV DWORD PTR SS:[ESP], xtfK1.004030>; |name 2 short!
004013A7 |. E8 B4050000 CALL <JMP.&msvcrt.printf> ; \printf
004013AC |. EB 43 JMP SHORT xtfK1.004013F1
004013AE |> C745 F4 00000>MOV DWORD PTR SS:[EBP-C], 0
004013B5 |> 8D85 78FFFFFF /LEA EAX, DWORD PTR SS:[EBP-88] ; |
004013BB |. 890424 |MOV DWORD PTR SS:[ESP], EAX ; | 将计算出来的序号和输入的序列号逐位比较,是注册成功,否则失败!
004013BE |. E8 7D050000 |CALL <JMP.&msvcrt.strlen> ; \strlen
004013C3 |. 3945 F4 |CMP DWORD PTR SS:[EBP-C], EAX
004013C6 |. 73 29 |JNB SHORT xtfK1.004013F1
004013C8 |. 8D45 F8 |LEA EAX, DWORD PTR SS:[EBP-8]
004013CB |. 0345 F4 |ADD EAX, DWORD PTR SS:[EBP-C]
004013CE |. 8D48 C0 |LEA ECX, DWORD PTR DS:[EAX-40]
004013D1 |. 8D45 F8 |LEA EAX, DWORD PTR SS:[EBP-8]
004013D4 |. 0345 F4 |ADD EAX, DWORD PTR SS:[EBP-C]
004013D7 |. 8D50 80 |LEA EDX, DWORD PTR DS:[EAX-80]
004013DA |. 0FB601 |MOVZX EAX, BYTE PTR DS:[ECX]
004013DD |. 3A02 |CMP AL, BYTE PTR DS:[EDX]
004013DF 75 02 JNZ SHORT xtfK1.004013E3
004013E1 |. EB 07 |JMP SHORT xtfK1.004013EA
004013E3 |> C745 F0 01000>|MOV DWORD PTR SS:[EBP-10], 1
004013EA |> 8D45 F4 |LEA EAX, DWORD PTR SS:[EBP-C]
004013ED |. FF00 |INC DWORD PTR DS:[EAX]
004013EF |.^ EB C4 \JMP SHORT xtfK1.004013B5
004013F1 |> 837D F0 01 CMP DWORD PTR SS:[EBP-10], 1
004013F5 75 02 JNZ SHORT xtfK1.004013F9
004013F7 |. EB 0C JMP SHORT xtfK1.00401405
004013F9 |> C70424 313040>MOV DWORD PTR SS:[ESP], xtfK1.004030>; |\ncorect, now make a keygen\n ;弹出注册成功标志.
00401400 |. E8 5B050000 CALL <JMP.&msvcrt.printf> ; \printf
00401405 |> B8 00000000 MOV EAX, 0
0040140A |. C9 LEAVE
0040140B \. C3 RET
--------------------------------------------------------------------------------
【经验总结】
这个crackme主要的感觉是对堆栈中计算过多,跟踪的时候比较费劲.
算法:(都是16进制的计算)
设每位字符的ascii码值为x1,x2,x3,...,xn
将x1进行左移两位加上自身,再将上面结果左移四位设为x1'
y1=x1'+12c6cc
y1'=(y1+77c0aead) xor 32
z1=(y1'*4)+8
z1'=y1'+z1+y1
到此,一个字符的结果计算出来了,但是这些结果并没有带到后面去,
只是利用运行期间一些变量的变化而已.紧接着是计算第二个字符.
y2=y1+x2'
y2'=(y2+y1') xor 32
z2=(y2'*4)+z1
z2'=y2'+z2+y2
直到最后的一个字母算出来的zn'
将zn'转换格式化为字符即为注册码
所以一组正确的注册码和用户名为:
name:heminrui
serial:7b52f4a1
;12c6cc的地址 ;12e74c
;12c6cc+2080=12e74c = y1 ;12e74c+1f90=1306dc =y2
;12e74c+77c0aead=77d395f9 1306dc+77d395cb=77e69ca7
;将结果异或77d395f9 xor 32=77d395cb 77e69ca7 xor 32 =77e69c95
[ebp-18]= 77d395cb = y1' [ebp-18]=77e69c95 =y2'
;edx=DF4E572C edx=DF9A7254
;ebp-1c存放着8 [ebp-1c]=DF4E5734
;[ebp-1c]=DF4E572C+8=DF4E5734 =z1 [ebp-1c]=DF9A7254+DF4E5734=BEE8C988 =z2
;[ebp-18]=77d395cb [ebp-18]=77e69c95 并送到eax
;eax=77d395cb+DF4E5734=5721ECF7 eax=77e69c95+BEE8C988=36CF661D
;eax=5721ecf7+12e74c=5734d44b eax=36CF661D+1306dc=36E26CF9
;[ebp-20]=5734d44b =z1' [ebp-20]=36E26CF9 =z2'
感觉比较复杂的运行多跟踪几个循环,就比教容易找到规律了.
--------------------------------------------------------------------------------
【版权声明】: 本文原创于看雪技术论坛, 转载请注明作者并保持文章的完整, 谢谢!
2006年10月12日 19:23:16
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!