这里先写个简单的静态加载到exe文件中,明天再来写个动态的
因为vs编译后自己会生成很多东西,我们稍微配置下
先获取kernel32基址
代码语言:javascript复制__declspec(naked) DWORD getKernel32()
{
__asm
{
mov eax, fs:[30h] //PEB
mov eax, [eax 0ch] //PEB->Ldr
mov eax, [eax 14h] //PEB->Ldr.InMemOrder
mov eax, [eax] //第二个模块
mov eax, [eax] //第三个模块
mov eax, [eax 10h] //base address
ret
}
}
获取GetProcAddress函数地址
代码语言:javascript复制FARPROC getProcAddress(HMODULE hModuleBase)
{
PIMAGE_DOS_HEADER lpDosHeader = (PIMAGE_DOS_HEADER)hModuleBase;
PIMAGE_NT_HEADERS32 lpNtHeader = (PIMAGE_NT_HEADERS32)((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;
}
首先定义ms-dos头
代码语言:javascript复制//some code……
PIMAGE_DOS_HEADER lpDosHeader = (PIMAGE_DOS_HEADER)hModuleBase;
然后得到pe头image-nt-header
代码语言:javascript复制//some code……
PIMAGE_NT_HEADERS32 lpNtHeader = (PIMAGE_NT_HEADERS32)((DWORD)hModuleBase lpDosHeader->e_lfanew);
直接dos头加e_lfanew,这里因为是c 代码就不用汇编写入偏移地址3c等等,后面也要贴上汇编代码,结合一起看其实也不难理解
代码语言:javascript复制//some code……
if (!lpNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size)
{
return NULL;
}
if (!lpNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress)
{
return NULL;
}
这里还是贴上这个图(转载的图)
在pe-option-header里面存在一个size和virualaddress,我们还是主要看 VirtualAddress(相对虚拟地址)字段,我们得到这个结构体
代码语言:javascript复制//some code……
PIMAGE_EXPORT_DIRECTORY lpExports = (PIMAGE_EXPORT_DIRECTORY)((DWORD)hModuleBase (DWORD)lpNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);
我们将会使用这个结构的如下字段:
AddressOfFunctions:指向一个DWORD类型的数组,每个数组元素指向一个函数地址。AddressOfNames:指向一个DWORD类型的数组,每个数组元素指向一个函数名称的字符串。AddressOfNameOrdinals:指向一个WORD类型的数组,每个数组元素表示相应函数的排列序号(16位整数)
代码语言:javascript复制//some code……
PDWORD lpdwFunName = (PDWORD)((DWORD)hModuleBase (DWORD)lpExports->AddressOfNames);
PWORD lpwOrd = (PWORD)((DWORD)hModuleBase (DWORD)lpExports->AddressOfNameOrdinals);
PDWORD lpdwFunAddr = (PDWORD)((DWORD)hModuleBase (DWORD)lpExports->AddressOfFunctions);
然后判断是否为GetProcAddress函数是就返回
代码语言:javascript复制//some code……
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;
头部再定义一下
代码语言:javascript复制//some code……
DWORD getKernel32();
FARPROC getProcAddress(HMODULE hModuleBase);
这里kernel32.dll和GetProcess函数地址都得到了后面就好说了
这里我们举CreateFile和Messagebox例子
这里是原来应该得写法
代码语言:javascript复制//some code……
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)GetProcAddress(LoadLibraryA("kernel32.dll"), "CreateFileA");
先得到GetProcAddress
代码语言:javascript复制typedef FARPROC(WINAPI * FN_GetProcAddress)(
_In_ HMODULE hModule,
_In_ LPCSTR lpProcName
);
FN_GetProcAddress fn_GetProcAddress = (FN_GetProcAddress)getProcAddress((HMODULE)getKernel32());
然后把"CreateFileA"字符串替换了
代码语言:javascript复制char szCreateFile[] = { 'C', 'r', 'e', 'a', 't', 'e', 'F', 'i', 'l', 'e', 'A',0 };
这里完整为
代码语言:javascript复制typedef FARPROC(WINAPI * FN_GetProcAddress)(
_In_ HMODULE hModule,
_In_ LPCSTR lpProcName
);
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
);
char szCreateFile[] = { 'C', 'r', 'e', 'a', 't', 'e', 'F', 'i', 'l', 'e', 'A',0 };
FN_CreateFileA fn_CreateFileA = (FN_CreateFileA)fn_GetProcAddress((HMODULE)getKernel32(), szCreateFile);
char szNewFile[] = { '1', '.', 't', 'x', 't', '