首页
社区
课程
招聘
TDC KeyFile ME 破解分析
发表于: 2006-5-4 19:28 8292

TDC KeyFile ME 破解分析

2006-5-4 19:28
8292

【破文标题】CRACKME破解分析
【破文作者】逍遥风
【破解工具】OD, WINHEX, PEID
【破解平台】WEINXP
【软件名称】 TDC KeyFile ME [#2]
【原版下载】http://www.crackmes.de/users/tdcnl/tdc_keyfile_me_2/
【软件简介】Difficulty: 2 - Needs a little brain (or luck)
            Platform: Windows
            Language: Assembler
【破解声明】菜鸟偶得一点心得,与大家分享
------------------------------------------------------------------------
1)PEID检查:MASM32 / TASM32,无壳
2)OD,载入,开始分析:
在命令行下断点:bp GetDlgItem
004010EE   .  A3 6E604000   MOV DWORD PTR DS:[40606E],EAX
004010F3   .  6A 75         PUSH 75                                  ; /ControlID = 75 (117.)
004010F5   .  FF75 08       PUSH DWORD PTR SS:[EBP+8]                ; |hWnd
004010F8   .  E8 BB030000   CALL <JMP.&user32.GetDlgItem>            ; \GetDlgItem
004010FD   .  A3 72604000   MOV DWORD PTR DS:[406072],EAX      中断在这里
00401102   .  6A 76         PUSH 76                                  ; /ControlID = 76 (118.)
00401104   .  FF75 08       PUSH DWORD PTR SS:[EBP+8]                ; |hWnd
00401107   .  E8 AC030000   CALL <JMP.&user32.GetDlgItem>            ; \GetDlgItem
0040110C   .  A3 76604000   MOV DWORD PTR DS:[406076],EAX
00401111   .  68 7A604000   PUSH keyfilem.0040607A                   ; /name
00401116   .  6A 74         PUSH 74                                  ; |ControlID = 74 (116.)
00401118   .  FF75 08       PUSH DWORD PTR SS:[EBP+8]                ; |hWnd
0040111B   .  E8 B0030000   CALL <JMP.&user32.SetDlgItemTextA>       ; \SetDlgItemTextA
00401120   .  68 7F604000   PUSH keyfilem.0040607F                   ; /serial
00401125   .  6A 75         PUSH 75                                  ; |ControlID = 75 (117.)
00401127   .  FF75 08       PUSH DWORD PTR SS:[EBP+8]                ; |hWnd
0040112A   .  E8 A1030000   CALL <JMP.&user32.SetDlgItemTextA>       ; \SetDlgItemTextA
0040112F   .  68 1F604000   PUSH keyfilem.0040601F                   ; /unregistered
00401134   .  6A 76         PUSH 76                                  ; |ControlID = 76 (118.)
00401136   .  FF75 08       PUSH DWORD PTR SS:[EBP+8]                ; |hWnd
00401139   .  E8 92030000   CALL <JMP.&user32.SetDlgItemTextA>       ; \SetDlgItemTextA
0040113E   .  E8 F0010000   CALL keyfilem.00401333                           重要CALL,跟进
----------------------------------------------------------------------------------------------------------------------------------------------------------
跟进后来到这里
00401333  /$  6A 00         PUSH 0                                   ; /hTemplateFile = NULL
00401335  |.  68 80000000   PUSH 80                                  ; |Attributes = NORMAL
0040133A  |.  6A 03         PUSH 3                                   ; |Mode = OPEN_EXISTING
0040133C  |.  6A 00         PUSH 0                                   ; |pSecurity = NULL
0040133E  |.  6A 01         PUSH 1                                   ; |ShareMode = FILE_SHARE_READ
00401340  |.  68 00000080   PUSH 80000000                            ; |Access = GENERIC_READ
00401345  |.  68 32604000   PUSH keyfilem.00406032                   ; |keyfile.dat
0040134A  |.  E8 93010000   CALL <JMP.&kernel32.CreateFileA>         ; \CreateFileA
0040134F  |.  A3 62604000   MOV DWORD PTR DS:[406062],EAX            ;  检测文件
00401354  |.  83F8 FF       CMP EAX,-1                               ;  有KEY文件吗?
00401357  |.  0F84 DB000000 JE keyfilem.00401438                     ;  没有就OVER
先检测有没有KEY文件,根据OD提示,KEY文件的文件名应为:keyfile.dat
用WINHEX建立一个keyfile.dat的文件
0040135D  |.  6A 00         PUSH 0                                   ; /pFileSizeHigh = NULL
0040135F  |.  FF35 62604000 PUSH DWORD PTR DS:[406062]               ; |hFile = 00000130 (window)
00401365  |.  E8 8A010000   CALL <JMP.&kernel32.GetFileSize>         ; \GetFileSize
0040136A  |.  83F8 20       CMP EAX,20                               ;  文件大小是32字节吗?
0040136D  |.  0F85 CE000000 JNZ keyfilem.00401441                    ;  不是就跳向失败
检测KEY文件的大小是否为32字节。
将keyfile.dat文件的字节数定为32字节
00401373  |.  6A 00         PUSH 0                                   ; /pOverlapped = NULL
00401375  |.  68 48634000   PUSH keyfilem.00406348                   ; |pBytesRead = keyfilem.00406348
0040137A  |.  6A 10         PUSH 10                                  ; |BytesToRead = 10 (16.)
0040137C  |.  68 3E604000   PUSH keyfilem.0040603E                   ; |Buffer = keyfilem.0040603E
00401381  |.  FF35 62604000 PUSH DWORD PTR DS:[406062]               ; |hFile = 00000130 (window)
00401387  |.  E8 86010000   CALL <JMP.&kernel32.ReadFile>            ; \ReadFile
0040138C  |.  FF35 62604000 PUSH DWORD PTR DS:[406062]               ; /hObject = 00000130 (window)
00401392  |.  E8 45010000   CALL <JMP.&kernel32.CloseHandle>         ; \CloseHandle
00401397  |.  33C9          XOR ECX,ECX                              ;  ECX清零
00401399  |.  33D2          XOR EDX,EDX                              ;  EDX清零
0040139B  |.  BA 0F000000   MOV EDX,0F                               ;  使EDX=0x0F
{   004013A0  |>  0FBE8A 3E6040>/MOVSX ECX,BYTE PTR DS:[EDX+40603E]
    004013A7  |.  4A            |DEC EDX
    004013A8  |.  83F9 20       |CMP ECX,20
    004013AB  |.  75 09         |JNZ SHORT keyfilem.004013B6
    004013AD  |.  C682 3F604000>|MOV BYTE PTR DS:[EDX+40603F],0
    004013B4  |.^ EB EA         \JMP SHORT keyfilem.004013A0               注意这个循环。后面还要用,设为循环A}
