首页
社区
课程
招聘
[原创]对happytown老大的KeyGenMe_08的分析
发表于: 2007-2-7 18:13 5676

[原创]对happytown老大的KeyGenMe_08的分析

2007-2-7 18:13
5676

【文章标题】:【原创】对happytown老大的KeyGenMe_08的分析
【文章作者】: rageliu
【破解日期】: 2007_02_07 17:29
【下载地址】:
【作者声明】: 兴趣,无它。
--------------------------------------------------------------------------------
【详细过程】

壳分析:目前happytown的系列KeyGenMe都没加壳,适合偶们新手练习。

运行KeyGenMe_08.exe,什么都不输入直接点击“Check”,没反映。输入用户名:rageliu,注册码:12345后点“Check”,一样没有什么反映。看来happytown延续了他的一惯风格,只有注册码正确了才会有提示出现。
老规矩,当然是OD出马了。
运行OD,加载KeyGenMe_08.exe,先看看字符串参考,哈哈,看到什么了“Good job,man”,就从这里入手。多说一点,这里不知道你有没有注意到,居然还有一个“C:\”,想到什么了吗?没想到也没关系,偶们后面要说。双击“Good job,man”来到下面这一行:

0040116A   .  56            PUSH ESI                                 ;

看看附近代码:

00401160   .  33C0          XOR EAX,EAX
00401162   .  5E            POP ESI
00401163   .  C2 1000       RETN 10                                                                         ;这个RETN说明上面是其他函数的代码了。
00401166   >  8B7424 08     MOV ESI,DWORD PTR SS:[ESP+8]             ;  Case 3EC of switch 00401145
0040116A   .  56            PUSH ESI                                 ;  参数入栈
0040116B   .  E8 90FEFFFF   CALL KeyGenMe.00401000                   ;  关键call
00401170   .  83C4 04       ADD ESP,4                                ;  平栈
00401173   .  85C0          TEST EAX,EAX                             ;  关键跳,跳就完蛋
00401175      0F84 C7000000 JE KeyGenMe.00401242
0040117B   .  6A 40         PUSH 40                                  ; /Style = MB_OK|MB_ICONASTERISK|MB_APPLMODAL
0040117D   .  68 A8D04000   PUSH KeyGenMe.0040D0A8                   ; |Title = "Congratulations"
00401182   .  68 98D04000   PUSH KeyGenMe.0040D098                   ; |Text = "Good job,man!"
00401187   .  56            PUSH ESI                                 ; |hOwner
00401188   .  FF15 C8C04000 CALL DWORD PTR DS:[<&USER32.MessageBoxA>>; \MessageBoxA

这里我们下关键call
0040116B   .  E8 90FEFFFF   CALL KeyGenMe.00401000
的断点,然后F7跟进去开始分析算法,算法如下:

00401000  /$  81EC DC050000 SUB ESP,5DC                              ;  给局部变量分配空间
00401006  |.  53            PUSH EBX
00401007  |.  55            PUSH EBP
00401008  |.  56            PUSH ESI
00401009  |.  57            PUSH EDI
0040100A  |.  33DB          XOR EBX,EBX                              ;  EBX=0,CF=0
0040100C  |.  B9 7C000000   MOV ECX,7C
00401011  |.  33C0          XOR EAX,EAX                              ;  EAX=0,CF=0
00401013  |.  8DBC24 F90300>LEA EDI,DWORD PTR SS:[ESP+3F9]
0040101A  |.  889C24 F80300>MOV BYTE PTR SS:[ESP+3F8],BL
00401021  |.  889C24 040200>MOV BYTE PTR SS:[ESP+204],BL
00401028  |.  F3:AB         REP STOS DWORD PTR ES:[EDI]
0040102A  |.  66:AB         STOS WORD PTR ES:[EDI]
0040102C  |.  AA            STOS BYTE PTR ES:[EDI]
0040102D  |.  B9 7C000000   MOV ECX,7C
00401032  |.  33C0          XOR EAX,EAX
00401034  |.  8DBC24 050200>LEA EDI,DWORD PTR SS:[ESP+205]
0040103B  |.  885C24 10     MOV BYTE PTR SS:[ESP+10],BL
0040103F  |.  F3:AB         REP STOS DWORD PTR ES:[EDI]
00401041  |.  66:AB         STOS WORD PTR ES:[EDI]
00401043  |.  AA            STOS BYTE PTR ES:[EDI]
00401044  |.  B9 7C000000   MOV ECX,7C
00401049  |.  33C0          XOR EAX,EAX
0040104B  |.  8D7C24 11     LEA EDI,DWORD PTR SS:[ESP+11]
0040104F  |.  8BB424 F00500>MOV ESI,DWORD PTR SS:[ESP+5F0]
00401056  |.  F3:AB         REP STOS DWORD PTR ES:[EDI]
00401058  |.  66:AB         STOS WORD PTR ES:[EDI]
0040105A  |.  8B2D D8C04000 MOV EBP,DWORD PTR DS:[<&USER32.GetDlgIte>;  USER32.GetDlgItemTextA
00401060  |.  68 F5010000   PUSH 1F5                                 ; /Count = 1F5 (501.)
00401065  |.  AA            STOS BYTE PTR ES:[EDI]                   ; |
00401066  |.  8D8424 FC0300>LEA EAX,DWORD PTR SS:[ESP+3FC]           ; |返回串在这里!!名字
0040106D  |.  50            PUSH EAX                                 ; |Buffer
0040106E  |.  68 EA030000   PUSH 3EA                                 ; |ControlID = 3EA (1002.)
00401073  |.  56            PUSH ESI                                 ; |hWnd
00401074  |.  FFD5          CALL EBP                                 ; \GetDlgItemTextA
00401076  |.  8BF8          MOV EDI,EAX                              ;  EAX返回名字长度
00401078  |.  83FF 02       CMP EDI,2                                ;  名字长度必须大于2,不然就Over
0040107B  |.  7D 0D         JGE SHORT KeyGenMe.0040108A
0040107D  |.  5F            POP EDI
0040107E  |.  5E            POP ESI
0040107F  |.  5D            POP EBP
00401080  |.  33C0          XOR EAX,EAX
00401082  |.  5B            POP EBX
00401083  |.  81C4 DC050000 ADD ESP,5DC
00401089  |.  C3            RETN
0040108A  |>  8D8C24 040200>LEA ECX,DWORD PTR SS:[ESP+204]           ;  返回串在这里!!偶们随便填的注册码
00401091  |.  68 F5010000   PUSH 1F5
00401096  |.  51            PUSH ECX
00401097  |.  68 EB030000   PUSH 3EB
0040109C  |.  56            PUSH ESI
0040109D  |.  FFD5          CALL EBP
0040109F  |.  8BF0          MOV ESI,EAX                              ;  EAX返回假注册码长度
004010A1  |.  3BF3          CMP ESI,EBX                              ;  注册码不能为空,不然就Over
004010A3  |.  75 0D         JNZ SHORT KeyGenMe.004010B2
004010A5  |.  5F            POP EDI
004010A6  |.  5E            POP ESI
004010A7  |.  5D            POP EBP
004010A8  |.  33C0          XOR EAX,EAX
004010AA  |.  5B            POP EBX
004010AB  |.  81C4 DC050000 ADD ESP,5DC
004010B1  |.  C3            RETN
004010B2  |>  33C9          XOR ECX,ECX                              ;  ECX=0,CF=0
004010B4  |.  3BF3          CMP ESI,EBX                              ;  为什么又判断注册码是否为空??
004010B6  |.  7E 22         JLE SHORT KeyGenMe.004010DA
004010B8  |>  33C0          /XOR EAX,EAX                             ;  EAX=0,CF=0
004010BA  |.  BB 1A000000   |MOV EBX,1A                              ;  EBX=1A
004010BF  |.  8A840C 040200>|MOV AL,BYTE PTR SS:[ESP+ECX+204]        ;  依次按Byte取注册码
004010C6  |.  03C7          |ADD EAX,EDI                             ;  EAX=AL+EDI,EDI为名字长度
004010C8  |.  99            |CDQ                                     ;  把EAX中的字的符号扩展到EDX中去
004010C9  |.  F7FB          |IDIV EBX                                ;  EAX=EAX/EBX
004010CB  |.  41            |INC ECX                                 ;  ECX+=1
004010CC  |.  3BCE          |CMP ECX,ESI                             ;  ECX和注册码长度比较
004010CE  |.  8A92 30D04000 |MOV DL,BYTE PTR DS:[EDX+40D030]         ;  取得一个字符
004010D4  |.  88540C 0F     |MOV BYTE PTR SS:[ESP+ECX+F],DL
004010D8  |.^ 7C DE         \JL SHORT KeyGenMe.004010B8                                 ;  循环注册码长度次
004010DA  |>  8D4424 10     LEA EAX,DWORD PTR SS:[ESP+10]
004010DE  |.  68 C8FB4000   PUSH KeyGenMe.0040FBC8                   ; /String2 = "JUYZZILVYICSONESXHC"
004010E3  |.  50            PUSH EAX                                 ; |String1
004010E4  |.  FF15 00C04000 CALL DWORD PTR DS:[<&KERNEL32.lstrcmpA>] ; \lstrcmpA
004010EA  |.  F7D8          NEG EAX
004010EC  |.  5F            POP EDI
004010ED  |.  5E            POP ESI
004010EE  |.  1BC0          SBB EAX,EAX
004010F0  |.  5D            POP EBP
004010F1  |.  40            INC EAX
004010F2  |.  5B            POP EBX
004010F3  |.  81C4 DC050000 ADD ESP,5DC
004010F9  \.  C3            RETN

这里一直分析到:
004010DA  |>  8D4424 10     LEA EAX,DWORD PTR SS:[ESP+10]
都是好理解的,不过接下来的:
004010DE  |.  68 C8FB4000   PUSH KeyGenMe.0040FBC8
这句让我迷惑了,上面算出来的东东居然是和它比较,那么0040FBC8地址的东西到底是什么呢?动态调试到这里显示是一串字符串,这个字符串是什么时候生成的呢,再看看上面也没有对0040FBC8地址的操作啊。看来是一早就生成在那里了,下面偶们来看看它是什么时候生成的。

Ctrl+F2,重新开始,输入DB 0040FBC8,来到这个地址,我们看到还是空的。对该地址下字节方式的硬件写入断点。F9运行,OD断在下面这个地方:
00401218   .  B8 ABAAAAAA   MOV EAX,AAAAAAAB
我们看看这句上面都有些什么代码:
004011D6   .  83C4 04       ADD ESP,4
004011D9   >  6A 00         PUSH 0                                   ; /pFileSystemNameSize = NULL
004011DB   .  6A 00         PUSH 0                                   ; |pFileSystemNameBuffer = NULL
004011DD   .  6A 00         PUSH 0                                   ; |pFileSystemFlags = NULL
004011DF   .  6A 00         PUSH 0                                   ; |pMaxFilenameLength = NULL
004011E1   .  68 C4FB4000   PUSH KeyGenMe.0040FBC4                   ; |pVolumeSerialNumber = KeyGenMe.0040FBC4
004011E6   .  6A 00         PUSH 0                                   ; |MaxVolumeNameSize = 0
004011E8   .  6A 00         PUSH 0                                   ; |VolumeNameBuffer = NULL
004011EA   .  68 94D04000   PUSH KeyGenMe.0040D094                   ; |RootPathName = "c:\"
004011EF   .  FF15 04C04000 CALL DWORD PTR DS:[<&KERNEL32.GetVolumeI>; \GetVolumeInformationA
004011F5   .  8B0D C4FB4000 MOV ECX,DWORD PTR DS:[40FBC4]
004011FB   .  85C9          TEST ECX,ECX
004011FD   .  76 43         JBE SHORT KeyGenMe.00401242
004011FF   .  57            PUSH EDI
00401200   .  BE C8FB4000   MOV ESI,KeyGenMe.0040FBC8
00401205   >  8BC1          MOV EAX,ECX
00401207   .  33D2          XOR EDX,EDX
00401209   .  BF 1A000000   MOV EDI,1A
0040120E   .  F7F7          DIV EDI
00401210   .  8A82 30D04000 MOV AL,BYTE PTR DS:[EDX+40D030]
00401216   .  8806          MOV BYTE PTR DS:[ESI],AL
00401218   .  B8 ABAAAAAA   MOV EAX,AAAAAAAB

哈哈,看到了吗?开始说的那个串“C:\”,还有函数GetVolumeInformationA(),原来是取C盘的逻辑序列号。

其实偶们要先看看引入的函数有GetVolumeInformationA(),也会有些想法的。

到这里2个比较串的来源都清楚了,接下来应该是写注册机。该下班了,偶找时间补上来,你也可以自己先练练写。呵呵


[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

上传的附件:
收藏
免费 7
支持
分享
最新回复 (6)
雪    币: 297
活跃值: (21)
能力值: ( LV9,RANK:330 )
在线值:
发帖
回帖
粉丝
2
分析得很清楚,不错,支持楼主!
2007-2-7 19:52
0
雪    币: 461
活跃值: (93)
能力值: ( LV9,RANK:1170 )
在线值:
发帖
回帖
粉丝
3
很不错,支持楼主!
2007-2-7 20:41
0
雪    币: 721
活跃值: (350)
能力值: ( LV9,RANK:1250 )
在线值:
发帖
回帖
粉丝
4
不错,不错。支持一下。
2007-2-13 11:40
0
雪    币: 263
活跃值: (10)
能力值: ( LV9,RANK:210 )
在线值:
发帖
回帖
粉丝
5
最初由 happytown 发布
不错,不错。支持一下。


只是觉得
如果这个时候放出你原crackme的加密结构比简单跟帖强很多
2007-2-13 12:18
0
雪    币: 721
活跃值: (350)
能力值: ( LV9,RANK:1250 )
在线值:
发帖
回帖
粉丝
6
最初由 fonge 发布
只是觉得
如果这个时候放出你原crackme的加密结构比简单跟帖强很多

我没那个机会了,唉,可惜啊。
2007-2-13 12:38
0
雪    币: 263
活跃值: (10)
能力值: ( LV9,RANK:210 )
在线值:
发帖
回帖
粉丝
7
就等你有机会了
2007-2-13 13:16
0
游客
登录 | 注册 方可回帖
返回
//