ROP Emporium
ROP Emporium 是一個ROP攻擊入門教學網站,提供了一系列的挑戰任務,這些挑戰對逆向工程或debug的要求不高,因此對初學者十分友好,適合初學者瞭解ROP攻擊。網站中共有8個挑戰任務,每個挑戰都引入了一個新概念/知識點,其複雜性和難度逐漸增加,循序漸進,而且每個挑戰都有32/64位兩個版本的程序,適合初學者瞭解二者之間的差異。
本文提供ROP Emporium所有挑戰的說明文件、二進制文件、在線動態靶機環境以及一些相關解題線索。讀者可前往動態靶場完成任務後,再返回本文查看相應題目的知識點、解題思路以及解題腳本。
附件下載:rop_emporium_all_challenges.zip
動態靶場:CTFq動態靶機練習平臺
靶機環境:Ubuntu 18.04
讀者可前往動態靶場完成任務後,再返回本文查看相應題目的知識點、解題思路以及解題腳本。
⓪ret2win
ret2win means ‘return here to win’ and it’s recommended you start with this challenge.
ret2win就是利用漏洞直接將程序控制流劫持到程序預置的後門函數win
win函數通常是可以打印flag,或者getshell
知識點
- 緩衝區溢出(覆蓋返回地址)
思路
- 使用ida或cutter反編譯程序
- 找到後門函數
ret2win
的地址 - 利用緩衝區溢出覆蓋返回地址爲後門
題解
建議完成任務後再查看題解
備註
本地測試64位程序時可能遇到的問題:
movaps xmmword ptr [rsp + 0x40], xmm0
出現這個問題的原因是執行某些libc
函數(如printf
, system
)時,棧指針rsp
沒有對齊0x10
字節,解決方法如下:
-
ret2win
時儘量避開棧操作指令:.text:0000000000400811 ret2win proc near .text:0000000000400811 ; __unwind { .text:0000000000400811 push rbp .text:0000000000400812 mov rbp, rsp .text:0000000000400815 mov edi, offset aThankYouHereSY ; "Thank you! Here's your flag:" .text:000000000040081A mov eax, 0 .text:000000000040081F call _printf .text:0000000000400824 mov edi, offset command ; "/bin/cat flag.txt" .text:0000000000400829 call _system .text:000000000040082E nop .text:000000000040082F pop rbp .text:0000000000400830 retn .text:0000000000400830 ; } // starts at 400811 .text:0000000000400830 ret2win endp
0x400811
處的push rbp
將使得rsp=rsp-0x8
,導致rsp
不能對齊0x10
稍作調整,跳過棧操作,改用
0x400815
即可 -
使用gadget (ret) 調整棧指針
①split
Combine elements from the ret2win challenge that have been split apart to beat this challenge. Learn how to use another tool whilst crafting a short ROP chain.
與ret2win
相比,這題將後門執行的命令由cat flag
改爲了/bin/ls
,因此不能直接獲取flag,但程序中給出了/bin/cat flag.txt
這個字符串,因此可以通過構造簡單的ROP鏈獲取flag
將
/bin/cat flag.txt
作爲參數傳給system
函數
知識點
- 簡單ROP鏈的編寫
思路
- 使用ida或cutter反編譯程序
- 找到指令
call system
的地址 - 找到字符串
/bin/cat flag.txt
的地址 - 構造rop鏈
- 利用緩衝區溢出覆蓋返回地址爲rop鏈
題解
建議完成任務後再查看題解
②callme
Chain calls to multiple imported methods with specific arguments and see how the differences between 64 & 32 bit calling conventions affect your ROP chain.
這題提供了一個自定義的動態鏈接庫,其中包含callme_one
,callme_two
和callme_three
,讀者需要通過ROP配置好相應的參數,並依次調用這三個函數來解密並輸出flag。
知識點
- 動態鏈接庫、PLT表
思路
- 使用ida或cutter反編譯程序、動態鏈接庫
- 在動態鏈接庫中大致瞭解三個
callme
函數的功能 - 在程序中找到三個
callme
函數在PLT表中的地址 - 構造rop鏈,配置函數參數
- 利用緩衝區溢出覆蓋返回地址爲rop鏈
題解
建議完成任務後再查看題解
③write4
Find and manipulate gadgets to construct an arbitrary write primitive and use it to learn where and how to get your data into process memory.
在這道題中,通過gadget可以實現內存任意寫,目標是將字符串/bin/sh
或$0
寫入內存。
知識點
- 任意寫gadget
思路
- 使用ida或cutter反編譯程序
- 找出可用於任意寫的gadget
- 構造rop鏈,將字符串寫入
bss
段 - 利用緩衝區溢出覆蓋返回地址爲rop鏈
題解
建議完成任務後再查看題解
備註
$0
的含義是第0個參數,即argv[0]
,默認情況下程序是通過/bin/sh
啓動的,因此argv[0]
就是/bin/sh
,在本題32位程序的題解中,使用$0
代替/bin/sh
作爲system
執行的命令。
④badchars
Learn to deal with badchars, characters that will not make it into process memory intact or cause other issues such as premature chain termination.
這道題與③write4相比,新增了對badchar的檢測,並且將用於任意寫的gadget換成了具有異或(寫內存)功能的gadget,因此目的是練習通過異或對badchar進行繞過。
badchar爲 b i c / f n s,所以其實也可以通過
$0
繞過
知識點
- 異或功能gadget
思路
- 使用ida或cutter反編譯程序
- 找出可用於異或寫內存的gadget
- 構造rop鏈,通過多次異或繞開badchar,將字符串寫入
bss
段 - 利用緩衝區溢出覆蓋返回地址爲rop鏈
題解
建議完成任務後再查看題解
懶得寫異或的exp了,大概就那個意思…
⑤fluff
Sort the useful gadgets from the fluff to construct another write primitive in this challenge. You’ll have to get creative though, the gadgets aren’t straight forward.
這題還是和③write4類似,與之相比,去掉了可以直接寫內存的gadget,換成了一些更爲複雜的gadget,因此需要利用多個gadget組合、配合實現寫內存的功能。
知識點
- 組合gadget,間接實現任意寫
思路
- 使用ida或cutter反編譯程序
- 找出可用於寫內存的gadget(這題多個gadget組合才能完成任意寫)
- 構造rop鏈,將字符串寫入
bss
段 - 利用緩衝區溢出覆蓋返回地址爲rop鏈
題解
建議完成任務後再查看題解,出於練習的目的,建議使用預期解再看一遍
32位程序的解法是預期解,64位的我偷了個懶:-p
⑥pivot
Stack space is at a premium in this challenge and you’ll have to pivot the stack onto a second ROP chain elsewhere in memory to ensure your success.
這題給了一個自定義的動態庫,要求調用其中的ret2win
函數,此外棧溢出的可利用空間不足,需要利用題目中給出的gadget進行棧遷移(交換rax和rsp)
知識點
- 棧遷移、動態鏈接庫、GOT表
思路
- 使用ida或cutter反編譯程序
- 棧遷移至題目給出的新緩衝區
- 構造rop鏈:
- 從foothold_function的GOT表泄漏libpivot地址
- 根據偏移量計算ret2win的真實地址
- 執行ret2win
題解
建議完成任務後再查看題解,出於練習的目的,建議使用預期解再看一遍
⑦ret2csu
Learn a ROP technique that lets you populate useful 64 bit calling convention registers like rdi, rsi and rdx even in an environment where gadgets are sparse.
知識點
__libc_csu_init
中的gadget
思路
- 使用ida或cutter反編譯程序
- 構造rop鏈:
- 通過
__libc_csu_init
中的gadget給rdx賦值 - 調用
fini_array
中的函數,保持rdx不變 - 執行ret2win函數
- 通過
- 利用緩衝區溢出覆蓋返回地址爲rop鏈
題解
建議完成任務後再查看題解,出於練習的目的,建議使用預期解再看一遍