逆向入門--第一次的HelloWorld
終於算是慢慢的爬入了逆向的大門,夢想雖遠,堅持就好
記第一次簡單的逆向過程
首先貼出CrackMe的原始碼,很簡單的一個if而已
#include <stdio.h>
#inclued <stdlib.h>
int main(int argc, char **argv)
{
char passWord[8] = {"pass"};
char word[8] ;
gets(word);
if(strncmp(passWord, word, 8) == 0)
{
printf("authorized !\n" );
}
return 0;
}
程式碼很簡單,輸對了就列印
(當然這個還存在緩衝區溢位,這個後面講)
開始Crack
因為我們的EXE檔案是標準的PE( Portable Executable )
所以我們使用IDA(靜態分析除錯工具)對檔案進行檢視
IDA 相當與我們的地圖一樣的作用
這個就是我們的IDA 載入之後的程式 ,當然是彙編,的形式
第一行可以看到,是main的入口
很多人都是認為程式是從main函式開始 的,其實不然,程式真正的入口我們稱之為OEP(original entry point)
然後我們向下讀程式碼,
30 地址之前的就是我們的變數地址分配,
ebp,exp也就是我們常提起的bp 和 sp 的extend版本
31到36是我們的棧初始化
- 30 基址壓棧
- 31 基址賦值
- 33 對棧指標做掩碼??(沒弄懂這個作用)
- 36 對棧頂指標做減法,即分配棧空間 20*16 個位元組
- 39 call _main (這裡才是真正的進入了main函式中去)
39往後main裡
- 3E 就是變數賦值 可以看到 str1的值是 -8h (這裡就很好解釋了棧地址是如何向低地址增長的),後面的字串當時我還沒反應過來,其實是端序的問題,在Win裡 都是大端格式,所以向下增長 的時候字串要反過來
- 46 這裡就是對字串後面新增 \0 作為結束符
- 4E ~52 原理同上分配buffer(IDA已經自動註釋,美哉)
- 55 就是呼叫我們的gets函式
- 5A~6E 就是strncmp的引數配置,str1 str2 maxcount這三個
- 71 呼叫strncmp函式
76 這個比較重要 這裡的顯然是不改變eax的值的,那麼他的作用是什麼呢? 就是設定flag暫存器的狀態
test 的作用不同於 cmp ,cmp 相當於算數相減,而test 是邏輯相與
所以這裡只有eax為0h的時候 才會出現 設定Z位為1
- 78這裡就是我們核心的一句! jnz就是不為零就調轉,而下面就是我們的puts 得到的函式,所以要想成功破解,這裡的就必須不能跳轉!
- 7A 字串壓棧,
- 81 列印
- 86~8B 就是我們的return 0了
eax 預設的就是傳遞的第一個引數
到此程式的靜態解讀告一段落 下面就是我們使用ollydbg進行動態除錯,或者直接使用UE對pe檔案進行修改(直接改jnz的彙編碼即可) Ollydbg: ![這裡寫圖片描述](https://img-blog.csdn.net/20170901001708367?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQveno3MDkxOTY0ODQ=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast) (2333 ollydbg 看著還是挺帥的) 這裡的地址,可以在ida裡面找到; 下面就是修改那個jnz了,反正什麼都行
- jz 剛好相反
- nop 啥都不動向下執行
那就Nop吧 隨便改一改
可見我們的authorized已經打印出來了
本次簡單逆向也是告一段落了
附加
下面附件一點:
* 緩衝區溢位問題*
因為上面剛剛好有彙編的程式碼,這樣解釋起來就是變得簡單了
可以看到,棧的空間分配是連續的,所以我的緩衝區給的大小是8 那麼這樣的話,他地址會基於棧地址來減去八個位元組,然而,gets() 函式是不會判斷緩衝區大小的,所以會把我們的輸入直接寫到地址。
所以,漏洞就產生了,
str1,str2 是地址連續的兩個8位元組的空間,那麼我們只要輸入一個16位元組對稱的字串,就可以完美繞過!
效果如上!
寫在最後的話
送給大家一句話吧: 鴻鵠志高而難酬,終而還是妥協泯然眾人
“”小鎮青年何必遠方?“” 於是我走出了這個熟悉的地方