首页
社区
课程
招聘
[原创]Slayer_Crackme2分析
发表于: 2006-11-26 12:49 6826

[原创]Slayer_Crackme2分析

2006-11-26 12:49
6826

【文章标题】: Slayer_Crackme2分析
【文章作者】: aal
【作者主页】: www.pediy.com
【软件名称】: Slayer_Crackme2
【下载地址】: http://crackmes.de/users/savage/slayers_crackme_2/download
【保护方式】: “Some big nums :)”
【编写语言】: Assembler
【使用工具】: OD,CALC,Radasm

--------------------------------------------------------------------------------
【详细过程】
很不错的一个crackme!peid:“什么都没找到  *”。输入表中只有LoadLibraryA和GetProcAddress,所以应该是加壳了。
载入OD慢慢来,最后到达一个似乎是OEP的地方:
00521101  -FFE0             JMP EAX                                         ; Crackm_1.0041DBA0
不会脱壳,所以走到这里全凭耐心.;)累 其间会有警告说"Bad File format"之类的,不管.
到了这里,高兴了半天才发现,这里只不过是到了原程序处理之后得到的一个upx压缩过的exe得入口处.不过upx也很简单了,还慢慢来,
又到这里:
0041DD2B  ^E9 D032FEFF      JMP Crackm_1.00401000
这次应该行了吧.
dump:
起始地址0400000 大小 20000
入口点地址 修正为01000
重建输入表方式1
将脱好的文件随意起个名字,我的文件名为why.exe.好,开始正式分析.
00401000 >/$ E8 F8000000    CALL why.004010FD                        ; loadlibrary("crap0.dll")...得到what_the函数得地址
00401005  |. 6A 00          PUSH 0                                   ; /hTemplateFile = NULL
00401007  |. 68 80000000    PUSH 80                                  ; |Attributes = NORMAL
0040100C  |. 6A 03          PUSH 3                                   ; |Mode = OPEN_EXISTING
0040100E  |. 6A 00          PUSH 0                                   ; |pSecurity = NULL
00401010  |. 6A 01          PUSH 1                                   ; |ShareMode = FILE_SHARE_READ
00401012  |. 68 00000080    PUSH 80000000                            ; |Access = GENERIC_READ
00401017  |. 68 1F354000    PUSH why.0040351F                        ; |FileName = "s2License.key"
0040101C  |. E8 51030000    CALL <JMP.&kernel32.CreateFileA>         ; \CreateFileA
00401021  |. 83F8 FF        CMP EAX,-1
00401024  |. 75 0C          JNZ SHORT why.00401032
00401026  |. C605 C5424000 >MOV BYTE PTR [4042C5],0
0040102D  |. E9 9D000000    JMP why.004010CF
00401032  |> A3 B4404000    MOV DWORD PTR [4040B4],EAX
00401037  |. 6A 00          PUSH 0                                   ; /pFileSizeHigh = NULL
00401039  |. FF35 B4404000  PUSH DWORD PTR [4040B4]                  ; |hFile = NULL
0040103F  |. E8 3A030000    CALL <JMP.&kernel32.GetFileSize>         ; \GetFileSize
00401044  |. A3 BC404000    MOV DWORD PTR [4040BC],EAX
00401049  |. 6A 00          PUSH 0                                   ; /pOverlapped = NULL
0040104B  |. 68 2D354000    PUSH why.0040352D                        ; |pBytesRead = why.0040352D
00401050  |. FF35 BC404000  PUSH DWORD PTR [4040BC]                  ; |BytesToRead = 0
00401056  |. 68 C0404000    PUSH why.004040C0                        ; |Buffer = why.004040C0
0040105B  |. FF35 B4404000  PUSH DWORD PTR [4040B4]                  ; |hFile = NULL
00401061  |. E8 30030000    CALL <JMP.&kernel32.ReadFile>            ; \ReadFile
00401066  |. FF35 B4404000  PUSH DWORD PTR [4040B4]                  ; /hObject = NULL
0040106C  |. E8 FB020000    CALL <JMP.&kernel32.CloseHandle>         ; \CloseHandle
00401071  |. 68 AC384000    PUSH why.004038AC
00401076  |. 68 C0404000    PUSH why.004040C0                        ;  文件
0040107B  |. 6A 10          PUSH 10
0040107D  |. 68 13304000    PUSH why.00403013                        ;  ASCII "8396A3806D9022BA3F636BFB4A310DEF15FF9A092289A2AC0312EBE7CD5B28438275EAEF3F74225201EA9DF584148A8BFF8382023AD508BBED7118CDA863B97E10B7938FEC257F13596D7B43E506674E1AC37EC60E62FB94FF4198417EE43B9ABF4870AC7F245AD905E55CFD856DB112A9C04A94E1670"...
00401082  |. 68 14324000    PUSH why.00403214                        ;  ASCII "6484DB2B4D06B0F0936190682A79A48A41C4BA574611DBB908B4188F3F58E63E03D7ADFACAFF1D048640421FFDA06F6198734E0A04051EA1E834DFDCA24863B7406FEB8222C355FA62F2F6199C4732FD0006DCBDD0D99E1368962407CC35EEAE3C76CAD38A602C21E2961E5DEFE22644FA7550C3C017A"...
00401087  |. FF15 B0404000  CALL DWORD PTR [4040B0]                  ;  调用what_the函数
0040108D     E8 90000000    CALL <why.big2bytes>                     ;  将得到得大数保存到4040C0
00401092     E8 CE000000    CALL why.00401165                        ;  分析处理的结果
00401097  |. C605 C5424000 >MOV BYTE PTR [4042C5],1
0040109E     E8 F3000000    CALL <why.sumofbytes>                    ;  key的第一部分的"和",保存到4042C1
004010A3  |. 68 4B354000    PUSH why.0040354B
004010A8     E8 6F020000    CALL why.0040131C                        ;  key的第二部分转化为数字
004010AD  |. 3B05 C1424000  CMP EAX,DWORD PTR [4042C1]
004010B3  |. 74 1A          JE SHORT why.004010CF
004010B5  |. 6A 40          PUSH 40                                  ; /Style = MB_OK|MB_ICONASTERISK|MB_APPLMODAL
004010B7  |. 68 15344000    PUSH why.00403415                        ; |Title = ".caption"
004010BC  |. 68 5B384000    PUSH why.0040385B                        ; |Text = "You have potential, go ahead :DD"
004010C1  |. 6A 00          PUSH 0                                   ; |hOwner = NULL
004010C3  |. E8 FE020000    CALL <JMP.&USER32.MessageBoxA>           ; \MessageBoxA
004010C8  |. C605 C5424000 >MOV BYTE PTR [4042C5],0
004010CF  |> 6A 00          PUSH 0                                   ; /pModule = NULL
004010D1  |. E8 AE020000    CALL <JMP.&kernel32.GetModuleHandleA>    ; \GetModuleHandleA
004010D6  |. A3 A8384000    MOV DWORD PTR [4038A8],EAX
004010DB  |. 6A 00          PUSH 0                                   ; /lParam = NULL
004010DD  |. 68 CE114000    PUSH why.004011CE                        ; |DlgProc = why.004011CE
004010E2  |. 6A 00          PUSH 0                                   ; |hOwner = NULL
004010E4  |. 6A 64          PUSH 64                                  ; |pTemplate = 64
004010E6  |. FF35 A8384000  PUSH DWORD PTR [4038A8]                  ; |hInst = NULL
004010EC  |. E8 B7020000    CALL <JMP.&USER32.DialogBoxParamA>       ; \DialogBoxParamA
004010F1  |. 6A 00          PUSH 0                                   ; /ExitCode = 0
004010F3  \. E8 80020000    CALL <JMP.&kernel32.ExitProcess>         ; \ExitProcess
004010F8     E8             DB E8
004010F9     DB             DB DB
004010FA     02             DB 02
004010FB     00             DB 00
004010FC     00             DB 00
004010FD  /$ 68 00304000    PUSH why.00403000                        ; /FileName = "crap0.dll"
00401102  |. E8 89020000    CALL <JMP.&kernel32.LoadLibraryA>        ; \LoadLibraryA
00401107  |. A3 AC404000    MOV DWORD PTR [4040AC],EAX
0040110C  |. 68 0A304000    PUSH why.0040300A                        ; /ProcNameOrOrdinal = "what_the"
00401111  |. FF35 AC404000  PUSH DWORD PTR [4040AC]                  ; |hModule = NULL
00401117  |. E8 6E020000    CALL <JMP.&kernel32.GetProcAddress>      ; \GetProcAddress
0040111C  |. A3 B0404000    MOV DWORD PTR [4040B0],EAX
00401121  \. C3             RETN

