Detours Loader實現對exe的API Hook

  • 4170
  • 0

Detours Loader實現對exe的API Hook

在前一篇http://www.dotblogs.com.tw/cmd4shell/archive/2011/10/26/46749.aspx中,主要介绍了一下Detours的一些基本编译,但是实际使用中,可能情况要比这个复杂一些。比如说,我们有一个不可控制程序HookTest.exe文件(事实上为了演示,这里的还是一个自己写的Messagebox程序,当然也只有这个功能)。


{
	MessageBox(NULL, TEXT("Are you Hooked?"), TEXT("Hook Test"), MB_OK);
	
	return 0;
}

这里演示的是使用Loader方式加载的API Hook,因此需要两个程序,一个Loader,一个Hook Dll。

先给一下HookDll的代码:


#include <windows.h>
#include <detours.h>

#pragma comment(lib, "detours.lib")

#define EXPORT_API extern "C" __declspec(dllexport)

EXPORT_API void InjectDll()
{
	return;
}

static int(WINAPI *TrueMessageBox)(__in_opt  HWND hWnd,
										  __in_opt  LPCTSTR lpText,
										  __in_opt  LPCTSTR lpCaption,
										  __in      UINT uType) = MessageBox;

int WINAPI MyMessageBox(__in_opt  HWND hWnd, __in_opt  LPCTSTR lpText, __in_opt  LPCTSTR lpCaption,__in UINT uType)
{
	OutputDebugString("API Hooked!\n");
	int rv = 0;
	__try{
		rv = TrueMessageBox(hWnd, TEXT("Hooked!"), lpCaption, uType);
	}
	__finally{
		OutputDebugString("Call OrgMessageBox!\n");
	}
	return rv;
}


//dllmain.cpp
#include "stdafx.h"
#include "hookdll.h"

BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
					 )
{
	switch (ul_reason_for_call)
	{
	case DLL_PROCESS_ATTACH:
		DetourTransactionBegin();
		DetourUpdateThread(GetCurrentThread());
		//DetourAttach(&(PVOID&)TrueSleep, TimedSleep);
		DetourAttach(&(PVOID&)TrueMessageBox, MyMessageBox);
		DetourTransactionCommit();
		break;
	case DLL_THREAD_ATTACH:
	case DLL_THREAD_DETACH:
	case DLL_PROCESS_DETACH:
		DetourTransactionBegin();
		DetourUpdateThread(GetCurrentThread());
		//DetourAttach(&(PVOID&)TrueSleep, TimedSleep);
		DetourDetach(&(PVOID&)TrueMessageBox, MyMessageBox);
		DetourTransactionCommit();
		break;
	}
	return TRUE;
}

Loader的代码比较长,主要的代码给一下就好了:


{
	BOOL    fHasOrdinal1;
	ULONG   nExports;
};

static BOOL CALLBACK ExportCallback(PVOID pContext,
									ULONG nOrdinal,
									PCHAR pszSymbol,
									PVOID pbTarget)
{
	(void)pContext;
	(void)pbTarget;
	(void)pszSymbol;

	ExportContext *pec = (ExportContext *)pContext;

	if (nOrdinal == 1) {
		pec->fHasOrdinal1 = TRUE;
	}
	pec->nExports++;

	return TRUE;
}

//主函数:
	ExportContext ec;
	ec.fHasOrdinal1 = FALSE;
	ec.nExports = 0;
	DetourEnumerateExports(hDll, &ec, ExportCallback);
	FreeLibrary(hDll);

	if (!ec.fHasOrdinal1) 
	{
		OutputDebugString("No ExportTable Found!\n");
		return -1;
	}

	STARTUPINFO si;
	PROCESS_INFORMATION pi;
	CHAR szCommand[2048];
	CHAR szExe[] = "HookTest.exe";
	CHAR szFullExe[1024] = "\0";
	PCHAR pszFileExe = NULL;

	ZeroMemory(&si, sizeof(si));
	ZeroMemory(&pi, sizeof(pi));
	si.cb = sizeof(si);

	szCommand[0] = '\0';

	DWORD dwFlags = CREATE_DEFAULT_ERROR_MODE | CREATE_SUSPENDED;

	SetLastError(0);
	SearchPath(NULL, szExe, ".exe", ARRAYSIZE(szFullExe), szFullExe, &pszFileExe);

	if (!DetourCreateProcessWithDll(szFullExe[0] ? szFullExe : NULL, szCommand,
		NULL, NULL, TRUE, dwFlags, NULL, NULL,
		&si, &pi, szDllPath, NULL))
	{
		OutputDebugString("CreateProcessFailed!\n");
		return -1;
	}

	ResumeThread(pi.hThread);

	WaitForSingleObject(pi.hProcess, INFINITE);

编译测试结果如图:

hook

 

 

------------------------------

文章的授權使用CC BY-ND2.5協議。凡是標示“轉載”的文章,均來源於網絡並儘可能標註作者。如果有侵犯您的權益,請及時聯繫刪除或者署名、授權。


Gtalk/Email: cmd4shell  [at]  gmail.com