【文章标题】: Riijj crackme 12 的调试分析
【文章作者】: LvG
【作者邮箱】: LvG2008@gmail.com
【下载地址】: http://bbs.pediy.com/showthread.php?s=&threadid=38692
【保护方式】: 驱动,加密算法
【使用工具】: OD,IDA
【作者声明】: 只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!
--------------------------------------------------------------------------------
【详细过程】
Riijj的这个CrackMe,其难点是用到了驱动,比较感兴趣,于是生成了此文。
本文分成三部分:1.观察主程序的特点,释放驱动。2.修改驱动属性,使可以用OD解码。3.用OD解码,找到关键算法。
一.观察主程序,释放驱动
用OD打开riijjcm12.exe,停在入口处。此时点击鼠标右键:查找――〉所有参考文本字串,在新的窗口中可以看到thing.sys字样,
就在这里下断,并在反汇编窗口中跟随。F9运行,立刻断下。如下图:
004012A2 |. 68 48A94000 push 0040A948 ; /Buffer = riijjcm1.0040A948
004012A7 |. 68 04010000 push 104 ; |BufSize = 104 (260.)
004012AC |. FF15 28704000 call dword ptr [<&KERNEL32.GetTemp>; \GetTempPathA
004012B2 |. 68 80804000 push 00408080 ; ASCII "thing.sys"
004012B7 |. 68 48A94000 push 0040A948 ; ASCII "C:\DOCUME~1\new\LOCALS~1\Temp\"
004012BC |. E8 CF060000 call <_strcat>
004012C1 |. 83C4 08 add esp, 8
004012C4 |. 68 8C804000 push 0040808C ; ASCII "wb"
004012C9 |. 68 48A94000 push 0040A948 ; ASCII "C:\DOCUME~1\new\LOCALS~1\Temp\"
004012CE |. E8 91060000 call <_fopen>
004012D3 |. 83C4 08 add esp, 8
004012D6 |. 8945 EC mov dword ptr [ebp-14], eax
004012D9 |. 8B45 EC mov eax, dword ptr [ebp-14]
004012DC |. 50 push eax
004012DD |. 6A 01 push 1
004012DF |. 8B4D F0 mov ecx, dword ptr [ebp-10]
004012E2 |. 51 push ecx
004012E3 |. 8B55 F8 mov edx, dword ptr [ebp-8]
004012E6 |. 52 push edx
004012E7 |. E8 4E050000 call <_fwrite>
004012EC |. 83C4 10 add esp, 10
004012EF |. 8B45 EC mov eax, dword ptr [ebp-14]
004012F2 |. 50 push eax
004012F3 |. E8 EC040000 call <_fclose>
从上面可以看出,先用GetTempPathA函数获得Temp目录,然后释放thing.sys文件,在向thing.sys写入内容。当执行完_fclose函数后
就可以得到完整的thing.sys驱动文件。那么是在什么地方打开这个驱动的呢?继续往下跟,先是创建窗口的一系列函数,直到如下:
00401540 /$ 55 push ebp
00401541 |. 8BEC mov ebp, esp
00401543 |. 83EC 4C sub esp, 4C
00401546 |. C745 DC 00000>mov dword ptr [ebp-24], 0
0040154D |. 6A 02 push 2
0040154F |. 6A 00 push 0
00401551 |. 6A 00 push 0
00401553 |. FF15 18704000 call dword ptr [<&ADVAPI32.OpenSCM>; ADVAPI32.OpenSCManagerA
00401559 |. 8945 FC mov dword ptr [ebp-4], eax
0040155C |. 837D FC 00 cmp dword ptr [ebp-4], 0
00401560 |. 75 0A jnz short 0040156C
00401562 |. B8 01000000 mov eax, 1
00401567 |. E9 FA000000 jmp 00401666
0040156C |> 68 FF010F00 /push 0F01FF
00401571 |. 68 AC804000 |push 004080AC ; ASCII "rc12"
00401576 |. 8B45 FC |mov eax, dword ptr [ebp-4]
00401579 |. 50 |push eax
0040157A |. FF15 1C704000 |call dword ptr [<&ADVAPI32.OpenSe>; ADVAPI32.OpenServiceA
00401580 |. 8945 D8 |mov dword ptr [ebp-28], eax
00401583 |. 8D4D E0 |lea ecx, dword ptr [ebp-20]
00401586 |. 51 |push ecx
00401587 |. 6A 01 |push 1
00401589 |. 8B55 D8 |mov edx, dword ptr [ebp-28]
0040158C |. 52 |push edx
0040158D |. FF15 14704000 |call dword ptr [<&ADVAPI32.Contro>; ADVAPI32.ControlService
00401593 |. 8945 B4 |mov dword ptr [ebp-4C], eax
00401596 |. 8B45 D8 |mov eax, dword ptr [ebp-28]
00401599 |. 50 |push eax
0040159A |. FF15 10704000 |call dword ptr [<&ADVAPI32.Delete>; ADVAPI32.DeleteService
004015A0 |. 8945 B4 |mov dword ptr [ebp-4C], eax
004015A3 |. 8B4D D8 |mov ecx, dword ptr [ebp-28]
004015A6 |. 51 |push ecx
004015A7 |. FF15 0C704000 |call dword ptr [<&ADVAPI32.CloseS>; ADVAPI32.CloseServiceHandle
可见是用服务控制管理器(SCM)动态添加服务,具体的方法就不谈了,这只是crack,又不是逆向,呵呵。。
二.修改驱动文件属性,使可以用OD解码
在第一步中我们已得到了thing.sys驱动,加密算法就在其中,下来就是分析thing.sys的时候了。用IDA加载,来到入口处:
.riijj:000109A0 start proc near
.riijj:000109A0
.riijj:000109A0 arg_0 = dword ptr 8
.riijj:000109A0
.riijj:000109A0 push esi
.riijj:000109A1 call sub_109D6
.riijj:000109A6 mov eax, [esp+arg_0]
.riijj:000109AA mov ecx, offset loc_108BE
.riijj:000109AF push eax
.riijj:000109B0 mov dword ptr [eax+34h], offset sub_1088A
.riijj:000109B7 mov dword ptr [eax+44h], offset sub_108EF
.riijj:000109BE mov [eax+40h], ecx
.riijj:000109C1 mov [eax+38h], ecx
.riijj:000109C4 call loc_107F6
.riijj:000109C9 mov esi, eax
.riijj:000109CB call near ptr loc_1052F+1
.riijj:000109D0 mov eax, esi
.riijj:000109D2 pop esi
.riijj:000109D3 retn 8
.riijj:000109D3 start endp ; sp = -4
这个入口处很简单,只有三个call。第一个call现不看,第二个和第三个call跟进,发现除了极个别的函数外,简直混乱一团,
很显然是被加密了。这也可以从向导条目上看出来,开始一段是灰色和红色,表明IDA没分析出来,是有问题的。那么是谁加密的呢?
这是我把目光集中到了第一个call上。跟进后:
sub_109D6 proc near ; CODE XREF: start+1p
.riijj:000109D6
.riijj:000109D6 var_5 = byte ptr -5
.riijj:000109D6 var_4 = dword ptr -4
.riijj:000109D6
.riijj:000109D6 push ecx
.riijj:000109D7 push ecx
.riijj:000109D8 push ebp
.riijj:000109D9 push esi
.riijj:000109DA push edi
.riijj:000109DB mov edi, offset dword_102C0
.riijj:000109E0 mov esi, edi
.riijj:000109E2 mov edx, edi
.riijj:000109E4 sub esi, 2C0h
.riijj:000109EA mov eax, edi
.riijj:000109EC lea ebp, [esi+850h]
.riijj:000109F2 cmp ebp, edi
.riijj:000109F4 jbe short loc_10A08
发现“riijj:000109DB mov edi, offset dword_102C0”,把102c0的地址放到edi,然后就是一系列的加减乘除和循环,有什么
意图?聪明的你应该猜到了,是把核心代码加密了。下来咋办,分析函数sub_109D6,然后写个脚本解码吗?勤快的你当然可以,
但我是个懒人啊。懒人自由懒人的办法,呵呵。。
由于驱动也是PE文件,但其加载在载在ring0,调用内核函数,用OD是无法正常加载的。不过可以对他进行一定的修改,就可用
OD蹂躏了。
(1)用LoadPe――〉PE Editor――〉把Subsystem由0001改为0002,让OD以为是GUI程序。
(2)...........................〉Characteristics――〉如果有dll选项,也去掉。这个没有。
(3)...........................>Directory――〉把输入表的RVA和Size都改为0,注意要记住原值(rva:be0;size:208),以便dump后恢复!
经过上面的修改(可别忘了保存!)后就可以用OD加载了。
三.用OD解码,找到关键算法代码
用OD载入后,
000109A0 >/$ 56 push esi
000109A1 |. E8 30000000 call 000109D6
000109A6 |. 8B4424 08 mov eax, dword ptr [esp+8]
000109AA |. B9 BE080100 mov ecx, 000108BE
看到第二行的call了吗,这是解码函数。先不要急,向上拉,可以看到:
000102C0 /$ 8C51 37 mov word ptr [ecx+37], ss
000102C3 |. 8D8C55 9AD8B8>lea ecx, dword ptr [ebp+edx*2+12B8D8>
000102CA |? 230C2A and ecx, dword ptr [edx+ebp]
000102CD |? 295E 8D sub dword ptr [esi-73], ebx
000102D0 |? C141 8E C4 rol dword ptr [ecx-72], 0C4
000102D4 |. 54 push esp
000102D5 |. 47 inc edi
000102D6 |? 8A38 mov bh, byte ptr [eax]
000102D8 |. 4C dec esp
000102D9 |? 873B xchg dword ptr [ebx], edi
000102DB |. 94 xchg eax, esp
000102DC |. AF scas dword ptr es:[edi]
000102DD |? C6 ??? ; 未知命令
000102DE |. AD lods dword ptr [esi]
000102DF |? F8 clc
000102E0 |.- 70 AF jo short 00010291
000102E2 |? 07 pop es
000102E3 |. 03E8 add ebp, eax
000102E5 |? D6 salc
000102E6 |? F4 hlt
000102E7 |? F1 int1
000102E8 |? F1 int1
000102E9 |. 3B31 cmp esi, dword ptr [ecx]
000102EB ? F0:F5 lock cmc ; 不允许锁定前缀
000102ED 3AA2 63058014 cmp ah, byte ptr [edx+14800563]
F8后变成:
000102C0 /$ 55 push ebp
000102C1 |. 8BEC mov ebp, esp
000102C3 |. 51 push ecx
000102C4 |. 51 push ecx
000102C5 |. 8B45 08 mov eax, dword ptr [ebp+8]
000102C8 |. 69C0 F0D8FFFF imul eax, eax, -2710
000102CE |. 8945 08 mov dword ptr [ebp+8], eax
000102D1 |. 8B45 08 mov eax, dword ptr [ebp+8]
000102D4 |. 99 cdq
000102D5 |. 8945 F8 mov dword ptr [ebp-8], eax
000102D8 |. 8D45 F8 lea eax, dword ptr [ebp-8]
000102DB |. 50 push eax
000102DC |. 6A 00 push 0
000102DE |. 6A 00 push 0
000102E0 |. 8955 FC mov dword ptr [ebp-4], edx
000102E3 |. FF15 280B0100 call dword ptr [10B28]
000102E9 |. C9 leave
000102EA \. C2 0400 retn 4
000102ED CC int3
怎么样变得很整齐了吧!
接下来就可以dump了,用OllyDump插件,注意dump时去掉"Rebuild Import"选项。我dump并命名为riijj.exe。
将riijj.exe的属性恢复(还记得在第二步中的修改吗,现在要全部恢复),用IDA载入分析。载入后发现,原来灰白和红色的导航条
变成了绿色(多舒服的颜色^_~)。
在字符串中,发现有注册成功(sucess..)字符串,一只向上找发现大体经历了start---->sub_10530---->startroutine---->sub_103c6
------>sub_102ee------>sub_10746。注册函数应该就是sub_10746了,无奈自己是算法盲,就不分析了还要向riijj等强人学习阿。
by LvG(吕歌)
--------------------------------------------------------------------------------
【经验总结】
从这个crackme分析看来,riijj大虾只是在尝试驱动加密的一般方法。如果把主程序的关键部分加密,再加上vm等,其难度就非我等菜鸟能企及的了。
--------------------------------------------------------------------------------
【版权声明】: 本文原创于看雪技术论坛, 转载请注明作者并保持文章的完整, 谢谢!
2007年03月12日 15:58:26
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!