编译器会把字符串放置在一个特定的Section中(如.rdata或.data)。
我们无法确定包含所需函数的DLL文件是否已经加载到内存。受ASLR(地址空间布局随机化)机制的影响,系统不会每次都把DLL文件加载到相同地址上。而且,DLL文件可能随着Windows每次新发布的更新而发生变化,所以我们不能依赖DLL文件中某个特定的偏移。
我们需要把DLL文件加载到内存,然后直接通过shellcode查找所需要的函数。幸运的是,Windows API为我们提供了两个函数:LoadLibrary和GetProcAddress。我们可以使用这两个函数来查找函数的地址。
空字节被认为是字符串的结束符
#include
#include
int main() {
// 字符串使用数组
char kernel32[] = { 0x5f,0x51,0x46,0x5a,0x51,0x58,0x07,0x06,0x34 };
HMODULE DD = LoadLibraryA(kernel32);
char addatoma[] = { 0x75,0x50,0x50,0x75,0x40,0x5b,0x59,0x75,0x34 };
// 函数使用相对地址
LPVOID FUN1 = GetProcAddress(DD, addatoma);
// FUN1();
return 0;
}
以上代码中,LoadLibraryA和GetProcAddress函数还没有实现相对地址——》这时候就要用到peb寄存器
参考:PEB TEB结构体使用
FS段寄存器指向当前的TEB结构,TEB偏移0x30处指针指向PEB,通过fs:[0x30]
即可获得PEB信息。0x030 ProcessEnvironmentBlock : Ptr32 _PEB 当前进程的PEB指针
PEB结构体偏移0c处指针ldr指向进程加载模块链表 PEB_LDR_DATA 。0x00c Ldr : Ptr32 _PEB_LDR_DATA 进程模块加载链表
PEB获取模块基址硬编码
注:MOV EAX,[EAX]
以eax里面的值做为地址,取出来给eax 。
比如地址100H = 88aaH
eax = 100H
那么mov eax, [eax]后
eax里面的值是88aaH
PEB_LDR_DATA 模块加载链表,包含有关为进程加载的模块的信息。
typedef struct _PEB_LDR_DATA
{
ULONG Length; // +0x00
BOOLEAN Initialized; // +0x04
PVOID SsHandle; // +0x08
LIST_ENTRY InLoadOrderModuleList; // +0x0c
LIST_ENTRY InMemoryOrderModuleList; // +0x14包含进程已加载模块的双向链表的头部。列表中的每一项都是指向LDR_DATA_TABLE_ENTRY结构的指针。
LIST_ENTRY InInitializationOrderModuleList;// +0x1c
} PEB_LDR_DATA,*PPEB_LDR_DATA; // +0x24
typedef struct _LDR_DATA_TABLE_ENTRY
{
LIST_ENTRY InLoadOrderLinks;
LIST_ENTRY InMemoryOrderLinks;
LIST_ENTRY InInitializationOrderLinks;
PVOID DllBase;
PVOID EntryPoint;
DWORD SizeOfImage;
UNICODE_STRING FullDllName;
UNICODE_STRING BaseDllName;
DWORD Flags;
WORD LoadCount;
WORD TlsIndex;
LIST_ENTRY HashLinks;
PVOID SectionPointer;
DWORD CheckSum;
DWORD TimeDateStamp;
PVOID LoadedImports;
PVOID EntryPointActivationContext;
PVOID PatchInformation;
}LDR_DATA_TABLE_ENTRY,*PLDR_DATA_TABLE_ENTRY;
获取模块的基址代码
void _getModuleBaseAddr()
{
void *PEB = NULL,
*Ldr = NULL,
*Flink = NULL,
*p = NULL,
*BaseAddress = NULL,
*FullDllName = NULL;
__asm
{
mov eax, fs:[0x30]
mov PEB, eax
}
Ldr = (PVOID)*((PDWORD)((DWORD)PEB + 0x0c));
Flink = (PVOID)*((PDWORD)((DWORD)Ldr + 0x14));
p = Flink;
do
{
BaseAddress = (PVOID)*((PDWORD)((DWORD)p + 0x10));
FullDllName = (PVOID)*((PDWORD)((DWORD)p + 0x20));
wprintf(L"FullDllName is %s\n", FullDllName);
printf("BaseAddress is %x\n", BaseAddress);
p = (PVOID)*((PDWORD)p);
} while (Flink != p);
}
课程:黑客高级技术织shellcode入门到精通
MT static 静态 (MTD debug模式使用)
MD dynamic 动态 release模式使用
链接器→子系统→改为窗口
关闭随机基址,方便调试:链接器→随机基址→改为否
GetProcAddress+LoadLibraryA可以实现其他函数的动态调用
#include
#include
int EntryMain() {
MessageBox(NULL, NULL, NULL, NULL);
return 0;
}
GetProcAddress从指定的动态链接库 (DLL) 中检索导出函数或变量的地址。通过它可以获得函数的真实地址。
LPVOID lp = GetProcAddress(LoadLibraryA("user32.dll"), "MessageBoxA");
此时lp记录的就是MessageBoxA的真实地址,如何调用呢?
#include
#include
#pragma comment(linker, "/subsystem:\"windows\" /entry:\"mainCRTStartup\"")
int EntryMain() {
//MessageBox(NULL, NULL, NULL, NULL);
LPVOID lp = GetProcAddress(LoadLibraryA("user32.dll"), "MessageBoxA");
char * pszData = (char *)"Hello World";
__asm {
push 0
push 0
push pszData
push 0
call lp
}
return 0;
}
如何编写正规的函数动态调用代码,以CreateFileA和printf作为示例
#include
#include
#pragma comment(linker, "/subsystem:\"windows\" /entry:\"mainCRTStartup\"")
int EntryMain() {
CreateFileA("hello.txt", GENERIC_WRITE,0,NULL, CREATE_ALWAYS,0,NULL);
printf("%s\n", "Hello World!");
return 0;
}
首先在CreateFileA函数上右键转到定义,将函数声明复制过来
WINBASEAPI
HANDLE
WINAPI
CreateFileA(
_In_ LPCSTR lpFileName,
_In_ DWORD dwDesiredAccess,
_In_ DWORD dwShareMode,
_In_opt_ LPSECURITY_ATTRIBUTES lpSecurityAttributes,
_In_ DWORD dwCreationDisposition,
_In_ DWORD dwFlagsAndAttributes,
_In_opt_ HANDLE hTemplateFile
);
修改为如下所示
#include
#include
#pragma comment(linker, "/subsystem:\"windows\" /entry:\"mainCRTStartup\"")
int EntryMain() {
// CreateFileA("hello.txt", GENERIC_WRITE,0,NULL, CREATE_ALWAYS,0,NULL);
typedef HANDLE(WINAPI* FN_CreateFileA)(
_In_ LPCSTR lpFileName,
_In_ DWORD dwDesiredAccess,
_In_ DWORD dwShareMode,
_In_opt_ LPSECURITY_ATTRIBUTES lpSecurityAttributes,
_In_ DWORD dwCreationDisposition,
_In_ DWORD dwFlagsAndAttributes,
_In_opt_ HANDLE hTemplateFile
);
//定义一个函数指针变量
FN_CreateFileA fn_CreateFileA;
//强制类型转换
fn_CreateFileA = (FN_CreateFileA)GetProcAddress(LoadLibraryA("kernel32.dll"), "CreateFileA");
//然后就可以正常使用CreateFileA了
fn_CreateFileA("hello.txt", GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
return 0;
}
#include
#include
#pragma comment(linker, "/subsystem:\"windows\" /entry:\"mainCRTStartup\"")
int EntryMain() {
// printf("%s\n", "Hello World!");
typedef int(__CRTDECL* FN_printf)(_In_z_ _Printf_format_string_ char const* const _Format, ...);
FN_printf fn_printf;
fn_printf = (FN_printf)GetProcAddress(LoadLibraryA("msvcrt.dll"), "printf");
fn_printf("%s\n", "Hello World!");
return 0;
}
在前一节中可以通过GetProcAddress和LoadLibraryA实现其他所有函数的动态调用,但是这两个函数也需要获得真实地址。
LoadLibraryA可以通过GetProcAddress获取,kernel32基址获取与getprocaddress地址获取
不管是winxp还是其他windows版本,kernel32.dll都是第三个被调用的模块
#include
#include
__declspec(naked) DWORD getKernel32()
{
__asm
{
mov eax,fs:[0x30] //fs:[30] 纯存的是PEB,也就是进程环境块,操作系统在加载进程的过程中会自动初始化一个PEB结构体用来初始化该进程的各种信息的结构体
mov eax,[eax+0x0c] //也就是PEB 0ch处的偏移,该结构体的三个成员链表都可以获取kernel32的基址
mov eax,[eax+0x14] //获取初始化顺序链表的地址,首地址是第一个模块
mov eax,[eax] //第二个模块
mov eax,[eax] //第三个模块
mov eax,[eax+0x10] // 10h偏移处就是kernel32的基地址
ret
}
}
int main() {
HMODULE hLoadLibraryA = (HMODULE)getKernel32();
printf("0x%08X\n", hLoadLibraryA);
printf("0x%08X\n", LoadLibraryA("kernel32.dll"));
LPVOID lpLoadLibraryA = GetProcAddress(hLoadLibraryA, "LoadLibraryA");
}
#include
#include
__declspec(naked) DWORD getKernel32()
{
__asm
{
mov eax,fs:[0x30] //fs:[30] 纯存的是PEB,也就是进程环境块,操作系统在加载进程的过程中会自动初始化一个PEB结构体用来初始化该进程的各种信息的结构体
mov eax,[eax+0x0c] //也就是PEB 0ch处的偏移,该结构体的三个成员链表都可以获取kernel32的基址
mov eax,[eax+0x14] //获取初始化顺序链表的地址,首地址是第一个模块
mov eax,[eax] //第二个模块
mov eax,[eax] //第三个模块
mov eax,[eax+0x10] // 10h偏移处就是kernel32的基地址
ret
}
}
FARPROC _GetProcAddress(HMODULE hModuleBase)
{
PIMAGE_DOS_HEADER lpDosHeader = (PIMAGE_DOS_HEADER)hModuleBase;
PIMAGE_NT_HEADERS32 lpNtHeader = (PIMAGE_NT_HEADERS)((DWORD)hModuleBase + lpDosHeader->e_lfanew);
if (!lpNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size) {
return NULL;
}
if (!lpNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress) {
return NULL;
}
PIMAGE_EXPORT_DIRECTORY lpExports = (PIMAGE_EXPORT_DIRECTORY)((DWORD)hModuleBase + (DWORD)lpNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);
PDWORD lpdwFunName = (PDWORD)((DWORD)hModuleBase + (DWORD)lpExports->AddressOfNames);
PWORD lpword = (PWORD)((DWORD)hModuleBase + (DWORD)lpExports->AddressOfNameOrdinals);
PDWORD lpdwFunAddr = (PDWORD)((DWORD)hModuleBase + (DWORD)lpExports->AddressOfFunctions);
DWORD dwLoop = 0;
FARPROC pRet = NULL;
for (; dwLoop <= lpExports->NumberOfNames - 1; dwLoop++) {
char* pFunName = (char*)(lpdwFunName[dwLoop] + (DWORD)hModuleBase);
if (pFunName[0] == 'G' &&
pFunName[1] == 'e' &&
pFunName[2] == 't' &&
pFunName[3] == 'P' &&
pFunName[4] == 'r' &&
pFunName[5] == 'o' &&
pFunName[6] == 'c' &&
pFunName[7] == 'A' &&
pFunName[8] == 'd' &&
pFunName[9] == 'd' &&
pFunName[10] == 'r' &&
pFunName[11] == 'e' &&
pFunName[12] == 's' &&
pFunName[13] == 's')
{
pRet = (FARPROC)(lpdwFunAddr[lpword[dwLoop]] + (DWORD)hModuleBase);
break;
}
}
return pRet;
}
int main() {
HMODULE hLoadLibraryA = (HMODULE)getKernel32();
typedef FARPROC (WINAPI *FN_GetProcAddress)(
_In_ HMODULE hModule,
_In_ LPCSTR lpProcName
);
FN_GetProcAddress fn_GetProcAddress;
fn_GetProcAddress = (FN_GetProcAddress)_GetProcAddress(hLoadLibraryA);
printf("0x%08X\n", fn_GetProcAddress);
printf("0x%08X\n", GetProcAddress);
//LPVOID lpLoadLibraryA = GetProcAddress(hLoadLibraryA, "LoadLibraryA");
}
将以下代码转换为shellcode
#include
#include
int EntryMain() {
CreateFileA("hello.txt", GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
return 0;
}
#include
#include
//声明
DWORD getKernel32();
FARPROC _GetProcAddress(HMODULE hModuleBase);
int EntryMain() {
typedef FARPROC(WINAPI* FN_GetProcAddress)(
_In_ HMODULE hModule,
_In_ LPCSTR lpProcName
);
//获取GetProcAddress实际地址
FN_GetProcAddress fn_GetProcAddress = (FN_GetProcAddress)_GetProcAddress((HMODULE)getKernel32());
typedef HANDLE (WINAPI *FN_CreateFileA)(
_In_ LPCSTR lpFileName,
_In_ DWORD dwDesiredAccess,
_In_ DWORD dwShareMode,
_In_opt_ LPSECURITY_ATTRIBUTES lpSecurityAttributes,
_In_ DWORD dwCreationDisposition,
_In_ DWORD dwFlagsAndAttributes,
_In_opt_ HANDLE hTemplateFile
);
//获取CreateFileA真实地址
char szCreateFileA[] = {'C','r','e','a','t','e','F','i','l','e','A', 0};
FN_CreateFileA fn_CreateFileA = (FN_CreateFileA)fn_GetProcAddress((HMODULE)getKernel32(), szCreateFileA);
//调用CreateFileA函数
char szhello[] = { 'h', 'e', 'l', 'l', 'o', '.', 't', 'x', 't', 0 };
fn_CreateFileA(szhello, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
// CreateFileA("hello.txt", GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
return 0;
}
__declspec(naked) DWORD getKernel32()
{
__asm
{
mov eax, fs: [30h]
mov eax, [eax + 0ch]
mov eax, [eax + 14h]
mov eax, [eax]
mov eax, [eax]
mov eax, [eax + 10h]
ret
}
}
FARPROC _GetProcAddress(HMODULE hModuleBase)
{
PIMAGE_DOS_HEADER lpDosHeader = (PIMAGE_DOS_HEADER)hModuleBase;
PIMAGE_NT_HEADERS32 lpNtHeader = (PIMAGE_NT_HEADERS)((DWORD)hModuleBase + lpDosHeader->e_lfanew);
if (!lpNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size) {
return NULL;
}
if (!lpNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress) {
return NULL;
}
PIMAGE_EXPORT_DIRECTORY lpExports = (PIMAGE_EXPORT_DIRECTORY)((DWORD)hModuleBase + (DWORD)lpNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);
PDWORD lpdwFunName = (PDWORD)((DWORD)hModuleBase + (DWORD)lpExports->AddressOfNames);
PWORD lpword = (PWORD)((DWORD)hModuleBase + (DWORD)lpExports->AddressOfNameOrdinals);
PDWORD lpdwFunAddr = (PDWORD)((DWORD)hModuleBase + (DWORD)lpExports->AddressOfFunctions);
DWORD dwLoop = 0;
FARPROC pRet = NULL;
for (; dwLoop <= lpExports->NumberOfNames - 1; dwLoop++) {
char* pFunName = (char*)(lpdwFunName[dwLoop] + (DWORD)hModuleBase);
if (pFunName[0] == 'G' &&
pFunName[1] == 'e' &&
pFunName[2] == 't' &&
pFunName[3] == 'P' &&
pFunName[4] == 'r' &&
pFunName[5] == 'o' &&
pFunName[6] == 'c' &&
pFunName[7] == 'A' &&
pFunName[8] == 'd' &&
pFunName[9] == 'd' &&
pFunName[10] == 'r' &&
pFunName[11] == 'e' &&
pFunName[12] == 's' &&
pFunName[13] == 's')
{
pRet = (FARPROC)(lpdwFunAddr[lpword[dwLoop]] + (DWORD)hModuleBase);
break;
}
}
return pRet;
}
#include
#include
int EntryMain() {
MessageBoxA(NULL, "Hello World!", "tip", MB_OK);
return 0;
}
#include
#include
//声明
DWORD getKernel32();
FARPROC _GetProcAddress(HMODULE hModuleBase);
int EntryMain() {
typedef FARPROC(WINAPI *FN_GetProcAddress)(
_In_ HMODULE hModule,
_In_ LPCSTR lpProcName
);
//获取GetProcAddress实际地址
FN_GetProcAddress fn_GetProcAddress = (FN_GetProcAddress)_GetProcAddress((HMODULE)getKernel32());
typedef HMODULE (WINAPI *FN_LoadLibraryA)(
_In_ LPCSTR lpLibFileName
);
//获取LoadLibraryA实际地址
char szLoadLibraryA[] = { 'L', 'o', 'a', 'd', 'L', 'i','b','r','a','r','y','A', 0};
FN_LoadLibraryA fn_LoadLibraryA = (FN_LoadLibraryA)fn_GetProcAddress((HMODULE)getKernel32(), szLoadLibraryA);
typedef int (WINAPI *FN_MessageBoxA)(
_In_opt_ HWND hWnd,
_In_opt_ LPCSTR lpText,
_In_opt_ LPCSTR lpCaption,
_In_ UINT uType);
//获取MessageBoxA实际地址
char szUser32[] = { 'U', 's', 'e', 'r', '3', '2', '.', 'd', 'l', 'l', 0 };
char szMessageBoxA[] = {'M','e', 's', 's', 'a', 'g', 'e', 'B', 'o', 'x', 'A', 0};
FN_MessageBoxA fn_MessageBoxA = (FN_MessageBoxA)GetProcAddress(fn_LoadLibraryA(szUser32), szMessageBoxA);
//调用fn_MessageBoxA函数
char szHelloWorld[] = { 'H','e', 'l', 'l', 'o', ' ', 'W', 'o', 'r', 'l', 'd', '!', 0 };
char szTip[] = { 't', 'i', 'p', 0 };
fn_MessageBoxA(NULL, szHelloWorld, szTip, MB_OK);
// MessageBoxA(NULL, "Hello World!", "tip", MB_OK);
return 0;
}
__declspec(naked) DWORD getKernel32()
{
__asm
{
mov eax, fs: [30h]
mov eax, [eax + 0ch]
mov eax, [eax + 14h]
mov eax, [eax]
mov eax, [eax]
mov eax, [eax + 10h]
ret
}
}
FARPROC _GetProcAddress(HMODULE hModuleBase)
{
PIMAGE_DOS_HEADER lpDosHeader = (PIMAGE_DOS_HEADER)hModuleBase;
PIMAGE_NT_HEADERS32 lpNtHeader = (PIMAGE_NT_HEADERS)((DWORD)hModuleBase + lpDosHeader->e_lfanew);
if (!lpNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size) {
return NULL;
}
if (!lpNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress) {
return NULL;
}
PIMAGE_EXPORT_DIRECTORY lpExports = (PIMAGE_EXPORT_DIRECTORY)((DWORD)hModuleBase + (DWORD)lpNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);
PDWORD lpdwFunName = (PDWORD)((DWORD)hModuleBase + (DWORD)lpExports->AddressOfNames);
PWORD lpword = (PWORD)((DWORD)hModuleBase + (DWORD)lpExports->AddressOfNameOrdinals);
PDWORD lpdwFunAddr = (PDWORD)((DWORD)hModuleBase + (DWORD)lpExports->AddressOfFunctions);
DWORD dwLoop = 0;
FARPROC pRet = NULL;
for (; dwLoop <= lpExports->NumberOfNames - 1; dwLoop++) {
char* pFunName = (char*)(lpdwFunName[dwLoop] + (DWORD)hModuleBase);
if (pFunName[0] == 'G' &&
pFunName[1] == 'e' &&
pFunName[2] == 't' &&
pFunName[3] == 'P' &&
pFunName[4] == 'r' &&
pFunName[5] == 'o' &&
pFunName[6] == 'c' &&
pFunName[7] == 'A' &&
pFunName[8] == 'd' &&
pFunName[9] == 'd' &&
pFunName[10] == 'r' &&
pFunName[11] == 'e' &&
pFunName[12] == 's' &&
pFunName[13] == 's')
{
pRet = (FARPROC)(lpdwFunAddr[lpword[dwLoop]] + (DWORD)hModuleBase);
break;
}
}
return pRet;
}
使用上面的代码生成.exe文件后,用peid查看文件偏移
从该偏移量开始即为shellcode
不过这里用视频里的方法,用这段shellcode直接替换目标exe偏移开始部分同等长度的16进制代码执行失败,因为自己对pe文件导出表、导入表部分基础还不太熟悉所以也不知道原因。
目标:直接把shellcode输出在bin文件中。
原理:看视频
#pragma once
#include
void ShellcodeStsrt();
void ShellcodeEntry();
void ShellcodeEnd();
void CreateShellcode();
0.entry.cpp
#include "header.h"
#pragma comment(linker,"/entry:EntryMain")
int EntryMain() {
CreateShellcode();
return 0;
}
void CreateShellcode() {
HMODULE hMsvcrt = LoadLibraryA("msvcrt.dll");
typedef int (__CRTDECL* fn_printf)(
_In_z_ _Printf_format_string_ char const* const _Format,
...);
fn_printf xprintf = (fn_printf)GetProcAddress(hMsvcrt, "printf");
xprintf("1");
HANDLE hBin = CreateFileA("sh.bin", GENERIC_ALL, 0, NULL, CREATE_ALWAYS, 0, NULL);
if (hBin == INVALID_HANDLE_VALUE)
{
xprintf("create file errot:%d\n",GetLastError());
return;
}
DWORD dwSize = (DWORD)ShellcodeEnd - (DWORD)ShellcodeStsrt;
DWORD dwWriten;
WriteFile(hBin, ShellcodeStsrt, dwSize, &dwWriten, NULL);
CloseHandle(hBin);
}
a.start.cpp
#include "header.h"
__declspec(naked) void ShellcodeStsrt() {
__asm {
jmp ShellcodeEntry
}
}
__declspec(naked) DWORD getKernel32()
{
__asm
{
mov eax, fs: [30h] ;
test eax, eax;
js finished;
mov eax, [eax + 0ch];
mov eax, [eax + 14h];
mov eax, [eax];
mov eax, [eax]
mov eax, [eax + 10h]
finished:
ret
}
}
FARPROC _GetProcAddress(HMODULE hModuleBase)
{
PIMAGE_DOS_HEADER lpDosHeader = (PIMAGE_DOS_HEADER)hModuleBase;
PIMAGE_NT_HEADERS32 lpNtHeader = (PIMAGE_NT_HEADERS)((DWORD)hModuleBase + lpDosHeader->e_lfanew);
if (!lpNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size) {
return NULL;
}
if (!lpNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress) {
return NULL;
}
PIMAGE_EXPORT_DIRECTORY lpExports = (PIMAGE_EXPORT_DIRECTORY)((DWORD)hModuleBase + (DWORD)lpNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);
PDWORD lpdwFunName = (PDWORD)((DWORD)hModuleBase + (DWORD)lpExports->AddressOfNames);
PWORD lpword = (PWORD)((DWORD)hModuleBase + (DWORD)lpExports->AddressOfNameOrdinals);
PDWORD lpdwFunAddr = (PDWORD)((DWORD)hModuleBase + (DWORD)lpExports->AddressOfFunctions);
DWORD dwLoop = 0;
FARPROC pRet = NULL;
for (; dwLoop <= lpExports->NumberOfNames - 1; dwLoop++) {
char* pFunName = (char*)(lpdwFunName[dwLoop] + (DWORD)hModuleBase);
if (pFunName[0] == 'G' &&
pFunName[1] == 'e' &&
pFunName[2] == 't' &&
pFunName[3] == 'P' &&
pFunName[4] == 'r' &&
pFunName[5] == 'o' &&
pFunName[6] == 'c' &&
pFunName[7] == 'A' &&
pFunName[8] == 'd' &&
pFunName[9] == 'd' &&
pFunName[10] == 'r' &&
pFunName[11] == 'e' &&
pFunName[12] == 's' &&
pFunName[13] == 's')
{
pRet = (FARPROC)(lpdwFunAddr[lpword[dwLoop]] + (DWORD)hModuleBase);
break;
}
}
return pRet;
}
void ShellcodeEntry() {
typedef FARPROC(WINAPI* FN_GetProcAddress)(
_In_ HMODULE hModule,
_In_ LPCSTR lpProcName
);
//获取GetProcAddress实际地址
FN_GetProcAddress fn_GetProcAddress = (FN_GetProcAddress)_GetProcAddress((HMODULE)getKernel32());
typedef HMODULE(WINAPI* FN_LoadLibraryA)(
_In_ LPCSTR lpLibFileName
);
//获取LoadLibraryA实际地址
char szLoadLibraryA[] = { 'L', 'o', 'a', 'd', 'L', 'i','b','r','a','r','y','A', 0 };
FN_LoadLibraryA fn_LoadLibraryA = (FN_LoadLibraryA)fn_GetProcAddress((HMODULE)getKernel32(), szLoadLibraryA);
typedef int (WINAPI* FN_MessageBoxA)(
_In_opt_ HWND hWnd,
_In_opt_ LPCSTR lpText,
_In_opt_ LPCSTR lpCaption,
_In_ UINT uType);
//获取MessageBoxA实际地址
char szUser32[] = { 'U', 's', 'e', 'r', '3', '2', '.', 'd', 'l', 'l', 0 };
char szMessageBoxA[] = { 'M','e', 's', 's', 'a', 'g', 'e', 'B', 'o', 'x', 'A', 0 };
FN_MessageBoxA fn_MessageBoxA = (FN_MessageBoxA)GetProcAddress(fn_LoadLibraryA(szUser32), szMessageBoxA);
//调用fn_MessageBoxA函数
char szHelloWorld[] = { 'H','e', 'l', 'l', 'o', ' ', 'W', 'o', 'r', 'l', 'd', '!', 0 };
char szTip[] = { 't', 'i', 'p', 0 };
fn_MessageBoxA(NULL, szHelloWorld, szTip, MB_OK);
// MessageBoxA(NULL, "Hello World!", "tip", MB_OK);
}
z.end.cpp
#include "header.h"
void ShellcodeEnd() {
}
这里运行一下就自动生成了含有MessageBoxA的shellcode的bin文件,我们用最后面的shellcode加载器就可以运行这段shellcode。
优化了一下,将功能部分和逻辑部分分开,直接把要实现的功能写在b.work.cpp中即可,逻辑部分写在其他三个文件中。
头文件
api.h
#pragma once
#include
typedef FARPROC(WINAPI* FN_GetProcAddress)(
_In_ HMODULE hModule,
_In_ LPCSTR lpProcName
);
typedef HMODULE(WINAPI* FN_LoadLibraryA)(
_In_ LPCSTR lpLibFileName
);
typedef int (WINAPI* FN_MessageBoxA)(
_In_opt_ HWND hWnd,
_In_opt_ LPCSTR lpText,
_In_opt_ LPCSTR lpCaption,
_In_ UINT uType);
typedef struct FUNCTIONS
{
FN_GetProcAddress fn_GetProcAddress;
FN_LoadLibraryA fn_LoadLibraryA;
FN_MessageBoxA fn_MessageBoxA;
}FUNCTIONS, *PFUNCTIONS;
header.h
#pragma once
#include "api.h"
#include
#include
void ShellcodeStsrt();
void ShellcodeEntry();
void ShellcodeEnd();
void CreateShellcode();
void InitFunctions(PFUNCTIONS pFn);
void CreateConfigFile(PFUNCTIONS pFn);
0.entry.cpp
#include "header.h"
#pragma comment(linker,"/entry:EntryMain")
int EntryMain() {
CreateShellcode();
return 0;
}
void CreateShellcode() {
HMODULE hMsvcrt = LoadLibraryA("msvcrt.dll");
typedef int (__CRTDECL* fn_printf)(
_In_z_ _Printf_format_string_ char const* const _Format,
...);
fn_printf xprintf = (fn_printf)GetProcAddress(hMsvcrt, "printf");
xprintf("1");
HANDLE hBin = CreateFileA("sh.bin", GENERIC_ALL, 0, NULL, CREATE_ALWAYS, 0, NULL);
if (hBin == INVALID_HANDLE_VALUE)
{
xprintf("create file error:%d\n",GetLastError());
return;
}
DWORD dwSize = (DWORD)ShellcodeEnd - (DWORD)ShellcodeStsrt;
DWORD dwWriten;
WriteFile(hBin, ShellcodeStsrt, dwSize, &dwWriten, NULL);
CloseHandle(hBin);
}
a.start.cpp
#include "header.h"
#include "api.h"
__declspec(naked) void ShellcodeStsrt() {
__asm {
jmp ShellcodeEntry
}
}
__declspec(naked) DWORD getKernel32()
{
__asm
{
mov eax, fs: [30h] ;
test eax, eax;
js finished;
mov eax, [eax + 0ch];
mov eax, [eax + 14h];
mov eax, [eax];
mov eax, [eax]
mov eax, [eax + 10h]
finished:
ret
}
}
FARPROC _GetProcAddress(HMODULE hModuleBase)
{
PIMAGE_DOS_HEADER lpDosHeader = (PIMAGE_DOS_HEADER)hModuleBase;
PIMAGE_NT_HEADERS32 lpNtHeader = (PIMAGE_NT_HEADERS)((DWORD)hModuleBase + lpDosHeader->e_lfanew);
if (!lpNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size) {
return NULL;
}
if (!lpNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress) {
return NULL;
}
PIMAGE_EXPORT_DIRECTORY lpExports = (PIMAGE_EXPORT_DIRECTORY)((DWORD)hModuleBase + (DWORD)lpNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);
PDWORD lpdwFunName = (PDWORD)((DWORD)hModuleBase + (DWORD)lpExports->AddressOfNames);
PWORD lpword = (PWORD)((DWORD)hModuleBase + (DWORD)lpExports->AddressOfNameOrdinals);
PDWORD lpdwFunAddr = (PDWORD)((DWORD)hModuleBase + (DWORD)lpExports->AddressOfFunctions);
DWORD dwLoop = 0;
FARPROC pRet = NULL;
for (; dwLoop <= lpExports->NumberOfNames - 1; dwLoop++) {
char* pFunName = (char*)(lpdwFunName[dwLoop] + (DWORD)hModuleBase);
if (pFunName[0] == 'G' &&
pFunName[1] == 'e' &&
pFunName[2] == 't' &&
pFunName[3] == 'P' &&
pFunName[4] == 'r' &&
pFunName[5] == 'o' &&
pFunName[6] == 'c' &&
pFunName[7] == 'A' &&
pFunName[8] == 'd' &&
pFunName[9] == 'd' &&
pFunName[10] == 'r' &&
pFunName[11] == 'e' &&
pFunName[12] == 's' &&
pFunName[13] == 's')
{
pRet = (FARPROC)(lpdwFunAddr[lpword[dwLoop]] + (DWORD)hModuleBase);
break;
}
}
return pRet;
}
void InitFunctions(PFUNCTIONS pFn)
{
//获取GetProcAddress实际地址
pFn->fn_GetProcAddress = (FN_GetProcAddress)_GetProcAddress((HMODULE)getKernel32());
char szLoadLibraryA[] = { 'L', 'o', 'a', 'd', 'L', 'i','b','r','a','r','y','A', 0 };
//获取LoadLibraryA实际地址
pFn->fn_LoadLibraryA = (FN_LoadLibraryA)pFn->fn_GetProcAddress((HMODULE)getKernel32(), szLoadLibraryA);
char szUser32[] = { 'U', 's', 'e', 'r', '3', '2', '.', 'd', 'l', 'l', 0 };
char szMessageBoxA[] = { 'M','e', 's', 's', 'a', 'g', 'e', 'B', 'o', 'x', 'A', 0 };
//获取MessageBoxA实际地址
pFn->fn_MessageBoxA = (FN_MessageBoxA)pFn->fn_GetProcAddress(pFn->fn_LoadLibraryA(szUser32), szMessageBoxA);
}
void ShellcodeEntry()
{
FUNCTIONS fn;
InitFunctions(&fn);
CreateConfigFile(&fn);
}
b.work.h
#include "api.h"
#include "header.h"
void CreateConfigFile(PFUNCTIONS pFn)
{
//调用fn_MessageBoxA函数
char szHelloWorld[] = { 'H','e', 'l', 'l', 'o', ' ', 'W', 'o', 'r', 'l', 'd', '!', 0 };
char szTip[] = { 't', 'i', 'p', 0 };
pFn->fn_MessageBoxA(NULL, szHelloWorld, szTip, MB_OK);
// MessageBoxA(NULL, "Hello World!", "tip", MB_OK);
}
z.end.cpp
#include "header.h"
void ShellcodeEnd() {
}
// runbin.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include
#include
int main(int argc,char* argv[])
{
HANDLE hFile = CreateFileA(argv[1], GENERIC_READ, 0, NULL, OPEN_ALWAYS, 0, NULL);
if (hFile == INVALID_HANDLE_VALUE)
{
printf("Open file error:%d\n", GetLastError());
return -1;
}
DWORD dwSize;
dwSize = GetFileSize(hFile, NULL);
LPVOID lpAddress = VirtualAlloc(NULL, dwSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
if (lpAddress == NULL)
{
printf("VirtualAlloc error :%d\n", GetLastError());
CloseHandle(hFile);
return -1;
}
DWORD dwRead;
ReadFile(hFile, lpAddress, dwSize, &dwRead, 0);
__asm
{
call lpAddress;
}
_flushall();
system("pause");
return 0;
}