棧溢位之Return2libc
參考文章:https://zhuanlan.zhihu.com/p/25816426
我們利用函式呼叫來實現攻擊,核心目的是用攻擊指令的地址來覆蓋返回地址
通常用的有以下四種方法:
修改返回地址,讓其指向溢位資料中的一段指令(shellcode)
修改返回地址,讓其指向記憶體中已有的某個函式(return2libc)
修改返回地址,讓其指向記憶體中已有的一段指令(ROP)
修改某個被呼叫函式的地址,讓其指向另一個函式(hijack GOT)
上次我們講解了一下shellcode,其適合於NX和PIE都不開啟的情況下,但是這種情況幾乎是遇不到的,所以這次我們來了解一下Return2libc
從上面的描述我們知道,要完成的任務包括:在記憶體中確定某個函式的地址,並用其覆蓋掉返回地址
由於 libc 動態連結庫中的函式被廣泛使用,所以有很大概率可以在記憶體中找到該動態庫。同時由於該庫包含了一些系統級的函式(例如 system() 等),所以通常使用這些系統級函式來獲得當前程序的控制權。
鑑於要執行的函式可能需要引數,比如呼叫 system() 函式開啟 shell 的完整形式為 system(“/bin/sh”) ,所以溢位資料也要包括必要的引數。
上圖即為return2libc 所用溢位資料的構造。
padding1
處的資料可以隨意填充(注意不要包含 “\x00” ,否則向程式傳入溢位資料時會造成截斷),長度應該剛好覆蓋函式的基地址。其長度的確定可以通過跟shellcode一樣的,在執行程式時用不斷增加輸入長度的方法來試探。
address of system()
是 system() 在記憶體中的地址,用來覆蓋返回地址。該地址如何確定呢?我們可能需要了解一下動態連結庫的知識:
當函式被動態連結至程式中,程式在執行時首先確定動態連結庫在記憶體的起始地址,再加上函式在動態庫中的相對偏移量,最終得到函式在記憶體的絕對地址。
但是如果作業系統打開了 ASLR(記憶體佈局隨機化),程式每次執行時動態庫的起始地址都會變化,也就無從確定庫內函式的絕對地址。在 ASLR 被關閉的前提下,我們可以通過除錯工具在執行程式過程中直接檢視 system() 的地址,也可以檢視動態庫在記憶體的起始地址,再在動態庫內檢視函式的相對偏移位置,通過計算得到函式的絕對地址。
padding2
處的資料長度為4(32位機),對應呼叫 system() 時的返回地址。因為我們在這裡只需要開啟 shell 就可以,並不關心從 shell 退出之後的行為,所以 padding2 的內容可以隨意填充。
address of “/bin/sh”
是字串 “/bin/sh” 在記憶體中的地址,作為傳給 system() 的引數。
關於ROP和hijack GOT我就不當文字的搬運工了,大家看這裡吧:
長亭科技牛逼!好想加入啊~加油加油加油~