首页
社区
课程
招聘
[推荐]令我战斗十小时的Crack_Me; 已加入分析
发表于: 2005-4-9 14:20 8051

[推荐]令我战斗十小时的Crack_Me; 已加入分析

2005-4-9 14:20
8051

要求: 此Crack me 的要求是写出Keygen,关键函数用了大量混乱码.
对象: 新手或中手
编译器:汇编

因为不能上传, 所以贴上连结 : http://www.crackmes.de/users/blueowl/crackmes/quantity_serial_protection_l.2/download

后天,我会上我的解答。希望对大家有帮助


[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

收藏
免费 7
支持
分享
最新回复 (7)
雪    币: 296
活跃值: (260)
能力值: ( LV9,RANK:210 )
在线值:
发帖
回帖
粉丝
2
Quantity Serial Protection #LEVEL 2#
by BlueOwl

Details:

Anti-Cracking.......None
Anti-Debugging......None
Encryption..........None
Packing.............None
Serial..............32bit
Language............Assembler
Difficulty..........Medium/Hard

Mission:

Creating a key generator, have fun.

User/Serial Examples:

User1: BlueOwl
Password1: GHICAEDK
User2: Coding4Ever
Password2: JDMBBDDB
2005-4-9 20:25
0
雪    币: 207
活跃值: (55)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
1. 用 IDA 反汇编 QSP Level 2.EXE , IDA 分析完后, 按 CTRL + E, 来到程序入口.

.code:00402000 start           proc near
.code:00402000                 push    0               ; lpModuleName
.code:00402002                 call    ds:GetModuleHandleA
.code:00402008                 push    0               ; dwInitParam
.code:0040200A                 push    offset DialogFunc ; lpDialogFunc
.code:0040200F                 push    0               ; hWndParent
.code:00402011                 push    25h             ; lpTemplateName
.code:00402013                 push    eax             ; hInstance
.code:00402014                 call    ds:DialogBoxParamA ; Create a modal dialog box from a
.code:00402014                                         ; dialog box template resource
.code:0040201A                 push    0               ; uExitCode
.code:0040201C                 call    ds:ExitProcess
.code:0040201C start           endp

分析: 可以从 push    offset DialogFunc ; lpDialogFunc 看出函数 DialogFunc 处理对话框的消息, 双击它来到以下:

2.
.code:00402022                 push    ebp
.code:00402023                 mov     ebp, esp
.code:00402025                 push    ebx
.code:00402026                 push    esi             ; nMaxCount
.code:00402027                 push    edi             ; hDlg
.code:00402028                 cmp     [ebp+Msg], WM_INITDIALOG
.code:0040202F                 jz      loc_402146
.code:00402035                 cmp     [ebp+Msg], WM_COMMAND
.code:0040203C                 jz      short WM_COMMAND ; 跳到处理 WM_COMMAND 消息的地方
.code:0040203E                 cmp     [ebp+Msg], WM_CLOSE
.code:00402042                 jz      Close_Dialog
.code:00402048                 xor     eax, eax
.code:0040204A                 jmp     Do_Nothing

.code:0040204F WM_COMMAND:                             ; CODE XREF: DialogFunc+1Aj
.code:0040204F                 cmp     [ebp+WPARAM], 66h ; "I give up" 按钮的ID
.code:00402053                 jz      Leave
.code:00402059                 cmp     [ebp+WPARAM], 65h ; "Test" 按钮的ID
.code:0040205D                 jnz     loc_402146      ; 如不相等,就不处理
.code:00402063                 push    13h             ; nMaxCount
.code:00402065                 push    offset Name     ; lpString
.code:0040206A                 push    0C9h            ; nIDDlgItem, "Name" 的 ID
.code:0040206F                 push    [ebp+hDlg]      ; hDlg
.code:00402072                 call    ds:GetDlgItemTextA
.code:00402078                 push    9               ; nMaxCount
.code:0040207A                 push    offset Serial_Part1 ; lpString
.code:0040207F                 push    0CAh            ; nIDDlgItem, "Serial" 的 ID
.code:00402084                 push    [ebp+hDlg]      ; hDlg
.code:00402087                 call    ds:GetDlgItemTextA
.code:0040208D                 mov     eax, Serial_Part1
.code:00402092                 sub     eax, 41414141h  ; AAAA
.code:00402097                 mov     ebx, Serial_Part2; "Serial_Part1" 的位移 +4
.code:0040209D                 sub     ebx, 41414141h  ; AAAA
.code:004020A3                 shl     ebx, 4
.code:004020A6                 or      eax, ebx
.code:004020A8                 mov     Temp, eax
.code:004020AD                 mov     esi, offset Name
.code:004020B2                 sub     edx, edx                ;edx 清零

分析: 从 push    9; nMaxCount 可看出它只把 Serial 的前九位放进内存,但是后 0040208D ~ 0040209D , 可看出它只取 Serial 的前八位计算

为了方便,我们首先定义 0040208D ~ 004020A8 为 F(Serial), 如果我们计算到 temp 的值如何找到 Serial 呢?即是要 F(Serial) 的逆运算,但是 004020A6 的 or      eax, ebx 是不可逆的,因为这个 or 令到一个正确的 temp 可导致很多正确的 Serial. 我们唯有做些取巧的工作,我们假设在执行004020A6时 eax 是这样形式的: 0X0X0X0X ;
ebx 是这样形式的: X0X0X0X0 。这里X是一个整数,并且 0 <= X <= F。这样如我们找到正确的 temp 值, 就可以以下的代码找回 Serial,可以看出这样求出的 Serial 是八个A-P字符来的
                        mov eax, temp
                        mov ebx, eax
                        and ebx, 0F0F0F0Fh
                        and eax, 0F0F0F0F0h
                        mov edx, offset Serial
                        add edx, 41414141h
                        mov [edx], ecx
                        shr eax, 4
                        add eax, 41414141h
                        mov [edx+4], eax                       
                        invoke SetDlgItemText, hWin, IDC_SERIAL,offset Serial
3. 继续看下去:

.code:004020B4 loc_4020B4:                             ; CODE XREF: DialogFunc+B3j
.code:004020B4                 lodsb                   ; Load byte ptr[ESI] into al
.code:004020B5                 or      al, al          ; 是 "Null" 吗? 处理完了吗
.code:004020B7                 jz      short Main_Calculation ; 如处理完,就跳
.code:004020B9                 mov     ecx, 8
.code:004020BE
.code:004020BE loc_4020BE:                             ; CODE XREF: DialogFunc+B1j
.code:004020BE                 shr     al, 1           ; 放 al 最右的位元进 C flag
.code:004020C0                 jb      short loc_4020CB ; 如果 C flag, 即是 al 最右的位元是一就跳
.code:004020C2                 xor     edx, 8F7BA832h
.code:004020C8                 rol     edx, 7
.code:004020CB
.code:004020CB loc_4020CB:                             ; CODE XREF: DialogFunc+9Ej
.code:004020CB                 add     edx, 9AB832ADh
.code:004020D1                 bswap   edx
.code:004020D3                 loop    loc_4020BE      
.code:004020D5                 jmp     short loc_4020B4 ; 下一个字符

分析: 这里是处理 Name 的地方, 我们定义004020B4 ~ 004020D5 为 G(Name)。因为我们的 Keygen 是用 Name 求出 Serial 的,所以不用逆 G(Name)

4.我们来到 Main_Calculation:

.code:004020D7                 mov     eax, Temp
.code:004020DC                 pusha                  
.code:004020DD                 call    Calculation
.code:004020E2                 xchg    eax, [esp+1Ch]  ; [esp+1c] 是经过 pusha,储存原本 EAX 的地方
.code:004020E2                                         ; 所以 xchg 和popa 后,
.code:004020E2                                         ; EAX 仍然是 Calculation 的结果, 否则会被覆盖
.code:004020E6                 popa                    
.code:004020E7                 cmp     edx, eax        ; G(Name) == H(F(Serial))?
.code:004020E9                 mov     eax, offset aVictory ; "Victory!"
.code:004020EE                 mov     ebx, offset aYouWonPlayAgai ; "You won! Play again? ;)"
.code:004020F3                 jz      short Sucess
.code:004020F5                 mov     eax, offset Caption ; "Nope."
.code:004020FA                 mov     ebx, offset Text ; "Sorry, thats not it."

分析: 如果各位想爆破的,可以修改 004020F3 的 jz      short Sucess 为 jmp short Sucess;如要写 Keygen ,就要写出 Calculation 的逆运算了,用枚举法是不行的,因为 Calculation 的指令太多了, 如用枚举法大概会当机的了。

5.进入 Calculation 你会发现这是一个 1541 行指令的函数。我发现后我立即放弃了。几天后,我比较有精神,才来处理它。
我们首先清理混乱码。这样我们就要从函数的后面开始分析:

.code:004032CF                 or      esi, ecx        ; Mov
.code:004032D1                 and     esi, ecx
.code:004032D3                 adc     edi, edi        ; No use
.code:004032D5                 xor     esi, 22h
.code:004032D8                 ror     edi, 1Eh        ; No use
.code:004032DB                 add     esi, 0FFFFFF97h
.code:004032DE                 not     esi
.code:004032E0                 not     edi             ; No use
.code:004032E2                 bswap   esi
.code:004032E4                 sal     ebp, 19h        ; No use
.code:004032E7                 not     esi
.code:004032E9                 inc     ecx                ;No Use
.code:004032EA                 ror     esi, 1
.code:004032EC                 and     ebx, 0FFFFFFA0h ; No Use
.code:004032EF                 neg     esi
.code:004032F1                 xor     esi, 0FFFFFFE2h
.code:004032F4                 std                     ; No use
.code:004032F5                 mov     eax, esi
.code:004032F7                 retn

分析: 明显影响结果的是 ESI 的值,4032F4, 4032EC 等不会影响 ESI 的值的就是混乱码。
注意: 这个函数有几个变形 mov, 就像处理壳时有变形 jmp 一样。以下是一些变形 mov

1. or esi, ecx; and esi, ecx 即是 mov esi, ecx
2. push ecx; pop esi 即是 mov esi, ecx
3. xchg ecx, esi 也是

这样 ESI 在只会在004032CF时被 ECX 影响, 其他的是混乱码,把它们全清除。并把所有变形 mov, 改为 mov 指令。在清理完后,Calculation 大概会剩下 1047 行令, 当然其中还包括混乱码,但是所有这些指令都是可逆的了。即是 Calculation 只有 mov, add, sub, ror, rol, xchg, dec, inc, bswap, xor 指令。 如有其他的,大概是混乱码了。
清理完后的函数Calculation, clean.asm 我已加入在以下的keygen_qsplevel2.zip 了

6.最后就是会把这些指令的顺序调换一下,即是把第 1047 行的指令调到第 1 行等等。我制作了一个在 Ultra-Edit 中运行的宏(已包含在后面的那个ZIP里)来完成这个动作。
并把所有add变成sub, sub变成add, ror变成rol, rol变成ror, mov 和 变形 mov 变成 xchg, inc变成dec, dec 变成inc (注意有个数字包令 DEC 三个字), inc 变成 dec,  把第一行指令xchg eax, esi 改成 xchg edx, esi, 因为G(name)的值在 EDX里

这时,我们已把Calculation逆了,要求出Serial只要 F'(H'(G(Name))), F'() 是 F 的逆运算, H' 是Calculation的逆运算。

这是关于这对这 crackme 有帮助的档案:
http://maxputer.tripod.com/pediy/keygen_qsplevel2.zip

那keygen的来源档建议用winasm来编译, winasm 是 MASM 的一个前端 IDE, 功能强大, 介面十分友善。
2005-4-10 08:43
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
最初由 Winter-Night 发布

.......
Difficulty..........Medium/Hard


2005-4-13 21:19
0
雪    币: 232
活跃值: (25)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
5
好东西!!!!
2005-4-14 10:50
0
雪    币: 277
活跃值: (37)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
6
帮你把文件上传了。
附件:QSPLevel2.zip
2005-4-23 13:33
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
好东西!!!!
2005-4-29 00:07
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
好东西!!!!!!!!!!!
2005-10-27 17:21
0
游客
登录 | 注册 方可回帖
返回
//