hysteriaCRKME 破解+算法(1)

时间:2008-08-10 14:24:29  来源:互联网  作者:  字号:【

这个CrackMe不是很难,但花去我不少时间,贴在这里和大家分享~

【文章标题】: hysteriaCRKME 破解+算法
【文章作者】: megadeath
【作者邮箱】: massacre@163.com
【作者QQ号】: 84227716
【软件名称】: hysteria_CRKME
【软件大小】: 266,240
【下载地址】: http://crackmes.de/users/haiklr/hysteria_crackme/
【加壳方式】: 无
【保护方式】: 无
【编写语言】: asm
【使用工具】: OllyICE
【操作平台】: WinXPsp2
【软件介绍】: 用户名+Keyfile
【作者声明】: 只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!
--------------------------------------------------------------------------------
【详细过程】
 
  拿到CrackMe后,执行后只有一个文本框,在里面输入任意的用户名,然后点击Check,在文本框中提示Try harder !,显然注册失败,OK,PEiD检查没有壳没有保护,直接用OD加载,来到程序的入口点:

0040142F >/$  6A 00         push    0                                ; /pModule = NULL  <--程序开始入口
00401431  |.  E8 86080000   call    <jmp.&kernel32.GetModuleHandleA> ; \GetModuleHandleA
00401436  |.  A3 9C634000   mov     dword ptr [40639C], eax
0040143B  |.  6A 03         push    3                                ; /RsrcName = 3.
0040143D  |.  50            push    eax                              ; |hInst
0040143E  |.  E8 37080000   call    <jmp.&user32.LoadIconA>          ; \LoadIconA
00401443  |.  A3 A0634000   mov     dword ptr [4063A0], eax


我们直接用串式参考搜索,发现有“congratz ! send me your keygen”字样,双击来到程序代码中:
00401C0F  |.  68 A5614000   push    004061A5                         ; /congratz ! send me your keygen
00401C14  |.  6A 08         push    8                                ; |ControlID = 8
00401C16  |.  FF75 08       push    dword ptr [ebp+8]                ; |hWnd
00401C19  |.  E8 7A000000   call    <jmp.&user32.SetDlgItemTextA>    ; \SetDlgItemTextA

往上搜寻,这个函数很长一直到这个函数的开头部分:

00401925  /$  55            push    ebp
00401926  |.  8BEC          mov     ebp, esp
00401928  |.  57            push    edi
00401929  |.  56            push    esi
0040192A  |.  53            push    ebx
0040192B  |.  90            nop

00401925 在两个地方被调用,00401736 和 00401698 ,在这两个地方下断点,然后F9运行,这时OD停在了00401736处,先不要进入,再F9运行,这时程序完全启动起来,显示出界面,如果这个时候点击 Check后,OD停在了00401698 处。嗯,我们可以估计到在程序启动的时候加载了一次,以后每次点击Chcek按钮就都会调用一次00401925,我们再看一下在00401698 附近的代码:

0040166D   .  837D 10 05    cmp     dword ptr [ebp+10], 5
00401671   .  75 1C         jnz     short 0040168F
00401673   .  6A 00         push    0                                ; /lParam = NULL
00401675   .  68 91174000   push    00401791                         ; |DlgProc = Hysteria.00401791
0040167A   .  FF75 08       push    dword ptr [ebp+8]                ; |hOwner
0040167D   .  6A 02         push    2                                ; |pTemplate = 2
0040167F   .  FF35 9C634000 push    dword ptr [40639C]               ; |hInst = 00400000
00401685   .  E8 BA050000   call    <jmp.&user32.DialogBoxParamA>    ; \DialogBoxParamA
0040168A   .  E9 C5000000   jmp     00401754
0040168F   >  837D 10 06    cmp     dword ptr [ebp+10], 6
00401693   .  75 0D         jnz     short 004016A2
00401695   .  FF75 08       push    dword ptr [ebp+8]
00401698   .  E8 88020000   call    00401925
0040169D   .  E9 B2000000   jmp     00401754
004016A2   >  837D 10 07    cmp     dword ptr [ebp+10], 7
004016A6   .  0F85 A8000000 jnz     00401754
004016AC   .  6A 00         push    0                                ; /lParam = 0
004016AE   .  6A 00         push    0                                ; |wParam = 0
004016B0   .  6A 10         push    10                               ; |Message = WM_CLOSE
004016B2   .  FF75 08       push    dword ptr [ebp+8]                ; |hWnd
004016B5   .  E8 D2050000   call    <jmp.&user32.SendMessageA>       ; \SendMessageA
004016BA   .  E9 95000000   jmp     00401754
004016BF   >  817D 0C 10010>cmp     dword ptr [ebp+C], 110
004016C6   .  75 75         jnz     short 0040173D


