#1 楼
x86可执行文件的静态分析论文很好地解释了重叠的指令。摘自以下示例(第28页):0000: B8 00 03 C1 BB mov eax, 0xBBC10300
0005: B9 00 00 00 05 mov ecx, 0x05000000
000A: 03 C1 add eax, ecx
000C: EB F4 jmp $-10
000E: 03 C3 add eax, ebx
0010: C3 ret
通过查看代码,不清楚返回指令上eax的值是多少(或者就此而言,到达返回指令)。这是由于从000C跳转到0002,该地址未在列表中明确显示(jmp $ -10表示从当前程序计数器值0xC到0xC10 = 2的相对跳转)。该跳转将控制转移到地址0000处的五个字节长移动指令的第三个字节。执行从地址0002开始的字节序列会展开一个全新的指令流:
0000: B8 00 03 C1 BB mov eax, 0xBBC10300
0005: B9 00 00 00 05 mov ecx, 0x05000000
000A: 03 C1 add eax, ecx
000C: EB F4 jmp $-10
0002: 03 C1 add eax, ecx
0004: BB B9 00 00 00 mov ebx, 0xB9
0009: 05 03 C1 EB F4 add eax, 0xF4EBC103
000E: 03 C3 add eax, ebx
0010: C3 ret
知道Ida Pro(尤其是Hex Rays插件)是否/如何进行处理将很有趣。也许@IgorSkochinsky可以对此发表评论...
#2 楼
这也称为“中间跳跃”技巧。解释
执行规则
大多数指令需要多个指令要编码的字节
它们在现代CPU上最多可以占用15个字节
只要权限有效,执行就可以在任何位置开始
因此,指令第一个指令之后的任何字节都可以重新用于启动另一条指令。
使用反汇编程序
直接反汇编程序启动最后一条指令之后的下一条指令。
,这样的反汇编程序(不遵循流程)将隐藏在可见指令中间的指令。
示例
琐碎的
00: EB 01 jmp 3
02: 68 c3 90 90 90 push 0x909090c3
将有效地执行为
00: EB 01 jmp 3
03: C3 retn
...
>因为第一个
jmp
跳过以下指令的第一个字节68
(编码立即推送)。多个重叠
从例如,
69 84
定义了一个imul
指令,最多可占用11个字节。因此,您可以在其“伪”操作数中放入几行指令。00: EB02 jmp 4
02: 69846A40682C104000EB02 imul eax, [edx + ebp*2 + 0102C6840], 0x002EB0040
0D: ....
实际上将被执行为
00: EB02 jmp 4
04: 6A40 push 040
06: 682C104000 push 0x40102C
0B: EB02 jmp 0xF
0F: ...
指令在其第二个字节中跳跃:
00: EBFF jmp 1
02: C0C300 rol bl, 0
实际上将被执行为
/>
00: EBFF jmp 1
01: FFC0 inc eax
03: C3 retn
不同的CPU模式
这种混淆可以扩展到跳转到相同的EIP,但是在不同的CPU模式下:
64b CPU仍支持32b指令
64b模式将
0x33
用于cs
某些指令仅在特定模式下可用:
在32b模式下的
arpl
在64b模式下的
movsxd
,因此您可以跳转到相同的
EIP
但使用不同的CS
并获得不同的说明。在此示例中,此代码首先在32b模式下执行:
00: 63D8 arpl ax,bx
02: 48 dec eax
03: 01C0 add eax,eax
05: CB retf
,然后在64位模式下重新执行为:
在这种情况下,指令是重叠的,不是因为EIP不同,而是因为CPU暂时从32b模式更改为64b模式。
评论
在任何主要操作系统上的用户空间中运行的程序是否都可以从32位模式更改为64位模式?
–道格拉
13年4月9日,0:26
@Dougall是的。在Windows上,这是通过X86SwitchTo64BitMode()完成的(或使用段选择器33通过远距离调用/跳转手动完成)。但是,我非常确定这是特定于Windows WOW64实现的,不适用于其他OS。
–user45891
2014年9月4日在20:17
@Ange,您可以更新链接code.google.com/p/corkami/source/browse/trunk/src/CoST/…吗?谢谢!
–robert
17年7月3日在9:09
#3 楼
在x86 / x86_64中,几乎所有多字节指令都可以用作重叠指令。原因很简单:x86和x86_64指令集是CISC。这意味着,其中的一条指令没有固定的长度。因此,由于指令是可变长度的,请仔细地编写该机器代码,每条指令都容易隐藏重叠的指令。例如,给定以下代码:[0x00408210:0x00a31e10]> b
0x000050f5 (01) 56 PUSH ESI
0x000050f6 (04) 8b742408 MOV ESI, [ESP+0x8]
0x000050fa (01) 57 PUSH EDI
0x000050fb (03) c1e603 SHL ESI, 0x3
0x000050fe (06) 8bbe58a04000 MOV EDI, [ESI+0x40a058]
0x00005104 (01) 57 PUSH EDI
0x00005105 (06) ff15f4804000 CALL 0x004080f4 ; 1 KERNEL32.dll!GetModuleHandleA
0x0000510b (02) 85c0 TEST EAX, EAX
0x0000510d (02) 750b JNZ 0x0000511a ; 2
假设在最后一条指令之后的某处,显示的代码中某条指令的中间出现了跳转,例如,跳转到MOV ESI ...指令的第二个字节:
[0x000050f7:0x00405cf7]> c
0x000050f7 (02) 7424 JZ 0x0000511d ; 1
0x000050f7 ----------------------------------------------------------------------
0x000050f9 (03) 0857c1 OR [EDI-0x3f], DL
0x000050fc (02) e603 OUT 0x3, AL
原来,该指令已更改为JZ。哪个有效跳转到第3个字节...
[0x000050f7:0x00405cf7]> s +1
[0x000050f8:0x00405cf8]> c
0x000050f8 (02) 2408 AND AL, 0x8
0x000050fa (01) 57 PUSH EDI
0x000050fb (03) c1e603 SHL ESI, 0x3
0x000050fe (06) 8bbe58a04000 MOV EDI, [ESI+0x40a058]
跳转到CALL指令的第2个字节:
[0x000050f5:0x00405cf5]> s 0x5106
[0x00005106:0x00405d06]> c
0x00005106 (05) 15f4804000 ADC EAX, 0x4080f4 ; '\x8e\x91'
0x0000510b (02) 85c0 TEST EAX, EAX
0x0000510d (02) 750b JNZ 0x0000511a ; 1
您可以看到,几乎所有多字节指令都可以用作重叠指令。
这种反反转技巧经常与不透明谓词一起使用,以使f ** k流程图。
评论
因此,您的意思是没有办法建立这样的列表?关于x86 / x86-64操作码,令我惊讶的另一点是,它在一段时间后可以与原始指令流重新同步。此属性还有助于使指令重叠。虽然,我不知道为什么重新同步如此出色。
–恐怖
13年4月4日在8:20
#4 楼
因为x86指令可以是任意长度,并且不需要对齐,所以一条指令的立即值可以是另一条指令。例如:00000000 0531C0EB01 add eax,0x1ebc031
00000005 055090EB01 add eax,0x1eb9050
0000000A 05B010EB01 add eax,0x1eb10b0
0000000F EBF0 jmp short 0x1
这完全按照它说的去做,直到跳转为止。当它跳转时,被添加到eax的立即值成为一条指令,因此代码如下所示:
手柱。在此示例中,短跳转指令用于跳过指令的
add eax
部分(05
)。应该注意的是,可以通过使用单字节吃掉05
来更有效地完成操作,例如3C05
就是cmp al, 0x5
,并且在不关心标志的代码中是无害的。在上述模式中,您可以轻松地将所有
05
替换为90
(nop),以查看正确的拆卸方法。通过将05
用作隐藏代码的立即值(执行依赖),可以使此过程更加棘手。实际上,混淆代码的人可能不会一遍又一遍地使用add eax
,并且可能会更改执行顺序以使其更难以跟踪。我使用上述模式准备了一个示例。这是base64中的32位Linux ELF文件。隐藏代码的效果正在运行
execve("//usr/bin/python", 0, 0)
。我建议您不要从SE答案中运行随机二进制文件。但是,您可以使用它来测试反汇编程序。乍一看,IDA,Hopper和objdump都惨败,尽管我想您可以使IDA以某种方式正确地执行此操作。
评论
我想知道正确的用词是什么。我听说过“指令断言”的使用非常频繁。我遇到了几种谈论这种技术的方式。但是,的确,没有一个被社区广泛采用。自从现在以来,“重叠说明”是我使用最多的。但是,我可能只阅读了有关它的现有文档的一小部分。