OD给我们标识得很清晰明了了.
继续分析窗口处理过程可以看到主要有两个验证的地方.

第一个:
004011FE   . 803D C5424000 >CMP BYTE PTR [4042C5],0
00401205   . 75 11          JNZ SHORT why.00401218

看前面的处理部分中可以看到,key的第一部分的"和"等于key的第二部分就可以满足这个条件:
00401097  |. C605 C5424000 >MOV BYTE PTR [4042C5],1
...
004010AD  |. 3B05 C1424000  CMP EAX,DWORD PTR [4042C1]
004010B3  |. 74 1A          JE SHORT why.004010CF
...
004010C8  |. C605 C5424000 >MOV BYTE PTR [4042C5],0
004010CF  |> 6A 00          PUSH 0                                   ; /pModule = NULL
...

第二个:
0040123B   . E8 DC000000    CALL why.0040131C                        ;  key的第三部分转化为数字
00401240   . A3 C6424000    MOV DWORD PTR [4042C6],EAX
00401245   . 0BC0           OR EAX,EAX
00401247   . 75 12          JNZ SHORT why.0040125B                   ;  不为0就不使important按钮disabled
.......
004012AD   . A1 C6424000    MOV EAX,DWORD PTR [4042C6]
004012B2   . 33D2           XOR EDX,EDX
004012B4   . 68 C8124000    PUSH why.004012C8
004012B9   . 64:FF32        PUSH DWORD PTR FS:[EDX]
004012BC   . 64:8922        MOV DWORD PTR FS:[EDX],ESP
004012BF   . 35 82198219    XOR EAX,19821982
004012C4   . FFD0           CALL EAX
四处看看发现eax=004012E1就可以,所以第三部分可以为固定值:19C20B63
004012E1     6A 40          PUSH 40

