-
-
学习脱壳穿山甲Armadillo 4.30a 的详细笔记
-
发表于: 2024-9-16 19:05 8953
-
学习脱壳穿山甲Armadillo 4.30a 的详细笔记
原文https://bbs.kanxue.com/thread-250085.htm
需要用到的工具,Xp虚拟机,ArmaFP(查看壳的版本),dillodie1.6(脱壳机),吾爱OD,IDA8.3,脱壳程序(见附件),Beyond Compare(比较工具),LordPE,improtRec。
0x01. 了解 Code Splicing
首先将脱壳程序GameJack.exe拖到打开的ArmaFP32中
可以看到保护设置只有Strategic Code Splicing ,中文意思就是叫做代码拼接,刚看到这个意思表示有疑问,网上搜了一大堆都是讲怎么处理,没有讲他的实现是怎么样的,于是我用MASM32写了一个非常简单的小程序让Armadillo 4.4加壳,保护设置只选Code Splicing,
0x02 设置OD
分析完Code Splicing 的原理后开始第一步设置好调试器,StrongOD这样设置,Skip Some Exceptions 这个中文意思是跳过一些异常,Od也有自带的忽略异常,但是使用OD的忽略异常调试不了,所以按照以下设置
还有硬件断点需要保护起来,OD插件-》Drx-Protect-》Config-》Drx勾上
补充一下硬件断点对话框的使用,
0x03 寻找OEP
看过上一篇文章的朋友知道,Asprotect壳找OEP用最后一次异常代码段下断点法,在这里是行不通的,我这边没有使用原文的方法,我的思路是,程序都会把自己的代码放到内存中去执行,接着解密完宿主程序之后跳回宿主程序的OEP去执行,所以第一步先找到包含执行代码的这段内存,我们就在命令行下HE kernel32.VirtualAlloc,下硬件断点是因为有对函数头部F2断点的检测,接着F9,断下看看堆栈中VirtualAlloc 的参数 Size 等于 65000 这个大小像是一个可执行文件的大小,我猜测这应该是为存放代码开辟的一段内存,然后ALT+F9,可以看到EAX等于0,返回值等于0,说明没成功。继续F9跟前面一样看看EAX,这时候EAX,有值了,我的是00DC0000,你们的可能不一样,查看00DC0000这个地址的内存数据都是0,这时候说明内存申请成功,接下去就是要写入数据了,然后我们在命令行给这个地址下个硬件写入断点HW 00DC0000 ,F9,程序断在了004E43B3,
查看此时ECX的值,很小,显然这一句代码运行完,这段内存还没写完,还有其他地方往这边写入数据,这时候不去找其他地方往这片内存写数据,直接F9运行,接着断下这时候大概率这片内存已经数据完全写入了,删除硬件断点,ALT+M,查看内存找到00DC0000 这个段下F2断点,
程序断下了,在00DC0000 这个段内,
接着在代码段下F2断点,F9,这时候断在了00DF0338,
然后F7一直单步走,当走到00DF039B的时候,
再单步一次来到了代码段,也就是OEP,
0x04 修复IAT
找到OEP之后我们看看有没有IAT加密,往下寻找,找到
有硬编码的地址的指令,dd 0x47B4F8 ,
可以看到
两个模块之前的分隔00000000,变成了00DD6E36,可以看到IAT被做了手脚,到目前为止Code Splicing 线索还没有找到,从开头了解到类似JMP XXXXXXXX,XXXXXXXX代表一个内存地址,我们先修复IAT,接着再寻找Code Splicing,首先先确定一下IAT,IAT是一段存放API地址的一段数据,不同的模块之前用00000000隔开,这段IAT开始的地方是47A000,结束的地方是47B990。大小0x1990,我们CTRL+F2重新运行程序,在IAT开头下个硬件写入断点HW 47A000看看壳对IAT做了什么,F9运行,程序断下了,ALT+F9执行到用户代码,在数据窗口可以看到,在00DECC56断下
继续F9运行,在
这时候47A000的值为00DDA6F4,dd 00DDA6F4 数据窗口中跟随,然后反汇编,
可以看到IAT函数被替换了,接着我们在这一句,
下个F2断点,F9运行,断下,重复这样的操作,IAT在一个一个的解密,这时候我们要做到知己知彼,百战不胜。就需要看看IAT哪里加密了,因为最后我们还原iat后面需要对比是不是都还原了,这个壳已经有脱壳机了,所以我们可以拿到他的脱壳后的文件,打开dilloDIE.exe,
把 For Strategic Code Splicing 勾上,点击UnPack,选择目录下Gamejack,打开,这时候脱壳机对其脱壳,完成后会得到GameJack.exe.dDIE.exe,这个就是脱壳后的文件了。接下去就是分别打开脱壳后的,和没脱壳的,程序在OD上运行,然后复制他们的IAT表用Beyond Compare做对比,这边是对比后的样子,
这些就是被加密的IAT函数,被加密后这些API地址会变成别的地址。所以咱们需要还原IAT,就需要了解壳是如何还原IAT的,首先需要找到往IAT写入数据的地方,
地址00DECC54(这个地址在你们机器上可能不一样)上mov dword ptr ds:[eax],ecx 这个指令就是,经过多次调试发现,IAT最终解密都是在这个地址完成的,这样我们可以重新运行程序,在0047A000 这个地址下个硬件写入断点,F9运行,这时第一次断下,
接着就要执行00DECC54上mov dword ptr ds:[eax],ecx这个指令,最终还原IAT了,我们可以在OD上看看00DECC54上代码有没被解密,可以看到
还没解密,因为这个壳反调试方面做得还算很严密的,很多代码都是运行前是加密的,运行后又加密,而且还有校验,我们下个硬件写入断点HW 00DECC54,F9运行,程序断下,我们删掉硬件断点,在00DECC54上mov dword ptr ds:[eax],ecx,这条指令上下个F2断点,F9运行,程序断下,这时候F7单步一下,数窗口中查看EAX的值,
这就是恢复IAT表的开始,不是自上而下恢复的,这个很重要,记住这个地址0047A8C0,接下来我们找个没有恢复IAT函数的地址分析,就选0047A018这个地址,下断点的话要下HW 0047A014,F9运行,程序断在了00DECC56,
F8单步走,走到00DECC5F的时候,此时Eax等于0047A018,这时候就是要去还原0047A018这个地址的IAT,当然这边是没有还原而是用别的函数代替,我们的任务是要还原,所以我们一边F8一边分析,
我猜测将00DECAA3 75 11 jnz short 00DECAB6 ,这个地址的代码改成
00DECAA3 75 11 jmp short 00DECAB6 ,是不是就可以还原IAT了,
这时我们重新载入程序,在刚刚记住的这个地址0047A8C0下硬件写入断点HW 0047A8C0,F9运行,程序断下,接着F9运行,程序断下,这时程序刚好还原第一个IAT,这时我们将将00DECAA3 75 11 jnz short 00DECAB6 ,这个地址的代码改成 00DECAA3 EB 11 jmp short 00DECAB6 ,现在我们有个疑问代码是改了,但是我们不知道IAT什么时候全部被还原完了,根据壳的特性,代码执行前会先解密,执行完又会加密,我们就在00DECAA3 75 11 jmp short 00DECAB6,这个代码处,下个硬件写入断点HR 00DECAA3 ,F9运行,程序断在了00DC13C4这个地址,
这段代码是访问 00DECAA3 这个地址的字节码,取出字节码放到EDX,可以看到此时EDX的值是858B11EB,其中EB是我们修改后的,没修改前是75,所以我们把EDX,改成
858B1175,这样就可以骗过壳的校验,同时我们还要把00DECAA3 EB 11 jmp short 00DECAB6 ,这个地址的代码改回 00DECAA3 75 11 jnz short 00DECAB6 ,删除所有断点,这时候我们按照前面找OEP的方法,在代码段下F2断点,F9运行,程序断下,单步到OEP,这时候我们再翻看IAT,可以看到没有被还原的统统被还原了,只是不同模块之前的分隔00000000,变成了别的地址,这个不影响程序运行,这个时候是不是忘了Code Splicing没有修复,这个先不着急,我们先按照正常脱壳流程走一边,先用ImportRec获取IAT表,再用LordPe Dump出来,再用ImportRec获取的IAT表,修复Dump出来的文件,最后用再用LordPe 重建PE
其中重新排列文件不要勾,我们再将修复好的文件载入OD看看,这时候排除了IAT的因素的干扰,F9运行,
OD上显示已终止,可以看到现在EIP是035CDBB4,通过堆栈回溯,找到这段代码!
正如我们开始的时候学习的Code Splicing一样,通过JMP XXXXXXXX ,跳到一个内存地址执行被偷走的代码,我们先记下这个地址 004274F3 ,然后重新载入原来的程序,通过OD查看004274F3这个地址代码情况,可以看到都是0,我们就在004274F3这个地方下硬件写入断点 HW 004274F3,程序断下,再ALT+F9返回到用户代码,再倒回去看地址004274F3的代码情况,
代码是正常的,跟随这个JMP,
也是个正确的,这时我们需要追根溯源,回到EIP所在的代码,可以看到上一句执行的是msvcrt.memcpy函数,这是个代码复制函数,我们可以通过他的参数,可以找到他的源头,我们对这个函数的地址00DEB833,下个硬件执行断点HE 00DEB833,因为OD硬件断点有记忆功能,如果重新载入程序下个内存上不存在的地址的断点是下不了的,下完断点我们重新载入程序,
这边有一个问题需要注意一下,图中圈起来的红色圆点是打开和关闭这个硬断对话框的,另外一个圈起来的像减号的是隐藏这一行断点的按钮,点一下他就变加号了,同时这个断点消失了,就不能断下了,再点一下加号,这一行又出现了,最好每次重新载入程序点这个QUIT按钮关闭,再点红色按钮打开,同时下什么断点必须在这个对话框里面看的到,否则可能无效,说的好像比较听不懂,但是你们多试几次就知道了,回归正题,F9运行,程序断在了
通过堆栈可以看到,从01600020这个地址复制到00402000,数据大小是00078000,通过计算004274F3对应的地址是1625513,
,我们也在1625513这个地址下硬件写入断点HW 1625513,重新载入程序,F9运行,程序断下,接着再F9,再断下,再F8单步一下,运行到这边
命令行dd 01625513 ,然后数据窗口选中01625513这一行反汇编,可以看到
接着删除所有断点,再在01625513这个地址下硬件写入断点,F9运行,程序断下,再F9运行,断下,然后再F8单步一下,此时EIP在这边,
这时查看一下01625513这个地址的代码,
E9后面都是0,这应该是要写入东西的,删除所有断点,在
01625514下个硬件写入断点HW 01625514,F9运行,现在EIP在00DEB613,
下面我们分析一下这段代码处理的表的结构,这个结构是以00F97950为起始点,0为结尾标志,有很多个组,每组构成了一次代码拼接,一组有四项,
下面是利用上面的数据修改jmp后面的字节码的代码,
调试跟踪这段代码可以在运行前在00DEB53C下个硬件执行断点。
这个表的每一组除了第一项,其他项都需要根据申请的内存基址计算出来的,所以我们再对这个表的起点00F97950下个硬件写入断点,重新运行程序,F9运行,程序断下,F9运行,再断下,
这时候EIP是00DEA6CC,然后执行命令dd 00F97950 ,看看数据窗口,可以看到,
可以看到第一项和第二项都有数据了后面都是零,所以断下的这段代码就是在构造这个表,让我们来看看这个表是如何构造的这又需要用到另外一个表,这时我们F7单步一直走,走到
这条指令就是跳回继续循环,再F7一下,走到这边
可以给这条指令下硬件执行断点,重新载入程序,F9运行,程序断下,F7单步一下,此时EAX等于00F81008
,所以表的起点是00F81008。接下来跟踪就可以从头开始看,这个表一直被填充,先看下代码拼接处执行的流程图,其中地址c和地址d之间的代码块包含被JMp指令覆盖的代码和垃圾指令
地址A和B之间相差5个字节,所以地址B可以通过地址A求出,刚刚说到构造这个表前面还有一个表,这个表每个数组有三项,其中第一项是地址A的偏移地址,第二项是地址D的偏移地址,第三项是地址C的偏移地址,其中代码段基址固定是400000,而内存基址是不断变化的,需要申请之后获得,EIP所在的这段代码会访问申请到的内存基址,通过这个表计算出数值再填入刚才那个表。
A的偏移地址 - 1 为什么还要减一,因为记录的不是jmp指令的偏移,而是E9 后面第一个字节的地址,方便等下修改E9的字节码,不需要再减一。
下面是对这段代码的部分关键注释
上面分析的代码可能有的地方有点错误,将就着看吧,写到这边已经有点晕了,就当大家都看懂了,之前文章,是修改那个关键内存的地址为下面这个代码段,
当然这个代码段刚好放的下,如果放不下我们就要,自己加个区段了,说到这边小明又要问了,IAT不是又要加个区段给他吗,IAT的话后面来,新的区段的基址就等于这个程序最后区段的地址加上大小,算出来等于7d4000,接着继续使用OD,在00DEA62C下个硬件执行断点,重新载入程序,程序断下,找到下面这一行
其中0xE0AFB0这个地址就是存放申请的内存地址的,记住现在这个地址等下需要,我们把他修改为7d4000,然后删除所有断点,在
00DEA78D 下个硬件执行断点,F9运行,程序断下,在数据窗口找到0xE0AFB0,右键撤销选择处修改,这么做就是修改前面的表格能够适合等下我们加的基址为7d4000的区段,这时EIP为00DEA78D
将jbe改为jmp,f7单步走过这条代码,再选中这条代码,右键撤销选择处修改,这个时候我们查看第一次的那个表,
需要将其修改为基址为02E10000对应的地址,因为等下我们需要用lordPE拷贝这段内存,作为基址为7d4000这个区段的数据。删除所有断点,在00DEB53C下个硬件执行断点,HE 00DEB53C,F9运行,程序断下,删除断点,这时我们需要打个补丁修改第三项的地址,
先用StrongOD申请一个内存,
将00DEB615这个地址的代码改为jmp 01690000,
在刚刚申请的内存中这样改
接着我们删除所有断点,在00DEB628下个硬件执行断点HE 00DEB628,
F9运行,程序断下,再将刚才打补丁的地方还原,
删除所有断点,然后在代码段下F2断点,F9运行,F7一直单步走到OEP,现在用lordPE找到我们的脱壳进程右键选择区域转存,找到我们刚才记住的内存地址,右键转存,名字就叫abc,选中这个进程右键修正进程大小,再右键完全转存,再用lordPE编辑这个刚才转存的exe文件,打开区段,选中区段表中的一项,右键从磁盘载入段,选中我们刚才转存的abc文件,打开,区段载入成功,接着点保存,接着用OD载入我们修复好的iat的那个文件,打开importREC,附加到那它上,点击iat自动搜索,点击获取导入表,点击显示无效的函数,选中右键剪切指针,再点击修正转储,选择刚才转储的exe文件,双击,最后用lordPE重建PE,成功脱壳。
00401031
E9 CA
4F
0D
00
jmp loc_4D6000 ; WinMain函数头,Jmp后面的地址在脱壳后新加的区段,
00401031
sub_401031 endp ; 未脱壳的话是在壳程序申请的一段内存中,
00401031
; 对付 Code Splicing 就要把这段代码拷贝到
00401031
; 我们程序新开辟一个区段,然后将jmp后面的地址
00401031
; 修改成我们的开辟的区段对应的地址中
00401036
loc_401036: ; CODE XREF: .spliced:loc_4D601F↓j
00401036
52
push edx ; 垃圾指令
00401037
5A
pop edx ; 垃圾指令
00401038
E8
50
00
00
00
call sub_40108D
00401031
E9 CA
4F
0D
00
jmp loc_4D6000 ; WinMain函数头,Jmp后面的地址在脱壳后新加的区段,
00401031
sub_401031 endp ; 未脱壳的话是在壳程序申请的一段内存中,
00401031
; 对付 Code Splicing 就要把这段代码拷贝到
00401031
; 我们程序新开辟一个区段,然后将jmp后面的地址
00401031
; 修改成我们的开辟的区段对应的地址中
00401036
loc_401036: ; CODE XREF: .spliced:loc_4D601F↓j
00401036
52
push edx ; 垃圾指令
00401037
5A
pop edx ; 垃圾指令
00401038
E8
50
00
00
00
call sub_40108D
004D6000
loc_004D6000: ; CODE XREF: sub_401031↑j
004D6000
F7 D0
not
eax ; 垃圾指令
004D6002
0F
CF bswap edi ; 垃圾指令
004D6004
66
91
xchg ax, cx ; 垃圾指令
004D6006
7A
02
jp short loc_004D600A ; 垃圾指令
004D6008
7A
17
jp short near ptr loc_004D601F
+
2
; 垃圾指令
004D600A
004D600A
loc_004D600A: ; CODE XREF:
004D6006
↑j
004D600A
0F
CF bswap edi ; 垃圾指令
004D600C
0F
CF bswap edi ; 垃圾指令
004D600E
7B
02
jnp short loc_004D6012 ; 垃圾指令
004D6010
7B
09
jnp short loc_004D601B ; 垃圾指令
004D6012
004D6012
loc_004D6012: ; CODE XREF:
004D600E
↑j
004D6012
66
91
xchg ax, cx ; 垃圾指令
004D6014
0F
CF bswap edi ; 垃圾指令
004D6016
F7 D0
not
eax ; 垃圾指令
004D6018
55
push ebp ; 被偷走的正常指令
004D6019
8B
EC mov ebp, esp ; 被偷走的正常指令
004D601B
004D601B
loc_004D601B: ; CODE XREF:
004D6010
↑j
004D601B
6A
00
push
0
; 被偷走的正常指令
004D601D
6A
00
push
0
; 被偷走的正常指令
004D601F
004D601F
loc_004D601F: ; CODE XREF:
004D6008
↑j
004D601F
E9
12
B0 F2 FF jmp loc_401036 ; 跳回去
004D6000
loc_004D6000: ; CODE XREF: sub_401031↑j
004D6000
F7 D0
not
eax ; 垃圾指令
004D6002
0F
CF bswap edi ; 垃圾指令
004D6004
66
91
xchg ax, cx ; 垃圾指令
004D6006
7A
02
jp short loc_004D600A ; 垃圾指令
004D6008
7A
17
jp short near ptr loc_004D601F
+
2
; 垃圾指令
004D600A
004D600A
loc_004D600A: ; CODE XREF:
004D6006
↑j
004D600A
0F
CF bswap edi ; 垃圾指令
004D600C
0F
CF bswap edi ; 垃圾指令
004D600E
7B
02
jnp short loc_004D6012 ; 垃圾指令
004D6010
7B
09
jnp short loc_004D601B ; 垃圾指令
004D6012
004D6012
loc_004D6012: ; CODE XREF:
004D600E
↑j
004D6012
66
91
xchg ax, cx ; 垃圾指令
004D6014
0F
CF bswap edi ; 垃圾指令
004D6016
F7 D0
not
eax ; 垃圾指令
004D6018
55
push ebp ; 被偷走的正常指令
004D6019
8B
EC mov ebp, esp ; 被偷走的正常指令
004D601B
004D601B
loc_004D601B: ; CODE XREF:
004D6010
↑j
004D601B
6A
00
push
0
; 被偷走的正常指令
004D601D
6A
00
push
0
; 被偷走的正常指令
004D601F
004D601F
loc_004D601F: ; CODE XREF:
004D6008
↑j
004D601F
E9
12
B0 F2 FF jmp loc_401036 ; 跳回去
004E43B1
/
72
29
jb short GameJack.
004E43DC
004E43B3
|F3:A5 rep movs dword ptr es:[edi],dword ptr ds>
004E43B5
|FF2495 C8444E00 jmp dword ptr ds:[edx
*
4
+
0x4E44C8
]
004E43B1
/
72
29
jb short GameJack.
004E43DC
004E43B3
|F3:A5 rep movs dword ptr es:[edi],dword ptr ds>
004E43B5
|FF2495 C8444E00 jmp dword ptr ds:[edx
*
4
+
0x4E44C8
]
00DF0338
8B0C3A
mov ecx,dword ptr ds:[edx
+
edi]
00DF033B
5B
pop ebx ; GameJack.
004E54D3
00DF033C
03D7
add edx,edi ; GameJack.
00402000
00DF033E
A1 A410E000 mov eax,dword ptr ds:[
0xE010A4
]
00DF0343
3148
58
xor dword ptr ds:[eax
+
0x58
],ecx
00DF0346
A1 A410E000 mov eax,dword ptr ds:[
0xE010A4
]
00DF034B
3148
58
xor dword ptr ds:[eax
+
0x58
],ecx
00DF034E
A1 A410E000 mov eax,dword ptr ds:[
0xE010A4
]
00DF0353
8B16
mov edx,dword ptr ds:[esi]
00DF0355
8B48
74
mov ecx,dword ptr ds:[eax
+
0x74
]
00DF0358
3348
6C
xor ecx,dword ptr ds:[eax
+
0x6C
]
00DF035B
3348
50
xor ecx,dword ptr ds:[eax
+
0x50
]
00DF035E
030D
BC10E000 add ecx,dword ptr ds:[
0xE010BC
] ; GameJack.
00400000
00DF0364
85D2
test edx,edx
00DF0366
75
18
jnz short
00DF0380
00DF0368
8B50
70
mov edx,dword ptr ds:[eax
+
0x70
]
00DF036B
FF76
18
push dword ptr ds:[esi
+
0x18
]
00DF036E
3350
6C
xor edx,dword ptr ds:[eax
+
0x6C
]
00DF0371
FF76
14
push dword ptr ds:[esi
+
0x14
]
00DF0374
3350
04
xor edx,dword ptr ds:[eax
+
0x4
]
00DF0377
FF76
10
push dword ptr ds:[esi
+
0x10
]
00DF037A
2BCA
sub ecx,edx
00DF037C
FFD1 call ecx
00DF0338
8B0C3A
mov ecx,dword ptr ds:[edx
+
edi]
00DF033B
5B
pop ebx ; GameJack.
004E54D3
00DF033C
03D7
add edx,edi ; GameJack.
00402000
00DF033E
A1 A410E000 mov eax,dword ptr ds:[
0xE010A4
]
00DF0343
3148
58
xor dword ptr ds:[eax
+
0x58
],ecx
00DF0346
A1 A410E000 mov eax,dword ptr ds:[
0xE010A4
]
00DF034B
3148
58
xor dword ptr ds:[eax
+
0x58
],ecx
00DF034E
A1 A410E000 mov eax,dword ptr ds:[
0xE010A4
]
00DF0353
8B16
mov edx,dword ptr ds:[esi]
00DF0355
8B48
74
mov ecx,dword ptr ds:[eax
+
0x74
]
00DF0358
3348
6C
xor ecx,dword ptr ds:[eax
+
0x6C
]
00DF035B
3348
50
xor ecx,dword ptr ds:[eax
+
0x50
]
00DF035E
030D
BC10E000 add ecx,dword ptr ds:[
0xE010BC
] ; GameJack.
00400000
00DF0364
85D2
test edx,edx
00DF0366
75
18
jnz short
00DF0380
00DF0368
8B50
70
mov edx,dword ptr ds:[eax
+
0x70
]
00DF036B
FF76
18
push dword ptr ds:[esi
+
0x18
]
00DF036E
3350
6C
xor edx,dword ptr ds:[eax
+
0x6C
]
00DF0371
FF76
14
push dword ptr ds:[esi
+
0x14
]
00DF0374
3350
04
xor edx,dword ptr ds:[eax
+
0x4
]
00DF0377
FF76
10
push dword ptr ds:[esi
+
0x10
]
00DF037A
2BCA
sub ecx,edx
00DF037C
FFD1 call ecx
00DECC4E
8B8D
68CAFFFF
mov ecx,dword ptr ss:[ebp
-
0x3598
]
00DECC54
8908
mov dword ptr ds:[eax],ecx
00DECC56
8B85
10D9FFFF
mov eax,dword ptr ss:[ebp
-
0x26F0
] ; GameJack.
0047A000
00DECC4E
8B8D
68CAFFFF
mov ecx,dword ptr ss:[ebp
-
0x3598
]
00DECC54
8908
mov dword ptr ds:[eax],ecx
00DECC56
8B85
10D9FFFF
mov eax,dword ptr ss:[ebp
-
0x26F0
] ; GameJack.
0047A000
00DECC54
8908
mov dword ptr ds:[eax],ecx
00DECC54
8908
mov dword ptr ds:[eax],ecx
0047A000
77DAEAF4
advapi32.RegCreateKeyExA
0047A018
77DCD5BB
advapi32.RegCreateKeyA
0047A71C
7C8137D9
kernel32.FindFirstFileA
0047A720
7C801E16
kernel32.TerminateProcess
0047A724
7C810B8E
kernel32.SetFilePointer
0047A72C
7C8111DA
kernel32.GetVersion
0047A754
7C801D4F
kernel32.LoadLibraryExA
0047A764
7C82F7A0
kernel32.FormatMessageA
0047A76C
7C812F1D
kernel32.GetCommandLineA
0047A778
7C80FE82
kernel32.GlobalUnlock
0047A77C
7C80FF19
kernel32.GlobalLock
0047A784
7C80FD2D
kernel32.GlobalAlloc
0047A78C
7C810D87
kernel32.WriteFile
0047A790
7C80180E
kernel32.ReadFile
0047A798
7C810A77
kernel32.GetFileSize
0047A7A0
7C809B47
kernel32.CloseHandle
0047A7A4
7C801A24
kernel32.CreateFileA
0047A7A8
7C80ABDE
kernel32.FreeLibrary
0047A7AC
7C80ADA0
kernel32.GetProcAddress
0047A7B0
7C801D77
kernel32.LoadLibraryA
0047A7C4
7C809915
kernel32.GetACP
0047A7CC
7C81CDDA
kernel32.ExitProcess
0047A7E4
7C80B6A1
kernel32.GetModuleHandleA
0047A7EC
7C80BE89
kernel32.FindResourceA
0047A7F4
7C80CC97
kernel32.SetHandleCount
0047A804
7C813093
kernel32.IsDebuggerPresent
0047A81C
7C81CE03
kernel32.TerminateThread
0047A874
7C80945C
kernel32.CreateFileMappingA
0047A878
7C80B905
kernel32.MapViewOfFile
0047A87C
7C80B974
kernel32.UnmapViewOfFile
0047B6B0
77D3212B
USER32.GetWindowTextA
0047B7F0
77D5058A
USER32.MessageBoxA
0047A000
77DAEAF4
advapi32.RegCreateKeyExA
0047A018
77DCD5BB
advapi32.RegCreateKeyA
0047A71C
7C8137D9
kernel32.FindFirstFileA
0047A720
7C801E16
kernel32.TerminateProcess
0047A724
7C810B8E
kernel32.SetFilePointer
0047A72C
7C8111DA
kernel32.GetVersion
0047A754
7C801D4F
kernel32.LoadLibraryExA
0047A764
7C82F7A0
kernel32.FormatMessageA
0047A76C
7C812F1D
kernel32.GetCommandLineA
0047A778
7C80FE82
kernel32.GlobalUnlock
0047A77C
7C80FF19
kernel32.GlobalLock
0047A784
7C80FD2D
kernel32.GlobalAlloc
0047A78C
7C810D87
kernel32.WriteFile
0047A790
7C80180E
kernel32.ReadFile
0047A798
7C810A77
kernel32.GetFileSize
0047A7A0
7C809B47
kernel32.CloseHandle
0047A7A4
7C801A24
kernel32.CreateFileA
0047A7A8
7C80ABDE
kernel32.FreeLibrary
0047A7AC
7C80ADA0
kernel32.GetProcAddress
0047A7B0
7C801D77
kernel32.LoadLibraryA
0047A7C4
7C809915
kernel32.GetACP
0047A7CC
7C81CDDA
kernel32.ExitProcess
0047A7E4
7C80B6A1
kernel32.GetModuleHandleA
0047A7EC
7C80BE89
kernel32.FindResourceA
0047A7F4
7C80CC97
kernel32.SetHandleCount
0047A804
7C813093
kernel32.IsDebuggerPresent
0047A81C
7C81CE03
kernel32.TerminateThread
0047A874
7C80945C
kernel32.CreateFileMappingA
0047A878
7C80B905
kernel32.MapViewOfFile
0047A87C
7C80B974
kernel32.UnmapViewOfFile
0047B6B0
77D3212B
USER32.GetWindowTextA
0047B7F0
77D5058A
USER32.MessageBoxA
00DECC54
8908
mov dword ptr ds:[eax],ecx ;往IAT某个项目写入
00DECC56
8B85
10D9FFFF
mov eax,dword ptr ss:[ebp
-
0x26F0
]
00DECC5C
83C0
04
add eax,
0x4
;计算出下一个需要写入的IAT
00DECC5F
8985
10D9FFFF
mov dword ptr ss:[ebp
-
0x26F0
],eax
00DECC65
^ E9
4DFCFFFF
jmp
00DEC8B7
; 跳回起点解密下一个IAT
00DECC54
8908
mov dword ptr ds:[eax],ecx ;往IAT某个项目写入
00DECC56
8B85
10D9FFFF
mov eax,dword ptr ss:[ebp
-
0x26F0
]
00DECC5C
83C0
04
add eax,
0x4
;计算出下一个需要写入的IAT
00DECC5F
8985
10D9FFFF
mov dword ptr ss:[ebp
-
0x26F0
],eax
00DECC65
^ E9
4DFCFFFF
jmp
00DEC8B7
; 跳回起点解密下一个IAT
00DECA99
FF15
8863DF00
call dword ptr ds:[
0xDF6388
] ; msvcrt._stricmp 字符串比较函数,比较函数名是不是一样
00DECA9F
59
pop ecx
00DECAA0
59
pop ecx
00DECAA1
85C0
test eax,eax
00DECAA3
75
11
jnz short
00DECAB6
函数名相同则不跳
00DECAA5
8B85
58C2FFFF
mov eax,dword ptr ss:[ebp
-
0x3DA8
]
00DECAAB
8B40
08
mov eax,dword ptr ds:[eax
+
0x8
]
00DECAAE
8985
68CAFFFF
mov dword ptr ss:[ebp
-
0x3598
],eax
00DECAB4
EB
02
jmp short
00DECAB8
运行到这原IAT将被替换
00DECAB6
^ EB
9C
jmp short
00DECA54
函数名不同则回循环
00DECA99
FF15
8863DF00
call dword ptr ds:[
0xDF6388
] ; msvcrt._stricmp 字符串比较函数,比较函数名是不是一样
00DECA9F
59
pop ecx
00DECAA0
59
pop ecx
00DECAA1
85C0
test eax,eax
00DECAA3
75
11
jnz short
00DECAB6
函数名相同则不跳
00DECAA5
8B85
58C2FFFF
mov eax,dword ptr ss:[ebp
-
0x3DA8
]
00DECAAB
8B40
08
mov eax,dword ptr ds:[eax
+
0x8
]
00DECAAE
8985
68CAFFFF
mov dword ptr ss:[ebp
-
0x3598
],eax
00DECAB4
EB
02
jmp short
00DECAB8
运行到这原IAT将被替换
00DECAB6
^ EB
9C
jmp short
00DECA54
函数名不同则回循环
00DC13C2
8B12
mov edx,dword ptr ds:[edx]
00DC13C4
8955
E4 mov dword ptr ss:[ebp
-
0x1C
],edx
00DC13C2
8B12
mov edx,dword ptr ds:[edx]
00DC13C4
8955
E4 mov dword ptr ss:[ebp
-
0x1C
],edx
00DEB833
E8
2EA00000
call
00DF5866
; jmp 到 msvcrt.memcpy
00DEB833
E8
2EA00000
call
00DF5866
; jmp 到 msvcrt.memcpy
00F97950
0040299F
代码段jmpXXXXXXXX的位置
00F97954
038CD65D
代码段jmp后面的字节码
00F97958
03CD0009
内存中jmpXXXXXXXX的位置
00F9795C
FC732996 内存中jmp后面的字节码
00F97960
004029C4
代码段jmpXXXXXXXX的位置
00F97964
038CD645
代码段jmp后面的字节码
00F97968
03CD003B
内存中jmpXXXXXXXX的位置
00F9796C
FC732989 内存中jmp后面的字节码
00F97950
0040299F
代码段jmpXXXXXXXX的位置
00F97954
038CD65D
代码段jmp后面的字节码
00F97958
03CD0009
内存中jmpXXXXXXXX的位置
00F9795C
FC732996 内存中jmp后面的字节码
00F97960
004029C4
代码段jmpXXXXXXXX的位置
00F97964
038CD645
代码段jmp后面的字节码
00F97968
03CD003B
内存中jmpXXXXXXXX的位置
00F9796C
FC732989 内存中jmp后面的字节码
.text:
00DEB53C
mov eax, [ebp
-
2A4Ch
] ; 第一次取出表头地址
00F97950
开始 一次循环 加
8
个字节
.text:
00DEB542
cmp
dword ptr [eax],
0
; 判断是否为
0
,为
0
就是结束的修改
.text:
00DEB545
jz loc_DEB628
.text:
00DEB54B
mov eax, [ebp
-
2A4Ch
]
.text:
00DEB551
mov eax, [eax]
.text:
00DEB553
mov [ebp
-
2A54h
], eax
.text:
00DEB559
mov eax, [ebp
-
2A4Ch
]
.text:
00DEB55F
add eax,
4
.text:
00DEB562
mov [ebp
-
2A4Ch
], eax
.text:
00DEB568
mov eax, [ebp
-
2A4Ch
]
.text:
00DEB56E
mov eax, [eax]
.text:
00DEB570
mov [ebp
-
2A50h
], eax
.text:
00DEB576
mov eax, [ebp
-
2A4Ch
]
.text:
00DEB57C
add eax,
4
.text:
00DEB57F
mov [ebp
-
2A4Ch
], eax
.text:
00DEB585
mov eax, [ebp
-
27F4h
] ; 取出
400000
.text:
00DEB58B
add eax, [ebp
-
2A38h
] ; 得到
00402000
.text:
00DEB591
cmp
[ebp
-
2A54h
], eax
.text:
00DEB597
jbe short loc_DEB615 ; 取出第三项当做地址
.text:
00DEB599
mov eax, [ebp
-
27F4h
]
.text:
00DEB59F
add eax, [ebp
-
2A38h
] ; 得到
00402000
.text:
00DEB5A5
add eax, [ebp
-
2A34h
]
.text:
00DEB5AB
cmp
[ebp
-
2A54h
], eax
.text:
00DEB5B1
jnb short loc_DEB615 ; 取出第三项当做地址
.text:
00DEB5B3
mov eax, [ebp
-
27F4h
]
.text:
00DEB5B9
add eax, [ebp
-
2A38h
]
.text:
00DEB5BF
mov ecx, [ebp
-
2A54h
]
.text:
00DEB5C5
sub ecx, eax ; 获取到的第一项的地址减去
402000
得到偏移地址
.text:
00DEB5C7
mov [ebp
-
2A58h
], ecx
.text:
00DEB5CD
mov al, byte_E0107C
.text:
00DEB5D2
mov [ebp
-
55F8h
], al
.text:
00DEB5D8
movzx eax, byte ptr [ebp
-
55F8h
]
.text:
00DEB5DF
test eax, eax
.text:
00DEB5E1
jz short loc_DEB5FF ; eax等于
01600020
.text:
00DEB5E3
mov eax, [ebp
-
2A50h
]
.text:
00DEB5E9
xor eax, [ebp
-
2A48h
]
.text:
00DEB5EF
mov ecx, [ebp
-
2A30h
]
.text:
00DEB5F5
add ecx, [ebp
-
2A58h
]
.text:
00DEB5FB
mov [ecx], eax
.text:
00DEB5FD
jmp short loc_DEB613
.text:
00DEB5FF
;
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
.text:
00DEB5FF
.text:
00DEB5FF
loc_DEB5FF: ; CODE XREF: sub_DEB53C
+
A5↑j
.text:
00DEB5FF
mov eax, [ebp
-
2A30h
] ; eax等于
01600020
.text:
00DEB605
add eax, [ebp
-
2A58h
] ; 将偏移偏移再加上EAX得到要修改字节的地址
.text:
00DEB60B
mov ecx, [ebp
-
2A50h
] ; 取出第二项的值当做字节码
.text:
00DEB611
mov [eax], ecx ; 修改代码段jmp指令后面的地址的字节码
.text:
00DEB613
.text:
00DEB613
loc_DEB613: ; CODE XREF: sub_DEB53C
+
C1↑j
.text:
00DEB613
jmp short loc_DEB623 ; 跳回继续循环修改
.text:
00DEB615
;
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
.text:
00DEB615
.text:
00DEB615
loc_DEB615: ; CODE XREF: sub_DEB53C
+
5B
↑j
.text:
00DEB615
; sub_DEB53C
+
75
↑j
.text:
00DEB615
mov eax, [ebp
-
2A54h
] ; 取出第三项当做地址
.text:
00DEB61B
mov ecx, [ebp
-
2A50h
] ; 取出第四项当做字节码
.text:
00DEB621
mov [eax], ecx ; 修改内存中jmp指令后面的地址的字节码
.text:
00DEB623
.text:
00DEB623
loc_DEB623: ; CODE XREF: sub_DEB53C:loc_DEB613↑j
.text:
00DEB623
jmp sub_DEB53C ; 跳回继续循环修改
.text:
00DEB628
;
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
.text:
00DEB53C
mov eax, [ebp
-
2A4Ch
] ; 第一次取出表头地址
00F97950
开始 一次循环 加
8
个字节
.text:
00DEB542
cmp
dword ptr [eax],
0
; 判断是否为
0
,为
0
就是结束的修改
.text:
00DEB545
jz loc_DEB628
.text:
00DEB54B
mov eax, [ebp
-
2A4Ch
]
.text:
00DEB551
mov eax, [eax]
.text:
00DEB553
mov [ebp
-
2A54h
], eax
.text:
00DEB559
mov eax, [ebp
-
2A4Ch
]
.text:
00DEB55F
add eax,
4
.text:
00DEB562
mov [ebp
-
2A4Ch
], eax
.text:
00DEB568
mov eax, [ebp
-
2A4Ch
]
.text:
00DEB56E
mov eax, [eax]
.text:
00DEB570
mov [ebp
-
2A50h
], eax
.text:
00DEB576
mov eax, [ebp
-
2A4Ch
]
.text:
00DEB57C
add eax,
4
.text:
00DEB57F
mov [ebp
-
2A4Ch
], eax
.text:
00DEB585
mov eax, [ebp
-
27F4h
] ; 取出
400000
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)