开始读取文件内容,并检验文件的第16个字节是不是空格。

如果第16个字节不是空格经过2个跳转后来到这里,对前16个字节的内容进行计算
0040146E  |> /0FB681 3E6040>/MOVZX EAX,BYTE PTR DS:[ECX+40603E]      ;  取每一个字符的ASCII码
00401475  |. |83C0 0F       |ADD EAX,0F                              ;  每一个字符的ASCII码加上0x0F
00401478  |. |83F0 20       |XOR EAX,20                              ;  与0x20做XOR运算
0040147B  |. |03D8          |ADD EBX,EAX                             ;  把每一位的计算结果累加
0040147D  |. |41            |INC ECX                                 ;  每计算一次ECX+1
0040147E  |. |3BCA          |CMP ECX,EDX                             ;  计算完了吗?
00401480  |.^\75 EC         \JNZ SHORT keyfilem.0040146E             ;  没有就继续
00401482  |.  33C9          XOR ECX,ECX                              ;  ECX清零
00401484  |.  69DB 697A0000 IMUL EBX,EBX,7A69                        ;  累加的结果乘以0x7A69
0040148A  |.  53            PUSH EBX                                 ; /<%X>
0040148B  |.  68 84624000   PUSH keyfilem.00406284                   ; |%x
00401490  |.  68 87624000   PUSH keyfilem.00406287                   ; |s = keyfilem.00406287
00401495  |.  E8 0C000000   CALL <JMP.&user32.wsprintfA>             ; \wsprintfA
0040149A  |.  83C4 0C       ADD ESP,0C
0040149D  |.  5F            POP EDI
0040149E  |.  5B            POP EBX
0040149F  |.^ E9 17FFFFFF   JMP keyfilem.004013BB                     计算完毕后跳回到开始读取文件的地方,对后16个字节进行检验

