1. 程式人生 > >一個簡單的例子入門pwn

一個簡單的例子入門pwn

首先,pwn大概是pwn  to  own的意思,就是通過二進位制/系統呼叫等方式獲得目標主機的shell

我直接以一個非常簡單的棧溢位例子(基於Linux)來講解pwn所要用到的一些常用的工具及命令;

所需要的工具安裝等,可以先看這個連結(https://blog.csdn.net/qq_40827990/article/details/83217716)

例子下載地址:https://download.csdn.net/download/qq_40827990/10740077

https://pan.baidu.com/s/1feWmSgR2c9mStjR6uzEO8Q

前言:棧溢位就是緩衝區溢位的一種。 由於

緩衝區溢位而使得有用的儲存單元被改寫,往往會引發不可預料的後果。程式在執行過程中,為了臨時存取資料的需要,一般都要分配一些記憶體空間,通常稱這些空間為緩衝區。如果向緩衝區中寫入超過其本身長度的資料,以致於緩衝區無法容納,就會造成緩衝區以外的儲存單元被改寫,這種現象就稱為緩衝區溢位。緩衝區長度一般與使用者自己定義的緩衝變數的型別有關。

從組合語言的方面來講直白但是不是特別準確的來講就是,當我們call一個函式的時候,我們會把返回地址push到棧中,但程式沒有檢查機制的時候,如果使用者輸入的字串太長了,就會覆蓋到返回地址,這時候程式就會出錯;但如果我們別有用心的構造一段字串來覆蓋返回地址的話,就可以讓程式執行我們想做的事情,為所欲為;

好了,直接開始講吧;

1.我們先用file命令檢視一下檔案的基本資訊:

可以看到這是一個32位的ELF檔案(這個影響後面我們shell code的書寫);

2.然後我們用checksec命令檢視一下檔案的安全性:

【1】RELRO:RELRO會有Partial RELRO和FULL RELRO,如果開啟FULL RELRO,意味著我們無法修改got表,設定符號重定向表格為只讀或在程式啟動時就解析並繫結所有動態符號,從而減少對GOT(Global Offset Table)攻擊。RELRO為”Partial RELRO”,說明我們對GOT表具有寫許可權

【2】Stack:如果棧中開啟Canary found,那麼就不能用直接用溢位的方法覆蓋棧中返回地址,而且要通過改寫指標與區域性變數、leak canary、overwrite canary的方法來繞過

【3】NX:NX enabled如果這個保護開啟就是意味著棧中資料沒有執行許可權,以前的經常用的call esp或者jmp esp的方法就不能使用,但是可以利用rop這種方法繞過

【4】PIE:PIE enabled如果程式開啟這個地址隨機化選項就意味著程式每次執行的時候地址都會變化,而如果沒有開PIE的話那麼No PIE (0x400000),括號內的資料就是程式的基地址 ;

這裡主要用到的資訊是stack裡的,沒有開啟保護;

3.然後我們看看程式的功能:

先直接執行程式看看,發現只有一個使用者輸入的地方:

然後用objdump  -R,檢視一下程式的只要函式有哪些;

然後看到這裡有一個關鍵的函式:system();

4,然後我們將檔案載入IDA中分析一下:

這裡我們看到一個明顯的gets()函式,這是一個非常不安全的函式,會造成溢位覆蓋到返回地址;

5,所以我們現在來看看多少位元組的字串會造成溢位覆蓋到返回地址;

這裡我們用cyclic命令來生成特定的字串,cyclic生成的字串的特點就是任意四個連續的字串都是獨一無二的,之後我們就可以通過檢測這個字串是多少來計算多少位元組的字串會造成溢位覆蓋到返回地址了;

我們先生成200個這樣的字串:cyclic 200

然後複製這串字串,用gdb執行epwn程式,並輸入這段字串:

(我的gdb安裝了pwngdb外掛);

因為根據呼叫約定,通常將函式的返回值放在EAX,這裡明顯返回地址被覆蓋了,根據不同的程式報錯的位置可能在DISASM中;

所以這裡我們用cyclic –l  0x62616164 來計算多少個字元覆蓋返回地址:

這裡看到是112個字元;

6,最後我們就要找將返回地址修改為什麼地方,才可以執行我們想要的東西,因為之前我們找到了一個sysytem()函式,所以我們只要找到這個函式的地址,用這個地址去覆蓋返回地址,就可以了:

我們在IDA中看到了system()的地址是0x08048641,因為這個函式相當於需要一個引數”/bin/sh”,所以要將返回地址覆蓋為0x0804864A;

7,知道了所有想要的資訊了,我們就可以寫shellcode了:

基本格式:

from pwn import *

p = process('檔案相對路徑')

p.sendline(需要填充的字元+ p32(修改的返回地址))

p.interactive()

 

此題shellcode:

from pwn import *

p = process('./ret')

p.sendline('a'*112+ p32(0x0804863A))

p.interactive()

這個是用python2寫的,如果程式是64位的,需要將p32換為p64;

執行結果:

Ok,就這樣了……

如果有哪裡出錯了請指出,感謝!