日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > linux >内容正文

linux

linux strcpy函数实现,strcpy(char *dest , char *src)的漏洞

發布時間:2023/12/4 linux 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 linux strcpy函数实现,strcpy(char *dest , char *src)的漏洞 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

前言:研究了幾天DOS下的溢出原理,最后明白了其實原理都很簡單關鍵是要懂得為什么C語言的strcpy函數有漏洞,為什么對這個函數的不正常使用會造成溢出。

一節:介紹strcpy函數能看到這篇文章的人可能都知道問題很多是出在它的身上吧呵呵。

先看一看在標準的C語言的string.h中對這個函數的申明char *_Cdecl stpcpy (char *dest, const char *src);對于代碼看下面的:(這是微軟對這個函數的說明)

(%VC%/vc7/crt/src/intel/strcat.asm)

;***

;char *strcpy(dst, src) - copy one string over another

;Purpose:

; Copies the string src into the spot specified by

; dest; assumes enough room.

;

; Algorithm:

; char * strcpy (char * dst, char * src)

; {

; char * cp = dst;

; while( *cp++ = *src++ ); /* Copy src over dst */

; return( dst );

; }

;Entry:

; char * dst - string over which "src" is to be copied

; const char * src - string to be copied over "dst"

;

;Exit:

; The address of "dst" in EAX

;

;Uses:

; EAX, ECX

;

;Exceptions:

;**********************************************************************

本來想去掉一些注解,不過覺得還是留著好哈:)

從上面我們可以看到這樣的代碼有問題有:

1.沒有檢查輸入的兩個指針是否有效。

2.沒有檢查兩個字符串是否以NULL結尾。

3.沒有檢查目標指針的空間是否大于等于原字符串的空間。

好了現在我們知道了對于調用string.h中的這個函數,和我們自已寫一個如下的程序沒有本質上的區別那么我們就來研究它就可以了.就叫它c4.exe吧.

main(){j();}

j()

{

char a[]={a,b,};

char b[1];

char *c=a;

char *d=b;

while(*d++=*c++);

printf("%sn",b);

}

二節:調試我們的c4.exe

所用工具W32dasm,debug,tcc,tc

第一步我們用TC2編繹生成可執行文件c4.exe.

第二步用TCC -B生成這段C代碼的匯編源代碼.

第三步用W32dasm和debug對c4.exe進行靜態和動態調試

先分析由TCC生成的c4.asm代碼如下:

先說明一下由于這是一個完整的包括了MAIN函數的C程序,程序剛開始時數據段和堆棧段還有代碼都不在一起但是當,執行到我們的J函數時堆棧和數段就在一起了這要特別注意.

ifndef ??version

?debug macro

endm

endif

?debug S "c4.c"

_TEXT segment byte public CODE

DGROUP group _DATA,_BSS

assume cs:_TEXT,ds:DGROUP,ss:DGROUP

_TEXT ends

_DATA segment word public DATA

d@ label byte

d@w label word

_DATA ends

_BSS segment word public BSS

b@ label byte

b@w label word

?debug C E930A68D2E0463342E63

_BSS ends

_TEXT segment byte public CODE

; ?debug L 1

_main proc near

; ?debug L 3

call near ptr _j //這兒執行我們的J函數

@1:

; ?debug L 4

ret

_main endp

_TEXT ends

_DATA segment word public DATA //最先在數據段中定義我們的源串ab結尾符

db 97

db 98

db 0

_DATA ends

_TEXT segment byte public CODE

; ?debug L 6

_j proc near

push bp //J函數入口

mov bp,sp

sub sp,6

push si

push di

push ss

lea ax,word ptr [bp-6]

push ax

push ds

mov ax,offset DGROUP:d@ //特別注意這是得到源串在數據段中的偏移

push ax //所有SCOPY@以上的代碼的作用是在堆棧中分配源串加目的串那么多個空間

mov cx,3 //cx=3指定要拷貝的字符數

call far ptr SCOPY@ //執行了另一個函數作用是把數據段中的源串拷到棧中

; ?debug L 10

lea si,word ptr [bp-6]

; ?debug L 11

lea di,word ptr [bp-2]

; ?debug L 12

jmp short @3

@5:

@3:

; ?debug L 12

mov bx,si

inc si

mov al,byte ptr [bx]

mov bx,di

inc di

mov byte ptr [bx],al

or al,al

jne @5

@4:

; ?debug L 13

lea ax,word ptr [bp-2]

push ax

mov ax,offset DGROUP:s@ //得到printf函數的打印格式參數

push ax

call near ptr _printf

pop cx

pop cx

@2:

; ?debug L 14

pop di

pop si

mov sp,bp

pop bp

ret

_j endp

_TEXT ends

?debug C E9

_DATA segment word public DATA

s@ label byte

db 37 //%

