【问题标题】:How does XOR prevent NULL bytes in shellcodeXOR 如何防止 shellcode 中出现 NULL 字节
【发布时间】:2018-12-29 18:43:39
【问题描述】:

我一直在尝试按照本教程 (https://paraschetal.in/writing-your-own-shellcode) 学习如何编写自己的 shellcode。 99% 对我来说是有意义的,但我心中只有两个挥之不去的疑虑——这与一般编写 shellcode 有关

首先,我想我理解为什么我们要避免空字节,但是如何使用以下避免空字节?

xor eax, eax

eax 现在不包含完全空字节吗?还是它包含 0?当我们与自身异或时,它返回 False,对吗?

其次,教程说:

最后,我们将系统调用号(11 或 0xb)加载到 eax 登记。但是,如果我们在指令中使用 eax,则结果 shellcode 将包含一些 NULL(\x00) 字节,我们不希望这样。 我们的 eax 寄存器已经是 NULL。所以我们只加载系统调用 编号到 al 寄存器而不是整个 eax 寄存器。

mov byte  al, 0x0b

现在我明白这里发生了什么,数字 11(代表 execve)正在加载到 eax 寄存器(即 al)的前 8 位。但是eax 的其余部分仍然包含空字节,那么这里究竟实现了什么?

请注意,在花了一天的大部分时间试图理解这一点之后,我作为最后的手段来到这里,所以请放轻松:)

【问题讨论】:

  • 重点是避免机器码本身的零字节,而不是运行时的寄存器中。如果你写mov eax, 0,它的有效载荷中将包含零。 xor eax, eax 恰好有一个不包含零字节的机器代码,但在运行时它会根据需要生成一个零。只需为两个版本创建有效负载并观察零字节。
  • 您说您“完全理解”为什么要避免空字节然后将它们与寄存器值混淆...
  • 抱歉,将编辑。

标签: c assembly shellcode execve


【解决方案1】:

漏洞利用通常攻击 C 代码,因此 shell 代码 通常需要以 NUL 终止的字符串 的形式传递。如果 shell 代码包含 NUL 字节,则被利用的 C 代码可能忽略并从第一个零字节开始删除其余代码。

这仅涉及机器码。如果需要调用编号为 0xb 的系统调用,那么自然需要能够在 EAX 寄存器中产生编号 0xb,但只能使用机器码本身不包含零字节的那些形式的机器码.


xor eax, eax

将反转 eax 中的所有 1 ,即 它。它的功能等同于

mov eax, 0

除了后者机器码中将0编码为零字节。


机器码

xor eax, eax
mov byte al, 0x0b

31 c0 b0 0b

如您所见,其中没有嵌入的零字节。机器码

mov eax, 0xb

b8 0b 00 00 00

这两个程序在功能上是等效的,它们将 EAX 寄存器的值设置为 0xb。

如果后面的 shell 代码被 C 程序处理为以空字符结尾的字符串,b8 0b 00 之后的其余部分可能会被程序丢弃并被内存中的其他字节替换,实质上是使 shellcode不工作。

【讨论】:

  • 后续问题:本质上,eax 包含的字节在语义上等同于空字节,但不包含实际的空字节,对吗?
  • @ak1652 唯一担心的是shell代码不能包含空字节。要写入值 0 而不使用数字 0,可以写入 1-1。结果仍然是 0。我们想要 0 作为结果。同样,EAX 将包含空字节,因为我们希望它拥有。我们的任务是在 编写 时不要使用数字 0。
  • 谢谢,感谢您的宝贵时间。
【解决方案2】:

指令mov eax, 0汇编成

b8 00 00 00 00

包含 NUL 字节。但是,指令xor eax, eax 汇编为

31 c0

没有NUL字节,适合shell代码。

这同样适用于mov al, 0x0b。如果你做mov eax, 0x0b,编码是

b8 0b 00 00 00

包含 NUL 字节。但是,mov al, 0x0b 编码为

b0 0b

避免 NUL 字节。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-18
    • 1970-01-01
    • 2019-04-11
    • 1970-01-01
    • 2012-08-02
    相关资源
    最近更新 更多