注意0040166D 、0040168F、004016A2这几行,在和5,6,7来比较,到这里能够看出一些端倪,其实这个是Windows回调函数中的对控件消息处理的 switch语句,因此在00401698 调用也就是点击Check按钮的一个响应。我们在00401698 处下断点,在文本框中输入用户名,然后点击check按钮,这时OD拦截,进入00401698 函数,我们一点一点往下看:

00401925  /$  55            push    ebp
00401926  |.  8BEC          mov     ebp, esp
00401928  |.  57            push    edi
00401929  |.  56            push    esi
0040192A  |.  53            push    ebx
0040192B  |.  90            nop
0040192C  |.  90            nop
0040192D  |.  90            nop
0040192E  |.  90            nop
0040192F  |.  90            nop
00401930  |.  90            nop
00401931  |.  90            nop
00401932  |.  90            nop
00401933  |.  6A 1E         push    1E                               ; /Count = 1E (30.)
00401935  |.  68 50624000   push    00406250                         ; |Buffer = Hysteria.00406250
0040193A  |.  6A 08         push    8                                ; |ControlID = 8
0040193C  |.  FF75 08       push    dword ptr [ebp+8]                ; |hWnd
0040193F  |.  E8 24030000   call    <jmp.&user32.GetDlgItemTextA>    ; \GetDlgItemTextA
00401944  |.  83F8 04       cmp     eax, 4
00401947  |.  0F8C D3020000 jl      00401C20                         ;  小于4就跳到错误处理
0040194D  |.  83F8 18       cmp     eax, 18
00401950  |.  0F8F CA020000 jg      00401C20                         ;  大于0x18就跳到错误处理
00401956  |.  90            nop
00401957  |.  90            nop
00401958  |.  90            nop
00401959  |.  90            nop
0040195A  |.  90            nop
0040195B  |.  90            nop
0040195C  |.  90            nop
0040195D  |.  A3 88634000   mov     dword ptr [406388], eax
00401962  |.  FF35 88634000 push    dword ptr [406388]               ;  将字符串长度压栈
00401968  |.  E8 93F6FFFF   call    00401000                         ;  计算用户名的CRC32值
0040196D  |.  A3 69624000   mov     dword ptr [406269], eax          ;  将用户名的CRC32值放到[00426269]中
00401972  |.  A0 50624000   mov     al, byte ptr [406250]            ;  取得用户名第一个字符放在CRC32的低8位中其余位不变
00401977  |.  50            push    eax                              ; /<%x>
00401978  |.  68 00604000   push    00406000                         ; |%x 拼接的字符串放在[00406000]中
0040197D  |.  68 03604000   push    00406003                         ; |s = Hysteria.00406003
00401982  |.  E8 B1020000   call    <jmp.&user32.wsprintfA>          ; \wsprintfA
00401987  |.  83C4 0C       add     esp, 0C
0040198A  |.  6A 00         push    0                                ; /hTemplateFile = NULL
0040198C  |.  6A 00         push    0                                ; |Attributes = 0
0040198E  |.  6A 03         push    3                                ; |Mode = OPEN_EXISTING
00401990  |.  6A 00         push    0                                ; |pSecurity = NULL
00401992  |.  6A 01         push    1                                ; |ShareMode = FILE_SHARE_READ
00401994  |.  68 00000080   push    80000000                         ; |Access = GENERIC_READ
00401999  |.  68 03604000   push    00406003                         ; |FileName = "7ff2506d"
0040199E  |.  E8 07030000   call    <jmp.&kernel32.CreateFileA>      ; \CreateFileA
004019A3  |.  83F8 FF       cmp     eax, -1                          ;  判断文件是否正常打开了
004019A6  |.  0F84 74020000 je      00401C20                         ;  如果没有打开文件就跳转到00401c20处,即失败
004019AC  |.  A3 98634000   mov     dword ptr [406398], eax
004019B1  |.  6A 00         push    0                                ; /pOverlapped = NULL
004019B3  |.  68 94634000   push    00406394                         ; |pBytesRead = Hysteria.00406394
004019B8  |.  68 FF000000   push    0FF                              ; |BytesToRead = FF (255.)
004019BD  |.  68 6D624000   push    0040626D                         ; |Buffer = Hysteria.0040626D
004019C2  |.  FF35 98634000 push    dword ptr [406398]               ; |hFile = FFFFFFFF
004019C8  |.  E8 0D030000   call    <jmp.&kernel32.ReadFile>         ; \ReadFile