db 115 //s

db 10 //換行符:)

db 0

_DATA ends

extrn SCOPY@:far

_TEXT segment byte public CODE

extrn _printf:near

_TEXT ends

public _main

public _j

end

三節:分析W32Dasm得來的靜態匯編代碼,也就是程序最終的代碼同時我們一步步來分析

這時堆棧的情況.

文章寫到這兒可能大家一定認識都是些看到就頭大的代碼吧,沒事我先分析一下

這些代碼就執行來說可以分為三個部分:

1.從01FE到020B是根據C代碼中的定義在堆棧中分配空間例子中分了6個字節,定義多少分多少也沒有毛病

2遠跳到0000:1395是把數據段中的源串放到堆棧中由于放入個數在cx中所以這兒也沒有毛病

3在堆棧中把源串拷到目的串所在的內存單元中問題就在這兒了!

:0001.01FA E80100 call 01FE //執行我們的j函數

:0001.01FD C3 ret

:0001.01FE 55 push bp

:0001.01FF 8BEC mov bp, sp

:0001.0201 83EC06 sub sp, 0006

:0001.0204 56 push si

:0001.0205 57 push di

:0001.0206 16 push ss

:0001.0207 8D46FA lea ax, [bp-06]

:0001.020A 50 push ax

:0001.020B 1E push ds

:0001.020C B89401 mov ax, 0194

:0001.020F 50 push ax

:0001.0210 B90300 mov cx, 0003

:0001.0213 9A95130000 call 0000:1395 //這兒先跳到1395去執行了由于它是在0000所以是遠跳

:0001.0218 8D76FA lea si, [bp-06]

:0001.021B 8D7EFE lea di, [bp-02]

:0001.021E EB00 jmp 0220

:0001.0220 8BDE mov bx, si

:0001.0222 46 inc si

:0001.0223 8A07 mov al , [bx]

:0001.0225 8BDF mov bx, di

:0001.0227 47 inc di

:0001.0228 8807 mov [bx], al

:0001.022A 0AC0 or al , al

:0001.022C 75F2 jne 0220

:0001.022E 8D46FE lea ax, [bp-02]

:0001.0231 50 push ax

:0001.0232 B89701 mov ax, 0197

:0001.0235 50 push ax

:0001.0236 E8BC08 call 0AF5 //執行打印輸出

:0001.0239 59 pop cx

:0001.023A 59 pop cx

:0001.023B 5F pop di

:0001.023C 5E pop si

:0001.023D 8BE5 mov sp, bp

:0001.023F 5D pop bp

:0001.0240 C3 ret

//下面的就是我們的SCOPY@

0001.1395 55 push bp

:0001.1396 8BEC mov bp, sp

:0001.1398 56 push si

:0001.1399 57 push di

:0001.139A 1E push ds

:0001.139B C57606 lds si, [bp+06]

:0001.139E C47E0A les di, [bp+0A]

:0001.13A1 FC cld

:0001.13A2 D1E9 shr cx, 01

:0001.13A4 F3 repz

:0001.13A5 A5 movsw

:0001.13A6 13C9 adc cx, cx

:0001.13A8 F3 repz

:0001.13A9 A4 movsb

:0001.13AA 1F pop ds

:0001.13AB 5F pop di

:0001.13AC 5E pop si

:0001.13AD 5D pop bp

:0001.13AE CA0800 retf 0008

我們現在開始DEBUG動態調試:

第一步D:turboc2>debug c4.exe

-g 01FE 通過W32DASM中的查找我們直接跳到J入口處執行

AX=0000 BX=0566 CX=000E DX=067F SP=FFE8 BP=FFF4 SI=00D8 DI=054B

DS=13DB ES=13DB SS=13DB CS=129F IP=01FE NV UP EI PL ZR NA PE NC

129F:01FE 55 PUSH BP

-t

AX=0000 BX=0566 CX=000E DX=1193 SP=FFE6 BP=FFF4 SI=00D8 DI=054B

DS=13DB ES=13DB SS=13DB CS=129F IP=01FF NV UP EI PL ZR NA PE NC

129F:01FF 8BEC MOV BP,SP

由于上一條指令是CALL O1FE,所以也就有一條POP 01FD,然后又是一個PUSH BP

-d ss:ffe0

13DB:FFE0 FF 01 9F 12 F3 0B F4 FF-FD 01 1D 01 01 00 F2 FF ................

13DB:FFF0 54 05 F6 FF 00 00 43 35-2E 45 58 45 00 00 FB 00 T.....C5.EXE....

現在就來看看棧的情況

mov bp,sp后BP就成了FFE6

FFE0 | ->SUB SP,0006(空了六個字節為源目的串在堆棧

總結

以上是生活随笔為你收集整理的linux strcpy函数实现,strcpy(char *dest , char *src)的漏洞的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。