使用pthread时,缓冲区溢出时的堆栈地址是什么?

4
我正在学习计算机安全课程,有一项额外的学分作业要求将可执行代码插入到缓冲区溢出中。我已经获取了目标程序的c源代码并且成功地覆盖了当前函数堆栈帧的eip。但是,我总是得到一个段错误(Segmentation fault)提示,因为提供的地址总是错误的。问题在于当前函数位于pthread内,因此堆栈的地址似乎在程序的不同运行之间总是变化的。是否有方法可以找到pthread中的堆栈地址(或估计pthread中的堆栈地址)?(注意:pthread_create的第二个参数为null,因此我们没有手动分配堆栈地址)
3个回答

9

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

以下是简短的摘录:

问题在于,我们不知道要利用程序内存空间中的代码(以及其后面的字符串)将被放置在哪里。解决方法之一是使用 JMP 和 CALL 指令。JMP 和 CALL 指令可以使用 IP 相对寻址,这意味着我们可以跳转到当前 IP 的偏移处,而无需知道要跳转到内存中的确切地址。


你可以通过一些内联汇编来检索栈指针的当前值。在Smashing The Stack For Fun And Profit中的所有示例都在 main 中溢出了一个缓冲区,但你同样可以使用相同的技术来溢出从 pthread 调用的函数中的缓冲区。下面的代码基于文章中的一个示例(overflow1.c),以展示使用 pthreads 也可以使用相同的技术。你将使用的实际技术将取决于你要尝试利用的目标程序。


/* 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;
}

我实际上正在阅读那篇文章。我得再研究一下,但是那个引用不是指获取缓冲区内“/bin/sh”的地址吗?难道我们仍然不必覆盖eip使其指向最初的跳转指令吗? - t2k32316
摘录正在构建的示例使用 strcpy() 溢出字符缓冲区。溢出会覆盖堆栈上保存的返回地址(已保存的 IP),使其指向缓冲区内部的 JMP 指令。JMP 指令跳转到 CALL 指令,该指令调用 /bin/shexecve(),所有这些都已作为 shellcode 复制到缓冲区中。文章后来建议在溢出缓冲区的前面填充 NOP 指令,以便返回地址只需要指向 NOP 中的某个位置即可。 - jschmier
感谢您的回复,jschmier。我的TA提到,通过使用pthread,程序有效地执行了堆栈随机化作为一种防止缓冲区溢出的技术。JMP和CALL指令的方法只有在返回地址被更改为指向缓冲区中我的代码时才起作用。然而,由于程序正在使用pthread,我不知道要使用哪个内存地址来覆盖返回地址。 - t2k32316

1

0

在不了解更多关于应用程序的情况下很难确定,但我首先想到的是堆喷洒


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接