我目前正在编写一个利用使用该puts
函数的目标程序的 shellcode。该程序如下所示:
#include <stdio.h>
main() {
char buf[123];
puts(gets(buf));
}
我想要做的是溢出这个缓冲区并execve
用一些参数调用。我有一个用 c/inline 程序集编写的测试程序,它可以execve
使用一些参数调用,然后我用来gdb
从这个程序中获取 shellcode。据我了解,堆栈布局如下所示:
|-------buffer(+padding)---------|---------sfp---------|------- ret--------------|
通过查看gcc生成的目标程序的部分汇编代码:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
addq $-128, %rsp
leaq -128(%rbp), %rax
movq %rax, %rdi
call gets
movq %rax, %rdi
call puts
leave
.cfi_def_cfa 7, 8
ret
.cfi_endproc
我认为缓冲区和填充占用128个字节,而 sfp 和返回地址各占用8个字节,所以总共是144个字节。基于此,我的 nop sled 、有效负载和新的返回地址(等于缓冲区的地址)组合(即我的 shellcode)也应该是144字节。例如,如果我的有效载荷是 36 个字节,由于返回地址占用 8 个字节,我的 nop sled 将是 100 个字节。但是当我这样做时,它不起作用。所以我想也许我理解堆栈布局的方式是错误的。这是错的吗?
请注意,在我的情况下,缓冲区地址是已知的,并且通过 using 将堆栈设置为可执行文件,execstack
并且通过 using 关闭了 ASLR setarch
。因此,如果返回地址被缓冲区地址覆盖,则写入该缓冲区的代码将运行。
我正在使用 x86 64 位机器。
如果我对堆栈布局的理解是正确的,我将提供有关我的 shellcode 的更多信息。