函数很长我们先看到这里,在00401968 处调用了在00401000的函数,这个函数调用其实是计算用户名的CRC32值,我们稍后再详细介绍这个函数,计算好的CRC32值在eax中返回,放到了[00426269]中,一会儿我们还要用到它,随后把用户名的第一个字符放在了CRC32值的低8位中,用这个数值的字符串作为文件名读取文件,这时我们知道这个CrackMe的注册需要Keyfile,并且Keyfile的名称我们已经能够构造出来了。读取文件的内容我们还不知道,明确知道的是文件读取的内容放在了0040626D,并且最长为0xFF个字符。我们停下OD,构造一个文件在CrackMe的目录下,填入足够长的测试数据,然后重新来过一次,断点定在004019CD  处。

004019CD  |.  33D2          xor     edx, edx
004019CF  |.  33F6          xor     esi, esi
004019D1  |.  BB 01000000   mov     ebx, 1
004019D6  |.  A1 6D624000   mov     eax, dword ptr [40626D]          ;  Keyfile中的字符串地址
004019DB  |.  A3 6C634000   mov     dword ptr [40636C], eax          ;  将Keyfile中的前0-3字符拷贝到[0040636c]中
004019E0  |.  83F8 00       cmp     eax, 0                           ;  是否没有字符串
004019E3  |.  0F84 37020000 je      00401C20                         ;  如果为0的话就跳到错误提示
004019E9  |.  A1 71624000   mov     eax, dword ptr [406271]
004019EE  |.  A3 70634000   mov     dword ptr [406370], eax
004019F3  |.  83F8 00       cmp     eax, 0
004019F6  |.  0F84 24020000 je      00401C20
004019FC  |.  A1 75624000   mov     eax, dword ptr [406275]
00401A01  |.  A3 74634000   mov     dword ptr [406374], eax
00401A06  |.  83F8 00       cmp     eax, 0
00401A09  |.  0F84 11020000 je      00401C20
00401A0F  |.  A1 79624000   mov     eax, dword ptr [406279]
00401A14  |.  A3 78634000   mov     dword ptr [406378], eax
00401A19  |.  83F8 00       cmp     eax, 0
00401A1C  |.  0F84 FE010000 je      00401C20
00401A22  |.  A1 7D624000   mov     eax, dword ptr [40627D]
00401A27  |.  A3 7C634000   mov     dword ptr [40637C], eax
00401A2C  |.  83F8 00       cmp     eax, 0
00401A2F  |.  0F84 EB010000 je      00401C20
00401A35  |.  A1 81624000   mov     eax, dword ptr [406281]
00401A3A  |.  A3 80634000   mov     dword ptr [406380], eax
00401A3F  |.  83F8 00       cmp     eax, 0
00401A42  |.  0F84 D8010000 je      00401C20                         ;  从KeyFile字符串中拷贝了前24个字符

这一段是将Keyfile中的字符拷贝24个放到了 [0040636C]中,拷贝了24个字符,因此Keyfile中最多出现的注册码也就是24个字符。我们把这个24个字符分为4个字符一组,共6组,如果每组的4个字符都转换为数值的话一组就是一个32位数,为什么要这么做,这个其实是到后面才知道的,这里先写出来,为了后面看得更清楚。记住这6组数值是从[0040636C]开始的,往下看:

