【文章标题】: Crackme6的破解和算法分析
【下载地址】: 自己搜索下载
【加壳方式】: ASPack 2.x
【编写语言】: C/C++
【使用工具】: OD PEID
【操作平台】: WIN XP
【作者声明】: 如果之前有高手已经破解了,请告诉我,我将把附件删了,给论坛省空间
--------------------------------------------------------------------------------
【详细过程】
peid 查壳 有壳ASPack 2.x (without poly) -> Alexey Solodovnikov [Overlay]
不过脱壳很容易,直接用工具脱就可以,为了省时间,我上传的附件是已经脱壳的了。
点击运行,随意输入,没有反应
运行OD,将crack载入,下断点在此处,F9运行到此处
0040139E |. 68 00010000 PUSH 100 ; /Count = 100 (256.)
004013A3 |. 8D85 E1FCFFFF LEA EAX,DWORD PTR SS:[EBP-31F] ; |
004013A9 |. 50 PUSH EAX ; |Buffer
004013AA |. 6A 66 PUSH 66 ; |ControlID = 66 (102.)
004013AC |. FF75 08 PUSH DWORD PTR SS:[EBP+8] ; |hWnd
004013AF |. E8 84030000 CALL <JMP.&USER32.GetDlgItemTextA> ; \GetDlgItemTextA
004013B4 |. 09C0 OR EAX,EAX
004013B6 |. 0F84 48010000 JE _UnPacke.00401504
004013BC |. B8 CF110000 MOV EAX,11CF EAX=11CF
004013C1 |. 0FB68D E1FCFF>MOVZX ECX,BYTE PTR SS:[EBP-31F] 取用户名的第一个字节到ECX
004013C8 |. 99 CDQ
004013C9 |. F7F9 IDIV ECX
004013CB |. 83FA 17 CMP EDX,17 将余数与17h相比较,如果不为零,则结束程序
由此我们知道,我们输入的序列号的第一位需满足这样
的条件,(11cfh-17h) mod 第一个字符 ==0
004013CE |. 74 07 JE SHORT _UnPacke.004013D7
004013D0 |. 31C0 XOR EAX,EAX
004013D2 |. E9 2D010000 JMP _UnPacke.00401504
004013D7 |> 31DB XOR EBX,EBX
004013D9 |. EB 0B JMP SHORT _UnPacke.004013E6
004013DB |> 8B45 10 /MOV EAX,DWORD PTR SS:[EBP+10]
004013DE |. 0FBE0418 |MOVSX EAX,BYTE PTR DS:[EAX+EBX] 依次取用户名的字节到EAX
004013E2 |. 0145 FC |ADD DWORD PTR SS:[EBP-4],EAX 将用户名的字符累加
004013E5 |. 43 |INC EBX
004013E6 |> 3B5D 0C CMP EBX,DWORD PTR SS:[EBP+C]
004013E9 |.^ 7C F0 \JL SHORT _UnPacke.004013DB
上面这个循环就是将用户名的各个字符累加
004013EB |. 31DB XOR EBX,EBX
004013ED |. E9 83000000 JMP _UnPacke.00401475
004013F2 |> 8B55 10 /MOV EDX,DWORD PTR SS:[EBP+10]
004013F5 |. 0FBE3C1A |MOVSX EDI,BYTE PTR DS:[EDX+EBX] 依次取用户名的一个字节
004013F9 |. 8B75 FC |MOV ESI,DWORD PTR SS:[EBP-4] 取累加和到ESI
004013FC |. 89D9 |MOV ECX,EBX EBX为第几次循环-1
004013FE |. C1E1 02 |SHL ECX,2 左移两位,即为*4
00401401 |. 89DA |MOV EDX,EBX
00401403 |. 42 |INC EDX EDX自加后,即为第几次循环
00401404 |. 29D1 |SUB ECX,EDX
00401406 |. 0FB68C0D E1FE>|MOVZX ECX,BYTE PTR SS:[EBP+ECX-11F] 取内存中的一个表的字节内容到ECX中
0040140E |. 89FA |MOV EDX,EDI
00401410 |. 31CA |XOR EDX,ECX
00401412 |. 89F1 |MOV ECX,ESI ECX此时为累加之和
00401414 |. 0FAFCB |IMUL ECX,EBX 累加之和*第几次循环-1
00401417 |. 29F1 |SUB ECX,ESI
00401419 |. 89CE |MOV ESI,ECX
0040141B |. 83F6 FF |XOR ESI,FFFFFFFF
0040141E |. 8DB432 4D0100>|LEA ESI,DWORD PTR DS:[EDX+ESI+14D] 取计算出来的地址到ESI
00401425 |. 8B4D 0C |MOV ECX,DWORD PTR SS:[EBP+C] ecx为用户名长度
00401428 |. 89DA |MOV EDX,EBX EDX=第几次循环-1
0040142A |. 83C2 03 |ADD EDX,3 edx=第几次循环+2
0040142D |. 0FAFCA |IMUL ECX,EDX ECX=用户名长度*第几次循环+2
00401430 |. 0FAFCF |IMUL ECX,EDI ECX=ECX*用户名的一个字节
00401433 |. 89F0 |MOV EAX,ESI 计算出来的地址送到EAX
00401435 |. 01C8 |ADD EAX,ECX
00401437 |. B9 0A000000 |MOV ECX,0A
0040143C |. 31D2 |XOR EDX,EDX
0040143E |. F7F1 |DIV ECX
00401440 |. 83C2 30 |ADD EDX,30 余数+30h
00401443 |. 88941D FCFEFF>|MOV BYTE PTR SS:[EBP+EBX-104],DL
0040144A |. 0FB6BC1D FCFE>|MOVZX EDI,BYTE PTR SS:[EBP+EBX-104] 算出来的字符送到EDI
00401452 |. 81F7 ACAD0000 |XOR EDI,0ADAC
00401458 |. 89DE |MOV ESI,EBX
0040145A |. 83C6 02 |ADD ESI,2
0040145D |. 89F8 |MOV EAX,EDI
0040145F |. 0FAFC6 |IMUL EAX,ESI
00401462 |. B9 0A000000 |MOV ECX,0A
00401467 |. 99 |CDQ
00401468 |. F7F9 |IDIV ECX
0040146A |. 83C2 30 |ADD EDX,30 余数+30
0040146D |. 88941D FCFEFF>|MOV BYTE PTR SS:[EBP+EBX-104],DL
00401474 |. 43 |INC EBX
00401475 |> 3B5D 0C CMP EBX,DWORD PTR SS:[EBP+C]
00401478 |.^ 0F8C 74FFFFFF \JL _UnPacke.004013F2
0040147E |. 8D85 FCFEFFFF LEA EAX,DWORD PTR SS:[EBP-104]
00401484 |. 50 PUSH EAX
00401485 |. 6A 54 PUSH 54
00401487 |. 8D85 DCFBFFFF LEA EAX,DWORD PTR SS:[EBP-424]
0040148D |. 50 PUSH EAX ; |Format
0040148E |. 8D85 E1FBFFFF LEA EAX,DWORD PTR SS:[EBP-41F] ; |
00401494 |. 50 PUSH EAX ; |s
00401495 |. E8 CE020000 CALL <JMP.&USER32.wsprintfA> ; \wsprintfA 格式化字符串,将上步算出来的字符串格式化
在上步格式化的字符串之前加上个"T"
0040149A |. 8B7D 0C MOV EDI,DWORD PTR SS:[EBP+C]
0040149D |. 89F8 MOV EAX,EDI
0040149F |. 0FAF45 FC IMUL EAX,DWORD PTR SS:[EBP-4]
004014A3 |. B9 64000000 MOV ECX,64
004014A8 |. 99 CDQ
004014A9 |. F7F9 IDIV ECX
004014AB |. 89D7 MOV EDI,EDX
004014AD |. 83C7 30 ADD EDI,30
004014B0 |. 57 PUSH EDI 以上几部,算出一个数字,加到上步算出的格式化字符串
004014B1 |. 8DBD E1FBFFFF LEA EDI,DWORD PTR SS:[EBP-41F]
004014B7 |. 57 PUSH EDI
004014B8 |. 8DBD D6FBFFFF LEA EDI,DWORD PTR SS:[EBP-42A]
004014BE |. 57 PUSH EDI ; |Format
004014BF |. 8DBD E1FDFFFF LEA EDI,DWORD PTR SS:[EBP-21F] ; |
004014C5 |. 57 PUSH EDI ; |s
004014C6 |. E8 9D020000 CALL <JMP.&USER32.wsprintfA> ; \wsprintfA
004014CB |. 83C4 20 ADD ESP,20
004014CE |. 8D8D E1FDFFFF LEA ECX,DWORD PTR SS:[EBP-21F]
004014D4 |. 83C8 FF OR EAX,FFFFFFFF
004014D7 |> 40 /INC EAX
004014D8 |. 803C01 00 |CMP BYTE PTR DS:[ECX+EAX],0
004014DC |.^ 75 F9 \JNZ SHORT _UnPacke.004014D7
004014DE |. 50 PUSH EAX ; /Arg3
004014DF |. 8D85 E1FCFFFF LEA EAX,DWORD PTR SS:[EBP-31F] ; |
004014E5 |. 50 PUSH EAX ; |Arg2
004014E6 |. 8D85 E1FDFFFF LEA EAX,DWORD PTR SS:[EBP-21F] ; |
004014EC |. 50 PUSH EAX ; |Arg1
004014ED |. E8 D0FDFFFF CALL _UnPacke.004012C2 ; \_UnPacke.004012C2 跟进
004012C2 /$ 55 PUSH EBP
004012C3 |. 89E5 MOV EBP,ESP
004012C5 |. 53 PUSH EBX
004012C6 |. 56 PUSH ESI
004012C7 |. 57 PUSH EDI
004012C8 |. 8B5D 10 MOV EBX,DWORD PTR SS:[EBP+10]
004012CB |. 31F6 XOR ESI,ESI
004012CD |. 46 INC ESI
004012CE |. EB 29 JMP SHORT _UnPacke.004012F9
004012D0 |> 8B55 08 /MOV EDX,DWORD PTR SS:[EBP+8]
004012D3 |. 0FBE3C32 |MOVSX EDI,BYTE PTR DS:[EDX+ESI] 从算出来序列号的第二个字符起开始
004012D7 |. 89F8 |MOV EAX,EDI
004012D9 |. 83F0 20 |XOR EAX,20
004012DC |. B9 0A000000 |MOV ECX,0A
004012E1 |. 99 |CDQ
004012E2 |. F7F9 |IDIV ECX
004012E4 |. 89D7 |MOV EDI,EDX
004012E6 |. 83C7 30 |ADD EDI,30
004012E9 |. 8B55 0C |MOV EDX,DWORD PTR SS:[EBP+C]
004012EC |. 0FBE1432 |MOVSX EDX,BYTE PTR DS:[EDX+ESI]
004012F0 |. 39D7 |CMP EDI,EDX 比较算出来的序列号经过再次计算后
与用户输入的序列号比较
004012F2 |. 74 04 |JE SHORT _UnPacke.004012F8
004012F4 |. 31C0 |XOR EAX,EAX
004012F6 |. EB 08 |JMP SHORT _UnPacke.00401300
004012F8 |> 46 |INC ESI
004012F9 |> 39DE CMP ESI,EBX
004012FB |.^ 7C D3 \JL SHORT _UnPacke.004012D0
004012FD |. 31C0 XOR EAX,EAX
004012FF |. 40 INC EAX
00401300 |> 5F POP EDI
00401301 |. 5E POP ESI
00401302 |. 5B POP EBX
00401303 |. 5D POP EBP
00401304 \. C3 RETN
算法分析
用户输入的序列号的第一个字符只要满足以下条件就可以,它在后面的比较中并不参与
(11cfh-17h) mod 第一个字符 ==0
将用户名的字符累加为sum
设内存表为table,表内的内容为
0013F890 43424100 .ABC
0013F894 47464544 DEFG
0013F898 4B4A4948 HIJK
0013F89C 4F4E4D4C LMNO
0013F8A0 53525150 PQRS
0013F8A4 57565554 TUVW
0013F8A8 005A5958 XYZ.
0013F8AC 30363638 8660
第一项为空
循环内的计算比较繁琐,且好像没有一个比较简练的公式可以表达出来,如果有谁可以看出来的话,请告知。
再比较循环中,再次对已经算出来的数据再次进行一次计算,不包括第一个字符,即为“T"
且要满足 (设输入的序列号为serial,计算的为a)
则((a[t] xor 20h) mod 0ah)+30==serial[t]即可,t为第几次循环。
--------------------------------------------------------------------------------
【版权声明】: 本文原创于看雪技术论坛, 转载请注明作者并保持文章的完整, 谢谢!
2006年08月23日 23:53:59
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)
上传的附件: