CTF中PWN題目實例分析_第1頁
CTF中PWN題目實例分析_第2頁
CTF中PWN題目實例分析_第3頁
CTF中PWN題目實例分析_第4頁
CTF中PWN題目實例分析_第5頁
已閱讀5頁,還剩34頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)

文檔簡介

CTF中PWN題目實例分析MS509PEDIYCrackMe版主CTF負(fù)責(zé)人、評委滲透測試工程師Sinopec測井工程師2017年以前2017年以后2006年開始2009年開始PWN題目中常見的漏洞堆棧溢出漏洞

棧溢出strcpy()、gets()PWN題目中常見的漏洞2.格式化字符串漏洞main(){

printf("%x")}

%d用于讀取10進(jìn)制數(shù)值

%x用于讀取16進(jìn)制數(shù)值

%s用于讀取字符串值

%n用于講當(dāng)前字符串的長度打印到var中,

例printf("test%hn",&var)main(){chars[]=“test”;

printf(“%x”,s)}

常見漏洞緩解措施0x01棧溢出漏洞進(jìn)入該vuln后subrsp-0x40,堆棧開辟了0x40字節(jié)空間然后調(diào)用gets函數(shù)讀入數(shù)據(jù)到edi所指向的空間,edi此時實際上是等于rsp的,指向棧頂?shù)奈恢胓ets函數(shù)讀入數(shù)據(jù)以換行符號為結(jié)束標(biāo)志,在遇到換行符號前,會讀取任意數(shù)據(jù)到棧里,這樣當(dāng)讀入超長字符串后,就會覆蓋函數(shù)的返回地址超長字符串導(dǎo)致返回地址被覆蓋棧溢出漏洞調(diào)試通過調(diào)試信息可以看到開啟了nx保護(hù)。棧溢出漏洞調(diào)試因為堆棧只開辟了0x40字節(jié)空間,那么我們用0x40個字符a覆蓋此空間,再用8個字符b覆蓋ebp,后面用8個字符c就可以覆蓋返回地址了棧溢出漏洞調(diào)試最后在執(zhí)行retn時將會跳轉(zhuǎn)到rsp指向的地址0x6363636363636363所指向的內(nèi)存去執(zhí)行棧溢出利用思路跳轉(zhuǎn)到libc空間去執(zhí)行代碼執(zhí)行system函數(shù)獲得SHELL獲得system函數(shù)地址利用printf打印函數(shù)地址根據(jù)偏移計算system地址使得system函數(shù)第一個參數(shù)為’/bin/sh’地址獲得/bin/sh地址利用gets讀入/bin/sh到.bss段利用ROP獲得SYSTEM函數(shù)地址返回地址處用0x40075a覆蓋。因為圖中call執(zhí)行完后要判斷rbxrbp是否相等,不等要繼續(xù)循環(huán),所以這里讓rbx為0,rbp為1就繞過了循環(huán)判斷。所以覆蓋完返回地址后繼續(xù)用0x0和0x1填充,這樣pop時就可以覆蓋掉rbx,rbp接下來用printf的got地址填充,這樣可以pop給r12,剛好rbx為0,然后call的時候執(zhí)行printfR13傳給了edx這里并沒什么作用,因此就用0x0填充R14傳給了RSI是我們想要打印的地址,這里打印printfgot表地址指向的內(nèi)容,所以用printfgot表地址覆蓋R15傳給了edi,對于printf來說他是一個格式化串,直接就用rop里該串的地址0x400784填充Popr15后執(zhí)行的是retn,要返回到rsp指向的空間,這里因為我們要跳轉(zhuǎn)到0x400740去執(zhí)行call,所以后面就用0x400740來填充Call執(zhí)行完后,還要執(zhí)行一個“addrsp,8”和6次pop,然后返回,那么我們在后面再布置7個地址,然后返回地址用vuln的地址,然后rop繼續(xù)跳轉(zhuǎn)到漏洞函數(shù)里去,方便后面再操作。所以接下來填充7個0x0和0x400656利用ROP獲得SYSTEM函數(shù)地址0x600af0棧里并沒有按我們預(yù)期的樣子填充數(shù)據(jù)???突然發(fā)現(xiàn),不用直接傳0x600af0進(jìn)去啊,可以配合rbx*8變換然后r12變成一個其他的沒有0x0a字節(jié)的值就可以了。這時r12=0x600af0-rbx*8,如果要改變到0x0a字節(jié),那么需要rbx*8>0xf0=>rbx>0xf0/8=>rbx>0x1e,這里不防取rbx=0x1f=>r12=0x600af0-0xf8。為了不有任何0x0a字節(jié),接下來我們把要打印的地址變成gets的地址,通過它和system的偏移也可以計算出system地址來。調(diào)整策略成功布置好棧數(shù)據(jù)進(jìn)程發(fā)出了一個它準(zhǔn)備退出的信號,好吧不跟我們玩了!漏洞分析調(diào)試就是一個讓人興奮與崩潰并存的事情,保持耐心,收拾好心情,我們再來分析分析!跟進(jìn)我們構(gòu)造的printf函數(shù)的情景跟進(jìn)正常的printf函數(shù)的情景前面完全沒有能控制rax的地方,那么怎么辦呢?我們在返回執(zhí)行0x40075a前,還要找到一處代碼片段(gadget)控制rax為0,然后再跳到0x40075a處執(zhí)行。通過搜索,發(fā)現(xiàn)了0x4005f3處的代碼。這里把eax置0,然后直接跳轉(zhuǎn)到poprbp處然后返回,可以滿足我們的需求。然后我們把返回地址覆蓋為0x4005f3,然后再填充一個0x0讓其popebp用,接著retn時返回地址我們就布置為上面的0x40075a,這樣就完成了rax指令操作后又跳回去執(zhí)行printf函數(shù)了。如何執(zhí)行SYSTEM函數(shù)X64系統(tǒng)下,函數(shù)的參數(shù)都是房子寄存器里的,第一個參數(shù)地址放在rdi里,這樣要執(zhí)行sytem(‘/bin/sh’)我們就需要找到’/bin/sh’字符串的地址,然后把該地址放到rdi再去調(diào)用執(zhí)行system函數(shù),才能獲得shell0x600b30System函數(shù)地址0x600b38‘/bin/sh/’利用ROP執(zhí)行g(shù)ets位于.bss段:固定、可寫這里要控制r15=rdi=0x600b30r12=getsgotrbx=0rbp=1這里要控制r15=rdi=0x600b38r12=0x600b30(system)rbx=0rbp=1構(gòu)造gets函數(shù)讀入system地址和’/binsh’構(gòu)造system函數(shù)target.sendline(rop)觸發(fā)溢出,根據(jù)我們的ROP鏈執(zhí)行g(shù)ets函數(shù),往600b30地址處寫數(shù)據(jù)target.sendline(p64(sys_addr)+'/bin/sh')繼續(xù)利用ROP鏈執(zhí)行SYSTEM函數(shù)GETSHELL!

