上次去除了一个软件的NAG,这次来获取它的注册码

声明:本人是刚学3天的菜鸟,文章有许多不足之处,请各位大牛指点。
      为了避免不必要的麻烦,软件名全用"VDT"代替

============================================================================================================
目标程序简介:该程序是一款虚拟桌面程序,如果没注册,每次关闭程序时会依次弹出两个对话框,要求注册、修改IE主页。

任务目标:    通过注册使得程序退出时不显示该对话框。

使用工具:    PEid,ImpREC,LoadPE,Ollydbg,Process Monitor,regedit
============================================================================================================
过程:

首先PEid查壳,是ASPack 2.12,为了彰显菜鸟本色,我决定手工脱壳

Ollydbg载入,按几个F7后到此处:

0056B01A    03DD            ADD EBX,EBP
0056B01C    81EB 00B01600   SUB EBX,16B000
0056B022    83BD 22040000 0>CMP DWORD PTR SS:[EBP+422],0
0056B029    899D 22040000   MOV DWORD PTR SS:[EBP+422],EBX
0056B02F    0F85 65030000   JNZ VDT.0056B39A                         ; 停于此处
0056B035    8D85 2E040000   LEA EAX,DWORD PTR SS:[EBP+42E]
0056B03B    50              PUSH EAX
0056B03C    FF95 4D0F0000   CALL DWORD PTR SS:[EBP+F4D]

enter到VDT.0056B39A,按F4,然后F7到RETN,就找到OEP了:

0056B39A    B8 40420D00     MOV EAX,0D4240                           ; 在此处F4
0056B39F    50              PUSH EAX
0056B3A0    0385 22040000   ADD EAX,DWORD PTR SS:[EBP+422]
0056B3A6    59              POP ECX
0056B3A7    0BC9            OR ECX,ECX
0056B3A9    8985 A8030000   MOV DWORD PTR SS:[EBP+3A8],EAX
0056B3AF    61              POPAD                                    ;标志性POPAD
0056B3B0    75 08           JNZ SHORT VDT.0056B3BA
0056B3B2    B8 01000000     MOV EAX,1
0056B3B7    C2 0C00         RETN 0C
0056B3BA    68 40424D00     PUSH VDT.004D4240
0056B3BF    C3              RETN                                     ; 在此处返回

执行到RETN时的堆栈:

ESP ==>  > 004D4240  VDT.004D4240

OEP的地址为004D4240
现在使用LoadPE,Dump Full...
然后ImpREC出场,选中进程后看到Log窗口中有句“Image Base:00400000 Size:0016E000”。
用堆栈中的OEP地址减去Image Base得到000D4240,输入到OEP框中,选AutoSearch,ImpREC自动找到了相应的RVA和Size。
现在点击Get Imports,显示出一堆信息。检查一下全是YES。没问题,直接Fix Dump

测试一下,没问题,那就脱壳完毕了。




现在运行脱壳后的程序(我的是dumped_.exe),点软件注册,输入用户名(我用"testname")和注册码(我用"testcode")。
再点注册验证按钮,直接弹出窗口说“注册完成,请重新运行”,然后程序就结束了。。。

然后我用od载入分析,用了2小时分析不出结果(crack功力太浅)。

于是放弃od分析,改而另辟蹊径。

猜测软件会改注册表(貌似很多软件都会这样做),于是用regedit在注册表里查找"VDT"。
有好几个结果是无用的,不过最后找着了:

[HKEY_CURRENT_USER\Software\VDT]
"RegUser"="testname"
"RegNo"="testcode"

正是用户名和注册码。
现在我要知道程序在运行过程中对注册表的查找及修改情况,请出Process Monitor
Ctrl+L设置以下过滤器:

列     关系   值               动作
------------------------------------------
操作   是     注册表-设置值    保留
操作   是     注册表-查询值    保留
进程名 不是   dumped_.exe      排除
路径   不包含 VDT              排除

然后运行dumped_.exe,点软件注册,输入用户名(我用"user")和注册码(我用"code")。
再点注册验证按钮,直接弹出窗口说“注册完成,请重新运行”,然后程序就结束了。。。

回到Process Monitor看到以下事件:

