1. 程式人生 > 其它 >20192431張瀟文《網路與系統攻防》實驗一 逆向及Bof基礎實踐

20192431張瀟文《網路與系統攻防》實驗一 逆向及Bof基礎實踐

實驗 逆向及Bof基礎

1.1 實驗目標

實驗物件是pwn1的Linux可執行檔案,該程式原本的正常執行流程是main函式呼叫foo函式,foo函式會回顯使用者輸入的字串。另一個程式碼片段為getshell,正常情況下這個程式碼段是不會執行的,本次的實驗目標就是想辦法執行這個程式碼片段。
實驗目標是:

  1. 學會利用反彙編檢視程式程式碼,使用vi等編輯器來手工修改call指令要跳轉到的地址,要會算這個地址,學會使用補碼進行地址的計算。從而使得程式直接跳轉到getshell。
  2. 通過foo函式的Bof漏洞,構造攻擊的字串覆蓋到函式的返回地址,從而使得程式跳轉到getshell函式。
  3. 仍然利用這個漏洞,注入一個自己的shellcode並執行。
  4. 通過這些過程瞭解緩衝區溢位的原理,掌握一些基礎的Linux命令。

1.2 基礎知識的學習以及原理的理解

  1. Linux基本操作命令:
    反彙編命令:objdump -d pwn20192431 | more
    -d表示disassemble ,表示從objfile中反彙編那些特定指令機器碼的section。
    more表示分頁顯示
    管道符表示將前面每一個程序的輸出直接作為下一個程序的輸入
    perl -e 'print "11111111222222223333333344444444\x7d\x84\x04\x08\x0a"' > input
    輸出重定向 >可以把一些字串或者一些檔案等輸出到一個新的檔案當中,在實驗裡輸入input檔案的時候都用到了輸出重定向。
    perl
    在linux下可以理解為增強版本的shell,是一種指令碼語言,具有程式結構,很多內建功能,也方便呼叫其它程式。
    catcat命令是linux下的一個文字輸出命令,通常是用於觀看某個檔案的內容的。
    xxd16進位制檢視檔案的內容。
    (gdb)info r用來顯示暫存器的值,可以方便我們找到EIP,EBP的值。
    cp可以複製這個檔案,用來備份。
    查詢需要的地址\e8d7,能夠省下一定的查詢所需要的時間。
    轉換16進製為原格式:%!xxd -r。
    轉換root許可權su
  2. EIP暫存器:EIP暫存器始終儲存的是下一條將要執行的指令的地址,所以在實驗當中就可以考慮改變EIP的值,使他指到我們的目標函式執行的地址。
  3. call指令:call指令就相當於兩條指令,分別是mov和jmp。先把下一個IP壓入棧後,跳轉到所要執行的地址,呼叫子函式。
  4. 補碼計算指令的地址,比如說本次實驗中的call 8048491,就是foo函式的地址,e8是跳轉的意思,d7ffffff是補碼,就是用你需要執行的函式地址減去下一條指令的地址,取補碼就可以算出來。可以採用計算器進行計算也可以手動按照補碼的規則進行計算。
  5. 堆疊的原理和緩衝區溢位的原理:
    記憶體和棧的增長方向是相反的,如下圖:也就是主函式先

實踐1 直接修改程式機器指令,改變程式的執行流程

1.1實驗思路

實驗思路:因為這個程式執行的過程比較簡單,就是通過call,把我們想要呼叫的函式的地址壓入EIP,使得執行的時候就執行到這個程式,我們就可以採用vi編輯器,直接把這個程式以16進位制的方式輸入到螢幕當中,然後通過r,修改一下地址就可以使得call的時候把getshell的執行地址壓入EIP中,然後觸發想要執行的函式。

1.2實驗步驟

  1. 使用objdump檢視原檔案的函式呼叫的過程,可以看到在主函式中,最右邊的組合語言裡有一個call 8048491,就說明接下來將要把這個foo函式調進來,然後呢左邊就是e8機器碼,跳轉到ffffffd7的位置,只要把這個使用vi編輯改掉就可以了。

  2. 通過計算(8048491-80484ba)補,可以算出ffffffc3就是getshell的地址,於是呢按:wq!儲存並退出即可。

  3. 再使用objdump反彙編修改好了程式,來驗證是否成功修改,如下圖:

  4. 執行一下修改後的檔案可以發現,修改後的檔案,就會從原來的回顯,變成現在的shell(類似於命令列)。

實踐2 通過構造輸入引數,造成BOF攻擊,改變程式執行

2.1 基礎知識

  1. 堆疊結構:一種先進後出的結構,通常用在函式的呼叫過程當中,基本的操作就是壓棧和彈棧,函式呼叫的過程和棧的先進後出的結構很類似,比如主函式第一個執行,最後一個退出。在記憶體中,函式是由高地址向低地址增長的。放的時候是高地址到低地址,指令執行的時候是低地址到高地址。
  2. 緩衝區溢位:馮諾依曼結構的缺陷就是資料和指令不好區分,所以填充過多的資料就會造成緩衝區溢位,改變了返回的地址。關鍵在於確定溢位的位置。溢位的位置就是在棧這種資料結構