0x02

格式化漏洞簡要分析任意地址讀取字符串格式化漏洞開啟的保護(hù)措施開啟了RELR0使得我們無法通過覆蓋GOT表來控制程序,開啟了NX使得無法在棧上執(zhí)行代碼。沒開啟PIE這樣代碼段的加載基址是固定的。

根據(jù)漏洞信息和開啟的保護(hù)措施的情況,我們現(xiàn)在能做的就是可以打印libc里的函數(shù)地址。由于提供了libc.so因此同時也可以得到LIBC的加載基址0x02

獲得LIBCBASEADDR格式化字符串漏洞可以導(dǎo)致任意地址寫任意值,但是現(xiàn)在覆蓋GOT表的方式已經(jīng)無效了,那么該如何控制程序流程呢?在執(zhí)行完leave()函數(shù)里的printf函數(shù)后,直接進(jìn)入了exit()函數(shù),我們在該函數(shù)處下斷,跟進(jìn)exit()函數(shù)F7跟進(jìn)call有如下代碼:覆蓋系統(tǒng)調(diào)用kernel_vsyscall發(fā)現(xiàn)最終會調(diào)用sysenter來實現(xiàn)exitCall調(diào)用后面跟的是地址的地址,也就是說內(nèi)存某處有個地址存放的是0xb7760cdc,實際上存放0xb7760cdc的地址就是__kernel_vsyscall的地址。如果覆蓋這個地址指向的內(nèi)容,那么程序在進(jìn)行系統(tǒng)調(diào)用的時候,就可以被我們控制。那么kernel_vsyscall的地址是多少呢?可以得知kernel_vsyscall的地址為0xb75d78e0,實際中還有兩處也可以搜索到這個數(shù)據(jù),但是實踐證明都不是__kernel_vsyscall的地址。這樣我們可以利用這個地址和printf函數(shù)地址的偏移,來定位其真實地址。并且這個偏移和操作系統(tǒng)的版本有關(guān)。定位syscall改寫syscall最后一個字節(jié)為0xEE這樣進(jìn)行系統(tǒng)調(diào)用時直接執(zhí)行retn指令,可以通過棧上的數(shù)據(jù)利用ROP技術(shù)進(jìn)行代碼執(zhí)行改寫syscall實際調(diào)試的時候發(fā)現(xiàn),在執(zhí)行printf函數(shù)的過程中也會進(jìn)行系統(tǒng)調(diào)用執(zhí)行sysenter,也就是覆蓋了kernel_vsyscall后,還沒有到exit的時候,中途已經(jīng)有多次執(zhí)行kernel_vsyscall了,如果不能很好的控制和布局?jǐn)?shù)據(jù),程序流程會出現(xiàn)意外的情況而終止。為了調(diào)試方便,我們需要在格式化寫地址的位置下斷,然后再到我們覆蓋的新地址處下斷來觀察堆棧數(shù)據(jù)布局,然后安排程序執(zhí)行流程。

