HITB_Binary_100_writeup

HITB Binary 100是之前的HITB CTF的一道簡單的逆向題,這裏簡單做一遍。

下載hitb-bin100.elf

將elf文件先跑一下,發現像歌詞播放一樣、每個一秒鐘左右輸出一句話,歌詞好像沒啥用,而且運行很久也還沒停下來:

根據字符串檢索法,扔到IDA的String窗口查看是否存在關鍵字符串,可以看到有“FLAG”相關的字符串:

點擊進去查看,發現這段代碼是在main()函數中的:

接着查看一下該二進制文件的函數等信息:

nm命令被用於顯示二進制目標文件的符號表,如函數和全局變量等。

objdump查看目標文件或者可執行的目標文件的構成的gcc工具。-t ,--syms,顯示文件的符號表入口。類似於nm -s提供的信息。objdump -t obj:輸出目標文件的符號表。

在Function Window也可以看到,除了調用一些標準庫的函數,整個程序幾乎都編譯到了main函數中:

查看main函數的彙編代碼,可以看到有兩個地址值得研究,即4007e8和400803,因爲其中都是會調用printf函數輸出內容:

直接在GDB上運行並jump到相應的地址查看:

可以看到,KEY是正常的輸出出來了,但是FLAG輸出的是一堆亂碼,然後就出現“stack smashing detected”的錯誤而終止運行了。跳過去直接輸出Flag是不可能的了。

F5看一下僞代碼吧,看到在輸出flag前一段主要的代碼:

分析可知,v20變量存放的是該循環執行的次數、無法改變;v21變量調用time函數生成一個時間戳,用於後續與v6變量的相減形成隨機種子值;v11變量用於內循環執行的次數,從0-36;v6變量同樣調用time函數生成一個時間戳,與v21變量不同在於每次內循環結束後重新生成時間戳時都會先sleep 1s後再生成;在內循環的最後是一個sleep()函數,調用來休眠1s;其餘的代碼都是用於生成輸出的字符串。

這裏如果想直接nop掉sleep()函數是行不通的,因爲整段代碼的執行依賴於該sleep()函數,v6與v21的差值在每次內循環結束的時候都會通過sleep()函數實現增一,如果不這樣正常處理,將得不到正常的flag。

換個思路,這裏關鍵的兩個函數是sleep()和time(),我們可以重新定義該兩個函數,通過LD_PRELOAD預先加載這兩個函數而不是調用系統自己的從而實現欺騙程序該代碼確實是睡眠了1s了,也就是說,自定義的sleep()函數直接對時間變量t自增1而不是真的等待了一秒才運行結束,從而可以將程序的休眠時間去掉:

gcc編譯爲so文件(-fpic參數指定爲位置無關、即使用相對地址,-shared參數指定爲共享庫),再通過LD_PRELOAD在該elf程序運行前優先加載生成的動態鏈接庫time.so並管道輸出到一個文件中查看,可以看到輸出了flag:

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