华科-计算机系统试验报告_第1页
华科-计算机系统试验报告_第2页
华科-计算机系统试验报告_第3页
华科-计算机系统试验报告_第4页
华科-计算机系统试验报告_第5页
已阅读5页,还剩31页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

印中科技上浮课程实验报告课程名称: 计算机系统基础专业班级: 学号: 姓名: 指导教师: 报告日期: 年月日计算机科学与技术学院目录TOC\o"1-5"\h\z实验1: 1实验2: 7实验3: 24\o"CurrentDocument"实验总结 34实验1: 数据表示 实验概述实验目的:更好地熟悉和掌握计算机中整数和浮点数的二进制编码表示。实验目标:加深对数据二进制编码表示的了解。实验要求:使用有限类型和数量的运算操作实现一组给定功能的函数。实验语言:c。实验环境:linux实验内容需要完成bits.c中下列函数功能,具体分为三大类:位操作、补码运算和浮点数操作。1)位操作表1列出了bits.c中一组操作和测试位组的函数。其中,“级别”栏指出各函数的难度等级(对应于该函数的实验分值),“功能”栏给出函数应实现的输出(即功能),“约束条件”栏指出你的函数实现必须满足的编码规则(具体请查看bits.c中相应函数注释),“最多操作符数量”指出你的函数实现中允许使用的操作符的最大数量。你也可参考tests.c中对应的测试函数来了解所需实现的功能,但是注意这些测试函数并不满足目标函数必须遵循的编码约束条件,只能用做关于目标函数正确行为的参考。表1位操作题目列表级别函数名功能约束条件最多操作符数1IsbZero将*的最低有效位(匕58)清零仅能使用!〜&AI+<<>>52byteNot将x的第n个字节取反(字节以SB开始到MSB依次编号为0-3)仅能使用!〜&A|+<<>>62byteXor比较x和y的第n个字节(字节从LSB开始到MSB依次编号为0-3),若不同,则返回1;若相同,则返回0仅能使用!〜&A|+<<>>20

3logicalAndx&&y仅能使用!〜&Al+<<>>203logicalOrxlly仅能使用!〜&A|+<<>>203rotateLeft将x循环左移"立仅能使用!〜&A|+<<>>254parityCheck若*有奇数个1,则返回1;否则,返回0仅能使用!〜&A|+<<>>202)补码运算表2列出了bits.c中一组使用整数的补码表示的函数。可参考bits.c中注释说明和tests.c中对应的测试函数了解其更多具体信息。表2补码运算题目列表级别函数名功能约束条件最多操作符数2mul2OK计算2*x,如果不溢出,则返回1,否则,返回0仅能使用〜&a|+<<>>202mult3div2计算(x*3)/2,朝零方向取整仅能使用!〜&A|+<<>>123subOK计算x-y,如果不溢出,则返回1,否则,返回0仅能使用!〜&A|+<<>>204absVal求x的绝对值仅能使用!〜&A|+<<>>103)浮点数操作表3列出了bits.c中一组浮点数二进制表示的操作函数。可参考bits.c中注释说明和tests.c中对应的测试函数了解其更多具体信息。注意float_abs的输入参数和返回结果(以及float_f2i函数的输入参数)均为unsignedint类型,但应作为单精度浮点数解释其32bit二进制表示对应的值。表3浮点数操作题目列表级别函数名功能约束条件最多操作符数2float_abs返回浮点数’|中的二进制仅能使用任何整型/无符10表示,当输入参数是NaN时,返回NaN号整型操作,包括II,&&以及if,while控制结构4float_f2i返回浮点数f的强制整型转换“(代)俨表示仅能使用任何整型/无符号整型操作,包括II,&&以及if,while控制结构30实验设计根据题目要求,选择合适的操作符来编写代码。具体设计参考实验过程中的代码注释。实验过程阅读相应的函数要求,利用合适的操作符编写代码。如下:lsbZero函数:HintlsbZero(intx)(return:”式与11111111111111111111111111111110B进行与运算1 //其中111,111111111Lill111111111111LllOB逋过1的取反来将到图1.1byteNot函数:FlintbyteNot(int羽intn)[return(Oxff«(n<<3));//取反可以对改为对某个掩码的异或来实现) //通过将Oxff向左移位n的,次方来构成掩码图1.2byteXor函数:EintbyteKorfintx,Lntysintn){return1!((x£(Dxff<<(n«3)))-(泄(Oxff<<(n«3))));J〃类似.匕一题做出相应的字节,然后通过异或.运算以及逻辑取反来输出正确的输出图1.3logicalAnd函数:BintlogicalAnd(intxtinty){return!!((I !v)&0x2);〃利用两次逻辑取反来取出冗,y代表的逻辑值} 〃相加后与0x2进行且运算后再道过逻辑取反来输出正确的输出图1.4logicalOr函数:□intlogicalOr(intxFinty){return]1((!!x+lly));//利用两次逻辑取反来取出x,y代表的逻辑值} //相加后再通过逻辑取反来输出正确的输出