00401A48  |.  90            nop
00401A49  |.  90            nop
00401A4A  |.  90            nop
00401A4B  |.  A1 6C634000   mov     eax, dword ptr [40636C]
00401A50  |.  3B05 74634000 cmp     eax, dword ptr [406374]
00401A56  |.  75 11         jnz     short 00401A69                   ;  第0组Key值和第2组Key值不能相同
00401A58  |.  A1 70634000   mov     eax, dword ptr [406370]
00401A5D  |.  3B05 78634000 cmp     eax, dword ptr [406378]
00401A63  |.  0F84 B7010000 je      00401C20                         ;  如果第0组Key值和第2组Key值相同了,那么第1组Key值和第3组Key值不能相同
00401A69  |>  A1 6C634000   mov     eax, dword ptr [40636C]
00401A6E  |.  3B05 7C634000 cmp     eax, dword ptr [40637C]
00401A74  |.  75 11         jnz     short 00401A87                   ;  第0组Key值和第4组Key值不能相同
00401A76  |.  A1 70634000   mov     eax, dword ptr [406370]
00401A7B  |.  3B05 80634000 cmp     eax, dword ptr [406380]
00401A81  |.  0F84 99010000 je      00401C20                         ;  如果第0组Key值和第4组Key值相同了,那么第1组Key值和第5组Key值不能相同
00401A87  |>  A1 74634000   mov     eax, dword ptr [406374]
00401A8C  |.  3B05 7C634000 cmp     eax, dword ptr [40637C]
00401A92  |.  75 11         jnz     short 00401AA5                   ;  第2组Key值和第4组Key值不能相同
00401A94  |.  A1 78634000   mov     eax, dword ptr [406378]
00401A99  |.  3B05 80634000 cmp     eax, dword ptr [406380]
00401A9F  |.  0F84 7B010000 je      00401C20                         ;  如果第2组Key值和第4组Key值相同了,那么第3组Key值和第5组Key值不能相同
00401AA5  |>  A1 70634000   mov     eax, dword ptr [406370]
00401AAA  |.  3B05 78634000 cmp     eax, dword ptr [406378]
00401AB0  |.  75 11         jnz     short 00401AC3                   ;  第1组Key值和第3组Key值不能相同
00401AB2  |.  A1 6C634000   mov     eax, dword ptr [40636C]
00401AB7  |.  3B05 74634000 cmp     eax, dword ptr [406374]
00401ABD  |.  0F84 5D010000 je      00401C20                         ;  如果第1组Key值和第3组Key值相同了,那么第0组Key值和第2组Key值不能相同
00401AC3  |>  A1 70634000   mov     eax, dword ptr [406370]
00401AC8  |.  3B05 80634000 cmp     eax, dword ptr [406380]
00401ACE  |.  75 11         jnz     short 00401AE1                   ;  第1组Key值和第5组Key值不能相同
00401AD0  |.  A1 6C634000   mov     eax, dword ptr [40636C]
00401AD5  |.  3B05 7C634000 cmp     eax, dword ptr [40637C]
00401ADB  |.  0F84 3F010000 je      00401C20                         ;  如果第1组Key值和第5组Key值相同了,那么第0组Key值和第4组Key值不能相同
00401AE1  |>  A1 78634000   mov     eax, dword ptr [406378]
00401AE6  |.  3B05 80634000 cmp     eax, dword ptr [406380]
00401AEC  |.  75 11         jnz     short 00401AFF                   ;  第3组Key值和第5组Key值不能相同
00401AEE  |.  A1 74634000   mov     eax, dword ptr [406374]
00401AF3  |.  3B05 7C634000 cmp     eax, dword ptr [40637C]
00401AF9  |.  0F84 21010000 je      00401C20                         ;  如果第3组Key值和第5组Key值相同了,那么第2组Key值和第4组Key值不能相同

这一段是比较复杂的一段,主要是Keyfile取得的6组数值的规则,花了好大一阵功夫写出来,再往下

00401AFF  |> \A1 69624000   mov     eax, dword ptr [406269]          ;  用户名的CRC32值放到eax中
00401B04  |.  B9 63000000   mov     ecx, 63
00401B09  |.  F7F9          idiv    ecx                              ;  除以0x63以求余数
00401B0B  |.  8915 8C634000 mov     dword ptr [40638C], edx          ;  余数放到[0040638c]中,记作MOD
00401B11  |.  81F2 07200000 xor     edx, 2007
00401B17  |.  8915 90634000 mov     dword ptr [406390], edx          ;  异或0x2007后放到[00406390]中,记作XOR

没有什么好说的,继续

