#include <iostream>
#include <windows.h>
#define __MYCALL __stdcall
typedef void(__MYCALL* pfnInit)();
typedef char* (__MYCALL* pfnGet)();
typedef char* (__MYCALL* pfnGet2)(char* str);
typedef char* (__MYCALL* pfnSet)(const char* str);
typedef void (__MYCALL* pfnGetNumber)(int * n);
BOOL FreeProcessImage(HMODULE hModule);
HMODULE LoadProcessImage(LPCTSTR strProcessPath);
int main()
{
std::cout << "Hello World!\n";
HMODULE hMoudle = LoadProcessImage(L"G:\\Load\\Debug\\Extern.exe");
pfnInit pInit = (pfnInit)::GetProcAddress(hMoudle, "_Init@0");
pfnInit pUnInit = (pfnInit)::GetProcAddress(hMoudle, "_UnInit@0");
pfnGet pGetText = (pfnGet)::GetProcAddress(hMoudle, "_GetText@0");
pfnGet2 pGetText2 = (pfnGet2)::GetProcAddress(hMoudle, "_GetText2@4");
pfnSet pSetText = (pfnSet)::GetProcAddress(hMoudle, "_SetText@4");
pfnGetNumber pGetNumber = (pfnGetNumber)::GetProcAddress(hMoudle, "_GetNumber@4");
int ret = 0;
char Buffer[100] = "buffer";
pInit();
pGetNumber(&ret);
char* strText = pGetText();
pGetText2(Buffer);
pSetText("Hello");
char* strText2 = pGetText();
pGetText2(Buffer);
pUnInit();
FreeProcessImage(hMoudle);
getchar();
return 0;
}
// 运行程序: Ctrl + F5 或调试 >“开始执行(不调试)”菜单
// 调试程序: F5 或调试 >“开始调试”菜单
// 入门使用技巧:
// 1. 使用解决方案资源管理器窗口添加/管理文件
// 2. 使用团队资源管理器窗口连接到源代码管理
// 3. 使用输出窗口查看生成输出和其他消息
// 4. 使用错误列表窗口查看错误
// 5. 转到“项目”>“添加新项”以创建新的代码文件,或转到“项目”>“添加现有项”以将现有代码文件添加到项目
// 6. 将来,若要再次打开此项目,请转到“文件”>“打开”>“项目”并选择 .sln 文件
//IMAGE_FILE_EXECUTABLE_IMAGE
BOOL FixIAT(HINSTANCE ModuleBase)
{
if (NULL == ModuleBase) return FALSE;
DWORD ulsize = 0;
PIMAGE_DOS_HEADER pDosHdr = (PIMAGE_DOS_HEADER)ModuleBase; //定位到IMAGE_DOS_HEADER
PIMAGE_NT_HEADERS pNtHdr = (PIMAGE_NT_HEADERS)((PCHAR)ModuleBase + pDosHdr->e_lfanew); //定位到IMAGE_NT_HEADERS
PIMAGE_IMPORT_DESCRIPTOR pImportDesc = (PIMAGE_IMPORT_DESCRIPTOR)(pNtHdr->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress + (PCHAR)ModuleBase);
if (!pImportDesc)
{
return FALSE;
}
// 遍历导入表
for (; pImportDesc->Name; pImportDesc++)
{
PSTR strModName = (PSTR)((PBYTE)ModuleBase + pImportDesc->Name);
if (!strModName)
{
return FALSE;
}
//加载对应的DLL
HINSTANCE hImportDLL = LoadLibraryA(strModName);
if (!hImportDLL)
{
return FALSE;
}
PIMAGE_THUNK_DATA pThunk = (PIMAGE_THUNK_DATA)
((PBYTE)ModuleBase + pImportDesc->FirstThunk);
HANDLE hProcess = GetCurrentProcess();
for (; pThunk->u1.Function; pThunk++)
{
FARPROC pfnNew = 0;
PVOID pBaseAddress = 0;
//判断是否以序号的方式导入,一般都以名称的方式导入
#ifdef _WIN64
if (pThunk->u1.Ordinal & IMAGE_ORDINAL_FLAG64)
#else
if (pThunk->u1.Ordinal & IMAGE_ORDINAL_FLAG32)
#endif
{
#ifdef _WIN64
LPCSTR pstrAddress = (LPCSTR)IMAGE_ORDINAL64(pThunk->u1.Ordinal);
#else
LPCSTR pstrAddress = (LPCSTR)IMAGE_ORDINAL32(pThunk->u1.Ordinal);
#endif
pBaseAddress = (PVOID)pThunk;
pfnNew = GetProcAddress(hImportDLL, (LPCSTR)pstrAddress);
if (!pfnNew)
{
return FALSE;
}
}
else
{
//说明是以名称方式导入的,此时pThunk->u1.Function是相对虚拟地址
if (0 == pThunk->u1.Function)
{
return FALSE;
}
//这个rva是导入函数地址要填入的地址,因为动态连接是FirstThunk指向的是
//导入函数名称地址表,一旦加载这边会被需改成导入函数所在真正地址
pBaseAddress = (PVOID)pThunk;
//获取函数名称地址
PSTR strName = (PSTR)ModuleBase;
strName += pThunk->u1.Function; //这边获取的结构为IMAGE_IMPORT_BY_NAME
strName += 2;
if (NULL == strName)
{
return FALSE;
break;
}
//获取导入函数所在真正地址
pfnNew = GetProcAddress(hImportDLL, strName);
if (!pfnNew)
{
return FALSE;
}
}
//其实此时模块是在该进程用户空间的,直接修改也是可以的
if (!WriteProcessMemory(hProcess, (LPVOID*)pBaseAddress, &pfnNew, sizeof(pfnNew), NULL) && (ERROR_NOACCESS == GetLastError()))
{
DWORD dwOldProtect;
if (VirtualProtect((LPVOID)pBaseAddress, sizeof(pfnNew), PAGE_WRITECOPY, &dwOldProtect))
{
if (!WriteProcessMemory(hProcess, (LPVOID*)pBaseAddress, &pfnNew, sizeof(pfnNew), NULL))
{
return FALSE;
}
if (!VirtualProtect((LPVOID)pBaseAddress, sizeof(pfnNew), dwOldProtect, &dwOldProtect))
{
return FALSE;
}
}
}
}
::CloseHandle(hProcess);
}
return TRUE;
}
enum class __scrt_module_type
{
dll,
exe
};
extern "C" BOOL WINAPI _CRT_INIT(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved);
extern "C" bool __cdecl __scrt_initialize_crt(__scrt_module_type module_type);
//extern "C" bool __cdecl __scrt_uninitialize_crt(bool is_terminating, bool from_exit);
BOOL FreeProcessImage(HMODULE hModule)
{
//_CRT_INIT(hModule, DLL_PROCESS_DETACH, NULL);
return FreeLibrary(hModule);
}
HMODULE LoadProcessImage(LPCTSTR strProcessPath)
{
HMODULE ModuleBase = ::LoadLibrary(strProcessPath);
if (ModuleBase && FALSE == FixIAT(ModuleBase))
{
FreeProcessImage(ModuleBase);
}
//__scrt_initialize_crt(__scrt_module_type::exe);
//_CRT_INIT(ModuleBase, DLL_PROCESS_ATTACH, NULL);
return ModuleBase;
}
调用exe接口
最新推荐文章于 2023-10-24 14:22:24 发布