2.2實驗步驟

  1. 觀察程式的漏洞,如圖:我們可以看到foo函式的漏洞在於這一個地方:

    sub $0x38,%esp
    lea -0x1c(%ebp),%eax。
    mov %eax,(%esp)
    思路:第一個指令就是給了foo函式一個棧幀,一個38的空間,下一個也就是表面了緩衝區的大小就是十進位制28這麼大的空間,也就是說一個字串的前28個會放到這個空間裡,超出的部分就會覆蓋別的地方,後面四個位元組是EBP,如果接下來的四個位元組則是EIP,如果我把getshell的地址放在這裡就可以使得程式跳轉到getshell執行。所以最重要的是三十二個位元組之後的那四個位元組。寫什麼很重要。call呼叫foo,會在堆疊上壓上返回地址值:80484ba,也就是下一條指令的地址。

  2. 確認哪些字元會覆蓋到返回地址:

通過gdb來除錯,用r,就是開始執行,可以看到不超過28的時候,沒問題,超過以後就會報出段錯誤。因為地址被改掉了。就可以看到是四個5覆蓋到了返回地址。接下來顯示暫存器的值。確認好究竟是哪些字元會覆蓋上去。
3. 只要把getshell的記憶體地址放到EIP上就行了,因為是小端優先,所以用\x7d\x84\x04\x08寫在那個位置上就可以。由於鍵盤沒辦法輸入ASCII碼,所以採用perl語言輸入。把這個字串放入input這個檔案。這裡就用到了輸出重定向。
4. 用16進位制檢視input裡的內容是否和我們預期的一樣。

5. 將input的輸入通過管道符,作為pwn的輸入。
6. 執行一下驗證可以看到已經成功的呼叫了getshell了。

實踐3 注入shellcode並執行

3.1 實驗思路

最重要的是考慮構造的shellcode的哪一部分會覆蓋EIP的值。shellcode要放在哪裡。EIP肯定需要放shellcode的起始地址,所以shellcode可能放在EIP之前,也可能放在EIP之後。前面的32位元組可以隨便填,後四個位元組放SHELLCODE的地址,但是要確定注入的時候記憶體把shellcode分配在哪裡了。所以常常在shellcode里加好多好多的空指令,看有沒有空指令落在RS上。

3.2 實驗步驟

  1. 準備一段shellcode,shellcode是一段機器指令。一般是為了獲取互動式的shell。
  2. 準備工作:
    要設定堆疊可執行,因為shellcode一般都是在快取區裡,只要作業系統限制堆疊中的資料只可讀寫,不可執行,一旦堆疊中的資料被執行立即報告錯誤,並退出。那麼溢位成功後也不能執行shellcode。但是為了本次實驗就需要設定堆疊可執行。
    同時也要關閉地址隨機化,也是為了防止緩衝區注入攻擊。不然每次的堆疊地址都不一樣,除錯起來就非常的麻煩。
  3. 構造要注入的程式碼。
    Linux下有兩種基本構造攻擊buf的方法:
    retaddr+nop+shellcode
    nop+shellcode+retaddr。
    使用第一種方式。
    perl -e 'print "\x90\x90\x90\x90\x90\x90\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x31\xd2\xb0\x0b\xcd\x80\x90\x4\x3\x2\x1\x00"' > input_shellcode
    由於返回位置大概在33,34,35,36的位置,所以呢就看上面最後的\x4\x3\x2\x1將覆蓋到堆疊上的返回地址的位置。我們得把它改為這段shellcode的地址。
  4. 利用gdb來除錯,找到1234的地址改成在記憶體的地址。首先找到程序號,啟動程序的除錯,然後設定斷點斷在ret,執行完ret以後就會把1234push進去。如圖:

我們可以看到我們的esp的棧頂的地址是:ffffd16c
找空指令就可以看到我們的shellcode的位置是:ffffd170,所以也就是說把1234改成我們自己的地址的話就可以成功的注入了。
5. 把shellcode輸入到檔案裡
6. 注入到程式碼中,就可以看到我們的實驗已經成功了。

四 實驗中遇到的問題

  1. 實驗三不能加\0a的原因是為了讓程式能夠停在那裡,相當於沒輸回車,就可以停在那邊觀察。
  2. 實驗三還出現注入沒有成功的情況:如圖:

原因是因為我最開始照搬了老師的地址,沒有看自己的地址,後來重新使用gdb查看了自己的地址之後,實驗成功。
3. 在實驗過程當中,出現了在虛擬機器裡安裝gdb的時候出現網址not found的情況。解決方法,經過查詢資料以後是因為以前使用的是國外的更新源,後來通過vim /etc/apt/sources.list指令把以前的網址註釋掉了,加上了清華源,然後再去安裝那些軟體最後就成功了。
4. 在修改主機名的時候,說我沒有許可權,而且當時修改更新源的時候還出現了Linux修改檔案出現錯誤E45:“readonly” option is set(add ! to override)退出不了vim。原因是因為我當時沒有以root身份登入這個kali。後來最開始解決的方法是切換成了root使用者,使用sudo passwd root設定密碼,然後用su切換身份最後成功。