00401B1D  |.  90            nop
00401B1E  |.  90            nop
00401B1F  |.  8B0D 8C634000 mov     ecx, dword ptr [40638C]          ;  刚才的MOD放到ecx中
00401B25  |.  A1 6C634000   mov     eax, dword ptr [40636C]          ;  第1组Key值
00401B2A  |.  2BC1          sub     eax, ecx                         ;  用第1组Key值减去MOD,得到的值放到eax中
00401B2C  |.  8B1D 70634000 mov     ebx, dword ptr [406370]          ;  第2组Key值
00401B32  |.  8B15 90634000 mov     edx, dword ptr [406390]          ;  XOR赋值给edx
00401B38  |.  2BDA          sub     ebx, edx                         ;  用第二组值减去XOR,结果放到ebx中
00401B3A  |.  0FAFC3        imul    eax, ebx
00401B3D  |.  A3 84634000   mov     dword ptr [406384], eax          ;  把结果暂存到[00406384]中
00401B42  |.  A1 6C634000   mov     eax, dword ptr [40636C]          ;  第0组Key值
00401B47  |.  8B0D 7C634000 mov     ecx, dword ptr [40637C]          ;  第4组Key值
00401B4D  |.  2BC1          sub     eax, ecx                         ;  第0组Key值 减去 第4组Key值,结果放到eax中
00401B4F  |.  8B1D 70634000 mov     ebx, dword ptr [406370]          ;  第1组Key值
00401B55  |.  8B15 80634000 mov     edx, dword ptr [406380]          ;  第5组Key值
00401B5B  |.  2BDA          sub     ebx, edx                         ;  第1组Key值 减去 第5组Key值,结果放到ebx中
00401B5D  |.  0FAFC3        imul    eax, ebx
00401B60  |.  0305 84634000 add     eax, dword ptr [406384]          ;  和刚才的结果相加
00401B66  |.  85C0          test    eax, eax
00401B68  |.  0F85 B2000000 jnz     00401C20                         ;  如果之和不为0则跳到错误的地方

到这里我们得到第一个公式,即:

(key[0] - MOD)*(key[1] - XOR) + (key[0] - key[4])*(key[1] - key[5]) = 0

往下看

00401B6E  |.  8B0D 8C634000 mov     ecx, dword ptr [40638C]          ;  MOD赋值给ecx
00401B74  |.  A1 74634000   mov     eax, dword ptr [406374]          ;  第2组Key值
00401B79  |.  2BC1          sub     eax, ecx                         ;  第2组Key值 减去 MOD,结果放到eax中
00401B7B  |.  8B1D 78634000 mov     ebx, dword ptr [406378]          ;  第3组Key值
00401B81  |.  8B15 90634000 mov     edx, dword ptr [406390]          ;  XOR赋值给edx
00401B87  |.  2BDA          sub     ebx, edx                         ;  第3组Key值 减去 XOR,结果放到ebx中
00401B89  |.  0FAFC3        imul    eax, ebx
00401B8C  |.  A3 84634000   mov     dword ptr [406384], eax          ;  把结果暂存到[00406384]中
00401B91  |.  A1 74634000   mov     eax, dword ptr [406374]          ;  第2组Key值
00401B96  |.  8B0D 7C634000 mov     ecx, dword ptr [40637C]          ;  第4组Key值
00401B9C  |.  2BC1          sub     eax, ecx                         ;  第2组Key值 减去 第4组Key值,结果放到eax中
00401B9E  |.  8B1D 78634000 mov     ebx, dword ptr [406378]          ;  第3组Key值
00401BA4  |.  8B15 80634000 mov     edx, dword ptr [406380]          ;  第5组Key值
00401BAA  |.  2BDA          sub     ebx, edx                         ;  第3组Key值 减去 第5组Key值,结果放到ebx中
00401BAC  |.  0FAFC3        imul    eax, ebx
00401BAF  |.  0305 84634000 add     eax, dword ptr [406384]          ;  和刚才的结果相加
00401BB5  |.  85C0          test    eax, eax
00401BB7  |.  75 67         jnz     short 00401C20                   ;  如果之和不为0则跳到错误的地方

到这里我们得到第二个公式,即:

0

顶一下

0

埋一下
点击查看更多关于 算法 的主题
引用地址: