孤漂江湖狼 发表于 2008-4-22 08:55:13

CodeFantasy系列Crackme1算法分析

【破文标题】CodeFantasy系列Crackme1算法分析
【破文作者】孤漂江湖狼
【作者邮箱】[email protected]
【破解工具】OD
【破解平台】WinXP
【软件名称】CodeFantasy系列Crackme1
【原版下载】https://www.chinapyg.com/viewthread.php?tid=2113&extra=page%3D10
【软件简介】这是在CRACKME版块找到的一个CRACKME,大家都没有给出算法分析,本人写了自己的分析,大家多提意见!

------------------------------------------------------------------------
【破解过程】
    PEID查壳,显示为Borland Delphi 6.0 - 7.0,无壳的,省了麻烦,但也少了练习脱壳的机会,呵


    OD载入,用字符串插件查看字符串,找到“恭喜您,注册码正确!”,双击,来到这里:
   
00408DEF|.E8 68B9FFFF   call    <jmp.&user32.GetDlgItemTextA> ; 在此下断
00408DF4|.8D45 B4       lea   eax, dword ptr
00408DF7|.BA 9CA24000   mov   edx, 0040A29C               ;取用户名
00408DFC|.B9 FF000000   mov   ecx, 0FF                      ;ecx初始为十六进制的FF,即十进制的255
00408E01|.E8 6AAAFFFF   call    00403870                      ;取用户名位数
00408E06|.837D B4 00    cmp   dword ptr , 0         ;比较是否用户名为空
00408E0A|.0F84 9E000000 je      00408EAE                      ;空则跳
00408E10|.68 FF000000   push    0FF                           ;
00408E15|.68 9CA34000   push    0040A39C                      ;
00408E1A|.68 F3030000   push    3F3                           ;
00408E1F|.8B45 08       mov   eax, dword ptr       ;
00408E22|.50            push    eax                           ;
00408E23|.E8 34B9FFFF   call    <jmp.&user32.GetDlgItemTextA> ; \取假码的位数传给EAX
00408E28|.8D45 AC       lea   eax, dword ptr
00408E2B|.BA 9CA24000   mov   edx, 0040A29C               ;同上面的00408de7--

00408e01
00408E30|.B9 FF000000   mov   ecx, 0FF
00408E35|.E8 36AAFFFF   call    00403870
00408E3A|.8B45 AC       mov   eax, dword ptr        ;用户名传给EAX
00408E3D|.8D55 B0       lea   edx, dword ptr
00408E40|.E8 23FCFFFF   call    00408A68                      ;算法CALL
00408E45|.8B45 B0       mov   eax, dword ptr        ;真码给EAX,在此可作内存注册机
00408E48|.50            push    eax                           ;真码入栈
00408E49|.8D45 A8       lea   eax, dword ptr
00408E4C|.BA 9CA34000   mov   edx, 0040A39C               ;
00408E51|.B9 FF000000   mov   ecx, 0FF
00408E56|.E8 15AAFFFF   call    00403870
00408E5B|.8B55 A8       mov   edx, dword ptr
00408E5E|.58            pop   eax
00408E5F      E8 84ABFFFF   call    004039E8
00408E64      75 48         jnz   short 00408EAE                ;爆破关键跳转
00408E66      6A 40         push    40                            ; /Style =

MB_OK|MB_ICONASTERISK|MB_APPLMODAL
00408E68      68 AC8F4000   push    00408FAC                      ; |注册提示
00408E6D|.68 B88F4000   push    00408FB8                      ; |恭喜您,注册码正确!
00408E72|.8B45 08       mov   eax, dword ptr       ;
00408E75|.50            push    eax                           ;
00408E76|.E8 19B9FFFF   call    <jmp.&user32.MessageBoxA>   ;

    后面我已经写了注释了,可以爆破,可以追码,做内存注册机。但这不是我们最主要的目的,我们

应该分析它的算法。
    在00408E40处,F7进入,来到这里:
00408A68/$55            push    ebp
00408A69|.8BEC          mov   ebp, esp
00408A6B|.B9 07000000   mov   ecx, 7                        ;计数器ECX初始为7
00408A70|>6A 00         /push    0
00408A72|.6A 00         |push    0
00408A74|.49            |dec   ecx                        ;计数器循环减一
00408A75|.^ 75 F9         \jnz   short 00408A70
00408A77|.51            push    ecx
00408A78|.53            push    ebx
00408A79|.56            push    esi
00408A7A|.57            push    edi
00408A7B|.8955 F8       mov   dword ptr , edx
00408A7E|.8945 FC       mov   dword ptr , eax
00408A81|.8B45 FC       mov   eax, dword ptr
00408A84|.E8 03B0FFFF   call    00403A8C
00408A89|.33C0          xor   eax, eax                      ;EAX清零
00408A8B|.55            push    ebp
00408A8C|.68 498C4000   push    00408C49
00408A91|.64:FF30       push    dword ptr fs:
00408A94|.64:8920       mov   dword ptr fs:, esp
00408A97|.8D45 F4       lea   eax, dword ptr
00408A9A|.E8 89ABFFFF   call    00403628
00408A9F|.8B45 FC       mov   eax, dword ptr
00408AA2|.E8 F5ADFFFF   call    0040389C                      ;取用户名位数
00408AA7|.8BF8          mov   edi, eax                      ;把位数再传给EDI
00408AA9|.85FF          test    edi, edi                      ;检测是不是为零
00408AAB|.7E 28         jle   short 00408AD5                ;为零则跳
00408AAD|.BE 01000000   mov   esi, 1                        ;计数器初始为1
00408AB2|>8B45 FC       /mov   eax, dword ptr        ;开始循环,算法一
00408AB5|.33DB          |xor   ebx, ebx
00408AB7|.8A5C30 FF   |mov   bl, byte ptr
00408ABB|.43            |inc   ebx
00408ABC|.8D45 D8       |lea   eax, dword ptr
00408ABF|.8BD3          |mov   edx, ebx
00408AC1|.E8 2EADFFFF   |call    004037F4
00408AC6|.8B55 D8       |mov   edx, dword ptr
00408AC9|.8D45 F4       |lea   eax, dword ptr
00408ACC|.E8 D3ADFFFF   |call    004038A4
00408AD1|.46            |inc   esi                        ;计数器
00408AD2|.4F            |dec   edi                        ;倒计数器,控制下面的跳


