编写的x86汇编Shell生成函数无执行效果,求技术指引
帮你搞定x86汇编生成Shell的问题
嘿,我来帮你梳理下这个x86汇编生成shell的问题~你的代码里有几个关键问题导致它没起作用,咱们一个个拆解:
核心错误点
- 系统调用号搞错了:你最后写的
mov $1,%eax是exit系统调用的编号(十进制1),但你需要调用的是execve(用来启动新进程的系统调用),它在32位Linux下的编号是0xb(十进制11),而且必须在触发int 0x80前把这个值放到eax里。 /bin/sh的构造方式不对:你用add %ebx,%edi的方式没法正确拼接出/bin/sh的字符串地址。x86是小端字节序,正确的做法是把字符串按字节逆序压栈,然后用栈顶地址作为文件名指针。- 缺少
execve的必要参数:execve需要三个参数,对应到系统调用的寄存器分配是:ebx:指向/bin/sh字符串的指针ecx:指向参数数组的指针(数组第一个元素是/bin/sh的指针,末尾要跟NULL)edx:指向环境变量数组的指针(一般传NULL即可)
- 程序入口不完整:你声明了
.global main但没实现main函数,而且代码写到mov $0,%e...就中断了,没法完成完整的调用流程。
修正后的完整代码
.global main .text main: call create_shell # 让程序入口main调用我们的shell生成函数 create_shell: push %ebp movl %esp, %ebp # 构造/bin/sh字符串并压栈(小端序,逆序存储为两个4字节值) pushl $0x0068732f # 对应字节: 0x2f('/'), 0x73('s'), 0x68('h'), 0x00(空终止符) pushl $0x6e69622f # 对应字节: 0x2f('/'), 0x62('b'), 0x69('i'), 0x6e('n') movl %esp, %ebx # 将栈顶地址赋值给ebx,也就是/bin/sh的指针 # 构造argv数组:[&/bin/sh, NULL] pushl $0x0 # 压入NULL作为数组结束标记 pushl %ebx # 压入/bin/sh的指针 movl %esp, %ecx # 将栈顶地址赋值给ecx,也就是argv数组的指针 # 设置envp为NULL xorl %edx, %edx # 用异或快速将edx置0 # 设置execve的系统调用号 movl $0xb, %eax # eax = 11,对应execve的系统调用编号 int $0x80 # 触发Linux系统调用 # 容错逻辑:如果execve失败,执行exit(0) movl $1, %eax # exit的系统调用编号 xorl %ebx, %ebx # exit码设为0 int $0x80
代码解释
- 程序入口:实现
main函数并调用create_shell,确保程序启动后能执行我们的逻辑。 - 构造
/bin/sh:把字符串拆成两个4字节的逆序值压栈,栈顶就是字符串的起始地址,刚好符合execve对文件名参数的要求。 - 参数数组构造:按
execve的要求,先压入NULL,再压入/bin/sh的指针,栈顶就是参数数组的首地址。 - 系统调用触发:把正确的调用号放到
eax,触发int 0x80,系统就会启动/bin/sh进程。 - 容错处理:如果
execve调用失败(比如权限问题),会执行exit(0)让程序正常退出。
编译运行提示
用32位gcc编译:
gcc -m32 -o shell_program shell.s
运行生成的程序就能看到shell了~
内容的提问来源于stack exchange,提问作者cloudiebro
相关产品推荐
相关产品推荐