往回说,其实key分做了三部分是通过分析crap0.dll中的what_the函数和下面这个函数得知的:
00401092     E8 CE000000    CALL why.00401165                        ;  分析处理的结果

先看what_the函数,crap0.dll经过了和主程序一样的处理,要脱壳的话同理即可.
...
10001189   52               PUSH EDX
1000118A   50               PUSH EAX
1000118B   E8 60470000      CALL <cinstr>
10001190   8B4C24 3C        MOV ECX,DWORD PTR [ESP+3C]
10001194   8B5424 20        MOV EDX,DWORD PTR [ESP+20]
10001198   51               PUSH ECX                         ; arg.2
10001199   52               PUSH EDX
1000119A   E8 51470000      CALL <cinstr>
1000119F   8B4424 4C        MOV EAX,DWORD PTR [ESP+4C]
100011A3   8B4C24 24        MOV ECX,DWORD PTR [ESP+24]
100011A7   50               PUSH EAX                         ; 文件中读取的内容
100011A8   51               PUSH ECX
100011A9   E8 42470000      CALL <cinstr>
100011AE   8D5424 30        LEA EDX,DWORD PTR [ESP+30]
100011B2   8D4424 34        LEA EAX,DWORD PTR [ESP+34]
100011B6   52               PUSH EDX                         ; 大数("8396...")
100011B7   8D4C24 30        LEA ECX,DWORD PTR [ESP+30]
100011BB   50               PUSH EAX                         ; 大数("6484...")
100011BC   8D5424 58        LEA EDX,DWORD PTR [ESP+58]
100011C0   51               PUSH ECX                         ; big(file)
100011C1   52               PUSH EDX                         ; arg.3=10h
100011C2   E8 39FEFFFF      CALL 10001000
100011C7   8B4C24 38        MOV ECX,DWORD PTR [ESP+38]
100011CB   8B10             MOV EDX,DWORD PTR [EAX]
100011CD   51               PUSH ECX
100011CE   52               PUSH EDX
100011CF   E8 0C100000      CALL 100021E0
...
其中10001000处的函数:
......
10001013   56               PUSH ESI                               ; 结果
10001014   8B08             MOV ECX,DWORD PTR [EAX]
10001016   8B02             MOV EAX,DWORD PTR [EDX]
10001018   51               PUSH ECX                               ; 大数("8396...")
10001019   8B4C24 1C        MOV ECX,DWORD PTR [ESP+1C]
1000101D   50               PUSH EAX                               ; 大数("6484...")
1000101E   8B11             MOV EDX,DWORD PTR [ECX]
10001020   52               PUSH EDX                               ; 大数(file)=k
10001021   E8 BA380000      CALL <powmod>
10001026   6A 00            PUSH 0
10001028   E8 63070000      CALL <mirvar>
1000102D   8B7C24 24        MOV EDI,DWORD PTR [ESP+24]
......
另b1=大数("8396..."),b2=大数("6484..."),所以这里就是计算
key=k^b2 mod b1(k是由文件内容转化成的大数,^代表幂运算)

