DLL劫持及调用数据跟踪二: 利用 MS 的Detours

MS 出来了Hook API的SDK:Detours, 利用dll inject技术把Hook DLL注入到目标进程中,以实际API的劫持。

官方的Demo以Messagebox API为例作了说明,实际应用时根据自己的需要修改DLL文件名以及过程参数。

 

已知某加密狗的接口如下:

long  CheckDog(); 返回狗是否存在,1存在,0或者<0错误

long  SedData(unsigned char* data); 返回发送是否成功,1成功,0失败,data是要发送的数据地址。

long GetData(unsigned char* data); 返回接收是否成功,1成功,0失败,data是要接收的数据地址。

 

下面我们利用Detours制作一个dll,实现原dll中的各个接口并对原dll的功能做替换,在原MessageBox Demo上的作修改如下:

// dllmain.cpp : 定义 DLL 应用程序的入口点。
#include "stdafx.h"
#include "detours.h"
#include "stdio.h"
#include "time.h"

LONG HOOKED = 0;

__declspec(dllexport) LONG WINAPI hook_usb(void)
{
	return HOOKED;
}

PVOID g_pOldMessageBoxW = NULL;
PVOID g_pOldMessageBoxA = NULL;
PVOID g_pOldcheckdog = NULL;
PVOID g_pOldsenddata = NULL;
PVOID g_pOldgetdata = NULL;

//typedef int (WINAPI *PfuncMessageBoxA)(HWND hWnd,LPCSTR lpText,LPCSTR lpCaption,UINT uType);
//typedef int (WINAPI *PfuncMessageBoxW)( HWND hWnd, LPCWSTR lpText,LPCWSTR lpCaption,UINT uType);

typedef int (WINAPI *Pfunccheckdog)();
typedef int (WINAPIV *Pfuncsenddata)(unsigned char* data);
typedef int (WINAPIV *Pfuncgetdata)(unsigned char* data);


void WriteLog(char *format,char *data)
{
	FILE *fp; 
	fp=fopen("test.log","a+");
	fprintf(fp,format,data);
	fclose(fp);
}

void WriteTime()
{
	time_t tim; 
	struct tm *at;
	time(&tim); 
	at=localtime(&tim);

	WriteLog("%s",asctime(at));
}


//int WINAPI ZwNewMessageBoxA(HWND hWnd,LPCSTR lpText,LPCSTR lpCaption,UINT uType)
//{
//	//return ((PfuncMessageBoxA)g_pOldMessageBoxA)(hWnd, "Hook This!","My hook",uType);
//	return ((PfuncMessageBoxA)g_pOldMessageBoxA)(hWnd, lpText,lpCaption,uType);
//}
//int WINAPI ZwNewMessageBoxW(HWND hWnd, LPCWSTR lpText,LPCWSTR lpCaption,UINT uType)
//{
//	//return ((PfuncMessageBoxW)g_pOldMessageBoxW)(hWnd,L"Hook This!",L"My hook",uType);
//	return ((PfuncMessageBoxW)g_pOldMessageBoxW)(hWnd,lpText,lpCaption,uType);
//}

int WINAPI Zwcheckdog()
{
	WriteTime();
	WriteLog("%s ","CheckDog");

	int tmpRet = ((Pfunccheckdog)g_pOldcheckdog)();
	char buffer [2];
	sprintf(buffer,"%d",tmpRet);

 	WriteLog("->%s\n",buffer);

	return tmpRet;	
}

int WINAPIV Zwsenddata(unsigned char * data)
{
	WriteTime();
	WriteLog("%s ","SendData");
	int tmpRet = ((Pfuncsenddata)g_pOldsenddata)(data);	

	FILE *fp; 
	fp=fopen("test.log","a+");
	for(int i=0;i<32;i++)
	{
		if(i>0 && *data==0)
		{
			break;
		}
		fprintf(fp,"%02x ",*data++);		
	}
	fclose(fp);

	char buffer [2];
	sprintf(buffer,"%d",tmpRet);

 	WriteLog("->%s\n",buffer);

	return tmpRet;	
}
 
