所以我最近对缓冲区溢出感兴趣,许多在线教程和资源都有这种类似CTF的攻击,你需要读取标志文件的内容(例如使用cat)。
所以我开始在网上寻找如何做到这一点的组装示例,我遇到了像这样的网站或 shell-storm,其中有很多关于如何做到这一点的例子。
所以我生成了我的漏洞并得到了这个机器代码(它基本上执行了一个做 cat 标志的 shell):
shellcode = b'x31xc0x50x68x2fx63x61x74x68x2fx62x69x6ex89xe3x50x68x66x6cx61x67x89xe1x50x51x53x89xe1x31xc0x83xc0x0bxcdx80'
问题是,由于使用 GDB 介入调试问题,我注意到我的缓冲区没有从\x0b开始复制到 shell 代码的末尾。我知道问题就在那里,因为如果我将其更改为\x3b,那么它可以工作(我的其余漏洞没有复制到这里),即使当它达到错误的值时它显然崩溃了,但至少整个缓冲区都被复制了。现在做一些研究,似乎\x0b是一个"坏字符",可能会导致问题,应该避免。话虽如此,我不明白如何:
所有这些在线甚至大学教程都使用该shell代码 对于这个确切的任务。
如何潜在地解决此问题。甚至没有完全可能 更改程序集代码?
我要补充一点,我在 Ubuntu 上并试图在 64 位上完成这项工作。
字节0x0b
的特别之处在于它是ASCII垂直制表符,它被认为是一个空格字符。
所以我要做一个疯狂的猜测,你正在利用的代码看起来像
// Dangerous code, DO NOT USE
char buf[TOO_SMALL];
scanf("%s", buf);
由于scanf("%s")
是一种常用(错误)使用的输入机制,当它遇到空格时会停止。 如果是这样,那么如果您的shellcode包含0x0b
或任何其他空格字符,它将被截断。
对于你的第一个问题,关于"为什么其他教程使用这样的shellcode",他们可能是在思考而不是利用这样的代码。
// Dangerous code, DO NOT USE
char buf[TOO_SMALL];
gets(buf);
gets()
不会在0x0b
停止阅读,而只会在换行0x0a
处停止阅读. 或者,也许他们正在考虑一个由strcpy()
填充的缓冲区,它只会在0x00
处停止,或者可能是一个由read()
填充的缓冲区,其大小由用户控制,无论它包含什么字节,它都会读取全部数据量。 因此,哪些字符是"坏"的问题取决于易受攻击的代码实际做了什么。
至于如何处理它,好吧,你需要修改你的shellcode,只使用不包含任何空格字节的指令。 这种事情与其说是一门科学,不如说是一门艺术;您必须非常了解您的指令集,并在考虑替代指令序列以达到预期结果时要有创造性。 有时您可以通过细微的调整来做到这一点;其他时候可能需要批量重写。 它确实有所不同。
在这种情况下,幸运的是0x0b
是整个代码中唯一的空格字符,它出现在指令中
83C00B add eax, 0x0b
由于eax
之前已归零,因此目标是使用值0xb
加载它,该值是execve
的系统调用号。 当"坏字节"作为即时数据的一部分出现时,通常不难找到另一种方法将数据送到需要的地方。 (当坏字节是操作码本身的一部分时,生活会更艰难。 在这种情况下,一个简单的解决方案是利用 two 的补码,然后写
83E8F5 sub eax, -0x0b
单字节-0x0b = 0xf5
被符号扩展为 32 位并用作要减去的值,从而根据需要eax
0x0b
。 当然还有很多其他方法,其中一些可能具有较小的代码大小;我会把这个留给你的聪明才智。
找出shellcode的"bad char"是利用溢出漏洞的重要步骤。
首先,您必须弄清楚目标可以溢出多少位(此字段也用于shellcode)。 如果这个区域足够大,你可以使用所有的"char"(从\x01到\xff的谷歌坏字符。 \x00是坏字符)作为Shellcode发送到目标。
然后你可以找到 寄存器 看看字符还剩下什么。(如果区域对于所有字符来说不够大,您可以只发送一些字符一次并重复)
您可以按照此 https://netsec.ws/?p=180 进行操作。