图图1.5rotateLeft函数:-lintrotateLeft(intint哨{inty=x;//利用y取出x左边门位.y向右趋动32~n位*再取出低n位.returD(x«n)|HyA「n+33)}&n+n<Q)+D); 〃其中涉及的减法都是利用反反』II-来实现的} //最后进行一次与运算图1.6parityCheck函数:BintparityCheck(int工){x=x"(x>>16):(x>>8);x=k"(x>>4);a=x"(z»2);x=F(x»l);returnx&l;} //利用异或运算的特点依次折半来操作,最后取出最低位也就是结果图1.7mu120K函数:□intQiu12CK(intk){nt内//是否港生就是看芯与2K符号位是否一样return(((Cx^(y«l))»31)&1)1);} “所以将区与2x异或后取出最高位判断图1.8mult3div2函数:Bintmult3div2(intx){inty=x,z:2=y=y+(y«l);//y等干3x2-z»31;//工是3x的符号位return(Cz)fi[y»l))+(E&((y»l)+(y&l))1;//e为0,直接输出y/2即可10.subOK函数:)〃当工为1时,将y/2加上y10.subOK函数:EzintsubOK(intx3inty){intz=C>,+l+x)>>31;//x-y的符号位y=>»31;y的符中ix=^>31;Hx的符号位return!屋y));//当且仅当减数与被减数符号不同但被减数与差符号捋同才判断为潜出) //故利口三或以及道辑取应来输出正确的输出图1.9图1.10absVal函数:SintabsVal(intx){inty=y»31;/7y为k符号位ret^n(「WaxHlyM'+Ub/yftUWy来决定输出x还是r}图1.11float_abs函数:EniDsignedfloat_abs(unsigneduf){unsignede=ufPf-jz;f=aOx?fffff; //f为尾数e=(e»23)&0xff; //e为阶码if((e==Oxff)64(f1=0))returnuf;〃特殊况单独输出returnuf&OsTfffffff;//取出uf除了符号位的位输出}图1.12float_f2i函数:早」utfl&at_f2i uf){inte=uf,f=uf,val;f=f&OxTfffff: //f为尾皴e=(e»23)&Oxff; //e为阶码if(&<127)return0; ”恃殊情况单独考虑if(&>157)returnfcSOOOOOOO;/'/特殊情况单独考虑-iif(&=127){ //特殊情况单独考虑if(uf»31)return_1;return1;:f=T+0x800000:H规约数例面疗个缺省的1ift&<150)val=f»(150-e);elseval-f<<(e-150)://移位if(uf»31)retum((-l)*(Fal)): //根据输出符号■位进行最后调整returnval;)图1.131.5实验结果.使用dlc检查函数实现代码是否符合实验要求的编码规则。a)首先./dlcbits.c直接检测是否有错误。如图1.14所示:Linux^Ubuntu:-/Public/tnip/labl-handout^./diebits.c/usr/include/stdc-predef.h:1:Warning:Non-includablefile〈command,lineaincludedfromincludablefile/usr/inelude/stdc-predef.h.CompilationSuccessful(1warning)图1.14由图知,输出CompilationSuccessful(1warning),故bits.c文件编写无误符合要求。b)然后用-e选项调用dlc,观察操作符数。如图1.15所示:

linux@Ubuntu:-/Public/tnp/labl-handout$,/die-ebits.c/usr/include/stdc-predef.h;1:Warning:Non-includabLefilecconiniand-lLne>includedfromincludablefile/usr/include/stdc'predef.Ii.die:bits.c:175:1sbZero:2operatorsdie:bits.c:106:byteNot:3aperatorsdie:bits.c:199:byteXor:9operatorsdie:bits.c:2GE:logicalAnd;8operatorsdie:bits.c:217:logicalOr:7operatorsdie:bits.c:229:rotateLeft:10operatorsdie:bits.c:244:paritycheck:11operatorsdie:bits.c:257:mul20K:5operatorsdie:bits.c:274:mult3di\/2:11operatorsdlc:blts.c:2B8:subOK:11operatorsdie:bits.c:3G1:absVal:7op^rattirsdie:bits.c:319:floatabs:7operatorsdie;bits.c;3A7:floatf2i;17operatorsCompilationSuccessful(1warning)图1.15.使用btest检查函数实现代码的功能正确性。a)首先使用make编译生成btest可执行程序,如图1.16所示:linux^Ubuntu:-/Public/tmp/l3bl-handout$makegcc-0-Wdll-Im-口bt^stbits.cbtest.d把cl.ttEst弓.匚图1.16b)然后调用btest命令检查bits.c中所有函数的功能正确性。如图1.17所示:linux@UbLintii:-/Puhlic/tmp/tabl-handcut$./btestscore RatingErrorsFunction1 1 3 LsbZero22333422223223334222233342G00eG0GaayteflotbyteXorlogicalAndlogic苜IOrrotateLeftparitycheckmulzoKmult3div2subOKabsVaLfloat3bsfloatf2.iTotalpoints:35/35图1.17由图知,得分全拿到了,故bits.c文件中函数功能都实现了。1.6实验小结这次实验让我更好地熟悉和掌握计算机中整数和浮点数的二进制编码表示。尤其是加深对数据二进制编码表示的了解。通过使用有限类型和数量的运算操作实现一组给定功能的函数来提高了我对数据表示方面的C语言编程能力。总之这次实验的过程整体还是很愉快的,耗时不是很长但是收获很大!实验2: 拆弹实验 实验概述实验目的:增强对程序的机器级表示、汇编语言、调试器和逆向工程等方面原理与技能的掌握。实验目标:需要拆除尽可能多的炸弹。实验要求:使用gdb调试器和objdump来反汇编炸弹的可执行文件,并单步跟踪调试每一阶段的机器代码,从中理解每一汇编语言代码的行为或作用,进而设法“推断”出拆除炸弹所需的目标字符串。实验语言:c。实验环境:linux实验内容一个"binarybombs"(二进制炸弹,下文将简称为炸弹)是一个Linux可执行C程序,包含了6个阶段(phasel〜phase6)。炸弹运行的每个阶段要求你输入一个特定的字符串,若你的输入符合程序预期的输入,该阶段的炸弹就被“拆除”,否则炸弹“爆炸”并打印输出"BOOM"字样。实验的目标是拆除尽可能多的炸弹层次。每个炸弹阶段考察了机器级语言程序的一个不同方面,难度逐级递增:阶段1:字符串比较阶段2:循环阶段3:条件/分支阶段4:递归调用和栈阶段5:指针阶段6:链表/指针/结构另外还有一个隐藏阶段,但只有当你在第4阶段的解之后附加一特定字符串后才会出现。为了完成二进制炸弹拆除任务,你需要使用gdb调试器和objdump来反汇编炸弹的可执行文件,并单步跟踪调试每一阶段的机器代码,从中理解每一汇编语言代码的行为或作用,进而设法“推断”出拆除炸弹所需的目标字符串。这可能需要你在每一阶段的开始代码前和引爆炸弹的函数前设置断点,以便于调试。阶段1字符串比较.任务描述:通过phase_1的反汇编代码找出要输入的字符串。.实验设计:利用gdb结合断点来动态地分析。.实验过程:观察phase_1的反汇编代码,如图2.1.1所示:eaO48b90<phase_l>:8048b90:83ec1csubesp,Oxlca043b93:c744240444al04movdwardptr[esp+0x4]^0x80431448048b9a:033043b9b:Bb442420moveaxpdwordptr[esp+OxJO]3048b9f:890424mo'jdi^ordutr[esp]TeaxS04Sba2:eS63040000call804900a<strings_notequalAS04Sba7:05cQtesteax*eax0040ba9:7405je8S48lbbfl<phasel+0x20>3943bab:e365日50000call8Q49H5^explodebomb>ao4abbe:83c41Caddesp,0x1c81348bb3;c3ret图2.1.1发现在调用strings_not_equal对比字符串之前,有一个地址送入了堆栈,大胆猜测该地址就是正确字符串的首址,于是在phase_1处下个断点,运行至此处后,用x命令查看字符串。如图2.1.2所示:(gdb)bphase1Breakpoint1atOxB04Bb90(gdb)rStartingprogram:/home/Iinux/Public/tmp/U20141457B/bombWelcometomyfiendishlittlebomb,Youhave&phaseswithBreakpoint1,0x0BO4Sb9Oinphase1()day!(gdb)x/ls0xBO4al44Qx304a144: "BorderrelationswithCanadahaveneverbeenbetter,(gdb)图2.1.2故猜测“BorderrelationswithCanadahaveneverbeenbetter."就是所需字符串。重新执行该程序,直接输入该字符串,观察结果。如图2.1.3所示:Linux@Ubuntiu:-/Public/tmp/U201414578$./bombWelcometomyfiendishlittlebomb.Youhave6phaseswithwhichtoblowyourselfup.Haveaniceday!BorderrelationswithCanadahaveneverbeenbetter.Phase1defused-Howaboutthenextone?图2.1.3.实验结果:如图2.1.3所示,阶段一拆弹成功!阶段一很简单,当初的找出字符串首地址就可以了,没有什么大的难点。阶段2循环.任务描述:通过phase_2的反汇编代码推断第二阶段要输入的数据.实验设计:利用gdb结合断点来动态地分析.实验过程:观察phase_1的前一部分反汇编代码,如图2.2.1所示:

QaO48bb4<phase_2>:S048bb4;53pushebxS3ec38sub8048bb8:8d442418leaeax,(esp+Sxl8J0048bbc:09442404movdwordptr[esp+Qx4]0048bc0i8b442440moveaxfdwardptrfesp+0x40]8048bc4;S90424movdwordptr[esp],eax0048bc7:e870050009call804913c|<readsixnumbers^3G48bCC:837c2418Q9cmpdwordptr[esp+Gxl8].GxQ8048bd1:7922Ins8G48bf5<phase2+0x41>3G48bd3:eB3d050000call8G49115^explodebomb>图2.2.1发现输入的应该是六个数字,而且要求[esp+0x18]必须大于等于0才行,于是测试输入“012345”,观察这些数字在调用read_six_numbers后是如何存放在栈中的,如图2.2.2所示:(gdb)x/12x$esp0xbfffef20:0XOSO4C43OOxbfffefSSexbjfbdsasOxO304al44QxbfffefJO;Oxbffffei49xb7ffd94e0x000000000x00000001Gxbfffef48:(gdb)|0X0GQ00GO20X0G0GO0030X00000004&X0OGOGQ05图2.2.2观察到执行read_six_numbers后,输入的数字依次存放在 esp+0x18、esp+0x1c、esp+0x20、esp+0x24、esp+0x28、esp+0x2c中,故对输入的数字首先就要有第一个数不能小于0。继续观察phase_2的后一部分反汇编代码,如图所示:864Bbdl:7922jns8048bf5<phase2+Gx41>8G48bd3;e83dS5DGSOcallB049115<explode_bomb>B048bdB:eblbjmp8Q43bf5<phase2+0x41>8S43bda:89moveaXjebx804SbdC:03449c14addeaxrdwordptr[它5P十启bx*4+@*14]8S48beO:39449cIScmpdwordptr(esp+ebx*4+0xlS],eax8048be4:7405隹8Q48beb<phase2+flx37>8048be6:启82aQ5OG09call8049115<explodebomb>8S4at)eb:B3c301addebxrOxi8048bee:S3fbQ6cmpebxfflx6S048bfl:75e7JneS043bda<phase2+0x26>6e48bf3:ebG7ji叩S04Sbfc<phase_2+0x4B^8048bf5:bb010000SOmovebxf0x1B048bfa:ebdejmpS348bda<phase2+0x26>8B4Bbfc:S3C438addesp,0x383048bff:5bpopebx8048C0O;c3ret图2.2.3能容易发现这是一个循环,首先将ebx赋值为1,然后比较[esp+ebx*4+0x14]加上ebx与[esp+ebx*4+0x18]是否相等,相等就ebx加一继续执行,直到ebx等于6后退出。然后来分析应该输入的值。第一个数只要大于等于0就可以。不妨就输入0。他将会被保存在esp+0x18处。所以ebx等于1时,有[esp+ebx*4+0x18]=[esp+0x1c]=[esp+ebx*4+0x14]+ebx=[esp+0x18]+1。故第二个输入的数字应该为0+1=1。同理分析可得后面的数依次为3、6、10、15。故这六个数依次为0、1、3、6、10、15。重新执行该程序,直接输入“01361015”,观察结果。如图2.2.4所示:PhdS€1defused.Howaboutthenextone?01361015That1snumber7.Keepgoing!图2.2.44.实验结果:如图2.2.4所示,阶段二拆弹成功!阶段二涉及到了小的循环,慢慢的依次执行很同意就能发现规律,也不是很难。阶段3条件/分支.任务描述:通过phase_3的反汇编代码推断第三阶段要输入的数据.实验设计:利用gdb结合断点来动态地分析.实验过程:观察phase_3的前一部分反汇编代码,如图2.3.1所示:08S43C01<phase3>;8048cfll: 83 ec 2c sub e5pd&x2<8Q48C04! 8d 44 24 1c lea eax^[esp8Q43C08: 89 44 24 0c mov dwordp18048cflc: 8d 44 24 18 lea eax^[esf8Q48C10: 89 44 24 08 mov dwordp18Q43C14! c7 44 24 04 2fa304 mov dwordp1B043clb: 088043clc: Sb 44 24 3Q niov eaxtdwo8O43C20: 89 04 24 mov dword p8。4耻23: €838忆ff” 811 加6电1+QxlcJ:r[esp+0xc]Heax1+0X18J:r[esp+flxB],eax:r[esp+0x4]H0x8Q4a32f"dptr[esp+Gx39]:rresol.eax<isoc99sscanfi^plt;*BG40C28: 83fe01 cmp|eax.GxlB043c2b: 7T05 回 BO46C32<Dhase3+0x31>B043c2d: e8e3040000 call8049115^explodebombH图2.3.1发现输入的应该要求__isoc99_sscanf@plt的返回值大于1,于是观察调用__isoc99_sscanf@plt时格式字符串的值,在0x8048c23处下断点然后进入函数单步调试,并测试输入“01234”,如图2.3.2所示:0xO8048c23inphase3{gdb)stepi0x68048860inisac99sscanfgplt什(gdb)niisac99sscanf(5=0x8O4c48O<inputstrings+160>"S1234*.fonrat=0x804i332ffd)atisoc99sscanf.c!2625i5oc99_sscanf.c;Nosuchfileordirectory.相曲)图2.3.2观察到格式字符串为“%d%d”,故只需输入两个数字即可。同phase_2操作可以发现输入的数字依次存放在esp+0x18、esp+0x1c中。继续观察phase_3的

后一部分反汇编代码,如图2.3.3所示:S048c2deSe30400日电call8049115cexplodebomb^804EC32837c241807cmpdwordptr[esp+0xl8],6x7804BC37773c804SC75<phase3+0x74>3Q4BC398b442418moveaxHdwordptr[esp+flxlS]8D48c3dff2485COal0408Impdwordptr[eax+4+OxS04alcG]894BC44bS4dG200白£)moveax.0x24d864SC49eb3bjnp8日4配86<=phase_3+0x35>8046c4bbSC0G2000®moveaxHGx2c0804SC5Oeb34jnp804Sc86<pha5e_3+0x35^8S4BC52b8bdG&00DGmoveax.Oxbd804BC57eb2djmp8048cB6<phase_B+0x35>8648C59b8b3030000moveaxH0x3b3304fic5eeb26jmpBQ4ScB6<phase3+flx35>8g4耻6gba22030000moveaxF0x322804SC65ebIfjmp804Sc86<phase3+flx85>B040C67b3吊9010000moveaxr0xla9804Sc6ceb18Imp8®48c86<phase3+0x85>8Q4Ec6ebS9aGO00QBmoveax,0x9a8Q48C73eb11imp8048c88^pfiase3+QxS5>804BC75eS9bG4白。OScall8049115^explodeboinb>8g48c7ab800000000moveax,0xQ8C4Bc7feb05jmp804Sc86<phase3+Qx85>304SC31b33d000000moveaxr0x3d8G4BC863b44241ccmpeaxpdwordptr[esp+GxlcJ3048c8a7405jeB048c91<phase_B+0x90>864SC8CeSS40400OScall.8049115<=explodebomb^BQ4SC9183c42caddespH0x2c8040C94c3ret图2.3.3可以显然的发现一个数字要求不能比0x7大,然后就会将第一个数字送入eax中,然后跳转至[eax*4+0x804a1c0]处执行,显然是个分支程序。重新调试程序输入“1100”,观察执行到0x8048c86处eax的值,即第二个数应该的值。如图2.3.4所示:Breakpoint3,Gx08648c86inphase_3()(gdb)inforegeax 0x3d61图2.3.4故第二个数为61。重新执行该程序,直接输入“161”,观察结果。如图2.3.5所示:That'snumber2.KeepgoingI161Halfwaythere!图2.3.5.实验结果:如图2.3.5所示,阶段三拆弹成功!阶段三用到了分支,由于没有必要弄懂整个分支的功能,只要选择其中的某一路就可以了,所以解决起来也不是很难,单步执行下去就能很快的找到第二个输入的正确值。

阶段4递归调用和栈.任务描述:通过phase_4以及func4的反汇编代码推断第四阶段要输入的数据.实验设计:利用gdb结合断点来动态地分析.实验过程:观察phase_4的前一部分反汇编代码,如图2.4.1所示:08O48cf2 4>:8048CT2:83ec2csubesp,0x2cB048cf5:8d44241cleaeax,[esp+Oxic]8048CT9:394424Ocinovd^ordptr[esp+&xc].eax8048cfd:8d4424ieleaeax,[esp+0x18]S040d01:394424呢movdwordptr[esp+GxS],eaxS白48dl35:c74424042fa304movdwordptr[esp+0x4],0x004a32fS04Sd0c:088048d0d:Sb442430moveaxdwordptr[esp+0x3Q]S040dll:890424movdwordptr[esp]peax8048dl4tcS47fbffffCdll30433^0|<isoc9955canf@plt>]SQ40dl9:83fB025PIeaxr6x2|SI340dlc:75671逆13Q48d25<phase_4+0x33>3948dle:837c2418呢cropdwordptr|lesp+OxlSJ,0xe|SQ40d23:7&65rr^~i8G43d2a<phase4+0x38>81348c125;eSeb030909call3049115<explode_bcinib>图2.4.1发现输入的应该要求__isoc99_sscanf@plt的返回值等于2,于是同阶段三一样测试观察调用_isoc99_sscanf@plt时格式字符串的值,发现为仍然为“%d%d",而且[esp+0x18]要求小于等于0xe。如图2.4.2所示:0x0804fldl4inphase4(gdb)stepi0x00048860in_iSQc99_553nT@plt()(gdbJniisoc99sscanf(s=Ox894c4d0<inputstrings+24O>"12"tformat=DxSQ4a32f”就I钊")atisoc99_sscanf.c:26(gdb)■图2.4.2继续观察phase_4的后一部分反汇编代码,如图2.4.3所示:BO46cl25:e8ebS3GO00call8G4^115<explode_bomb>BG43d2a:匚74424030e0GG0movdwordptr[esp+0x8JfOxe8G43d31:GO8G4Sd32:c74424G4000GGOmovdwordptr[esp+Gx41p0xG8G48d39:008048d3a:8b442418moveax,dwordptr[esp+Gxl8]8048d3e:890424movdwordptrfesp],eax8e48d41:e84fffffffcall8G48C95<func4>8G48d46:83fS0fcmpeaXpOxfBG43d49:7507jneBG43d52vph口su4+Gx60>8G48d4b:837c241cOfcmpdwordptrfesp+Oxlc]dQxf8G48d50:7口05在8G48d57^phase_4+Gx65>8048d52;e8be030000callBG49115<explode_tiomb>8日48d57:83c42caddespr0x2c8048d5a:c3ret图2.4.3

