调用exe接口


#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;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值