上次去除了一个软件的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日凌晨
===========================================================================================================
最后的话:困了,不多写了,明天要上学。。。
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课