Neovim中运行pwntools脚本时io.interactive()进程异常终止
问题描述
使用Python 3.10.x搭配pwntools编写漏洞利用脚本时,代码中的io.interactive()本该启动交互shell,但在Neovim通过!./%命令运行脚本时,交互shell未正常启动,进程直接停止,同时伴随BytesWarning类型的警告。
原代码
#!/usr/bin/python3 from pwn import * elf = context.binary = ELF("house_of_force") libc = elf.libc gs = ''' continue ''' def start(): if args.GDB: return gdb.debug(elf.path, gdbscript=gs) else: return process(elf.path) # Select the "malloc" option, send size & data. def malloc(size, data): io.send("1") io.sendafter("size: ", f"{size}") io.sendafter("data: ", data) io.recvuntil("> ") # Calculate the "wraparound" distance between two addresses. def delta(x, y): return (0xffffffffffffffff - x) + y io = start() # This binary leaks the address of puts(), use it to resolve the libc load address. io.recvuntil("puts() @ ") libc.address = int(io.recvline(), 16) - libc.sym.puts # This binary leaks the heap start address. io.recvuntil("heap @ ") heap = int(io.recvline(), 16) io.recvuntil("> ") io.timeout = 0.1 # ============================================================================= # =-=-=- EXAMPLE -=-=-= # The "heap" variable holds the heap start address. log.info(f"heap: 0x{heap:02x}") # Program symbols are available via "elf.sym.<symbol name>". log.info(f"target: 0x{elf.sym.target:02x}") # The malloc() function chooses option 1 from the menu. # Its arguments are "size" and "data". malloc(24, b"Y"*24) # The delta() function finds the "wraparound" distance between two addresses. log.info(f"delta between heap & main(): 0x{delta(heap, elf.sym.main):02x}") # ============================================================================= io.interactive()
错误信息
/home/pegasus/Documents/Courses/HeapLAB-main/house_of_force/./exploit.py:19: BytesWarning: Text is not bytes; assuming ASCII, no guarantees. See https://docs.pwntools.com/#bytes io.sendafter("size: ", f"{size}") /home/pegasus/.local/lib/python3.10/site-packages/pwnlib/tubes/tube.py:813: BytesWarning: Text is not bytes; assuming ASCII, no guarantees. See https://docs.pwntools.com/#bytes res = self.recvuntil(delim, timeout=timeout) /home/pegasus/Documents/Courses/HeapLAB-main/house_of_force/./exploit.py:21: BytesWarning: Text is not bytes; assuming ASCII, no guarantees. See https://docs.pwntools.com/#bytes io.recvuntil("> ") [*] delta between heap & main(): 0xfffffffffebd9816 [*] Switching to interactive mode [*] Stopped process '/home/pegasus/Documents/Courses/HeapLAB-main/house_of_force/house_of_force' (pid 7496)
解决方案
1. 解决Neovim交互终端限制
Neovim的!./%命令属于非交互式执行,无法支持pwntools的交互shell功能,换用以下方式运行脚本:
- 直接在系统终端执行:
./exploit.py - 在Neovim内打开交互式终端运行:
:terminal ./%
2. 修复BytesWarning警告
pwntools要求所有IO操作必须使用字节类型,修改代码中字符串为字节格式:
io.send("1")→io.send(b"1")io.sendafter("size: ", f"{size}")→io.sendafter(b"size: ", f"{size}".encode())io.recvuntil("> ")→io.recvuntil(b"> ")io.recvuntil("puts() @ ")→io.recvuntil(b"puts() @ ")io.recvuntil("heap @ ")→io.recvuntil(b"heap @ ")
修正后的完整代码
#!/usr/bin/python3 from pwn import * elf = context.binary = ELF("house_of_force") libc = elf.libc gs = ''' continue ''' def start(): if args.GDB: return gdb.debug(elf.path, gdbscript=gs) else: return process(elf.path) # Select the "malloc" option, send size & data. def malloc(size, data): io.send(b"1") io.sendafter(b"size: ", f"{size}".encode()) io.sendafter(b"data: ", data) io.recvuntil(b"> ") # Calculate the "wraparound" distance between two addresses. def delta(x, y): return (0xffffffffffffffff - x) + y io = start() # This binary leaks the address of puts(), use it to resolve the libc load address. io.recvuntil(b"puts() @ ") libc.address = int(io.recvline(), 16) - libc.sym.puts # This binary leaks the heap start address. io.recvuntil(b"heap @ ") heap = int(io.recvline(), 16) io.recvuntil(b"> ") io.timeout = 0.1 # ============================================================================= # =-=-=- EXAMPLE -=-=-= # The "heap" variable holds the heap start address. log.info(f"heap: 0x{heap:02x}") # Program symbols are available via "elf.sym.<symbol name>". log.info(f"target: 0x{elf.sym.target:02x}") # The malloc() function chooses option 1 from the menu. # Its arguments are "size" and "data". malloc(24, b"Y"*24) # The delta() function finds the "wraparound" distance between two addresses. log.info(f"delta between heap & main(): 0x{delta(heap, elf.sym.main):02x}") # ============================================================================= io.interactive()
额外排查点
如果修改后仍存在问题,可检查:
- 目标程序是否在
io.interactive()执行前已崩溃,可添加io.wait_for_close()查看进程退出状态 - 若使用GDB调试,确保
context.terminal配置正确,比如添加context.terminal = ['gnome-terminal', '-e'](根据你的终端模拟器调整)
内容的提问来源于stack exchange,提问作者NobinPegasus
相关产品推荐
相关产品推荐

