首页
社区
课程
招聘
Arm3.70a with IAT Elimination脱壳
发表于: 2004-10-25 18:48 10868

Arm3.70a with IAT Elimination脱壳

2004-10-25 18:48
10868

好久没怎么脱过壳,最近碰到一个软件是用arm加的壳,用到了arm的输入表乱序和远地址跳转,只有找些资料来补课,略有些心得,还望指正。

下面以某软件为例,这个是arm3.70a加的壳,单进程,用了输入表乱序和远地址跳转。某软件已经是双进程CC壳了,还不敢碰,:(

第1部分:准备工作&抵达OEP

先需要找到一些基本数据
1. OEP
设断点he SetProcessWorkingSetSize断下后再设断点he GetCurrentThreadId
断下后,Ctrl+F9返回,去除这两个断点,向下看,看到那个call edi了没,在按F2那里设个断点
断下后,F7跟入,就来到OEP了
记住: OEP=004E8850

2. magicjump
好几个地方修改跳转都可以放置arm破坏输入表的,都可以称之为magicjump
来看arm处理输入表的流程
先将一些预设的api经过处理
然后在读入输入表时候,比较api名称是否为壳中处理过的api名称
如果相同则将该地址指向壳中的函数地址,程序所得到的地址就指向壳里了,importRec就识别不出该

api了

这个虽然代码比较长,不过流程还算清楚,可以跟上几遍就大概知道是怎么回事了
因为相关文章比较多,这里简单看一下

00DC96FD    8D85 B4FEFFFF   LEA EAX,DWORD PTR SS:[EBP-14C]
00DC9703    50              PUSH EAX
00DC9704    FF15 C8B0DE00   CALL DWORD PTR DS:[DEB0C8]               ;

kernel32.GetModuleHandleA
00DC970A    8B0D C04CDF00   MOV ECX,DWORD PTR DS:[DF4CC0]
00DC9710    89040E          MOV DWORD PTR DS:[ESI+ECX],EAX
00DC9713    A1 C04CDF00     MOV EAX,DWORD PTR DS:[DF4CC0]
00DC9718    393C06          CMP DWORD PTR DS:[ESI+EAX],EDI
00DC971B    75 16           JNZ SHORT 00DC9733
00DC971D    8D85 B4FEFFFF   LEA EAX,DWORD PTR SS:[EBP-14C]
00DC9723    50              PUSH EAX
00DC9724    FF15 D0B0DE00   CALL DWORD PTR DS:[DEB0D0]               ;

kernel32.LoadLibraryA
00DC972A    8B0D C04CDF00   MOV ECX,DWORD PTR DS:[DF4CC0]
00DC9730    89040E          MOV DWORD PTR DS:[ESI+ECX],EAX
00DC9733    A1 C04CDF00     MOV EAX,DWORD PTR DS:[DF4CC0]
00DC9738    393C06          CMP DWORD PTR DS:[ESI+EAX],EDI
00DC973B    0F84 AD000000   JE 00DC97EE                           //magicjump 记录该地址


00DC9741    33C9            XOR ECX,ECX

如果是dll可能还需要更改这个地址,od载入dll基地址为10000000,而输入表在该地址以下
造成在ImportRec设不了IAT RVA地址

00DE489D    8B85 1CE8FFFF   MOV EAX,DWORD PTR SS:[EBP-17E4]       //保存当前IAT指针
00DE48A3    8B8D 80E2FFFF   MOV ECX,DWORD PTR SS:[EBP-1D80]
00DE48A9    8908            MOV DWORD PTR DS:[EAX],ECX            //一个api地址写入IAT
00DE48AB    8B85 1CE8FFFF   MOV EAX,DWORD PTR SS:[EBP-17E4]
00DE48B1    83C0 04         ADD EAX,4
00DE48B4    8985 1CE8FFFF   MOV DWORD PTR SS:[EBP-17E4],EAX
对[EBP-17E4]来设内存写断点,可以找到这里
00DE453B    8B8D F0E6FFFF   MOV ECX,DWORD PTR SS:[EBP-1910]       //保存IAT的首地址,记录

该地址值00E9A880
00DE4541    8D0481          LEA EAX,DWORD PTR DS:[ECX+EAX*4]
00DE4544    8985 1CE8FFFF   MOV DWORD PTR SS:[EBP-17E4],EAX       //载入下一个dll的IAT中

首地址

3.antidump
OD把原代码中一些代码,jmp较高的地址了 如jmp 03171000,造成lordpe dump文件时候,这段代码丢

失,
该地址是不是固定的。
可以直接下断VirtualAlloc,查看申请地址值,如果比较大就需要注意了,返回后代码类似下面
00DE2612    6A 40           PUSH 40
00DE2614    68 00200000     PUSH 2000
00DE2619    FFB5 70E6FFFF   PUSH DWORD PTR SS:[EBP-1990]
00DE261F    FF35 3092DF00   PUSH DWORD PTR DS:[DF9230]
00DE2625    FF15 A0B1DE00   CALL DWORD PTR DS:[DEB1A0]               ;

kernel32.VirtualAlloc
00DE262B    8985 78E6FFFF   MOV DWORD PTR SS:[EBP-1988],EAX
00DE2631    83BD 78E6FFFF 0>CMP DWORD PTR SS:[EBP-1988],0
00DE2638    74 33           JE SHORT 00DE266D
00DE263A    6A 40           PUSH 40
00DE263C    68 00100000     PUSH 1000
00DE2641    FFB5 70E6FFFF   PUSH DWORD PTR SS:[EBP-1990]
00DE2647    FF35 3092DF00   PUSH DWORD PTR DS:[DF9230]
00DE264D    FF15 A0B1DE00   CALL DWORD PTR DS:[DEB1A0]               ;

kernel32.VirtualAlloc
00DE2653    8985 78E6FFFF   MOV DWORD PTR SS:[EBP-1988],EAX          //保存codesplit 首地

址 在这里断下修改eax值到一较低地址我选择写到arm的adata节

00DE2659    83BD 78E6FFFF 0>CMP DWORD PTR SS:[EBP-1988],0
00DE2660    74 0B           JE SHORT 00DE266D

记录CodeSplit addr=00DE2653

4. 用脚本来走到OEP
因为要修改的地方比较多,而且后面我们调试脚本难免要重复工作,所以还是写个od脚本吧,可以节省点体力 :)
因为要向rdata段写IAT数据,所以先将该段内存设为可写
Memory窗口选中该段,右键set access ->full access

