AlphaRom是日本游戏常用的保护方式,它的新版本比以前加强了不少。最近脱一个galgame的壳,略有心得,记录如下:

首先是反调试强度增加,在xp中用普通ollydbg也无法运行,可能是StrongOD和HideOD没调对选项吧。还好用nooby的ollydbg能正常运行。

其次是IAT加密,它把一大部分API的代码复制进自己分配的内存中去,并加上大量垃圾指令。如果事先在API的任何位置下了int 3断点的话,复制过程中就直接出错导致程序跳出。而如果在API下硬件断点,则经常无法断在需要的地方,因为程序本体执行API大部分都是去壳复制完的代码里执行。

以下是脱壳过程:

1.  运行AlphaRom激活工具alsignup_act_100723_110729.exe并运行游戏, 这样游戏就被激活,可以正常运行了。

2.  PEID显示连接器版本6.0,所以找GetVersion,把它的最后一个指令retn改成EB FE。然后运行一阵暂停看一眼,如果停在这个指令上就手动让函数返回。继续运行直到某次停在另外一个地址的EB FE上,这就是被壳复制过去的GetVersion,返回后上面的push ebp就是OEP了。

3.  找到OEP后以后只要在OEP上下硬件断点就可以停在OEP了。停在OEP上后可以dump,只需要头两个section就够了,后面5个都是壳的section。

4.  在dump下来的文件中搜索call [address]和jmp [address],也就是FF15和FF25开头的call和jmp,address限制在程序本体范围内。这可以写几句C完成。

5.  整理上面搜到的address,就是iat的thunks的地址。在importrec里手动填写iat的起始地址和大小,Get Imports后Save tree保存为iat.txt。注意这里如果叫importrec自动搜索iat的话搜不全。

6.  发现有一小部分iat是正确API地址,其他大多都是壳分配的地址,还有几个地址本身处于壳区段。

7.  首先解决在壳分配的地址里复制的API。先尝试hook GetVersion,让它用E9跳到一个空白处再跳回来。重新运行程序,惊喜地发现GetVersion对应的iat地址上直接变成了旧版AlphaRom里的jmp GetVersion。得出结论:API开头若是E9大跳,壳就不会复制代码了。通过对GetVersion开头下内存访问断点分析,找到了四个相关的跳转位置,写一个ODBGScript,负责在这四个跳转处改变eip,也就是让壳以为所有API的开头都是E9大跳转。不能直接在代码上patch,否则会出错跳出。完事后复制代码部分的iat就全得到了。ODBGScript如下:

lc
dbh

mov OEP, 43ab20
mov CHECK_1, 9692db
mov JUMP_1, 9695cd
mov CHECK_2, 965781
mov JUMP_2, 965868
mov CHECK_3, 967828
mov JUMP_3, 968443
mov CHECK_4, 968524
mov JUMP_4, 968540


bphws OEP, "x"

loop:

bphws CHECK_1, "x"
run
cmp eip, CHECK_1
jne end
mov eip, JUMP_1
bphwc CHECK_1

bphws CHECK_2, "x"
run
cmp eip, CHECK_2
jne end
mov eip, JUMP_2
bphwc CHECK_2

bphws CHECK_3, "x"
run
cmp eip, CHECK_3
jne end
mov eip, JUMP_3
bphwc CHECK_3

bphws CHECK_4, "x"
run
cmp eip, CHECK_4
jne end
mov eip, JUMP_4
bphwc CHECK_4

jmp loop

end:
cmp eip, OEP
jne final
log "Finished"

final:

8.  注意,此时得到的API中有ntdll里的,要把这些换成对应的kernel32里的API。在dump下来的文件中,iat的thunks的地址后面一点就有全部的API名字与dll名字,把API名字整理出来,找出现在iat.txt中不存在的,然后就可以轻易找出ntdll函数与kernel32函数的对应。这种对应比如像ntdll.RtlFreeHeap其实是kernel32.HeapFree。

9.  然后还剩5个壳区段中的iat,这些都是复制的API。这个并没有被前面的脚本简化,应该是壳在不同的地方进行的复制。通过与剩下的名字对比,并查看调用它们的地方,很容易根据参数个数和种类猜出来。

10. 最后用importrec来Load tree,加载修改过的iat.txt,Fix dump,脱壳就完成了。