可以不难发现依次将输入的第一个数,以及0x0和0xe作为参数传给func4,要求返回值为0xf而且输入的第二个数与0xf相等才不会爆炸。所以需要输入一个正确的数来保证func4的返回值为0xf。于是观察func4的反汇编代码,如图2.4.4所示:8040C95:56804BC96:538040C95:56804BC96:53SG48C97:83ec148G48c9a:8b5424208G48c9e:8b4424248@48ca2:Sb7424288048ca6:89fl8G48ca8:29clSG4Scaa:89Cb&048cac:clebIf8048caf:G1d9BG4Scbl:dlf9&G48cb3:Sd1c018e48cb6:39d3S04BcbB:7e173G4dcba:8d4bff804Scbd:894c24088G48ccl:894424G4SG4&CC5:8914248G48CC8:君8c8ffftff8G48ecd:gida8G4&CCT:eblb804Scdl:89d88G48cd3:39d3S048cd5:7d15&04Scd7:897424088G48cdb:8d43GlBG40cde:89442404SG4Sce2:S91424e8<ibffffff804Bcea:eids3G4Sccc;33c4148048cef:5b8G4Scf0:5e8648cfl:匚3OS048c95unc4>:pushesipushebxmubesp,Gxl4movedXpdwordptr[esp+0x2G]moveax.dwordptr[esp+Gx24Jmove$lrdwordptr[esp+0x2Bjmovecx.esisubecx,eaxmovebx,ecxshrebXpOxlfaddecx.ebxsarecx,1leaebx,[ecx+eax*l]cmpebx,edxjlE8G48cdl<func4+0x3c^lu日ecx.febx-&xllmovdwondptr[esp+QxB],ecxmovdwordptr[esp+Sx4],eaxmovdwordptr[espjfedxcall8G48C95<func4>addeax,ebxjmp8Q48cec<func4+0x57>moveax,ebxcmpebx.edxiae804Bcec<func4+0x57>movdwordptr[esp+QxS].esileaeax,[ebx+Oxl]movdwordptr[esp+Gx4],eaxmovdwo「dptr[esp]Pedxcall8G4&C95<func4>aHdeax,ebxaddesp,0xl4POPebxPOPesiret图2.4.4很快就能发现其中有递归调用,仔细分析发现,第一次调用时其中edx,eax,esi依次为x(为输入的第一个数),0x0,0xe。然后ecx=(esi-eax)/2,然后ebx=ecx+eax=(esi+eax)/2,然后根据ebx与edx比较也就是传入func4的第一个参数与后两个参数的平均值的比较结果进行相应的处理。当第一个参数小于后两个参数的平均值时,就依次将原来的第一次参数、原来的第二个参数、原来后两个参数的平均值减一作为参数调用func4,然后将返回值以及原来的后两个参数的平均值的和作为返回值输出。即原来参数依次为a、b、。,传入参数依次为a、b、(b+c)/2-1;当第一个参数大于后两个参数的平均值时,就依次将原来的第一次参数、原来后两个参数的平均值加一、原来的第三个参数作为参数调用func4,然后将返回值以及原来的后两个参数的平均值的和作为返回值输出。即原来参数依次为a、b、。,传入参数依次为a、(b+c)/2+1、c;当第一个参数等于两个参数的平均值时,就直接将平均值直接输出。所以通过反推,要求func4的返回值必须为0xf也就是15,显然直接输出平均值不可行。若第一个参数大于0x0与0xe的平均值也就是7的话,则下一层调用func输出的返回值必定大于(8+15)/2>8,故结果必定大于15,所以也不行。故输入的第一个参数必定小于7,演算之后发现5正好符合要求,第一次调用平均值为7,然后传递5、0、6为参数第二次调用,平均值为3,再次传递5、4、6为参数第三次调用,平均值为5,与输入相等,故输出7+3+5=15,即0xf。综上,重新执行该程序,直接输入“515”,观察结果。如图2.4.5所示:Halfwaythere!515Soyougotthatone.Trythisone.图2.4.5.实验结果:如图2.4.5所示,阶段四拆弹成功!阶段四难度开始提升,调用了别的函数,而且函数还有递归调用,这就要求必须完整的看懂递归的函数的功能,分析出来功能后才能反过来推测正确的输入。阶段5指针.任务描述:通过phase_5的反汇编代码推断第五阶段要输入的数据.实验设计:利用gdb结合断点来动态地分析.实验过程:观察phase_5的前一部分反汇编代码,如图2.5.1所示:08O48d5b<phase_5>:5。48d5b;S3ec2csubesp,Gx2cS048d5e:8d44241Cleaeax,[esp+Gxlc]8043d62;S94424Bemovdwordptr[esp+Oxc],eax8048d66:8d442418leaeax,Lesp+QxlSj8048d6a:894424OSmovdwordptr[esp+Gx8],eax8043d6e;c74424042f 04movdwordptr[esp+0x4]H0x3O4a32f8048(175:esSG48d76:Gb442430rtioveaxpdwordptr[esp+ex3G]8043d7a:S90424movdwordptr[tsp]eax8048(J7d:eSdefaffftcall3048S6Ov_i5oc99_S5canf^plt>6048d82:E3fllcn)peax,Gxl8048d85;7f05jg004Sd8c<phase_5+0x31>8048(187:eS3903幽00call8Q49115<expLodebamb>图2.5.1发现输入的应该要求__isoc99_sscanf@plt的返回值大于1,于是同阶段三一样测试观察调用_isoc99_sscanf@plt时格式字符串的值,发现为仍然为

“%d%d”。如图2.5.2所示:Oxe8048d7dinphase5()(gdb}step!0x0894^860inisoc99sscanf@plt()(gdb)ni_isoc99_sscanf(s=Sx804c52S<input_slrings+32fl>"1234",fonnat=SxBe4a32f"%d%d")atisoc99sscanf.c:26(gdb)|图2.5.2继续观察phase_5的后一部分反汇编代码,8fl48d878g48d8c8Q4Sd908048d938048d97Hg48dgmSG48d9c能48gl8048da6804Sda98048dbO8048db28G48db58048db78043dbb3043dbe8Q4BdcG804fldc48048dc63048dcb8048dce94848be80&384小980000a020oe图2.5.2继续观察phase_5的后一部分反汇编代码,8fl48d878g48d8c8Q4Sd908048d938048d97Hg48dgmSG48d9c能48gl8048da6804Sda98048dbO8048db28G48db58048db78043dbb3043dbe8Q4BdcG804fldc48048dc63048dcb8048dce94848be80&384小980000a020oe5804040175601-0fefc142c43b4ase2Ccall8049115<explt>de_bonib>moveax.dwordptrlesp+6xl8]andeax10xfmovdwordptr[esp+flj(18]HeaxcmpeaxdGxfje8&46dc6<phase5+&x6b>moveexj0x0movedx.OxSaddedx,Gxlm<iveax.dwordptr(eax+4+Sx804alea]addecx^eaxcmpeax^Oxfjne8048da6<phase5+&x4b>movdwordptr[esp+GxlS]reaxcmpedxfGxfjne3043d 印h鸣cmpecx±dwrdptr(esp+Sxlc]柞8048dcb<phase5+Ox70>call8Q49115<explodebomb>addespd0x2cret如图2.5.3所示:图2.5.3仔细分析发现,首先将第一个输入的值送入6@乂后与0xf做且运算,然后在与0xf比较,相等就会爆炸,不相等就将[eax*4+0x804a1e0]的值赋给eax,然后直到eax等于0xf,比较进行该赋值的次数,赋值次数也等于0xf且输入的第二个值恰好为赋值后eax的总和,则完成这个炸弹的拆除。于是执行到phase_5后,用x命令观察0x804a1e0后的连续15个值,如图2.5.4所示:图2.5.4(gdb)x/L5d@x884ale60x804alefl<array.3143=*:109xS04alfO<array,3143+16>:Dx8Q4a20Ocarray.3143+32>:图2.5.40x&S4a210orray.3143+4B>:(gdb)|由图2.5.4可以列出改数组的值,如表2.5.5:A[0]=10A[1]=2A[2]=14A[3]=7A[4]=8A[5]=12A[6]=15A[7]=11A[8]=0A[9]=4A[10]=1A[11]=13A[12]=3A[13]=9A[14]=6表2.5.5所以通过反推,要求15次后的eax值必须为0xf也就是15,则反推有15-6-14-2-1-10-0-8-4-9-13-11-7-3-12-5,所以第一个输入的值为5,第二个值为15+6+14+2+1+10+0+8+4+9+13+11+7+3+12=115。综上,重新执行该程序,直接输入“5115”,观察结果。如图2.5.6所示:Soyougotthatone.Trythisone.5115Goodwork!Ontothenext...图2.5.6.实验结果:如图2.5.6所示,阶段五拆弹成功!阶段五用到了数组,只要正确的找到了数组中元素的值,后面的循环就很简单了。阶段6链表/指针/结构.任务描述:通过phase_6的反汇编代码推断第五阶段要输入的数据.实验设计:利用gdb结合断点来动态地分析.实验过程:观察phase_6的前一部分反汇编代码,如图2.6.1所示:0004Sdcf<phase6>;S04Sdcf:56pushesi8Q48dd0:53pushebx81348dd1;83CC44 subesp19x44Bd44241G leaeaxf[esp+6xl6]ai340dda:B94424G4 movdwordptr[esp+Gx4],eax3O40ddc:Sb44245Q moveaxrdwordptrLesp+Qx5G]S048deO:890424 movdwordotr[espj,eax8G48de3:eS54S30Q0Q call804913c<readsixnumbers^304SdeB:beSO000000 movesirOxs8048ded:Sb44b4IQ moveax.dwordptr[esp+esi*4+0xL0]8048dfli83e801 subeaxp0x1S048df4:S3f805 cmpeaxp0x5S043df7:7605jbej8Q48dfe<phase6+0x2f>S048df9ie81703BO00 call8Q49115<explodebomb>图2.6.1仍然是读取六个数字,输入“012345”测试,然后在read_six_numbers返回后观察数字是否被存放在[esp+0x10]处,如图2.6.2所示:9x9&04Bdedinphases()(gdb)x/6d$e&p+QxlO9xbfffef2O:0123。工bH也门削4 5(gdb)|图2.6.2所以这段代码还对输入的值有一定的要求,要求减去以后必须不能大于5,即要在1、2、3、4、5、6中的数字才可以。继续看phase_6的下一段反汇编代

码,如图2.6.3所示。BG4Sdf9:8B48dfe:e817 00GOS3c601calladd8@49115<explode_bomb!>esirSxl8048eei:83fe06Icmpesi,0x6|SQ48eO4;7507jne8O48e0d<phase6+Qx3e>bb00oooo0Qmovebx,0x6B043eOb:eb3SjmpB048e45<pha5e_6+0x76>6048eGd:39f3movebXjesiEG4aeflf:Sb449c10moveax,dwordptr[esp+ebx+4+0xlO]S048el3:3944b4Be5口dwordpt「|[「占口+「£1才4+日*匚]|」『曰卜B048el7;7505jne|BQ43ele<pha5e_b+0x4i:>BS43el9:e8f7020000callB049115<exploEebamb>SG48ele:83c3&1addebx.SS48e21:83fb05cnnpebx.DxSjE048e24:7e€9jteEO48e0f<phase6+0x4G>BS43e26:ebc5川pB043ded<phase_6+exle>图2.6.3不难发现这是通过esi与ebx来实现的双重循环,一一比较输入的值是否相同,只要有一对相同该炸弹就会爆炸,所以输入的数据应该是1到6的一种排列才可以。继续看phase6的下一段反汇编代码,如图2.6.4所示。8048e280O4Be2b3S4Se2e804fie308048e32804能34B04Be398Q4Se3d0O4Be4O804fie43804fie458048e47804ee4b8fl4fie4e8Q4Se500O4Be55804fie5a8100-148048e280O4Be2b3S4Se2e804fie308048e32804能34B04Be398Q4Se3d0O4Be4O804fie43804fie458048e47804ee4b8fl4fie4e8Q4Se500O4Be55804fie5a8100-1416cb0OC101900CrD710movmovaddcmpjemovmovcmp止movmovjmp图2.6.4edx±dwordptr[edx+Sxfl,eax0x1eaxdecx804Be28.cphase6+fix59>804Be39_<pti£5e_6+9x6a>edx]ex804c13c|dwordptr[esp+esi+4+0x28],edxebx10x1ebx^0x6SG4Be5c<phase6+0xSd>esifebxecXfdwurdptr[esp+ebx:*4+0x16]ecx,0x18046e34<phase6+0x65>eaxtSxl edxj0x804c:13c|8G46e28<phase6+&x59>发现出现了一个奇怪的地址,用x命令观察一下,如图2.6.5所示:(gdb)xQx304cl3cOx804cl3c<nodel>: 9B&(gdb)|图2.6.5很容易发现是一个节点,用X命令将该链表所有节点全部罗列出来,如图2.6.6所示:(gdb)x/3xI3x&04cl3c8x8B4cl3c<nodel>:(gdb)x/3x0X&O4C143OXGSGO00010x0804c148Gx8fi4cl4S<node2>:(gdb)x/3xexO8G4c1540XGOS0GO02—88日4c1540x804cl54<node3>:(gdb)x/3x0x0804c1600x00000003flxB864cl6fiflxS04cl6&<node4>:(gdb)x/3x0x08G4cl6cGx0GGQ003e0x00000004Ox0BG4cl6c0x804cl&c<node5>:(gdb)x/3x歌。864cl78日日日0日呼0x804cl7S<node6>j(gdb)I0x0000037a0x000000060X00000000图2.6.6根据该链表并继续观察代码,仔细大胆猜测这段代码是根据输入的序列,将链表的顺序进行改排。然后再判断改排后的链表中的数据是否是从小到大进行排序的。所以不妨大胆的猜测应该输入的排序序列应该为4(0x3e)<5(0x1bc)<2(0x263)<3(0x2bc)<6(0x37a)<1(0x3dc)。故猜测输入的字符串应该为“452361”,重新运行程序,输入该字符串进行测试,如图2.6.7所示:Goodwork!Ontothenext,Pr452361Cong『占tul■自ti■白ns!You've th白bomb!图2.6.7.实验结果:如图2.6.7所示,阶段六拆弹成功!阶段六难度大大加大,由于有大量的地址的操作,所以乍一看很难看懂功能,查看相应地址后发现是个链表,在结合反汇编代码,很容易能猜测出大概的功能,从而来推测正确的输入。阶段7隐藏阶段.任务描述:找出隐藏阶段开启方式并且拆除隐藏阶段的炸弹。.实验设计:利用gdb结合断点来动态地分析.实验过程:直接在反汇编代码中观察发现,只有phase_defused函数中有对secret_phase函数的调用,于是观察phase_defused函数的反汇编代码,如图2.7.1所示:观察不难发现,要经过两个比较,以及一个字符串比较后才能开启隐藏阶段。而第一个比较是一个数与常数0x6的比较,结合隐藏阶段的开启条件,必须在阶段6完成后才能开启就很容易发现,这个数(ds:0x804c3c8)应该就是用来指示当前阶段的。于是在phase_6完成后,在phase_defused处下断点,观察ds:0x804c3c8处的值,如图2.7.2所示:

08049286<phasedefused>:3049286: 81 ec Sc GO GG SO sub esprGxScS0492SC: 65 al 14 00 00 00 mov eax:Gxl48049292: 89 44 24 7c mov dwordptr [esp+0x7c],eax8049296: 31 ce xor eaxP«ax3Q4929B: 833dcBc30408日6 cmpdwordptirds:0x304c3cBf9x6B0492&f: 7572 ]ne8G49313<phasedefused+&x8d>30492al: 8d 44 24 2c lea eax^[esp+Gxlc]S0492a5: 89 44 24 10 mov dwordptr[esp+QxlQ],eax80492a9: 8d 44 24 28 lea eaxt[e5p+0x28]3Q492ad: 89 44 24 0c mov dwordptr[esp+Oxc]teax39492til: 即 44 24 24 lea eaxr[esp+0x24]B®492tl5: 89 44 24 08 mov dward ptr [esp+Dx8]Teax30492b9: c7 44 24 04 89 a3 04 mov dword ptr [esp+0x4]f&xSS4a368O492C0: OSS0492C1; c7 04 24 dO c4 04 08 mov dword ptr [esp]h0x804c4d980492cEi e8 93 f5 ff ff call 8Q48860< isoc99sscanf^plt19>39492cd: 83fB03 IFcmpeax.GxSS0492dS: 75 35 ]ne 8049307<B0492d2: c74424G492 34movdwordptr80492d9: 03S0492da: 8d 44 242c lea eaxt[e&p+80492de; 89 04 24 mov dwordptrphasedefused+0x81>[esp+0x4]JOxSO4a3920x2c][esp],eax30492el; e324fdffff call304960a<strings_not_equal>8M92第; 35c& test eax.eax30492eS: 75Id ]ne 8S493S7<phasedefused+&x81>30492ea: c7 04 24 58 a2 04 SB mov dwordptr[esp]T0x8&4a25S8Q492f1: e8 fa f4 ff ff call 80487fB<puts@pl.t>S0492f6; c7 04 24 80 32 04 08 mov dwordptr[esp]h0x804a2E930492fd: e3 ee 14 ff ff call aO487fG<pjts@plt>3949302: 已8 ec Tb ff ff call aQ48ef3<secret_phase>图2.7.1Breakpoint2t0x06049236inphasedefused()(gdb)x/lx0x&S4c3c8GxS94c3c8<ndm_inpdt_5trings>; 0X0G00B0O6(gdb)|图2.7.2果然与猜测相同,继续执行观察__isoc99_sscanf@plt函数的输入字符串格式,如图2.7.3所示:Breakpoint3,0x0804886©inisoc99sscanf0plt()(gdb)step!_isoca^ssc^nf(s=0xS04c4d0^inputstrings+a^,515”,Tormat=0xS04a3S9"M专d电£")atisoc99_sscanf.c:2626 isoc99_sscanf.c:Nosuchfileordirectory,tgdb)|图2.7.3观察发现与第四次的输入相同,但是输入字符串格式不同,于是应该是在第四次输入的数据后加上一段字符串。而字符串首址的位置显然为0x804a392,用x命令观察,如图2.7.4所示:(gdb)x/ls0x&04a392曲的44392: "DrEvil"(gdb)|图2.7.4所以修改第四次的输入为“515DrEvil”,测试观察是否开启了secret_phase阶段,如图2.7.5所示:linux@Ubuntu:'/Publi€/tmp/U2ei41457B$,/bombWelcometomyfiendishlittlebomb.Youhave6phaseswithwhichtoblowyourselfup.Haveaniceday!BorderrelationswithCanadahaveneverbeenbetter.Phase1defused.Howaboutthenextone?01361015That'snumber2.Keepgoing!161Halfwaythere!515DrEvilSoyougotthatone,Trythisone.5115Goodwork!Ontothenext...452361Curses,you'vefoundthesecretpha5e!Butfindingitandsolvingitarequitedifferent..r图2.7.5接下来开始拆除secret_phase阶段的炸弹,首先观察secret_phase函数的反汇编代码,如图2.7.6所示:e804Bef3^secretpha&e>:S04Sef353pushebx804Bef483ec18subesp.OxlB804SeT7e89002G000call804918c<rcadlino|B04Befcc74424080aQ000movdwordptr[esp+Qx^lFSxa804&f03804Sf04c74424G40000OQmovdwordptr[esp+Qx4]rOx08O4&f0bG&B04Bf0c890424movdwordutr[esc],eax804Bf0f€8bef9ffftcallB048Bc0<strtol.@plt>|804Bfl489nioveb^.ea^804Bfl68d40ffleaeaXj[eax-Gxl]8G4Sfl93d旺8 ©00Gemp|eaxf0x3e8804Bfle7605PTbel8048吊25<secretphase+0x32>804Bf20e8fO010000call8049115<explodebomb>B04fif25895亡2404movdwordptr[t5p+0x4]hebxBG4Bf29C7042483CO04OSmovdwordptr[esp],Qxa9'4c088864fif30€86dffffffcallBfl48ea2<fun7^8G4Sf3583fS07empeax,0x7804Bf367405je的48门中 reiphase+0x4c;*8G4Bf3ae8610000call8049115^explodebomb〉804Bf3fc704247cal040&movdwnrdptr[esp],BxflO4al7c8G4Bf46e3a5fSffffcall80487fG<putseplt>8G4Bf4b36&3G&00callSQ49286^phasedefused?*8G4BfSe83C4IBadde&p^QxlS迪48f535bPOPebx8G4Bf54c3ret图2.7.6很显然输入的是一个数值,而且该数值要求不能大于0x3e8+0x1=1001。然后将0x804c088以及该数值作为fun7参数传递进去,如果返回值为0x7就拆除了改炸弹。所以来观察一下fun7的反汇编代码,如图2.7.7所示:0SO48ea2<fun7>:53pushebx8048ea3S3ec18subespr6x188043ea6SO542420 movedXjdwordptr[esp+0x2GJ8048eaaSb4c2424 novecx.dwordptr[esp+0x24J3043eaeB5d2testedx,edx8048eb07437ie804See9<fun7+0x47>8048eb28blamovebx,dwordptr[edx]8B4Seb439cbcmpebx,ecxS048eb67e13jle8G48ecb<fun7+0x29>S048eb8894c24t)4 movawordptiriesp+t)x4],ecxSb4204moveax^dwordptr[edx+0x4]8648ebfS90424movdwordptr[esp]Feax8048ec2eBdbffffff call8B48ea2<fun7>8G48ec701存ddeaxeaxsb23imp3Q43eee^fun7+0x4c>3043ecbGO00&Q00 HQVeax.QxO8048edO39cbcmpebx,ecx74laje8043eee<fun7+0x4c>8048ed4894c2404 movdwordptrlesp+0x4]recxa048ed8Bb42S3moveax,dwordptr[edx+0x8]B9G424movdwO'rdptr[e?p],eaxeBbfffffff callS04Bea2<fun7>8048ee3Sd440001 leaeaxj[eax+eax*l+OxlJ8048ee7eb65imp3048eeetfun7+0x4c>3043ee9bSffffffff moveax,©xfffiffff8048eee83c413addesp,6x138048efl5bpopebxS048ef2c3ret图2.7.7很快就能发现其中有递归调用,仔细分析发现,第一次调用时其中edx,ecx依次为0x804c088,x(为输入的数)。然后比较edx与0,如果相等就返回-1,否则ebx=[edx],然后比较ebx与ecx,也就是根据传入fun7的第一个参数处的数值与第二个参数比较结果进行相应的处理。当第一个参数处的数值小于第二个参数时,就依次将原来的第一次参数加上0x8处的值、原来的第二个参数作为参数调用fun7,然后将返回值乘以2后再加上0x1作为返回值输出。即原来参数依次为a、,传入参数依次为[a+0x8]、b;当第一个参数处的数值大于第二个参数时,就依次将原来的第一次参数加上0x4处的值、原来的第二个参数作为参数调用fun7,然后将返回值乘以2作为返回值输出。即原来参数依次为a、^传入参数依次为[a+0x4]、b;当第一个参数等于两个参数的平均值时,就直接将平均值置为0输出。所以通过反推,要求fun7的返回值必须为0x7也就是7,显然直接输出0或者-1都不可行。当第一个参数处的数值大于第二个参数的话,则最后的返回值必定为偶数,所以也不行。所以第一个参数处的数值应该小于第二个参数,用x命令观察0x804c088处的值,如图2.7.8所示:(gdb}x/lx0xSG4c0S80x8O4cOS&<nl>:0x00000024(gdb)■图2.7.8所以输入要大于0x24,再向下一层,就要求fun7返回值为0x3,所以这次第一个参数处的数值还要大

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论