00408AD3|.^ 75 DD         \jnz   short 00408AB2
00408AD5|>8D45 F0       lea   eax, dword ptr
00408AD8|.8B55 F4       mov   edx, dword ptr
00408ADB|.E8 E0ABFFFF   call    004036C0
00408AE0|.8D45 F4       lea   eax, dword ptr
00408AE3|.E8 40ABFFFF   call    00403628
00408AE8|.8B45 F0       mov   eax, dword ptr
00408AEB|.E8 ACADFFFF   call    0040389C
00408AF0|.8BF8          mov   edi, eax
00408AF2|.85FF          test    edi, edi
00408AF4|.7E 2A         jle   short 00408B20
00408AF6|.BE 01000000   mov   esi, 1                        ;计数器初始位一
00408AFB|>8B45 F0       /mov   eax, dword ptr       ;有一个循环,算法二
00408AFE|.33DB          |xor   ebx, ebx
00408B00|.8A5C30 FF   |mov   bl, byte ptr
00408B04|.83C3 02       |add   ebx, 2
00408B07|.8D45 D4       |lea   eax, dword ptr
00408B0A|.8BD3          |mov   edx, ebx
00408B0C|.E8 E3ACFFFF   |call    004037F4
00408B11|.8B55 D4       |mov   edx, dword ptr
00408B14|.8D45 F4       |lea   eax, dword ptr
00408B17|.E8 88ADFFFF   |call    004038A4
00408B1C|.46            |inc   esi
00408B1D|.4F            |dec   edi
00408B1E|.^ 75 DB         \jnz   short 00408AFB
00408B20|>8D45 EC       lea   eax, dword ptr
00408B23|.8B55 F4       mov   edx, dword ptr
00408B26|.E8 95ABFFFF   call    004036C0
00408B2B|.8D45 F4       lea   eax, dword ptr
00408B2E|.E8 F5AAFFFF   call    00403628
00408B33|.8B45 EC       mov   eax, dword ptr
00408B36|.E8 61ADFFFF   call    0040389C
00408B3B|.8BF8          mov   edi, eax
00408B3D|.85FF          test    edi, edi
00408B3F|.7E 2A         jle   short 00408B6B
00408B41|.BE 01000000   mov   esi, 1
00408B46|>8B45 EC       /mov   eax, dword ptr       ;有一个循环,算法三
00408B49|.33DB          |xor   ebx, ebx
00408B4B|.8A5C30 FF   |mov   bl, byte ptr
00408B4F|.83C3 03       |add   ebx, 3
00408B52|.8D45 D0       |lea   eax, dword ptr
00408B55|.8BD3          |mov   edx, ebx
00408B57|.E8 98ACFFFF   |call    004037F4
00408B5C|.8B55 D0       |mov   edx, dword ptr
00408B5F|.8D45 F4       |lea   eax, dword ptr
00408B62|.E8 3DADFFFF   |call    004038A4
00408B67|.46            |inc   esi
00408B68|.4F            |dec   edi
00408B69|.^ 75 DB         \jnz   short 00408B46
00408B6B|>8D45 E8       lea   eax, dword ptr
00408B6E|.8B55 F4       mov   edx, dword ptr
00408B71|.E8 4AABFFFF   call    004036C0
00408B76|.8D45 F4       lea   eax, dword ptr
00408B79|.E8 AAAAFFFF   call    00403628
00408B7E|.8B45 E8       mov   eax, dword ptr
00408B81|.E8 16ADFFFF   call    0040389C
00408B86|.8BF8          mov   edi, eax
00408B88|.85FF          test    edi, edi
00408B8A|.7E 2A         jle   short 00408BB6
00408B8C|.BE 01000000   mov   esi, 1
00408B91|>8B45 E8       /mov   eax, dword ptr       ;有一个循环,算法四
00408B94|.33DB          |xor   ebx, ebx
00408B96|.8A5C30 FF   |mov   bl, byte ptr
00408B9A|.83C3 04       |add   ebx, 4
00408B9D|.8D45 CC       |lea   eax, dword ptr
00408BA0|.8BD3          |mov   edx, ebx
00408BA2|.E8 4DACFFFF   |call    004037F4
00408BA7|.8B55 CC       |mov   edx, dword ptr
00408BAA|.8D45 F4       |lea   eax, dword ptr
00408BAD|.E8 F2ACFFFF   |call    004038A4
00408BB2|.46            |inc   esi
00408BB3|.4F            |dec   edi
00408BB4|.^ 75 DB         \jnz   short 00408B91
00408BB6|>8D45 E4       lea   eax, dword ptr
00408BB9|.E8 6AAAFFFF   call    00403628
00408BBE|.8B45 F4       mov   eax, dword ptr
00408BC1|.E8 D6ACFFFF   call    0040389C
00408BC6|.8BF8          mov   edi, eax
00408BC8|.4F            dec   edi
00408BC9|.85FF          test    edi, edi
00408BCB|.7C 4E         jl      short 00408C1B
00408BCD|.47            inc   edi
00408BCE|.33F6          xor   esi, esi
00408BD0|>8D45 DC       /lea   eax, dword ptr       ;真正的算法部分,前面的都是修改内存数值
00408BD3|.50            |push    eax
00408BD4|.8B45 F4       |mov   eax, dword ptr
00408BD7|.0FB60430      |movzx   eax, byte ptr       ;从内存地址00d009f0+x中,取字符
00408BDB|.8945 C4       |mov   dword ptr , eax
00408BDE|.C645 C8 00    |mov   byte ptr , 0
00408BE2|.8D55 C4       |lea   edx, dword ptr
00408BE5|.33C9          |xor   ecx, ecx
00408BE7|.B8 608C4000   |mov   eax, 00408C60                ;
00408BEC|.E8 1FD1FFFF   |call    00405D10
00408BF1|.8B45 DC       |mov   eax, dword ptr
00408BF4|.E8 A3ACFFFF   |call    0040389C
00408BF9|.48            |dec   eax
00408BFA|.75 10         |jnz   short 00408C0C
00408BFC|.8D45 DC       |lea   eax, dword ptr
00408BFF|.8B4D DC       |mov   ecx, dword ptr
00408C02|.BA 6C8C4000   |mov   edx, 00408C6C                ;
00408C07|.E8 DCACFFFF   |call    004038E8
00408C0C|>8D45 E0       |lea   eax, dword ptr
00408C0F|.8B55 DC       |mov   edx, dword ptr
00408C12|.E8 8DACFFFF   |call    004038A4                     ;将字符连起来
00408C17|.46            |inc   esi                        ;加一
00408C18|.4F            |dec   edi                        ;减一
00408C19|.^ 75 B5         \jnz   short 00408BD0
00408C1B|>8B45 F8       mov   eax, dword ptr
00408C1E|.8B55 E0       mov   edx, dword ptr        ;真码出现




   
------------------------------------------------------------------------
------------------------------------------------------------------------
【版权声明】本文纯属技术交流, 转载请注明作者信息并保持文章的完整, 谢谢!

[ 本帖最后由 孤漂江湖狼 于 2008-10-11 10:50 编辑 ]

tianxj 发表于 2008-4-22 18:44:04

作了一下/:017

unpack 发表于 2008-4-22 21:45:10

很轻松的就跟踪到了o(∩_∩)o...
算法就不搞了

孤漂江湖狼 发表于 2008-4-22 21:55:12

呵呵,tianxj给点建议吧

[ 本帖最后由 孤漂江湖狼 于 2008-4-27 13:12 编辑 ]

hflywolf 发表于 2008-5-10 01:56:33

原帖由 孤漂江湖狼 于 2008-4-22 21:55 发表 https://www.chinapyg.com/images/common/back.gif
呵呵,tianxj给点建议吧

/:013 /:013

俺菜鸟一个,也来凑个热闹吧,接上你没分析算法部分. 如有错误还望包涵哈.

00408AA2|.E8 F5ADFFFF   call    0040389C                      ;取用户名位数
00408AA7|.8BF8          mov   edi, eax                      ;把位数再传给EDI
00408AA9|.85FF          test    edi, edi                      ;检测是不是为零
00408AAB|.7E 28         jle   short 00408AD5                ;为零则跳
00408AAD|.BE 01000000   mov   esi, 1                        ;计数器初始为1
00408AB2|>8B45 FC       /mov   eax, dword ptr        ;把用户名传给EAX
00408AB5|.33DB          |xor   ebx, ebx                        
00408AB7|.8A5C30 FF   |mov   bl, byte ptr    ;依次取用户名的字符
00408ABB|.43            |inc   ebx                        ;把取出的字符的16进制数加1
00408ABC|.8D45 D8       |lea   eax, dword ptr       ;
00408ABF|.8BD3          |mov   edx, ebx                     ;将加1得到的结果传入EDX
00408AC1|.E8 2EADFFFF   |call    004037F4
00408AC6|.8B55 D8       |mov   edx, dword ptr       
00408AC9|.8D45 F4       |lea   eax, dword ptr
00408ACC|.E8 D3ADFFFF   |call    004038A4
00408AD1|.46            |inc   esi                        ;计数器
00408AD2|.4F            |dec   edi                        ;倒计数器,控制下面的跳转
00408AD3|.^ 75 DD         \jnz   short 00408AB2      


上面循环的作用是依次取用户名16进制字符 ,然后加1操作

比如 "hflywolf" 依次取其16进制字符就是(68 66 6C 79 77 6F 6C 66 )

