天天看點

C和混編混合程式設計----strcpy緩存溢出原理

今天老師給了一到程式,讓我們分析分析原理,關于strcpy緩存溢出原理的,反彙編一遍遍調試,終于看明白了,記錄一下

C程式:

#include "string.h"
#include "stdio.h"
char *shellcode="\x64\x65\x66\x67\x68\x69\x70\x71\x05\x10\x40\x00";
void fun1(int a, int b)
{
   printf("fun1 run!para a=%d,b=%d\n",a,b);
}
void fun2(int a)
{
   printf("fun2 run! para a=%d\n",a);
}
void fun3(int a,int b,int c)
{
  printf("fun3 run! para a=%d,b=%d,c=%d\n",a,b,c);
}
int main(int argc, char* argv[])
{
	printf("begin\n");
    char a[4]={0};
	strcpy(a,shellcode);
	fun1(2,3);
    fun2(4);
	fun3(4,5,6);

	return 0;
}
           

運作結果:

C和混編混合程式設計----strcpy緩存溢出原理

可以看出,按照正常的C的話,fun2函數應該隻會執行一次,但執行了兩次,事出反常必有妖,讓我們來分析一下,反彙編:

當程式執行strcpy前,a的值是0x0019ff2c,這個是位址,存放的是0000000,在這裡我們要特别注意0019ff30和0019ff34位址裡面的值,後面執行fun2會用到

C和混編混合程式設計----strcpy緩存溢出原理

執行完strcpy後,a内容是位址為0x0019ff2c存放的值,我們可以看到0019ff30和0019ff34位址存放的内容發生了改變,這個時候我們再看C程式中shellcode數組的值:

C和混編混合程式設計----strcpy緩存溢出原理
char *shellcode="\x64\x65\x66\x67\x68\x69\x70\x71\x05\x10\x40\x00";
           

發現0x0019ff2c到0019ff34存放的資料就是這些值,而且0019ff30和0019ff34存放的資料被這些覆寫了。a數組大小為4,shellcode是12,a的數組存放不了shellcode的值,而strcpy函數不會檢查要複制的内容的大小,隻管把要複制的内容複制過來,記憶體不夠,覆寫記憶體中其他資料。

當執行完fun3是,按說應該程式結束,來讓我們看看,為什麼fun2還會執行

C和混編混合程式設計----strcpy緩存溢出原理

當執行到pop ebp是,目前esp的值為0019ff30,内容為68697071,執行完後ebp的值就是68697071,ebp的值原本不是這個,因為使用strcpy把原本的内容覆寫了

C和混編混合程式設計----strcpy緩存溢出原理

當執行到ret時,這個時候我們就要注意了,因為執行完這條語句就會去執行fun2函數,ret指令相當于執行:

pop eip
           

這個時候esp的值為0019ff34,内容為00401005,執行ret後eip=00401005

C和混編混合程式設計----strcpy緩存溢出原理

我們來看看fun2函數位址,是00401005,這就是為什麼執行完fun3回去執行fun2

C和混編混合程式設計----strcpy緩存溢出原理

總結:

  1. strcpy 函數不對數組邊界進行檢查,隻管把要複制的内容複制過來,記憶體不夠,覆寫記憶體中其他資料,很容易造成緩沖區溢出的漏洞
  2. shellcode數組裡的值一共12位,最後ret語句會把最後4位指派給eip,我們可以利用這個跳轉到我們想要執行的代碼處
  3. 向緩沖區内填充資料,如果資料的長度很長,超過了緩沖區本身的容量,那麼資料就會溢出存儲空間,而這些溢出的資料還會覆寫在合法的資料上,這就是緩沖區和緩沖區溢出的道理。

參考

https://blog.csdn.net/yahohi/article/details/7724669

https://blog.csdn.net/xiaoyuai1234/article/details/52121588