如何找到溢出错误的堆栈指针?

信息安全 linux 开发 缓冲区溢出 部件
2021-09-03 00:46:21

我读过该堆栈通常从同一地址开始,因此攻击者可能会猜测缓冲区的起始点溢出。必须知道该地址才能使恶意代码运行。我用几行代码编写了一个程序,每次启动时获取堆栈指针地址并将其打印在屏幕上:

int * get_stack_pointer(){
    __asm__("mov %esp,%eax");
}
void main(){
  printf("Address: %p\n",get_stack_pointer());
}

这是程序的反汇编:

<get_stack_pointer>:
push   %rbp
mov    %rsp,%rbp
mov    %esp,%eax
pop    %rbp
retq   

<main>:
push   %rbp
mov    %rsp,%rbp
mov    $0x0,%eax
callq  40050c <get_stack_pointer>
mov    %rax,%rsi
mov    $0x4005ec,%edi
mov    $0x0,%eax
callq  4003e0 <printf@plt>
pop    %rbp
retq 

但是每次我启动程序时,我都会得到不同的地址。其中一些如下:

Address: 0xc31b2c80
Address: 0x2e041e0
Address: 0x7b003190
Address: 0xb3fd1350

那么在这种情况下,攻击者怎么可能在易受攻击的程序上运行他的代码呢?(我的操作系统是 Linux 64 位)

编辑:我在汇编中制作了另一个程序,其中包括一些简单的行。我只是在每次从调试器启动时检查 RSP 的值,我看到 RSP 总是具有相同的值,但不是用 c 编写的程序。

1个回答

您的问题是ASLR随机选择程序的加载位置。您可以在 Linux 中使用sudo sysctl -w kernel.randomiz_va_space=0.

这是我的程序。我使用的是 RAX 而不是 EAX,unsigned long *而不是int *.

#include <stdio.h>
#include <stdlib.h>

unsigned long *get_stack_ptr(void) {
  __asm__(
    "mov %rsp, %rax"
  );
}

int main(int argc, char **argv) {
  unsigned long *stack_ptr = get_stack_ptr();

  printf("Size Of Ptr: %d bytes\n", sizeof(unsigned long *));
  printf("Stack Pointer: %llX\n", stack_ptr);

  return 0;
}

这是我在 ASLR 上的程序:

@narrator:$ ./stackptr 
Size Of Ptr: 8 bytes
Stack Pointer: 7FFD328233D0
@narrator:$ ./stackptr 
Size Of Ptr: 8 bytes
Stack Pointer: 7FFC2B5F07E0
@narrator:$ ./stackptr 
Size Of Ptr: 8 bytes
Stack Pointer: 7FFFE3A2FF10
@narrator:$ ./stackptr 
Size Of Ptr: 8 bytes
Stack Pointer: 7FFE5F0795F0

现在我执行: sudo sysctl -w kernel.randomize_va_space=0

这是我没有 ASLR 的程序:

@narrator:$ ./stackptr 
Size Of Ptr: 8 bytes
Stack Pointer: 7FFFFFFFDF70
@narrator:$ ./stackptr 
Size Of Ptr: 8 bytes
Stack Pointer: 7FFFFFFFDF70
@narrator:$ ./stackptr 
Size Of Ptr: 8 bytes
Stack Pointer: 7FFFFFFFDF70
@narrator:$ ./stackptr 
Size Of Ptr: 8 bytes
Stack Pointer: 7FFFFFFFDF70