Hello World!
,然后像这样退出:无法找到对
objdump
或printf
的任何调用,也找不到对字符串write
的调用。 >伪装(请参阅本文)。有人可以解释一下它是什么以及它是如何工作的吗?#1 楼
伪装指令是一种针对二进制的简单幼稚静态分析的迷惑技术。二进制程序由两部分组成:解码器
编码的有效载荷
执行时,二进制文件首先进入解码器并进行解码揭示真实汇编代码的有效载荷。最后,解码器
跳转到解码的有效载荷并执行代码。
该技术的好处是静态分解
二进制文件不会给您提示什么确实是在做程序。
以某种方式,它迫使分析人员首先执行解码器部分(对于
(无论是真实的还是象征性的)),然后再看解码后的有效载荷。
在建议的示例中,解码器部分如下:到有效负载中的每个字节(从
0x8048418
0x804841c,循环计数器是
0xaa
)。因此,了解有效负载中执行的最佳方法是采用
0x804841e
,并在解码器完成任务后设置断点:
0804840c <main>:
804840c: be 1e 84 04 08 mov GNU gdb (GDB) 7.4.1-debian
Copyright (C) 2012 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later
(gdb) break main
Breakpoint 1 at 0x804840c
(gdb) run
Starting program: ./instruction_camouflage
Breakpoint 1, 0x0804840c in main ()
x804841e,%esi
8048411: 89 f7 mov %esi,%edi
8048413: b9 26 00 00 00 mov (gdb) disas
Dump of assembler code for function main:
=> 0x0804840c <+0>: mov (gdb) break *0x0804841e
Breakpoint 2 at 0x804841e
(gdb) continue
Continuing.
Breakpoint 2, 0x0804841e in main ()
x804841e,%esi
0x08048411 <+5>: mov %esi,%edi
0x08048413 <+7>: mov (gdb) disas
Dump of assembler code for function main:
0x0804840c <+0>: mov (gdb) x /s 0x08048436
0x8048436 <main+42>: "Hello World!\n"
x804841e,%esi
0x08048411 <+5>: mov %esi,%edi
0x08048413 <+7>: mov q4312078qx26,%ecx
0x08048418 <+12>: lods %ds:(%esi),%al
0x08048419 <+13>: xor q4312078qxaa,%al
0x0804841b <+15>: stos %al,%es:(%edi)
0x0804841c <+16>: loop 0x8048418 <main+12>
=> 0x0804841e <+18>: and %ebp,%esp
0x08048420 <+20>: sub q4312078qx4,%esp
0x08048423 <+23>: and q4312078qxfffffff0,%esp
0x08048426 <+26>: add q4312078qx4,%esp
0x08048429 <+29>: push q4312078qx8048436
0x0804842e <+34>: call 0x80482f0 <puts@plt>
0x08048433 <+39>: mov %ebp,%esp
0x08048435 <+41>: ret
0x08048436 <+42>: dec %eax
0x08048437 <+43>: gs
0x08048438 <+44>: insb (%dx),%es:(%edi)
0x08048439 <+45>: insb (%dx),%es:(%edi)
0x0804843a <+46>: outsl %ds:(%esi),(%dx)
0x0804843b <+47>: and %dl,0x6f(%edi)
0x0804843e <+50>: jb 0x80484ac <__libc_csu_init+76>
0x08048440 <+52>: and %ecx,%fs:(%edx)
0x08048443 <+55>: add %dl,-0x6f6f6f70(%eax)
0x08048449 <+61>: nop
...
0x0804844f <+67>: nop
End of assembler dump.
x26,%ecx
0x08048418 <+12>: lods %ds:(%esi),%al
0x08048419 <+13>: xor q4312078qxaa,%al
0x0804841b <+15>: stos %al,%es:(%edi)
0x0804841c <+16>: loop 0x8048418 <main+12>
0x0804841e <+18>: and 0x29(%edi),%ecx
0x08048421 <+21>: inc %esi
0x08048422 <+22>: scas %es:(%edi),%al
0x08048423 <+23>: sub %ecx,0x5a(%esi)
0x08048426 <+26>: sub %ebp,-0x52(%esi)
0x08048429 <+29>: ret q4312078qx2e9c
0x0804842c <+32>: scas %es:(%edi),%al
0x0804842d <+33>: mov %al,0x55541742
0x08048432 <+38>: push %ebp
0x08048433 <+39>: and 0x69(%esi),%eax
0x08048436 <+42>: loop 0x8048407 <frame_dummy+39>
0x08048438 <+44>: mov q4312078qxc5,%dh
0x0804843b <+47>: mov %ch,%bh
0x0804843d <+49>: vshufps q4312078qx8b,%xmm6,%xmm4,%xmm1
0x08048442 <+54>: mov 0x909090aa,%al
0x08048447 <+59>: nop
...
0x0804844f <+67>: nop
End of assembler dump.
x26,%ecx
8048418: ac lods %ds:(%esi),%al
8048419: 34 aa xor q4312078qxaa,%al
804841b: aa stos %al,%es:(%edi)
804841c: e2 fa loop 8048418 <main+0xc>
让我们检查代码是否未更改。
q4312078q
让我们在循环和con之后放置一个断点
q4312078q
现在,我们应该能够访问将要执行的代码。
q4312078q
而且,在
0x804841e + 0x25 = 0x8048443
之后仍然存在这些奇怪的指令,让我们将其可视化为字符串。q4312078q
因此,我们发现了所有该程序及其工作方式。
评论
我个人从未听说过“代码屏蔽”一词,Google或Wikipedia也未提供任何提示。您可以链接到实际使用该术语的某些资源吗?
–彼得·安德森(Peter Andersson)
13年4月9日在9:23
我不知道如何称呼这种混淆。我找不到适合的通用名称。给个名字,我将在问题和答案中更改它。
–恐怖
13年4月9日在9:30
我习惯称其为“天真的加密”,因为我假设您是说这个问题要涵盖的范围不仅仅限于xor?例如旋转和异或的一些简单组合?否则,它是异或密码。对于微不足道的可逆密码,我实际上想不出一个好名字。根据您的解释,同样的答案也将涵盖任何复杂的密码方案。即,您的入口点和断点之间的操作可能是任意复杂的,但仍然取决于您的技术。它不依赖于琐碎的密码。
–彼得·安德森(Peter Andersson)
13年4月9日在9:42
我认为我们称之为“自我修改”。
–滚轴
13年4月9日在10:14
知道算法和密钥不会改变它是解密的事实。我并不是在建议一个新词,而是在提到我期望的词。
–天使
13年4月10日在7:27
#2 楼
这通常也称为加密包装器。我敢肯定行业中还有其他几个类似的名称。实际的代码并不像概念那么重要。明文代码由负责对代码主体进行解码的解密存根(按执行顺序)放在前面。这样,主体代码主体(在恶意软件的情况下是有效载荷)被加密,因此没有恒定的字节数。在此示例中,解码器存根本身保持不变,尽管多态性是后来的发展,它重新生成了编码器和解码器,因此它们也不包含恒定字节。通过减少代码副本之间的恒定字节数,可以减少检测签名的暴露。
解码器存根也可以提供解压缩功能。自我复制PC病毒的初期。这些被标记为具有自我加密的特征。今天,某些颠覆性软件仍在使用它。
重要的是,本机代码并不是唯一可以这种方式“包装”的代码。
评论
通常,掩码是通过按位操作应用于位字段的值,以读取,设置或重置特定位。我同意必须更改名称。但是,似乎很难找到合适的解决方案。该技术的重点主要是从简单的朴素静态分析中隐藏执行的代码。就目前而言,经过讨论,“代码伪装”是我所能拥有的最好的……但是我不知道它是否会被接受。
对我(个人)而言,大多数社区的理解比使用一个没人听说过且可能会被误解的完美但新颖的词更为重要(因此,即使我个人更喜欢“返回libc”)。而且“隐藏”和“模糊”比“隐瞒”恕我直言更普遍。
因此,您建议“隐藏代码”? (代码混淆不能成为一种选择,因为它不能标记其他一种技术)。我也完全可以。 (后记:“ ROP”和“ return-in-libc”实际上是两种不同的技术)
我找到了有关指令迷彩的参考。尽管它不是非常出名的论文,但它们的名称似乎还可以(我希望这是我最后一次修改它……我只是一团糟,对不起)。