中间过程省略,直接再次来到循环A
0040140C  |> /0FBE8A 4E6040>/MOVSX ECX,BYTE PTR DS:[EDX+40604E]      ;  倒序取后16个字节的每个字节的内容
00401413  |. |4A            |DEC EDX
00401414  |. |83F9 20       |CMP ECX,20                              ;  是空格吗?
00401417  |. |75 09         |JNZ SHORT keyfilem.00401422             ;  不是就跳走
00401419  |. |C682 4F604000>|MOV BYTE PTR DS:[EDX+40604F],0
00401420  |.^\EB EA         \JMP SHORT keyfilem.0040140C             ;  取下一位继续计算
一直取到第一个不是空格的地方
00401422  |>  68 87624000   PUSH keyfilem.00406287                   ;
00401427  |.  68 4E604000   PUSH keyfilem.0040604E                   ;
0040142C  |.  E8 ED000000   CALL <JMP.&kernel32.lstrcmpA>            ;  比较后16个字节的内容与前16个字节累加计算和是否相等
00401431  |.  83F8 00       CMP EAX,0                                ;  如果EAX=0就成功
00401434  |.  74 1D         JE SHORT keyfilem.00401453               ;  跳向成功

注意:
建立KEY文件时:
因为程序对文件中的内容反复进行读取。
所以前16个字节的内容与后16个字节的内容最好不一样,以便于分析和得出正确的结论

------------------------------------------------------------------------
破解总结:
1)KEY文件的文件名为keyfile.dat,大小为32字节
2)对KEY文件的前16个字节每一字节的字符进行计算:(ASCII码-0x0F) XOR 0x20。并把每一位的结果累加,结果设为A
3)后16个字节的内容格式为:A+“空格”。(注意:后16个字节的前N位必须为累加结果A,再用空格将其补足16个字节)N为累加结果A的位数。
4)NAME=全部32个字节的内容
   SERIAL=后16个字节的内容
例:
文件名:keyfile.dat
大小:32字节
内容:7869616F79616F66656E676C6F76656533304543313644202020202020202020         
            (xiaoyaofenglovee30EC16D   )
------------------------------------------------------------------------
【版权声明】本文只为交流,转载请保留作者及文章完整性


[注意]APP应用上架合规检测服务,协助应用顺利上架!

上传的附件:
收藏
免费 7
支持
分享
最新回复 (7)
雪    币: 443
活跃值: (200)
能力值: ( LV9,RANK:1140 )
在线值:
发帖
回帖
粉丝
2
搬张凳子坐着学习~

2006-5-4 20:50
0
雪    币: 615
活跃值: (1267)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
3
如果第16个字节不是空格经过2个跳转后来到这里,对前16个字节的内容进行计算
0040146E  |> /0FB681 3E6040>/MOVZX EAX,BYTE PTR DS:[ECX+40603E]      ;  取每一个字符的ASCII码
00401475  |. |83C0 0F       |ADD EAX,0F    ;  每一个字符的ASCII码减去0x0F
00401478  |. |83F0 20       |XOR EAX,20    ;  与0x20做XOR运算
0040147B  |. |03D8          |ADD EBX,EAX   ;  把每一位的计算结果累加
0040147D  |. |41            |INC ECX       ;  每计算一次ECX+1
0040147E  |. |3BCA          |CMP ECX,EDX   ;  计算完了吗?

上面的ADD EAX,0F   ;  每一个字符的ASCII码减去0x0F
应该是ADD EAX,0F   ;  每一个字符的ASCII码加上0x0F
2006-5-5 13:41
0
雪    币: 203
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
ding
2006-5-5 14:40
0
雪    币: 2256
活跃值: (941)
能力值: (RANK:2210 )
在线值:
发帖
回帖
粉丝
5
最初由 xzchina 发布
如果第16个字节不是空格经过2个跳转后来到这里,对前16个字节的内容进行计算
0040146E |> /0FB681 3E6040>/MOVZX EAX,BYTE PTR DS:[ECX+40603E] ; 取每一个字符的ASCII码
00401475 |. |83C0 0F |ADD EAX,0F ; 每一个字符的ASCII码减去0x0F
00401478 |. |83F0 20 |XOR EAX,20 ; 与0x20做XOR运算
0040147B |. |03D8 |ADD EBX,EAX ; 把每一位的计算结果累加
........

呵呵~谢谢提醒,笔误笔误.
2006-5-5 14:42
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
写的不错呀,本人新到学学先
2006-5-5 15:15
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
最初由 逍遥风 发布
【破文标题】CRACKME破解分析
【破文作者】逍遥风
【破解工具】OD, WINHEX, PEID
【破解平台】WEINXP
【软件名称】 TDC KeyFile ME [#2]
........


写得很详细,狂顶你,我终于明白了keyfile的破解过程了,非常感谢
2006-10-24 06:12
0
雪    币: 207
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
最初由 逍遥风 发布
呵呵~谢谢提醒,笔误笔误.


写得很详细,顶你个肺!
2006-10-24 17:16
0
游客
登录 | 注册 方可回帖
返回
//