逆向工程这门课也已经上完了,作为考查课需要交一份实验报告,这里我学习(抄袭)了我是用户大佬的破解实战-第一战,由于大佬水平高深,步骤间跳跃很大,我这里把大佬的意思加上自己的理解写成实验报告,仅供小白参考。
出处:https://www.52pojie.cn/thread-197281-1-1.html
注:中间有几处坑,表示自己掉进去的地方,如果想一次性实现,可以看完再练习。
开始吧!
超级U盘锁的逆向分析
超级U盘锁是一款功能强大的锁定系统U盘使用软件,限制他人使用U盘或其它移动存储设备从你的电脑复制或盗取重要资料。另外新版增加锁定光驱和锁定网络功能,防止更多方式盗走你的数据。软件提供密码设置,可以自由设置解除和锁定限制的功能。锁定U盘后,插上任意U盘或移动存储设备到计算机是没有任何反应的,需要解锁后才能正常使用U盘设备。
它全面支持Win 2000/XP/2003/Win7/Win8 32/64位。但其试用版不能添加密码,需要购买了才能设置密码。
超级U盘锁下载地址:http://www.onlinedown.net/soft/52481.htm
2.2 逆向过程及分析
2.2.1安装逆向相关工具
下载并安装逆向相关工具,本人使用的工具如下:
VMware虚拟机,WIN7操作系统,PEiD查壳工具以及OD。
2.2.2 脱壳
首先将超级U盘锁软件下载安装到虚拟机中,并使用PEiD查看该软件,如图2-1所示,显示该程序加的是ASpack压缩加密壳。
图2-1 查壳
然后使用OD手动脱壳,我采用的是单步跟踪法,即向上的跳转不能让他实现,向下的跳转让他实现。
把超级U盘锁(Ulock)软件载入OD,会出现如图2-2所示的入口点警告,这就是因为软件加壳,因而无法直接找到程序入口点。
这里不管他,我们点击确认,然后进行单步跟踪法,按F8或者菜单栏的单步步过。期间在汇编的一个CALL命令后步过,软件就直接运行了。这里我们称为软件跑飞(图2-3)了,即没有找到OEP就直接运行了软件。
图2-3 软件跑飞
所以我们需要重新再次跑程序,不能步过(F8)这个函数,而应该步入F7这个函数继续去找OEP。
在遇到如图2-4示的需要往回跳转时候,按照单步跟踪法,我们点击下一行即005C205F 然后按F4(运行到选定位置)执行到这一行。
图2-4 单步跟踪法
按照这种方法,我们很快就找到了有RETN的地方,这里也就会进入OEP了,如图2-5边寄存器也显示模块入口点了
图2-5 程序OEP进入点
我们继续跟踪步入,会进入图2-6所示的地方,这里没有任何的反汇编,只需要右键分析即可显示OEP了(图2-7)。
图2-6 未分析的OEP
图2-7分析后的OEP
这时,我们就可以使用插件中的OD脱壳模块来脱壳了(图2-8)。
图2-8 OD自带脱壳来脱壳
我们随机保存为ssozh.exe文件,然后打开发现无法运行该程序(图2-9),百度发现这是因为ASLR基地址随机化的原因,这样脱壳dump插件获取的地址不对,而ASLR是在WIN7/8或以上系统才有,因而,我改换成了XP的系统重新脱壳。
图 2-9 程序错误
图 2-10 编程语言E language
2.2.3去自校验
二次脱壳我采用了ESP定律法进行手动脱壳,这里不再赘述,很成功,发现是用E language写的(图2-10)。
打开脱壳后的软件(名字叫123),这时候直接运行OD是看不出来程序有自校验了。因为这个程序不能同时开两个,在电脑去壳期间已经运行着一个程序,而去壳后用OD再次载入,他并没有再次打开该程序而是OD自己结束了,没有运行起来。这时候会把之前运行的误认为是当前OD调试的。因而无法出现如下的自校验窗口,你需要先把软件强制关闭,再次打开。
你会发现这个软件很难关闭,因此需要使用上面推荐的PChunter强制关闭,再次打开OD调试就会发现程序有自效验(图2-11)。
图 2-11 自校验
OD打开123.exe(代码2-1)
00401000 >/$ E8 06000000 call 123.0040100B 00401005 |. 50 push eax ; \ExitCode = 0x0 00401006 \. E8 BB010000 call 0040100B $ 55 push ebp 0040100C . 8BEC mov ebp,esp 0040100E . 81C4 F0FEFFFF add esp,-0x110 00401014 . E9 83000000 jmp 123.0040109C 00401019 . 6B 72 6E 6C 6>ascii "krnln.fnr",0 00401023 . 20 20 20 20 2>ascii " ",0 0040102D . 47 65 74 4E 6>ascii "GetNewSock",0 00401038 . 20 20 20 20 2>ascii " " 00401048 . 20 20 20 20 2>ascii " ",0 00401052 . 20 20 20 20 0>ascii " ",0 00401057 . c8 b1c9 d9 enter 0xc9b1,0xd9 0040105B . c8 edbc fe enter 0xbced,0xfe 0040105F . BA CBD0C4D6 mov edx,0xD6C4D0CB 00401064 . A7 cmps dword ptr ds:[esi],dword ptr es:[ed> 00401065 . B3 D6 mov bl,0xD6 00401067 . BF E22CC7EB mov edi,0xEBC72CE2 0040106C . D6 salc 0040106D . D8D0 fcom st |
代码2-1
命令行对window下的MessageBoxA 下断点,即 BP MessageBoxA。然后进行堆栈回溯(图2-12)。图中右边是堆栈区,显示了图2-11中“程序已经被破坏”的位置,因为操作系统是小端模式,为了寻找代码段所在的位置,应该向之前的高地址寻找到第一次出现“程序已经被破坏”字符前面对应的代码段堆栈地址(代码2)找到堆栈地址0012FBD0进行反汇编窗口跟随(按回车)。图2-13所示即反汇编窗口跟随的用户代码领空,上一句CALL调用函数应该就是自校验,我们需要跳过这个自校验,即继续向上找找到可以跳过的JMP之类的语句。最后在005AECD9地址把反汇编语句jle 123.005AED5B改成JMP 123.005AED5B即可。
图 2-12 下断,堆栈回溯
0012FBD0 005AED3E 返回到 123.005AED3E 来自 123.005B2D86;第一句出现堆栈回溯的用户领空 0012FBD4 00000003 0012FBD8 00166868 ASCII "程序已经被破坏!" 0012FBDC 00000000 … 0012FBEC 80000301 0012FBF0 00403452 123.00403452 0012FBF4 00000000 … 0012FC00 0017A9FC 0012FC04 100E7A1C krnln.100E7A1C 0012FC08 100E5948 krnln.100E5948 0012FC0C 0012FC50 0012FC10 001C5400 ASCII "(((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((((" 0012FC14 00166868 ASCII "程序已经被破坏!";\第一句关键字符串 0012FC18 00464100 ASCII "B3CCD0F2D2D1BEADB1BBC6C6BBB521" |
代码2-2
图2-14 反汇编窗口跟随
双击右下角图标,,弹出程序被损坏(图2-15)
图2-15程序被破坏
BP ExitProcess,堆栈回溯,定位程序退出为005B0B27处,向上找出关键跳转为005B0A76 改为JMP。完成去自校验(如图2-16)
图2-16
2.2.4 爆破
如图2-16试用版不能保存密码,点击密码修改按钮,弹出提示,试用版不能保存密码。为了保存多个情况下的软件去自校验后的名字为ssozh.exe。
前面我们查壳的时候已经知道这款软件是用易语言写的,我们采用二进制字符串查找法,查找易语言的按钮事件(特征码 )FF55FC,然后找到关键代码即可实现注册。
具体过程如下:
第一步,直接在反汇编窗口的00401000处搜索特征码FF55FC,发现找不到,说明这个软件不是静态编译,而是动态编译的,因此我们需要到易语言下的运行库(krnln.fnr,注一般来说运行库(动态库)是dll格式的,易语言的运行库后缀不太一样)里面查找特征码。
第二步,因此我们先在OD中运行程序,打开模块窗口(Alt+E)或者点击上面的e按钮,找到krnln.fnr并回车,在CPU中查看代码(如图2-17)。并再次在CPU反汇编窗口查找二进制字符串FF55FC,找到相关代码段(代码2-3),第一行二进制代码就是\FF55FC,在这里设置断点。
图2-17 在模块中找到易语言的运行库
10028B46 |> \FF55 FC call [local.1] ; krnln.100E5948 10028B49 |. 5F pop edi ; user32.77D191BE 10028B4A |. 5E pop esi ; user32.77D191BE 10028B4B |. 895D F4 mov [local.3],ebx 10028B4E |. 8945 F8 mov [local.2],eax 10028B51 |. 8B55 E8 mov edx,[local.6] 10028B54 |. C782 0C020000>mov dword ptr ds:[edx+0x20C],0x0 10028B5E |. 837D F4 00 cmp [local.3],0x0 |
代码2-3
第三步,点击设置密码按钮,此时程序会运行到断点处停止,这里F7步入CALL,即找到关键代码处(代码2-4),代码2-4中005AE463地址显然这两行是一个if-else语句,在动态调试中表明会直接跳转到代码2-4最后一行005AE4AA,显然是无法设置密码,因此我们可以猜测,比较一定是关于是否注册的比较,而紧接着if成立就是已经注册的程序,不成立则是试用版。
如果想要实现设置密码,则可以直接对005AE463填充成nop。
。
005AE453 55 push ebp 005AE454 8BEC mov ebp,esp 005AE456 81EC 08000000 sub esp,0x8 005AE45C 833D F40CB600 0>cmp dword ptr ds:[0xB60CF4],0x0 005AE463 0F84 41000000 je ssozh.005AE4AA 005AE469 68 02000080 push 0x80000002 005AE46E 6A 00 push 0x0 005AE470 68 01000000 push 0x1 005AE475 68 01000100 push 0x10001 005AE47A 68 00000106 push 0x6010000 005AE47F 68 01000152 push 0x52010001 005AE484 68 01000100 push 0x10001 005AE489 68 CB000106 push 0x60100CB 005AE48E 68 CC000152 push 0x520100CC 005AE493 68 03000000 push 0x3 005AE498 BB 20030000 mov ebx,0x320 005AE49D E8 E4480000 call ssozh.005B2D86 ; 弹出密码窗口 005AE4A2 83C4 28 add esp,0x28 005AE4A5 E9 90000000 jmp ssozh.005AE53A 005AE4AA 68 02000080 push 0x80000002
|
代码2-4
重新运行程序,定位[0xB60674],下断硬件断点,重启程序,因为一开始内存中没有0xB60674这个地址使用,因此在多次执行到代码段005xxxxxx的时候找到这段代码在代码2-5的第三句。显然这段代码表示未注册的意思,我们向上找到跳转到这里的语句(第一句),我们把第一句nop掉,或把005AD381 代码处的0x0改为0x1,即可表示已经注册。
005AD31D /0F84 5E000000 je ssozh1.005AD381 005AD323 C705 F40CB600 0>mov dword ptr ds:[0xB60CF4],0x1 //关于注册的相关语句 … 005AD381 C705 F40CB600 0>mov dword ptr ds:[0xB60CF4],0x0 |
第三章 实验总结
3.1 实验结果总结
成功爆破后可以使用密码了。
3-1 设置密码
3.2 实验心得
写实验报告,自己实践是提升自我解决问题能力以及快速掌握一些知识点的良好途径,作为一名跨专业的学生,在本课程中学会了很多,感谢何老师的引领入门,感谢同学们的帮助,感谢网络上的各位网友的指导。