最近做一些難的題目,越來越自閉,感覺自己的基礎知識還有待補充,索性暫停源短時間做題,先把一些基礎知識理一理。本系列博客以《ctf-in-all》以及i春秋的《linux pwn基礎入門》為基礎開始學習。
第一篇博客,來理一理如何利用漏洞獲取libc。
首先,libc是什么?
libc 即在 Linux系統下的C語言函數庫。
不同版本的libc,函數首地址相對於文件開頭的偏移和函數間的偏移不 一定一致。所以如果題目不提供libc,通過泄露任意一個庫函數地址計算出system函數地址的方法就不好使 了。這就要求我們想辦法獲取目標系統的libc。
在某不知名網站找到了一段視頻,講了一下關於這一知識點,講的比較通俗易懂,就將部分重要的地方截了下來。
在《Linux PWN入門》和《ctf-in-all》中主要就是使用DynELF來泄露函數地址。
利用 如 pwntools 的 DynELF 模塊,對內存進行搜索,直接得到我們需要的函數地址。
下面闡述一下關於DynELF的知識點:
使用方法如下:
io = remote(ip, port) def leak(addr): payload2leak_addr = “****” + pack(addr) + “****” io.send(payload2leak_addr) data = io.recv() return data d = DynELF(leak, pointer = pointer_into_ELF_file, elf = ELFObject) system_addr = d.lookup(“system”, libc)
使用DynELF時,我們需要使用一個leak函數作為必選參數,指向ELF文件的指針或者使用ELF類加載的目標文件至少提供一個作為可選參數,以初始化一個DynELF類的實例d。然后就可以通過這個實例d的方法lookup來搜尋libc庫函數了。
其中,leak函數需要使用目標程序本身的漏洞泄露出由DynELF類傳入的int型參數addr對應的內存地址中的數據。且由於DynELF會多次調用leak函數,這個函數必須能任意次使用,即不能泄露幾個地址之后就導致程序崩潰。由於需要泄露數據,payload中必然包含着打印函數,如write, puts, printf等,我們根據這些函數的特點將其分成兩部分分別進行講解
DynELF原理:
截圖自《ctf-in-all》
DynELF實例:
在 libc 中,我們通常使用 write 、 puts 、 printf 來打印指定內存的數據。
1、write 函數
write函數的特點在於其輸出完全由其參數size決定,只要目標地址可 讀,size填多少就輸出多少,不會受到諸如‘\0’, ‘\n’之類的字符影響。因此leak函數中對數據的讀取 和處理較為簡單。
2、puts 函數
3、printf 函數