2010-03-08 33 views
4

我正在学习计算机安全课,并且还有一项额外的功劳分配,用于将可执行代码插入缓冲区溢出。我有我想要操作的目标程序的c源代码,并且我已经到了可以成功覆盖当前函数堆栈帧的eip的地步。但是,我总是遇到分段错误,因为我提供的地址总是错误的。问题是当前函数在pthread中,因此堆栈的地址似乎总是在程序的不同运行之间改变。是否有任何方法可以在pthread中查找堆栈地址(或者用于估计pthread中的堆栈地址)? (注意:pthread_create的第二个参数为空,因此我们不是手动分配堆栈地址)对于缓冲区溢出,使用pthread时,堆栈地址是什么?

回答

0

不知道更多关于应用程序的信息,有点难以理解,但首先想到的是heap spraying

7

我建议阅读有关利用缓冲区溢出漏洞的优秀(如果有点过时的)文章/教程Smashing The Stack For Fun And Profit

这里是一个简要摘录:

的问题是,我们不知道在 程序,我们正在试图利用代码的存储空间(与下面的字符串 吧)会放置。其中一种方法是使用JMP和CALL 指令。 JMP和CALL指令可以使用IP相对寻址,即 ,这意味着我们可以跳到当前IP的偏移量,而不需要 知道我们要跳转到的内存中的确切地址。


您可以检索堆栈指针的一个位内联汇编的当前值。 Smashing The Stack For Fun And Profit中的所有示例溢出main中的一个缓冲区,但您可以轻松地使用相同的技术来从pthread调用的函数中溢出缓冲区。下面的代码基于文章(overflow1.c)中的一个示例进行构建,以表明使用pthread可以使用相同的技术。您将使用的实际技术取决于您尝试利用的目标程序。


/* get value of sp off the stack - not essential to example */ 
unsigned long get_sp() 
{ 
    __asm__("movl %esp,%eax"); /* equiv. of 'return esp;' in C */ 
} 

int foo() 
{ 
    char buffer[96]; 

    /* overflow buffer to overwrite return address */ 
    /* and place code to be executed into buffer. */ 
    ... 

    return 0; 
} 

void *thread(void *arg) 
{ 
    printf("thread stack 0x%x\n", get_sp()); 

    foo(); 

    return NULL; 
} 

int main(int argc, char **argv) 
{ 
    printf("main stack 0x%x\n", get_sp()); 

    pthread_t t; 
    pthread_create(&t, NULL, thread, NULL); 
    pthread_join(t, NULL); 

    return 0; 
} 
+0

我其实读那篇文章。我将不得不再次研究它,但是不是引用了在缓冲区内获取“/ bin/sh”地址的引用吗?我们还不得不重写这个eip,以便它指向最初的跳转指令吗? – t2k32316 2010-03-08 23:02:29

+0

这个例子中,片段使用'strcpy()'建立起来以溢出一个字符缓冲区。溢出将覆盖堆栈上的返回地址(保存的IP),以便它指向缓冲区内的JMP指令。 JMP指令跳转到调用'/ bin/sh'的'execve()'的CALL指令,该指令全部被复制到缓冲区中作为shellcode。后面的文章建议用NOP指令填充溢出缓冲区的前端,这样返回地址只需要指向NOP中的某处。 – jschmier 2010-03-09 15:37:17

+0

谢谢你,jschmier,感谢你的回应。我的TA提到,通过使用pthreads,程序可以有效地执行堆栈随机化,作为缓冲区溢出的预防技术。 JMP和CALL指令的方法只有在返回地址更改为指向缓冲区中的代码后才可用。但是,由于程序使用pthreads,我不知道用什么内存地址来覆盖返回地址。 – t2k32316 2010-03-10 18:46:30