萌新帶你開車上p站(終極番外)

本文由「合天智匯」公眾號首發,作者:萌新

 

0x01前言


這關其實和pwn關係不大,主要考察的都是linux下一些函數的操作,考察linux的基本功。涉及到的知識點包括一些經典的函數原型、IO重定向、文件描述符、管道、環境變數、socket編程、符號鏈接等。

這裡順便真心安利一本書,《UNIX環境高級編程》,簡稱APUE書里介紹UNIX文件和目錄、標準I/O庫、系統數據文件和資訊、進程環境、進程式控制制、進程關係、訊號、執行緒、執行緒控制、守護進程、各種I/O、進程間通訊、網路IPC、偽終端等方面的內容,還在此基礎上結合函數原型介紹了多個應用示例,如果這本書啃透,正常題型linux下的pwn問題都不大。

 

0x02


登錄後直接看源文件

可以看到這裡分成了好幾關

先看第一關//argv

第一個if要求傳入100個參數

第二個if要求第A個(也就是ascii的65)參數的值為』\x00』

第三個if要求第B個(也就是ascii的66)的參數值為』\x20\x0a\x0d』

這題我們寫c

這裡的execve的原型為:

int execve(const char * filename,char * const argv[ ],char * const envp[ ]);

execve()用來執行參數filename字元串所代表的文件路徑,第二個參數是利用指針數組來傳遞給執行文件,並且需要以空指針(NULL)結束,最後一個參數則為傳遞給執行文件的新環境變數數組。

也就是說程式碼中的execve是用於執行input程式的,而作為傳入的參數,最後要以null結尾,對應程式碼中的args[100]=NULL

看第二部分//stdio

read函數原型為ssize_t read [1]  (int fd, void *buf, size_t count);

read()會把參數fd所指的文件傳送count 個位元組到buf 指針所指的記憶體中。

而題目源碼中的fd的0,2分別對應的是stdin,stderr,這裡是讀4個位元組到buf

然後調用memcmp

memcmp函數的原型為 int memcmp(const void *str1, const void *str2, size_t n));其功能是把存儲區 str1 和存儲區 str2 的前 n 個位元組進行比較

 

整理一下,程式碼的邏輯就是從stdin中讀4個位元組,與\x00\x0a\x00\xff比較,從stderr讀4個位元組,與\x00\x0a\x02\xff比較

那麼問題來了,stdin是標準輸入,我們可以直接通過輸入來控制,而stderr,該怎麼控制呢

答案是IO重定向

 

這裡涉及管道pipe的應用

pipe有兩端,一段write寫入,一端read讀出,這裡解題用到的就是把管道的read重定向到某一個流中,從而進程間可以進行通訊。

這裡我們的思路是父進程fork子進程,子進程write需要的四位元組到pipe,父進程把pipe的read重定向到stdin,stderr。通過這種方式我們就可以控制stdin和stderr的內容了

先定義pipe

 

第三關//env

strcmp()用於字元串的比較,getenv()用來取得參數envvar環境變數的內容。參數envvar為環境變數的名稱,如果該變數存在則會返回指向該內容的指針。環境變數的格式為envvar=value。

正常情況下肯定沒有0deadbeef的環境變數,要想if條件成立,肯定需要我們自己寫一個鍵值對

我們可以使用setenv()增加環境變數

setenv()原型為int setenv(const char *name,const char * value,int overwrite)

函數說明 setenv()用來改變或增加環境變數的內容。參數name為環境變數名稱字元串。參數 value則為變數內容,參數overwrite用來決定是否要改變已存在的環境變數。如果沒有此環境變數則無論overwrite為何值均添加此環境變數

本地寫好源文件,對應程式碼為

setenv("\xde\xad\xbe\xef", "\xca\xfe\xba\xbe", 1);

 這時候execve傳入的第三個參數為新環境變數數組,我們聲明為environ

 

第四關//file

打開名為」\x0a」的文件,比較前四個位元組是否為」\x00\x00\x00\x00」

這關很簡單,我們相應的用寫許可權打開該文件,寫前四個位元組即可

 

第五關//network

程式碼的意思是以input這個文件作為伺服器,監聽C埠

通過recv來接收,如果收到的為\xde\xad\xbe\xef,則通過

我們根據對應的程式碼稍微修改下就可以了

在本地編寫完整的程式碼

通過scp上傳

登錄後切換到相應的路徑編譯源文件

直接執行是會報錯的,因為當前目錄下沒有flag文件,我們又沒有許可權移動它,此時可以考慮使用符號鏈接的方式,通過絕對路徑或者相對路徑的形式指向flag。因為對符號鏈接文件進行讀寫會表現為直接對目標文件進行操作

這裡是讓/tmp/yale/flag直接指向/home/input2/flag,然後執行

Tags: