为什么C语言的strcpy函数有漏洞(转)

本文深入探讨了C语言中strcpy函数存在的安全漏洞及其原因,详细分析了strcpy函数的工作原理,并通过实际代码示例展示了不当使用该函数导致的安全隐患。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

为什么C语言的strcpy函数有漏洞(转)[@more@]

  前言:研究了几天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(空了六个字节为源目的串在堆栈

  

本文来自:http://www.linuxpk.com/30481.html

--&gtlinux电子图书免费下载和技术讨论基地

·上一篇: 缓冲区溢出漏掘之整数范围限制浅析

·下一篇: 黑客中级技术--缓冲区溢出攻击
 
     最新更新
·注册表备份和恢复

·低级格式化的主要作用

·如何防范恶意网站

·常见文件扩展名和它们的说明

·专家:警惕骇客骗局,严守企业信息

·PGPforWindows介紹基本设定(2)

·解剖安全帐号管理器(SAM)结构

·“恶作剧之王”揭秘

·绿色警戒

·黑客反击战

·网络四大攻击方法及安全现状描述

·可攻击3种浏览器代码流于互联网

·黑客最新的兴趣点,下个目标会是谁?

·“僵尸”——垃圾邮件的主要传播源

·Lebreat蠕虫惊现3变种

·POSTFIX反病毒反垃圾Ų…

·在FreeBSD上用PHP实现在线添加FTP用户

·简单让你在FreeBSDADSL上…

·安全版本:OpenBSD入门技巧解析

·Internet连接共享上网完全攻略

·关于ADSL上网网速常识

·静态缓存和动态缓存的比较

·最友好的SQL注入防御方法

·令网站提速的7大秘方

·网络基础知识大全

·路由基本知识

·端口映射的几种实现方法

·VLAN经典诠释

·问题分析与解决——ADSL错误代码

·问题分析——关于2条E1的线路绑定


关于我们 | 联系方式 | 广告合作 | 诚聘英才 | 网站地图 | 网址大全 | 友情链接 | 免费注册

Copyright © 2004 - 2007 All Rights Reserved

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/10752043/viewspace-969882/,如需转载,请注明出处,否则将追究法律责任。

user_pic_default.png
请登录后发表评论 登录
全部评论
<%=items[i].createtime%>

<%=items[i].content%>

<%if(items[i].items.items.length) { %>
<%for(var j=0;j
<%=items[i].items.items[j].createtime%> 回复

<%=items[i].items.items[j].username%>   回复   <%=items[i].items.items[j].tousername%><%=items[i].items.items[j].content%>

<%}%> <%if(items[i].items.total > 5) { %>
还有<%=items[i].items.total-5%>条评论 ) data-count=1 data-flag=true>点击查看
<%}%>
<%}%> <%}%>

转载于:http://blog.itpub.net/10752043/viewspace-969882/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值