int WINAPIV Zwgetdata(unsigned char * data)
{
	WriteTime();
	WriteLog("%s ","GetData");
	int tmpRet = ((Pfuncgetdata)g_pOldgetdata)(data);


	FILE *fp; 
	fp=fopen("test.log","a+");
	for(int i=0;i<32;i++)
	{
		fprintf(fp,"%02x ",*data++);		
	}
	fclose(fp);

	char buffer [2];
	sprintf(buffer,"%d",tmpRet);

 	WriteLog("->%s\n",buffer);

	return tmpRet;	
	//return 1;
}



BOOL APIENTRY SetHook()
{
	DetourTransactionBegin();
	DetourUpdateThread(GetCurrentThread());
	//g_pOldMessageBoxA=DetourFindFunction("User32.dll","MessageBoxA");
	//g_pOldMessageBoxW=DetourFindFunction("User32.dll","MessageBoxW");
	//DetourAttach(&g_pOldMessageBoxA,ZwNewMessageBoxA);
	//DetourAttach(&g_pOldMessageBoxW,ZwNewMessageBoxW);

	g_pOldcheckdog=DetourFindFunction("usblib.dll","CheckDog");
	g_pOldsenddata=DetourFindFunction("usblib.dll","SendData");
	g_pOldgetdata=DetourFindFunction("usblib.dll","GetData");

	DetourAttach(&g_pOldcheckdog,Zwcheckdog);
	DetourAttach(&g_pOldsenddata,Zwsenddata);
	DetourAttach(&g_pOldgetdata,Zwgetdata);

	LONG ret=DetourTransactionCommit();
	HOOKED = ret;
	return ret==NO_ERROR;
}


BOOL APIENTRY DropHook()
{
	DetourTransactionBegin();
	DetourUpdateThread(GetCurrentThread());
	//DetourDetach(&g_pOldMessageBoxA, ZwNewMessageBoxA);
	//DetourDetach(&g_pOldMessageBoxW, ZwNewMessageBoxW);

	DetourDetach(&g_pOldcheckdog,Zwcheckdog);
	DetourDetach(&g_pOldsenddata,Zwsenddata);
	DetourDetach(&g_pOldgetdata,Zwgetdata);

	LONG ret=DetourTransactionCommit();
	return ret==NO_ERROR;
}

static HMODULE s_hDll;

HMODULE WINAPI Detoured()
{
	return s_hDll;
}  

BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
					 )
{
	switch (ul_reason_for_call)
	{
	case DLL_PROCESS_ATTACH:
		s_hDll = hModule;
		DisableThreadLibraryCalls(hModule);
		SetHook();		//安装Hook
		break;
	case DLL_THREAD_ATTACH:
		break;
	case DLL_THREAD_DETACH:
		break;
	case DLL_PROCESS_DETACH:
		DropHook();//UNHOOK //卸载Hook
		break;
	}
	return TRUE;
}


以上代码中新的DLL首先劫持旧的DLL的地址,然后做日志记录,最后调用旧的DLL返回结果。

新的DLL加载的时候安装Hook,销毁的时候卸载Hook.

 

下一步要做的工作是把新的DLL注入到目标进程中去,官方文档中已经有相关的说明了。

我这里想使用简单的办法,给要调用原DLL的文件增加Import表,也就是修改调用程序,让他加载原DLL的同时了加载新的Hook DLL.

这个办法不用写代码,并且效果还不错,找到 PE-DIY Tools 工具,利用Add Import Functions(往PE文件中添加需要的输入函数)这个功能,增加Hook DLL的文件名和接口,注意为了能Hook DLL必须有一个导出的接口,本例使用了hook_usb这个函数。

另外,用DIY Tools修改时,需要找到调用原DLL的exe或者lib,再对其修改。对于DLL被多个exe或lib调用的问题,我想只要在第一次加载的实现Hook应该就没有问题了吧,具体还没有测试,有兴趣可以后面再研究。

最后就是就是运行测试了,执行以后记录的日志文件如下:

Wed Mar 13 17:34:40 2013
CeckDog->1
Wed Mar 13 17:34:42 2013
SendData 00 03 04 08 ->1
Wed Mar 13 17:34:44 2013
GetData b0 03 01 00 02 01 01 d2 40 80 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ->1

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值