這里我們先利用格式化漏洞給0x41414141地址寫數(shù)據(jù),由于地址不可訪問,中斷如下:syscall_talbe:p_addr-0x4a3a0

breakpoint:p_addr-0x5bad下好斷點可以看到控制程序流程時:esp=0xBFC6C784我們格式化字符串傳入的數(shù)據(jù)在0xBFC6C834處,兩者相差0xb0。如果我們能找到一條指令比如retn0xb9,讓現(xiàn)在的eip指向此指令,那么執(zhí)行后棧地址就會加0xb9,下次再次retn的時候就可能跳轉(zhuǎn)到棧上我們布局的地址處去執(zhí)行代碼。抬高棧利用工具ROPgadget搜索如下:

ROPgadget--binarylibcmy.so>rx1

grep"ret0xb"rx1rop_addr=libc_base_addr+0x0011b9d2尋找gadget至此已經(jīng)控制了程序流程,并且控制了棧里的數(shù)據(jù)可為我所用。但是由于覆蓋了syscall,我們已經(jīng)沒有辦法再去調(diào)用系統(tǒng)函數(shù)來獲得SHELL了,接下來該怎么獲得SHELL?巧用int80H獲得SHELLLibc.so反匯編可以看到edi為第一個參數(shù),ecx,edx分別為后兩個參數(shù),然后通過給eax賦值中斷向量0x0bh,最后進(jìn)入sysenter執(zhí)行系統(tǒng)功能,通過查找資料,了解到此時直接執(zhí)行int80h也可以達(dá)到同樣的效果。nasm-felf32execve.asm(linux是32位的,如果是64,請使用elf64)

ld-s-oexecveexecve.o

./execve如上圖,可以成功SHELL。于是

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論