c语言整数溢出溢出错误分析

&&问题点数:0&&回复次数:8&&&
谭浩强《C语言程序设计(第二版)》的前50页中的错误分析[转帖]
看见论坛上有人说推荐谭的书,本人不以为然,特此转了这个强人写帖子,给大家看看,谭浩强《C语言程序设计(第二版)》的前50页中的错误分析 :谭书也算是一本奇书了,据说已经发行了300多万册。这本书真的那么好吗?师长早有教诲,因此本人从来没有好好读过谭书。近日遇周围人盛赞谭书,非辩论不可。虽本人不愿应战,但也不得已将谭书找来翻翻。随便翻了一段,就发现错误百出,在此将其中最前面的一些整理出来,提出与国内广大行家和新入道者讨论,望行家们提出批评,供新入道者参考。 书中程序的不规范性、不良的格式和低劣的编程都不在这里深究了。实在是太多,要深究、分析和改正起来,必须写一本数倍于谭书的大作,本人实在没这个时间和精力。水平高的人有的是,欢迎写几个续篇。注:下面将作者尊称为“谭先生”。负的行号表示一页里倒数的行数。P1行1:…,它适于作为系统描述语言,… 这开宗明义的第一句话就说明谭先生对于计算机科学的术语不甚了了。什么叫“系统描述”,什么叫“系统程序设计”?人们都都说C是一种“系统程序设计语言”,而“系统描述语言”则完全是另一种东西。想必谭先生对它们之间的差异和关系都不清楚。在这种情况下就来下断言,一上马就露了怯。 P2表格:if (e) S; 这个错误说明谭先生对C语句基本结构也不清楚。在C语言里,分号是普通语句的结束符号,是语句的一部分。如果谭先生的S表示语句,那么后随的分号是必需的吗?如果谭先生的S表示语句中分号前面的一部分,那么又如何理解可以放在这里的 { ... } 顺序结构呢?它算语句吗?可以放在这里吗?要加分号吗?无论怎么看,谭先生都难以自圆其说! P3行4:C语言是理想的结构化语言,… 不知谭先生的这个论断由何而来。C的创造者肯定不会说这句话,即使是C语言最狂热的崇拜者恐怕也不敢这样说。幸亏谭先生生在中国,其书只在中国出版,否则恐怕他就不会好过了,不知有多少人要找谭先生理论个究竟。
P3行7-8:例如整型量与字符型数据以及逻辑型数据可以通用。 此句子表现出的语文水平就不深究了。要问谭先生的简单问题是,“量”与“数据”是什么关系?再一个问题是,C语言什么时候增加了“逻辑型数据”?
P3行14:C语言允许直接访问物理地址。不知这个论断从何而来。至少无法从C语言参考手册中找到根据,看来是谭先生为C语言增加的特殊功能。 P4程序:This is a c program. 通观世界上所有有关C语言的重要著作,C语言的名字“C”都是用大写表示。这里好象谭先生表示了对C的不肖,与前面大相径庭,不知何故。 P5行9:注释可以出现在程序中的任何位置。 这里又修改了C语言的规则。这里给谭先生提个小问题:“请找出在C程序里不能出现注释的位置(或说,加了注释就会改变程序意义的位置)。”请10秒钟内回答。P5行12:“%d”表示“十进制整数类型”。写程序有问题呀!怎么一遇到具体问题,写出的解释到处都是毛病。“%d”根本就不表示任何类型,它只是对函数printf提出一个转换要求。如果一个初学者产生这种理解偏差还有情可言,像谭先生这样的“大师”级人物也犯此等低级错误,实在是不可原谅。 P5行-8:scanf和printf都是C语言提供的标准输入输出函数… 按本人理解,C语言本身不提供任何有关输入输出的功能,也不提供任何标准函数。只是ANSI C建议了一个标准函数库。至少C参考手册上是这么说的,在谭书中其他部分也这么说。概念不太清楚就容易漏马脚。 P6行13:可以说C是函数式的语言。太荒唐了,完全是望文生义。谭先生的计算机科学技术知识水平可见一斑。函数式语言是计算机科学领域中有明确意义的术语。再者说,即使不理解,也应该尽量回避一下大家都知道的东西,这下不就漏了底。说C是函数式语言,就像说谭先生是“错话大师”一样(毕竟他也说了许多对的话嘛!)。看来谭先生需要补一补计算机科学的基础知识,听说谭先生是清华大学毕业,那里的计算机系也还不错嘛。P6行14-15:…ANSI C提供100多个库函数,Torbo C和MSC 4.0提供300多个库函数。
什么叫“提供”,这里的两个“提供”无论如何也不是同一个意思,因为将ANSI C和Torbo C、MSC 4.0并列讨论根本就没道理。谭先生知道它们各表示什么吗?知道语言标准和语言实现之间的关系和差异吗?P7行12-14:当然,不同的计算机系统需要对函数库中的函数做不同的处理。不同的计算机系统除了提供函数库中的标准函数外,还按照硬件的情况提供一些专门的函数。
谭先生在这里说的是什么“计算机系统”,哪个层次的计算机系统?首先应该将这里的计算机系统都改为“C语言系统”。但是即使修改之后,最后一句话也没有讲到点子上,应该怎样修改就算留给谭先生的能力测验题了。 P9行-12和-2:选择“Compiler”菜单… (4)执行程序。按“F10”键,… 看来谭先生也没怎么用过Turbo C。编辑之后如何去选择“Compiler”菜单,当然要先按F10键。但谭先生在这里就不讲,而到后面又讲。估计还是自己没怎么用过,没什么印象,不知怎样讲有助于学生使用。
P10行8:脱离Turbo C,… 这又是谭先生发明的不规范词汇。正规的术语是“退出”,“结束”,“终止”。 P11行5:…,但将后缀自动改成“.o”(表示它是 .obj文件),…改什么后缀?实在弄不明白,至少不是规范的说法。再说了,它怎么又成了 .obj文件,在UNIX系统里那有“.obj文件”的容身之地?对UNIX术语不熟悉也不要自己随便发明说法嘛。 P11行13-14:此时,a.out中不存放目标文件。
首先,谭先生对目标文件和可执行文件的差异认识不清,在这里就露了马脚。另外,后半句的说法也实在不规范,a.out不过是个文件名,文件名中存放文件是什么意思呢?当然,初学者这么说也就罢了,“大师”这么说,实在令人遗憾!P14行18:计算机算法可分为两大类别:数值运算算法和非数值运算算法。 听说过“数值算法”,但没有听说过“数值运算算法”。对于“非数值”也一样。谭先生在发明术语方面建树颇丰,但在基础教科书中大量发明术语又有什么理由呢?或者就是要给初学者找麻烦,或者就是对计算机科学技术的基本术语不甚了了,还能找到其他解释吗?P19行-2:…,已为世界各国程序工作者普遍采用。 谭先生对世界了解得也不多呀!现在哪国程序工作者还广泛采用流程图呢?请列举一二!
P21行6-7:…,可以看出流程图是表示算法的较好工具。 和什么比较得出这个结论?今天计算机科技界还有多少人这样认识?谭先生独领风骚了。 P22行-6:1966年,Bohra和Jacopini提出了以下三种基本结构,… 请谭先生问问这两位先生是不是他们的发明,他们肯定诚惶诚恐。看来谭先生对计算机科学技术发展的历史也知之有限(知之有限并没有什么,但不要信口开河嘛)。这里给谭先生上一课:在ALGOL 60里这三种结构已经很清楚了。如果不信,请谭先生查阅ALGOL 60的手册(编程语言的最有名的文献了,谭先生没有看过吗?枉为大师了!)。60这个数我们都认识,它好象也比66小一点嘛。 P24行4:…有两类循环结构。谭先生又下结论了,而且又是错的。究竟有多少类“典型的”循环结构?本人也不敢下结论。这方面的经典(全世界计算机专业工作者认为的,可能谭先生不这样认为)文献是Knuth的一篇文章,请谭先生自己找找看看。当然,还是先要弄清楚是那一篇,这就算是给谭先生出的一个查文献题吧。P25行-5:因此,人们都普遍认为最基本的是本节介绍的三种基本结构。 谭先生这样认为,难道人们就得这样认为吗?实际上,人们认为是三类基本结构(不是三种),其中的分支结构和循环结构又有许多典型情况。谭先生的“本节”和这本书一样不可作为凭据。 P25行-1:1973年美国学者…和…提出了一种新的流程图形式。…… 可惜新世纪版之新早已是旧世纪之旧了。综观世界,还有什么比较新的程序设计基础教材还在用N-S图讨论程序设计吗?这已经成为“中国特色”“谭先生特色”的东西了。中国的计算机基础教育早就应该抛弃这些已经被世界抛弃的落后描述技术了。 P28行14-21:归纳起来可知,一个结构化的算法是由一些基本结构顺序组成的;…。如果一个算法不能分解为若干个基本结构,则它必然不是一个结构化的算法。 看来谭先生对于计算机科学领域中的术语“嵌套”并不了解,也不会用。仔细看看谭先生书上的几个算法,就可以发现它们大都不是基本结构的顺序组合,而是嵌套组合。又学了一招。 P32行-14:…,保证了程序的质量。 保证了?没有吧!结构化方法的创始人们也不敢这样说。采用结构化方法一点也不耽误我们大家(包括谭先生)写出低质量的程序,如谭书中到处都可以看到的那样。 P38行3.1 什么是数据结构,计算机界自有公论。将“结构体”说成是一种数据结构实在会让人笑掉大牙的。是不是应该建议谭先生先读一两本数据结构教科书,而后在考虑写什么东西。 P39行-6:其值可以改变的量称为变量。 真糟糕!程序里的变量居然被谭先生当作一种“量”。任何通晓计算机科学技术的人都不会同意这种说法。“变量”到底是什么?将谭先生的上述说法与随后的描述做个对比,就不难发现他自己都无法自圆其说。 P39行-4到-2:变量名实际上是一个符号地址,在对程序编译连接时由系统给每一个变量名分配一个内存地址。 这么简单的一句话里包含的错误太多了,谭先生请慎言,言多必失。首先,变量名根本不是什么符号地址(懂得什么叫符号地址吗?),它不过是在程序中代表变量的一种记号。一个变量也未必有地址(如寄存器变量),未必有唯一的地址(什么变量?谭先生知道吗?C语言里大量变量都是这样),这些都说明,将变量名看成符号地址是不行的,说不通的。其次,系统(什么系统?请说清楚。这里不想给出修改错误的提示了,算是给谭先生的一道语言作业题)是给变量分配地址,而不是给“变量名”分配地址。再者,每个变量的地址都是“编译连接”时分配的吗?或是对C语言了解肤浅,或者就是信口开河。要把这个论述改正确,请谭先生查阅有关材料,看C语言中有几种变量,地址是什么时候确定的(分配的)。 P40行-12:在C语言中,要求对所有用到的变量作强制定义,… 什么叫“强制定义”,好象没有这种说法嘛!我们都知道“强制”在C语言里有一个意思,就是不知道什么是“强制定义”。谭先生就简单说“先定义,后使用”还好一点,错误少一点,但这个说法也是有条件的(请谭先生想想,有什么条件?)。 P41图3.2(b)。 谭先生在这里将整数确定为两个字节,这本身就需要说明(免了吧,反正本书一贯不追求严谨)。更可笑的是这里还自作聪明地将它画成两个分离的字节。请问,知道什么叫byte order(字节序)吗,如果你画出各个字节,就必须解释这个问题。奉劝谭先生,不知道的东西还是别碰它,老老实实画出连续的16位,免得让别人知道你不懂。 P42整页。 到底C语言有几个整数类型?谭先生知道什么是“一个类型”吗?这里先说“整型变量的基本类型符”(什么叫基本类型符,不懂),又说“因此有以下三类整型变量”,又说“归纳起来,可以用以下6种整型变量”。谭先生的“种”和“类”是什么关系?和术语“类型”又是什么关系?这里的一片混乱反映出概念上的一锅糨糊。关于各种整数类型的表示范围的一般性说法和最后一段所说的C标准规定也是不和谐的,前面说得有鼻子有眼,后边又说C标准没规定,这算怎么回事呢! P43行4-6:在微机上用long可以得到更大范围的整数,但同时会降低运算速度,因此除非万不得已,不要随便使用long类型。 用long什么整数也得不到,更不说得到什么范围的整数了。long的一个用途是用于定义变量,而被定义的变量(可能,注意,只是可能)能够存储更大的数。此外,这里的论断也早已过时了,谭先生还是生活在旧世纪,在旧世纪写新世纪教材,而且主观地为新世纪下结论,太武断了!当然,错误也就不可抵赖了(300万本,焚书也难尽)。 P44-45第4小节。 关于整数类型的值范围,C标准都只定义了原则,谭先生总自作主张地将它具体化,现在又想来定义计算溢出的意义了。首先,整型的表示范围未必如谭先生所说,如果这个不对乎,下面的讨论也就都是瞎掰了。其次,即使运算出现在整型值的边界上,其效果也未必如谭先生所述。语言标准说这时求出的值是undefined,谭先生却说是defined。看来ANSI C标准化组还需要谭先生垂帘听政,给他们纠正失误。不知新的C标准化组请谭先生做什么。 P47行-6:许多C编译系统将实型常量作为双精度来处理。 前面还有类似说法,这里一并讨论。首先,C语言根本就没有实型常量,只说浮点常量。另外就是想请谭先生告诉我们,那个C系统“不”把浮点常量看作双精度类型的。其实ANSI C标准已经规定了,浮点常量就是双精度类型的。这里谭先生怎么该肯定的又不肯定了呢?你查查标准呀!! P49行-6:字符型变量用来存放字符常量。 荒唐!真是莫名其妙。到底是变量还是常量?如果一个变量里存放了一个常量,存放之后还能修改吗?要是能修改,那怎么叫常量呢?要是不能修改,那怎么叫变量呢?自己套住了吧。这里根本就没“常量”什么事!字符型变量里存的东西,大家都称它为“字符值”。 P50行5:…,实际上并不是把该字符本身放到内存单元中,而是将该字符的ASCII代码放到存储单元中。 可笑!可笑!难道还有某种语言、某种机器,能把字符“本身”放到存储单元里吗?那大概是谭先生自己用的“谭先生计算机”,反正大家是用不到了(还没有用到,或许将来这种计算机要取代冯-诺依曼计算机。谁敢说一定不会呢!)。还有,C标准也没说一定用美国人搞的ASCII代码呀,美国人都没有说,谭先生怎么就帮助他们说了呢?谭先生知道还有别的编码字符集吗?欧洲人要是听到这种说法,非和谭先生急了不可。 好不容易到了50页,感谢读者(可能也包括谭先生及其崇拜者)耐心地读了这么长时间。谢谢了。可惜的是,本人无法将1-50页的所有问题一一列出(否则篇幅还要大几倍,大家更觉得厌烦了),更无法将整本书中的问题一一列出分析(否则就是一本比原书厚得多得大书了),当然,本人也无义务为谭先生找出所有的问题。作为一个测验,还是请谭先生自己找吧,本文只算是抛砖引玉了。 谭先生的书能改好吗?本人实在深表怀疑。这样一本错误百出(不,错误千出)的书,由谭先生这样丰富学识和程序设计经验的人来修改,没有两三年时间,或许更长,是不要希望能改到令人满意程度的。再者说,这里列举的都是小问题,谭书本身的整体结构和教学目标都值得提出深深的疑问。如果能够改好,那早就是另一本书了。但是,能写出来吗? 或许,最值得深思的是,这样一本不合格(按照计算机科学技术及其教育的评价标准)的东西居然统治了中国计算机基础教育这么多年,这个问题真是中国计算机教育界和计算机实业界的悲哀啊!300万本,搞坏了多少投身于计算机领域学习的人,难道我们还希望这个数字再无穷无尽地增加下去吗?!如果问,为什么中国的计算机软件行业一直无法起飞,这些难道不也是一方面的问题吗?
搜索更多相关主题的帖子:
等 级:新手上路
帖 子:422
是不是买盗版了?
菜鸟~~请多指教~~
等 级:新手上路
帖 子:261
P49行-6:字符型变量用来存放字符常量。 荒唐!真是莫名其妙。到底是变量还是常量?如果一个变量里存放了一个常量,存放之后还能修改吗?要是能修改,那怎么叫常量呢?要是不能修改,那怎么叫变量呢?自己套住了吧。这里根本就没“常量”什么事!字符型变量里存的东西,大家都称它为“字符值”。 变量里存放了一个常量有创意一直都没注意过
哎 时间....................
等 级:新手上路
帖 子:47
我觉得有一些错误也是再所难免的你既然看起比他专业那么多
你为什么不去编一本书呢我们这些初学者就可以看你的书了
等 级:贵宾
威 望:59
帖 子:3988
专家分:684
支持一下,在此告戒大家:不要迷信盲从,更不要迷信书本,要有格物致知的探索精神
虽然我的路是从这里开始的,但是这里不再是乐土.感谢曾经影响过,引导过,帮助过我的董凯,飞燕,leeco,starwing,Rockcarry,soft_wind等等等等.别了,BCCN.
等 级:新手上路
帖 子:69
4楼的朋友,不知道你说的有一些错误再所难免是指哪些错误?我转帖之前认真的对着书看了一遍帖子上写的错误.虽然,有些小错误无关紧要,比如c的大小写之类的(或许在有些人眼里,这种错误也是不可原谅的吧,但我看来,这种问题,对于读者的影响并不大)但是,更多的错误,是完全不应该出现的,上面列出来的错误,很多地方容易误道初学者~~~(因为一般初学者对第一次参考的书籍的信任是不可动摇的)至于说让我编书,那是有点免为其难了,毕竟,我一直只是以学习者的姿态来看待自己的,自认为没有编书实力,而且帖子也仅仅是转了别人的.当然,这些错误也不应该全都归于谭先生,至少有一半的责任在这本书的校对工作者身上.至于2楼的盗版说法,更加可以肯定的告诉你,100%正版,很多学校发这本书做为教材,我都有看过.还要感谢5楼的支持,我发这个帖子的动机,有一部分也是因为昨天看到一个朋友说发现谭书中变量初始化问题有错误,才发上来,告诉他们,其实书上有错是很正常的.
等 级:新手上路
帖 子:422
惭愧.....没有去仔细研究过~毕竟书是起个引导作用哪个有能保证没点错误呢?也就不去管那么多了~~我也用了这本书~~可前4章都没有看~后面有没错误~也没仔细研究我只相信我的上机结果
菜鸟~~请多指教~~
来 自:安徽
等 级:贵宾
威 望:17
帖 子:1611
我认为那书还不错。。
这个社会太复杂。。。
等 级:新手上路
帖 子:335
to 剑风曲:向您致敬!我觉得,中国人要提高治学的素质,就得要有您的这种叫真的精神!谭书的这种现象多少也代表了大多数中国人的某些不好的方面我从两年前开始学习C(总共大约学了一年时间,今年上半年,花了三个月写了可以部分替代GHOST的系统备份兼硬盘扇区工具TOdisk),学的就是谭书C,初学者自然不会发现这些逻辑的不严密,概念的错乱。不过,虽然在前面可能受了点误导,在以后的认真钻研中,自然真正明白了。。。现在,看了您的《讨谭C檄》一文,还真是有点震惊!确实是这么回事呢!不过,说实在的,对一无所知的初学者造成的不好影响可能实际上不会太大,尤其是较抽象的概念。。。
有缘相识!我中文系的 3月拿下C/C++/VC 5天写游戏 2月写游戏系统
有空去http://mykool.
版权所有,并保留所有权利。
Powered by , Processed in 0.024389 second(s), 8 queries.
Copyright&, BCCN.NET, All Rights ReservedC语言程序溢出错误分析_百度知道
C语言程序溢出错误分析
void main(){a=b;double b=123;}这个为什么会出现溢出错误.h&gt.#include&lt
我有更好的答案
按默认排序
语法错误就是你编写的程序里面使用了不规范的关键字或者变量名之类的错误,笼统得说就是编译都无法通过的程序,编译器无法识别你写的程序
我问的是a=b那里怎么溢出错误
其他类似问题
等待您来回答
下载知道APP
随时随地咨询
出门在外也不愁一个简单的C语言 整型数据溢出问题
[问题点数:20分,结帖人zengqing108]
一个简单的C语言 整型数据溢出问题
[问题点数:20分,结帖人zengqing108]
不显示删除回复
显示所有回复
显示星级回复
显示得分回复
只显示楼主
相关帖子推荐:
2012年 总版技术专家分年内排行榜第一
2013年 总版技术专家分年内排行榜第七2011年 总版技术专家分年内排行榜第五2009年 总版技术专家分年内排行榜第九
2010年12月 C/C++大版内专家分月排行榜第三
2010年12月 C/C++大版内专家分月排行榜第三
本帖子已过去太久远了,不再提供回复功能。软件漏洞分析入门_4_初级栈溢出C_修改程序流程
日07:07  来源:
  上节课没有操练滴东西,不少蠢蠢欲动的同学肯定已经坐不住了。悟空,不要猴急,下面的两堂课都是实践课,用来在实践中深入体会上节课中的知识,并且很有趣味性哦  第4讲 初级栈溢出C  To be the apostrophe which changed “Impossible” into“I"mpossible”   ―― failwest  没有星星的夜里,我用知识吸引你  上节课没有操练滴东西,不少蠢蠢欲动的同学肯定已经坐不住了。悟空,不要猴急,下面的两堂课都是实践课,用来在实践中深入体会上节课中的知识,并且很有趣味性哦  信息安全技术是一个对技术性要求极高的领域,除了扎实的计算机理论基础外、更重要的是优秀的动手实践能力。在我看来,不懂二进制就无从谈起安全技术。  缓冲区溢出的概念我若干年前已经了然于胸,不就是淹个返回地址把CPU指到缓冲区的shellcode去么。然而当我开始动手实践的时候,才发现实际中的情况远远比原理复杂。  国内近年来对网络安全的重视程度正在逐渐增加,许多高校相继成立了“信息安全学院”或者设立“网络安全专业”。科班出身的学生往往具有扎实的理论基础,他们通晓密码学知识、知道PKI体系架构,但要谈到如何真刀实枪的分析病毒样本、如何拿掉PE上复杂的保护壳、如何在二进制文件中定位漏洞、如何对软件实施有效的攻击测试……能够做到的人并不多。  虽然每年有大量的网络安全技术人才从高校涌入人力市场,真正能够满足用人单位需求的却聊聊无几。捧着书本去做应急响应和风险评估是滥竽充数的作法,社会需要的是能够为客户切实解决安全风险的技术精英,而不是满腹教条的阔论者。  我所知道的很多资深安全专家都并非科班出身,他们有的学医、有的学文、有的根本没有学历和文凭,但他们却技术精湛,充满自信。  这个行业属于有兴趣、够执着的人,属于为了梦想能够不懈努力的意志坚定者。如果你是这样的人,请跟着我把这个系列的所有实验全部完成,之后你会发现眼中的软件,程序,语言,计算机都与以前看到的有所不同――因为以前使用肉眼来看问题,我会教你用心和调试器以及手指来重新体验它们。  首先简单复习上节课的内容:  高级语言经过编译后,最终函数调用通过为其开辟栈帧来实现  开辟栈帧的动作是编译器加进去的,高级语言程序员不用在意  函数栈帧中首先是函数的局部变量,局部变量后面存放着函数返回地址  当前被调用的子函数返回时,会从它的栈帧底部取出返回地址,并跳转到那个位置(母函数中)继续执行母函数  我们这节课的思路是,让溢出数组的数据跃过authenticated,一直淹没到返回地址,把这个地址从main函数中分支判断的地方直接改到密码验证通过的分支!  这样当verify_password函数返回时,就会返回到错误的指令区去执行(密码验证通过的地方)  由于用键盘输入字符的ASCII表示范围有限,很多值如0x11,0x12等符号无法直接用键盘输入,所以我们把用于实验的代码在第二讲的基础上稍加改动,将程序的输入由键盘改为从文件中读取字符串。  #include  #define PASSWORD "1234567"  int verify_password (char *password)    char buffer[8];  authenticated=strcmp(password,PASSWORD);  strcpy(buffer,password);//over flowed here!    main()  int valid_flag=0;  char password[1024];  FILE *  exit(0);  fscanf(fp,"%s",password);  valid_flag = verify_password(password);  printf("incorrect password!\n");  else  printf("Congratulation! You have passed theverification!\n");  fclose(fp);  程序的基本逻辑和第二讲中的代码大体相同,只是现在将从同目录下的password.txt文件中读取字符串而不是用键盘输入。我们可以用十六进制的编辑器把我们想写入的但不能直接键入的ASCII字符写进这个password.txt文件。  用VC6.0将上述代码编译链接。我这里使用默认编译选项,BUILD成debug版本。鉴于有些同学反映自己的用的是VS2003和VS2005,我好人做到底,把我build出来的PE一并在附件中双手奉上――没话说了吧!不许不学,不许学不会,不许说难,不许不做实验!呵呵。  要PE的点这里: stack_overflow_ret.rar  在与PE文件同目录下建立password.txt并写入测试用的密码之后,就可以用OllyDbg加载调试了。  停~~~啥是OllyDbg,开玩笑,在这里问啥是Ollydbg分明是不给看雪老大的面子么!如果没有这个调试器的话,去工具版找吧,帖子附件要挂出个OD的话会给被人鄙视的。  在开始动手之前,我们先理理思路,看看要达到实验目的我们都需要做哪些工作。  要摸清楚栈中的状况,如函数地址距离缓冲区的偏移量,到底第几个字节能淹到返回地址等。这虽然可以通过分析代码得到,但我还是推荐从动态调试中获得这些信息。  要得到程序中密码验证通过的指令地址,以便程序直接跳去这个分支执行  要在password.txt文件的相应偏移处填上这个地址  这样verify_password函数返回后就会直接跳转到验证通过的正确分支去执行了。  首先用OllyDbg加载得到的可执行PE文件如图:  图1  阅读上图中显示的反汇编代码,可以知道通过验证的程序分支的指令地址为0x。  简单解释一下这段汇编与C语言的对应关系,其实凭着OD给出的注释,就算你没学过汇编语言,读懂也应该没啥问题。  0x处的函数调用就是verify_password函数,之后在0x0040110A处将EAX中的函数返回值取出,在0x0040110D处与0比较,然后决定跳转到提示验证错误的分支或提示验证通过的分支。提示验证通过的分支从0x处的参数压栈开始。  啥?用OllyDbg加载后找不到verify_password函数的位置?这个嘛,我这里只说一次啊。  OllyDbg在默认情况下将程序中断在PE装载器开始处,而不是main函数的开始。如果您有兴趣的话可以按F8单步跟踪一下看看在main函数被运行之前,装载器都做了哪些准备工作。一般情况下main函数位于GetCommandLineA函数调用后不远处,并且有明显的特征:在调用之前有3次连续的压栈操作,因为系统要给main传入默认的argc、argv等参数。找到main函数调用后,按F7单步跟入就可以看到真正的代码了。  我相信你,你一定行的,找到了吗?什么?还找不到?好吧,按ctr+g后面输入截图中的地址0x,这回看到了吧。建议你按F2下个断点记住这个位置,别一会儿又在PE里边迷路了。  这步完成后,您应该对这个PE的主要代码有了一个把握了。这才牙长一点指令啊,真正的漏洞要对付的是软件,那个难缠~~~好,不泼冷水了  如果我们把返回地址覆盖成这个地址,那么在0x处的函数调用返回后,程序将跳转到验证通过的分支,而不是进入0x处分支判断代码。这个过程如下图所示:  图2  通过动态调试,发现栈帧中的变量分布情况基本没变。这样我们就可以按照如下方法构造password.txt中的数据:  仍然出于字节对齐、容易辨认的目的,我们将“4321”作为一个输入单元。  buffer[8]共需要2个这样的单元  第3个输入单元将authenticated覆盖  第4个输入单元将前栈帧EBP值覆盖  第5个输入单元将返回地址覆盖  为了把第5个输入单元的ASCII码值0x修改成验证通过分支的指令地址0x,我们采取如下方式借助16进制编辑工具UltraEdit来完成(0x40,0x11等ASCII码对应的符号很难用键盘输入)。  步骤1:创建一个名为password.txt的文件,并用记事本打开,在其中写入5个“4321”后保存到与实验程序同名的目录下:  图3  步骤2:保存后用UltraEdit_32重新打开,如图:  图4  啥?问啥是UltraEdit?去工具版找吧,多的不得了,这里是看雪!  步骤3:将UltraEdit_32切换到16进制编辑模式,如图:  步骤写到这个份上了,您不会还跟不上吧。  步骤4:将最后四个字节修改成新的返回地址,注意这里是按照“内存数据”排列的,由于“大顶机”的缘故,为了让最终的“数值数据”为0x,我们需要逆序输入这四个字节。如图:  步骤5:这时我们可以切换回文本模式,最后这四个字节对应的字符显示为乱码:  最终的password.txt我也给你附上。  要txt的点这里: password.txt  将password.txt保存后,用OllyDbg加载程序并调试,可以看到最终的栈状态如下表所示:  局部变量名 内存地址 偏移3处的值 偏移2处的值 偏移1处的值 偏移0处的值  buffer[0~3] 0xx31 ("1") 0x32 ("2") 0x33 ("3")0x34("4")  buffer[4~7] 0xx31 ("1") 0x32 ("2") 0x33 ("3")0x34("4")  authenticated  (被覆盖前) 0xx00 0x00 0x00 0x01  authenticated  (被覆盖后) 0xx31 ("1") 0x32 ("2") 0x33 ("3") 0x34 ("4")  前栈帧EBP  (被覆盖前) 0xx00 0x12 0xFF 0x80  前栈帧EBP  (被覆盖后) 0xx31 ("1") 0x32 ("2") 0x33 ("3") 0x34 ("4")  返回地址  (被覆盖前) 0xx00 0x40 0x11 0x07  返回地址  (被覆盖后) 0xx00 0x40 0x11 0x22  程序执行状态如图:  由于栈内EBP等被覆盖为无效值,使得程序在退出时堆栈无法平衡,导致崩溃。虽然如此,我们已经成功的淹没了返回地址,并让处理器如我们设想的那样,在函数返回时直接跳转到了提示验证通过的分支。  同学们,你们成功了么?  最后再总结一下这个实验的内容:  通过Ollydbg调试PE文件确定密码验证成功的分支的指令所处的内存地址为0x  通过调试确定buffer数组距离栈帧中函数返回地址的偏移量  在password.txt相应的偏移处准确的写入0x,当password.txt被读入后会同样准确的把verify_password函数的返回地址从分支判断处修改到0x(密码正确分支)  函数返回时,笨笨的返回到密码正确的地方  程序继续执行,但由于栈被破坏,不再平衡,故出错  试想一下,如果我们在buffer中填入一些可执行的机器码,然后用溢出的数据把返回地址指向buffer,那么函数返回后这些代码是不是就会执行了?  答案是肯定的,下一讲我将用类似的叙述方式,同样手把手的和您一起完成这段机器代码的编写,并把它们准确的布置在password.txt中,这样原本用来读取密码文件的程序读了这样一个精心构造的“黑文件”之后,就会做出一些“出格”的事情了。  明天见,顺便说一下,我一般会在凌晨1点左右发文,想坐沙发的同学注意了呦。
【作者:佚名 来源:】
(责任编辑:和讯网站)
感谢您的参与!查看[]
script src="/track/track_xfh.js?ver=">}

我要回帖

更多关于 c语言常见错误 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信