加1后就是(69 67 6D 7A 78 70 6D 67 )

00408AFB|>8B45 F0       /mov   eax, dword ptr       ;将上面循环的结果存入EAX
00408AFE|.33DB          |xor   ebx, ebx
00408B00|.8A5C30 FF   |mov   bl, byte ptr    ;依次取字符
00408B04|.83C3 02       |add   ebx, 2                     ;把取出的字符的16进制数加2      

上面循环后的结果是(6B 69 6F 7C 7A 72 6F 69)

00408B46|>8B45 EC       /mov   eax, dword ptr       ;将上面循环的结果存入EAX
00408B49|.33DB          |xor   ebx, ebx                  
00408B4B|.8A5C30 FF   |mov   bl, byte ptr    ;依次取字符
00408B4F|.83C3 03       |add   ebx, 3                     ;把取出的字符的16进制数加3

上面循环后的结果是(6E 6C 72 7F 7D 75 72 6C)

00408B91|>8B45 E8       /mov   eax, dword ptr       ;将上面循环的结果存入EAX
00408B94|.33DB          |xor   ebx, ebx
00408B96|.8A5C30 FF   |mov   bl, byte ptr    ;依次取字符
00408B9A|.83C3 04       |add   ebx, 4                     ;把取出的字符的16进制数加4

上面循环后的结果是(72 70 76 83 81 79 76 70)

00408BD0|>8D45 DC       /lea   eax, dword ptr       ;真正的算法部分,前面的都是修改内存数值
00408BD3|.50            |push    eax
00408BD4|.8B45 F4       |mov   eax, dword ptr
00408BD7|.0FB60430      |movzx   eax, byte ptr       ;从内存地址00d009f0+x中,取字符
00408BDB|.8945 C4       |mov   dword ptr , eax
00408BDE|.C645 C8 00    |mov   byte ptr , 0
00408BE2|.8D55 C4       |lea   edx, dword ptr
00408BE5|.33C9          |xor   ecx, ecx
00408BE7|.B8 608C4000   |mov   eax, 00408C60                ;
00408BEC|.E8 1FD1FFFF   |call    00405D10
00408BF1|.8B45 DC       |mov   eax, dword ptr
00408BF4|.E8 A3ACFFFF   |call    0040389C
00408BF9|.48            |dec   eax
00408BFA|.75 10         |jnz   short 00408C0C
00408BFC|.8D45 DC       |lea   eax, dword ptr
00408BFF|.8B4D DC       |mov   ecx, dword ptr
00408C02|.BA 6C8C4000   |mov   edx, 00408C6C                ;
00408C07|.E8 DCACFFFF   |call    004038E8
00408C0C|>8D45 E0       |lea   eax, dword ptr
00408C0F|.8B55 DC       |mov   edx, dword ptr
00408C12|.E8 8DACFFFF   |call    004038A4                     ;将字符连起来
00408C17|.46            |inc   esi                        ;加一
00408C18|.4F            |dec   edi                        ;减一
00408C19|.^ 75 B5         \jnz   short 00408BD0

这个循环就是把(72 70 76 83 81 79 76 70) 连接起来

即"7270768381797670" 这结果就是真码.

vb 代码Dim i As Integer
Dim user As String
Dim key As String

    For i = 1 To len(username)
      user = Hex(Asc(Mid(username, i, 1)) + 10)
      key = key & user
    Next i嘿嘿,再附个注册机的图

[ 本帖最后由 hflywolf 于 2008-5-10 02:21 编辑 ]

孤漂江湖狼 发表于 2008-5-11 18:06:26

不错,学习了!谢谢了!

Squn 发表于 2008-6-8 03:37:57

/:018 追码小跟了一下 o(∩_∩)o

jsj731 发表于 2008-6-25 08:01:15

pyg高手真多呀,向大家学习学习!

lixy8888 发表于 2008-7-25 20:00:49

呵呵,很简单吗,我用了好几种方法作,但DEDE怎么不行?
页: [1]
查看完整版本: CodeFantasy系列Crackme1算法分析