再看why.00401165:
00401165  /$ 56             PUSH ESI
00401166  |. 57             PUSH EDI
00401167  |. BE C0404000    MOV ESI,why.004040C0
0040116C  |. BF 31354000    MOV EDI,why.00403531
00401171  |> AC             /LODS BYTE PTR [ESI]
00401172  |. 3C 2C          |CMP AL,2C                               ;  ", " 逗号
00401174  |. 74 03          |JE SHORT why.00401179
00401176  |. AA             |STOS BYTE PTR ES:[EDI]
00401177  |.^EB F8          \JMP SHORT why.00401171                  ; key.part1
00401179  |> BF 4B354000    MOV EDI,why.0040354B
0040117E  |> AC             /LODS BYTE PTR [ESI]
0040117F  |. 3C 2C          |CMP AL,2C
00401181  |. 74 03          |JE SHORT why.00401186
00401183  |. AA             |STOS BYTE PTR ES:[EDI]
00401184  |.^EB F8          \JMP SHORT why.0040117E
00401186  |> BF 54354000    MOV EDI,why.00403554                     ;  key.part2
0040118B  |> AC             /LODS BYTE PTR [ESI]
0040118C  |. 3C 24          |CMP AL,24                               ;  $
0040118E  |. 74 03          |JE SHORT why.00401193
00401190  |. AA             |STOS BYTE PTR ES:[EDI]
00401191  |.^EB F8          \JMP SHORT why.0040118B                  ;  key.part3
00401193  |> 5F             POP EDI
00401194  |. 5E             POP ESI
00401195  \. C3             RETN

所以key的格式应该是这样
keypart1,keypart2,keypart3$

00401218   > 68 31354000    PUSH why.00403531                        ; /String2 = "";keypart1
0040121D   . 68 97384000    PUSH why.00403897                        ; |String1 = "Registered to : "
00401222   . E8 75010000    CALL <JMP.&kernel32.lstrcat>             ; \lstrcat
00401227   . 68 97384000    PUSH why.00403897                        ; /Text = "Registered to : "
0040122C   . 6A 68          PUSH 68                                  ; |ControlID = 68 (104.)
0040122E   . FF75 08        PUSH DWORD PTR [EBP+8]                   ; |hWnd
00401231   . E8 9C010000    CALL <JMP.&USER32.SetDlgItemTextA>       ; \SetDlgItemTextA

所以如果对应"aalloverred",就有key:
aalloverred,29EBF1DD,19C20B63$
其中29EBF1DD=sum("aalloverred")
因为这是处理过后的字节转化成数字的结果
0040108D     E8 90000000    CALL <why.big2bytes>                     ;  将得到得大数保存到4040C0
所以将对应的二进制值作为大数处理:
61 61 6C 6C 6F 76 65 72 72 65 64 2C 32 39 45 42 46 31 44 44 2C 31 39 43 32 30 42 36 33 24
所以key=61616C6C6F7665727265642C32394542463144442C313943323042363324
又因为有key=k^b2 mod b1所以k=key^D mod b1
但是b1有2048位之大,所以直接计算D估计是不可行的.不懂算法,但是看过bLaCk-eye的RSA攻击的文章,
用他的RAT(RSA ATTACKING TOOLKITT v.0.1f)试了试,^_^,还真行,使用wiener attack 瞬间就得到了D=10001.

到这里,注册机就简单了,见附件!
--------------------------------------------------------------------------------
【经验总结】
感觉数学学得太差,分析这种cm没有数论的基础太难了,这次这么顺利主要是运气好吧.期望看到大侠们更多的关于算法的文章.
--------------------------------------------------------------------------------
【版权声明】: 本文原创于看雪技术论坛, 转载请注明作者并保持文章的完整, 谢谢!


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

上传的附件:
收藏
免费 7
支持
分享
最新回复 (2)
雪    币: 538
活跃值: (505)
能力值: ( LV9,RANK:290 )
在线值:
发帖
回帖
粉丝
2
看不懂!还是顶一下,继续学习中!!
2006-11-26 21:37
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
好久没来,也好久没学了。认真学习中。。。。。。
2006-11-26 22:20
0
游客
登录 | 注册 方可回帖
返回
//