適合初學者的ROP攻擊入門教程 - [Pwn] ROP Emporium Guide

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_twocallme_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鏈

題解

建議完成任務後再查看題解,出於練習的目的,建議使用預期解再看一遍

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章