//脚本1,直达OEP,顺便处理magicjump和antidump
var NewIatHead
var NewSplitCodeHead
var SetIatHead
var SetSplitCodeHead
var IatOver
var MagicJmp
var OEP

var bSplitCodeOver
var bIatOver
var pTempAddr

var VirtualAlloc


//需要填入的信息内容
mov NewIatHead, 5CA000
mov NewSplitCodeHead, 674000
mov MagicJmp, 00DC973B
mov SetIatHead, 00DE453B
mov IatOver, 00DE498E
mov SetSplitCodeHead, 00DE2653
mov OEP, 004E8850


//变量初始化
mov bIatOver, 0
mov bSplitCodeOver, 0

//获得VirtualAlloc首地址
gpa "VirtualAlloc", "kernel32.dll" 
mov VirtualAlloc, $RESULT

BPHWS VirtualAlloc, "x"
run
BPHWC VirtualAlloc

//此时,壳内存代码已分配
//开始设断点
BPHWS MagicJmp, "x"  //magicjump之处
//BPHWS 00994704, "x"  写入内存时
BPHWS SetIatHead, "x"  //载入输入表首地址时候
BPHWS IatOver, "x"  //处理完所有dll
BPHWS SetSplitCodeHead, "x"  //申请高位内存处,需更改返回eax为一段低位内存 

eoe _Exception
eob _Break
run 

//遇例外继续执行
_Exception: 
esto
 
//处理断点中断
_Break:
cmp eip, SetIatHead
je _SetIatHead
cmp eip, MagicJmp
je _MagicJmp
cmp eip, IatOver
je _IATOver
cmp eip, SetSplitCodeHead
je _SetSplitCodeHead
jmp _InvalidBreak


//设置新的IAT首地址
/*
00DE453B    8B8D F0E6FFFF   MOV ECX,DWORD PTR SS:[EBP-1910]       //保存IAT的首地址
00DE4541    8D0481          LEA EAX,DWORD PTR DS:[ECX+EAX*4]
00DE4544    8985 1CE8FFFF   MOV DWORD PTR SS:[EBP-17E4],EAX       //当前IAT指针
*/
_SetIatHead:
mov pTempAddr, ebp
sub pTempAddr, 1910          //看上面数据
mov [pTempAddr], NewIatHead
log NewIatHead
BPHWC SetIatHead
run 

//修改magicjump, 来得到原始的IAT
_MagicJmp:
mov !ZF, 1     //修改magicjump
run 

//maigcjump处理完毕
_IATOver:
BPHWC MagicJmp
BPHWC IatOver
mov bIatOver, 1
cmp bSplitCodeOver,1
je _FixOver
run 