时间     进程名      操作          路径                           结果 详细信息
33:00.4  dumped_.exe 注册表-查询值 HKCU\Software\Vdesktop\RegUser 成功 Type: REG_SZ, 长度: 18, 数据: testname
33:00.4  dumped_.exe 注册表-查询值 HKCU\Software\Vdesktop\RegUser 成功 Type: REG_SZ, 长度: 18, 数据: testname
33:00.4  dumped_.exe 注册表-查询值 HKCU\Software\Vdesktop\RegUser 成功 Type: REG_SZ, 长度: 18, 数据: testname
33:00.4  dumped_.exe 注册表-查询值 HKCU\Software\Vdesktop\RegUser 成功 Type: REG_SZ, 长度: 18, 数据: testname
33:00.4  dumped_.exe 注册表-查询值 HKCU\Software\Vdesktop\RegNo   成功 Type: REG_SZ, 长度: 18, 数据: testcode
33:00.4  dumped_.exe 注册表-查询值 HKCU\Software\Vdesktop\RegNo   成功 Type: REG_SZ, 长度: 18, 数据: testcode
33:00.4  dumped_.exe 注册表-查询值 HKCU\Software\Vdesktop\RegNo   成功 Type: REG_SZ, 长度: 18, 数据: testcode
33:00.4  dumped_.exe 注册表-查询值 HKCU\Software\Vdesktop\RegNo   成功 Type: REG_SZ, 长度: 18, 数据: testcode
33:09.0  dumped_.exe 注册表-查询值 HKCU\Software\Vdesktop         成功 查询: 名称
33:09.0  dumped_.exe 注册表-设置值 HKCU\Software\Vdesktop\RegUser 成功 Type: REG_SZ, 长度: 10, 数据: user
33:09.0  dumped_.exe 注册表-查询值 HKCU\Software\Vdesktop         成功 查询: 名称
33:09.0  dumped_.exe 注册表-设置值 HKCU\Software\Vdesktop\RegNo   成功 Type: REG_SZ, 长度: 6, 数据: sn

分析上述数据可以知道,程序在开始时读取了用户名和注册码,在结束时保存了用户名和注册码,注册信息的验证很可能是在开始时进行的
(不然开始时为什么要读取用户名和注册码?)

回到od,载入dumped_.exe,Ctrl+N查看API名称,其中涉及到注册表读写的只有RegQueryValueEx,于是在每个参考上设断。

查查RegQueryValueEx:


RegQueryValueEx:
VB声明 
Declare Function RegQueryValueEx Lib "advapi32.dll" Alias "RegQueryValueExA" (ByVal hKey As Long, ByVal lpValueName As String, ByVal lpReserved As Long, lpType As Long, lpData As Any, lpcbData As Long) As Long 
说明 
获取一个项的设置值 
返回值 
Long,零(ERROR_SUCCESS)表示成功。其他任何值都代表一个错误代码 
参数表 
参数 类型及说明 
hKey Long,一个已打开项的句柄,或者指定一个标准项名 
lpValueName String,要获取值的名字 
lpReserved Long,未用,设为零 
lpType Long,用于装载取回数据类型的一个变量 
lpData Any,用于装载指定值的一个缓冲区 
lpcbData Long,用于装载lpData缓冲区长度的一个变量。一旦返回,它会设为实际装载到缓冲区的字节数

其中lpData表示读注册表所取得的信息的存储地址,lpValueName表示要获取值的名字(这两个比较重要)。

现在不停F9,大概20次后堆栈窗口中会出现如下信息:

ESP ==>  > 000002A4  |hKey = 2A4
ESP+4    > 004D34A8  |ValueName = "RegNo"
ESP+8    > 00000000  |Reserved = NULL
ESP+C    > 0012FDB8  |pValueType = 0012FDB8
ESP+10   > 00B33884  |Buffer = 00B33884
ESP+14   > 0012FDC8  \pBufSize = 0012FDC8

只要ValueName=="RegNo"且Buffer!=null就行了。(其实应该可以用条件断点,以后有时间就试试)

现在一路F8,直到此处:

004D334E  |.  8B45 E8       MOV EAX,DWORD PTR SS:[EBP-18]
004D3351  |.  50            PUSH EAX
004D3352  |.  8D4D E4       LEA ECX,DWORD PTR SS:[EBP-1C]
004D3355  |.  BA B8344D00   MOV EDX,dumped_.004D34B8                 ;  ASCII "vdesktopChina"
004D335A  |.  A1 34A34D00   MOV EAX,DWORD PTR DS:[4DA334]
004D335F  |.  E8 B8DCFFFF   CALL dumped_.004D101C                    ;  此call生成正确的注册码,在此处停下
004D3364  |.  8B55 E4       MOV EDX,DWORD PTR SS:[EBP-1C]
004D3367  |.  58            POP EAX
004D3368  |.  E8 BB14F3FF   CALL dumped_.00404828
004D336D  |.  75 07         JNZ SHORT dumped_.004D3376
004D336F  |.  C605 30A34D00>MOV BYTE PTR DS:[4DA330],1

F8步过这个函数,发现堆栈里多了一点东西:

ESP+1C   > 00B3383C  ASCII "7EE3FF6E000E21F5"
ESP+20   > 00B33884  ASCII "sn"
ESP+24   > 00B3AE48  ASCII "user"
ESP+28   > 00B327EC  ASCII "http://www.baidu.com/index.php?tn=tjywmaxdg"
ESP+2C   > 00B32778  ASCII "220.220.220.12"
ESP+30   > 00B3275C  ASCII "220.220.220.1"
ESP+34   > 00B32740  ASCII "110.110.110.110"

这个"7EE3FF6E000E21F5"应该就是正确的注册码了。

现在关掉od,运行VDT,用户名为"user",注册码为"7EE3FF6E000E21F5",注册,重启软件。
测试一下,点软件注册,显示“此软件已注册给:user”,呵呵,成功了。
再关掉软件,发现没有弹出NAG,即完成任务。
============================================================================================================
任务完成情况:成功完成任务。

完成时间:    09年8月6日凌晨
===========================================================================================================
最后的话:困了,不多写了,明天要上学。。。