c-XOR如何防止外壳代码中的NULL字节



我一直在努力学习本教程(https://paraschetal.in/writing-your-own-shellcode)关于如何编写自己的shell代码。99%对我来说是有意义的,但我脑子里只有两个挥之不去的疑问——这与用编写外壳代码有关

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

xor eax, eax

eax现在不包含完全为空的字节吗?或者它包含0?当我们对某个东西进行异或时,它会返回False,对吗?

其次,教程说:

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

mov byte  al, 0x0b

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

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

漏洞通常攻击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程序作为以null结尾的字符串处理,那么b8 0b 00之后的其余部分可能会被程序丢弃,并被内存中的其他字节替换,这基本上会使shell代码无法工作。

指令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字节。

最新更新