//设置新的保存CodeSplit代码的首地址
/*
00DE263A    6A 40           PUSH 40
00DE263C    68 00100000     PUSH 1000
00DE2641    FFB5 70E6FFFF   PUSH DWORD PTR SS:[EBP-1990]
00DE2647    FF35 3092DF00   PUSH DWORD PTR DS:[DF9230]
00DE264D    FF15 A0B1DE00   CALL DWORD PTR DS:[DEB1A0]               ; 

kernel32.VirtualAlloc
00DE2653    8985 78E6FFFF   MOV DWORD PTR SS:[EBP-1988],EAX          //保存antidump首地址
00DE2659    83BD 78E6FFFF 0>CMP DWORD PTR SS:[EBP-1988],0
00DE2660    74 0B           JE SHORT 00DE266D
*/
_SetSplitCodeHead:
mov eax, NewSplitCodeHead
mov bSplitCodeOver, 1
BPHWC SetSplitCodeHead
cmp bIatOver,1
je _FixOver
run 

//其它未处理的断点
_InvalidBreak:
log eip
msg "Invalid Break"
ret



//IAT,AntiDump处理完毕
//准备跳往OEP
_FixOver:
eoe _Continue
eob _End
BPHWS OEP, "x"
run

_Continue: 
esto 

_End:
BPHWC OEP
msg "Success!"
ret


[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

收藏
免费 7
支持
分享
最新回复 (18)
雪    币: 898
活跃值: (4039)
能力值: ( LV9,RANK:3410 )
在线值:
发帖
回帖
粉丝
2
GOOD   辛苦  :D
2004-10-25 18:56
0
雪    币: 205
活跃值: (12)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
好文。
2004-10-25 19:25
0
雪    币: 124
活跃值: (107)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
4
顶。
2004-10-25 19:31
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
nice tut...
keep up good work..:)
2004-10-25 19:59
0
雪    币: 383
活跃值: (786)
能力值: ( LV12,RANK:730 )
在线值:
发帖
回帖
粉丝
6
Yeah, 期代你对付 CC :D
2004-10-25 20:30
0
雪    币: 223
活跃值: (106)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
7
老大很久不上,一上来就是好文呀!:D
2004-10-25 20:42
0
雪    币: 282
活跃值: (233)
能力值: ( LV9,RANK:210 )
在线值:
发帖
回帖
粉丝
8
谢谢,无私的奉献
2004-10-25 20:45
0
雪    币: 494
活跃值: (629)
能力值: ( LV9,RANK:1210 )
在线值:
发帖
回帖
粉丝
9
强!
2004-10-25 20:46
0
雪    币: 250
活跃值: (105)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
佩服,收下。 arm新版是越来越烦。
2004-10-26 02:10
0
雪    币: 282
活跃值: (233)
能力值: ( LV9,RANK:210 )
在线值:
发帖
回帖
粉丝
11
老大什么时候能看看双进程的,比如Arm375a1.exe,我用kernel32.VirtualAlloc函数什么有用的东西也没拦到,而且它把代码段用异或加密了,而且改变magicjump跳转后,一部分代码也丢失了,我脱出来了,也修复了cc,但是一压缩文件就出错,如下图:
老大能帮忙看看吗?
2004-10-26 10:28
0
雪    币: 323
活跃值: (589)
能力值: ( LV12,RANK:450 )
在线值:
发帖
回帖
粉丝
12
呵呵,很久没能见到你的大作啦,强烈支持一下!
2004-10-26 11:35
0
雪    币: 251
活跃值: (260)
能力值: ( LV12,RANK:210 )
在线值:
发帖
回帖
粉丝
13
最初由 wangli_com 发布
老大什么时候能看看双进程的,比如Arm375a1.exe,我用kernel32.VirtualAlloc函数什么有用的东西也没拦到,而且它把代码段用异或加密了,而且改变magicjump跳转后,一部分代码也丢失了,我脱出来了,也修复了cc,但是一压缩文件就出错,如下图:
老大能帮忙看看吗?

这个对我还太难了,:(
这位xDREAM发布了arm3.75a的破解,也许你可以和他联系讨论一下 :)
http://www.exetools.com/forum/showthread.php?t=5681
2004-10-26 20:03
0
雪    币: 241
活跃值: (160)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
14
顶一下,慢慢看
2004-10-26 21:43
0
雪    币: 220
活跃值: (55)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
15
收藏阿!谢谢yesky1大哥
2004-10-27 10:15
0
雪    币: 236
活跃值: (74)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
16
最初由 yesky1 发布

这个对我还太难了,:(
这位xDREAM发布了arm3.75a的破解,也许你可以和他联系讨论一下 :)
http://www.exetools.com/forum/showthread.php?t=5681


能贴一份过来吗?
2004-10-27 18:24
0
雪    币: 220
活跃值: (55)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
17
多谢yesky1大哥的指导和Ricardo的教程,Ricardo的教程确实写得很透彻,从中学到了不少分析方法,但是在看他的乱序iat修复方法时,觉得很费解(其实是没看懂,哈哈)。觉得既然我们可以得到正确的iat表和call/jmp地址表,那么为什么不直接修复iat呢?尝试写了个修复脚本,跟yesky1大哥一样都是用要用到call/jmp地址表,具体方是:在修改magic jmp,arma把iat的所有api地址还原后,并且在arma把iat混乱前(这个位置可以取magic jmp后有一个往前跳的大jmp的下一条指令),把正确的iat拷下来,放到一个无用空间,然后call/jmp地址表也一样处理,运行到oep处,这时jmp dword ptr[xxxxxxx]的xxxxxxx是乱序iat中的一个地址,我们读取该api地址值,然后在正确的iat表里面找,找到后就把xxxxxxxx替换成该api地址在正确iat表里的地址。脚本如下:

======================================================================
/*
在oep运行该脚本。
运行前必须先得到一张正确的iat表和远地址jmp/call地址表
*/

var imagebase
var iat_table
var jmp_table
var piat
var pjmp
var viat
var vjmp
var temp
var oldpiat

gmi eip,MODULEBASE     //获得基地址
mov imagebase,$RESULT
log imagebase

ask "new iat table:"
cmp $RESULT,0
je error
mov iat_table,$RESULT  //iat_table:正确iat的地址.修改magic jmp后,并且被乱序之前得到的iat
log iat_table

ask "new jmp table:"
cmp $RESULT,0
je error
mov jmp_table,$RESULT //复制的call调用表的地址,在文中是00E92000
log jmp_table

mov pjmp,jmp_table   //取jmp table的首地址
jmp loop1

loop0:
add pjmp,4          //下一个jmp的地址

loop1:
mov vjmp,[pjmp]     //取jmp table的一个值,就是一个jmp的地址索引
cmp vjmp,0          //如果0,结束
je finish
add vjmp,imagebase  //加上基地址就是该jmp的VA
mov piat,iat_table  //取得新的iat首地址
jmp loop2

loop21:
add piat,4          //下一个api地址指针

loop2:
mov viat,[piat]     //得到api地址
cmp viat,ffffffff   //如果ffffffff结束。注意,该脚本是通过iat中api指针为ffffffff,
                    //判断是否结束,所以要保证iat结束处是ffffffff,并且iat中间不能有ffffffff
je loop0
mov temp,[vjmp]    //得到乱序iat中队应api地址的指针
mov oldpiat,temp   
mov temp,[temp]    //得到api地址
cmp temp,viat      //上面的到api地址与正确的iat表的每一个api地址进行比较,
jne loop21
mov [vjmp],piat   //如果相等就修改。这样就可以对每一个远地址jmp和call进行修复
log oldpiat       //修复前的api地址指针(在乱序的iat表内)
log piat          //修复后的api地址指针(在新的iat表内)
jmp loop0

finish:
msg "finish"
jmp end

error:
msg "error"

end:
ret
==========================================================================
这样会省点功夫,不过运行脚本会挺耗时,耐心等等。

小弟刚接触armadillo不久,当时是为了破解一个叫prtg v4.0.7.139软件,拜读了无数篇破文,在搞定了
debug-blocker,code splicing和import table elimination后,用ollydby装入,发现还加了CC:

0069F13E     E8 7163D6FF         call dumped_.004054B4
0069F143     CC                  int3
0069F144     7A 8D               jpe short dumped_.0069F0D3
0069F146     45                  inc ebp
0069F147     F8                  clc
0069F148     BA 04F36900         mov edx,dumped_.0069F304                  ; ASCII " (Site License)"
0069F14D     E8 EE5FD6FF         call dumped_.00405140

看了fxyang的《UltraEdit-32 10.20版脱壳记》还是不理解,各位大哥可否再指点一下啊?先谢了

2004-10-27 18:49
0
雪    币: 217
活跃值: (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
18
可以自己在oep前模拟这段混乱代码
2004-11-4 08:37
0
雪    币: 161
活跃值: (231)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
19
有没有脱壳机啊?
2004-11-4 13:34
0
游客
登录 | 注册 方可回帖
返回
//