Detours使用说明
2012-02-06 16:02
393 查看
Detours使用说明
1介绍
2DetoursAPIhook
2.1hookDLL中的函数
2.2hook自定义c函数
2.3hook类成员函数
2.4DetourCreateProcessWithDll
2.5DetouringbyAddress
user-provideddetourfunction.Instructionsfromthetargetfunctionareplacedinatrampoline.Theaddressofthetrampolineisplacedinatargetpointer.Thedetourfunctioncaneitherreplacethetargetfunction,orextenditssemanticsbyinvokingthe
targetfunctionasasubroutinethroughthetargetpointertothetrampoline."
在Detours库中,驱动detours执行的是函数DetourAttach(…).
LONGDetourAttach(
PVOID*ppPointer,
PVOIDpDetour
);
这个函数的职责是挂接目标API,函数的第一个参数是一个指向将要被挂接函数地址的函数指针,第二个参数是指向实际运行的函数的指针,一般来说是我们定义的替代函数的地址。但是,在挂接开始之前,还有以下几件事需要完成:
需要对detours进行初始化.
需要更新进行detours的线程.
这些可以调用以下函数很容的做到:
DetourTransactionBegin()
DetourUpdateThread(GetCurrentThread())
在这两件事做完以后,detour函数才是真正地附着到目标函数上。在此之后,调用DetourTransactionCommit()是detour函数起作用并检查函数的返回值判断是正确还是错误。
intsend(
__inSOCKETs,
__inconstchar*buf,
__inintlen,
__inintflags
);
因此,指向这个函数的指针看起来应该是这样的:
int(WINAPI*pSend)(SOCKET,constchar*,int,int)=send;
把函数指针初始化成真正的函数地址是ok的;另外还有一种方式是把函数指针初始化为NULL,然后用函数DetourFindFunction(…)指向真正的函式地址.把send(…)和recv(…)初始化:
int(WINAPI*pSend)(SOCKETs,constchar*buf,intlen,intflags)=send;
intWINAPIMySend(SOCKETs,constchar*buf,intlen,intflags);
int(WINAPI*pRecv)(SOCKETs,char*buf,intlen,intflags)=recv;
intWINAPIMyRecv(SOCKETs,char*buf,intlen,intflags);
现在,需要hook的函数和重定向到的函数已经定义好了。这里使用WINAPI是因为这些函数是用__stdcall返回值的导出函数,现在开始hook:
INTAPIENTRYDllMain(HMODULEhDLL,DWORDReason,LPVOIDReserved)
{
switch(Reason)
{
caseDLL_PROCESS_ATTACH:
DisableThreadLibraryCalls(hDLL);
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
DetourAttach(&(PVOID&)pSend,MySend);
if(DetourTransactionCommit()==NO_ERROR)
OutputDebugString("send()detouredsuccessfully");
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
DetourAttach(&(PVOID&)pRecv,MyRecv);
if(DetourTransactionCommit()==NO_ERROR)
OutputDebugString("recv()detouredsuccessfully");
break;
.
.
.
它基本上是用上面介绍的步骤开始和结束——初始化,更新detours线程,用DetourAttach(…)开始hook函数,最后调用DetourTransactionCommit()函数,当调用成功时返回NO_ERROR,失败是返回一些错误码.下面是我们的函数的实现,我发送和接收的信息写入到一个日志文件中:
intWINAPIMySend(SOCKETs,constchar*buf,intlen,intflags)
{
fopen_s(&pSendLogFile,"C://SendLog.txt","a+");
fprintf(pSendLogFile,"%s/n",buf);
fclose(pSendLogFile);
returnpSend(s,buf,len,flags);
}
intWINAPIMyRecv(SOCKETs,char*buf,intlen,intflags)
{
fopen_s(&pRecvLogFile,"C://RecvLog.txt","a+");
fprintf(pRecvLogFile,"%s/n",buf);
fclose(pRecvLogFile);
returnpRecv(s,buf,len,flags);
}
intRunCmd(constchar*cmd);
如果要hook这个函数,可以按照以下几步来做:
a)include声明这个函数的头文件
b)定义指向这个函数的函数指针,int(*RealRunCmd)(constchar*)=RunCmd;
c)定义detour函数,例如:intDetourRunCmd(constchar*);
d)实现detour函数,如:
IntDetourRunCmd(constchar*cmd)
{
//extendthefunction,addwhatyouwant:)
ReturnRealRunCme(cmd);
}
这样就完成了hookRunCmd函数的定义,所需要的就是调用DetourAttack
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
DetourAttach(&(PVOID&)RealRunCmd,DetourRunCmd);
if(DetourTransactionCommit()==NO_ERROR)
{
//error
}
还是举例说明,假如有个类定义如下:
classCData
{
public:
CData(void);
virtual~CData(void);
intRun(constchar*cmd);
};
现在需要hookintCData::Run(constchar*)这个函数,可以按照以下几步:
a)声明用于hook的类
classCDataHook
{
public:
intDetourRun(constchar*cmd);
staticint(CDataHook::*RealRun)(constchar*cmd);
};
b)初始化类中的static函数指针
int(CDataHook::*CDataHook::RealRun)(constchar*cmd)=(int(CDataHook::*)(constchar*))&CData::Run;
c)定义detour函数
intCDataHook::DetourRun(constchar*cmd)
{
//添加任意你想添加的代码
intiRet=(this->*RealRun)(cmd);
returniRet;
}
e)调用detourAttach函数
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
DetourAttach(&(PVOID&)CDataHook::RealRun,(PVOID)(&(PVOID&)CDataHook::DetourRun));
if(DetourTransactionCommit()==NO_ERROR)
{
//error
}
1介绍
Apihook包括两部分:api调用的截取和api函数的重定向。通过apihook可以修改函数的参数和返回值。关于原理的详细内容参见《windows核心编程》第19章和第22章。2DetoursAPIhook
"DetoursisalibraryforinterceptingarbitraryWin32binaryfunctionsonx86machines.Interceptioncodeisapplieddynamicallyatruntime.Detoursreplacesthefirstfewinstructionsofthetargetfunctionwithanunconditionaljumptotheuser-provideddetourfunction.Instructionsfromthetargetfunctionareplacedinatrampoline.Theaddressofthetrampolineisplacedinatargetpointer.Thedetourfunctioncaneitherreplacethetargetfunction,orextenditssemanticsbyinvokingthe
targetfunctionasasubroutinethroughthetargetpointertothetrampoline."
在Detours库中,驱动detours执行的是函数DetourAttach(…).
LONGDetourAttach(
PVOID*ppPointer,
PVOIDpDetour
);
这个函数的职责是挂接目标API,函数的第一个参数是一个指向将要被挂接函数地址的函数指针,第二个参数是指向实际运行的函数的指针,一般来说是我们定义的替代函数的地址。但是,在挂接开始之前,还有以下几件事需要完成:
需要对detours进行初始化.
需要更新进行detours的线程.
这些可以调用以下函数很容的做到:
DetourTransactionBegin()
DetourUpdateThread(GetCurrentThread())
在这两件事做完以后,detour函数才是真正地附着到目标函数上。在此之后,调用DetourTransactionCommit()是detour函数起作用并检查函数的返回值判断是正确还是错误。
2.1hookDLL中的函数
在这个例子中,将要hookwinsock中的函数send(…)和recv(…).在这些函数中,我将会在真正调用send或者recv函数前,把真正说要发送或者接收的消息写到一个日志文件中去。注意:我们自定义的替代函式一定要与被hook的函数具有相同的参数和返回值。例如,send函数的定义是这样的:intsend(
__inSOCKETs,
__inconstchar*buf,
__inintlen,
__inintflags
);
因此,指向这个函数的指针看起来应该是这样的:
int(WINAPI*pSend)(SOCKET,constchar*,int,int)=send;
把函数指针初始化成真正的函数地址是ok的;另外还有一种方式是把函数指针初始化为NULL,然后用函数DetourFindFunction(…)指向真正的函式地址.把send(…)和recv(…)初始化:
int(WINAPI*pSend)(SOCKETs,constchar*buf,intlen,intflags)=send;
intWINAPIMySend(SOCKETs,constchar*buf,intlen,intflags);
int(WINAPI*pRecv)(SOCKETs,char*buf,intlen,intflags)=recv;
intWINAPIMyRecv(SOCKETs,char*buf,intlen,intflags);
现在,需要hook的函数和重定向到的函数已经定义好了。这里使用WINAPI是因为这些函数是用__stdcall返回值的导出函数,现在开始hook:
INTAPIENTRYDllMain(HMODULEhDLL,DWORDReason,LPVOIDReserved)
{
switch(Reason)
{
caseDLL_PROCESS_ATTACH:
DisableThreadLibraryCalls(hDLL);
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
DetourAttach(&(PVOID&)pSend,MySend);
if(DetourTransactionCommit()==NO_ERROR)
OutputDebugString("send()detouredsuccessfully");
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
DetourAttach(&(PVOID&)pRecv,MyRecv);
if(DetourTransactionCommit()==NO_ERROR)
OutputDebugString("recv()detouredsuccessfully");
break;
.
.
.
它基本上是用上面介绍的步骤开始和结束——初始化,更新detours线程,用DetourAttach(…)开始hook函数,最后调用DetourTransactionCommit()函数,当调用成功时返回NO_ERROR,失败是返回一些错误码.下面是我们的函数的实现,我发送和接收的信息写入到一个日志文件中:
intWINAPIMySend(SOCKETs,constchar*buf,intlen,intflags)
{
fopen_s(&pSendLogFile,"C://SendLog.txt","a+");
fprintf(pSendLogFile,"%s/n",buf);
fclose(pSendLogFile);
returnpSend(s,buf,len,flags);
}
intWINAPIMyRecv(SOCKETs,char*buf,intlen,intflags)
{
fopen_s(&pRecvLogFile,"C://RecvLog.txt","a+");
fprintf(pRecvLogFile,"%s/n",buf);
fclose(pRecvLogFile);
returnpRecv(s,buf,len,flags);
}
2.2hook自定义c函数
举例来说明,假如有一个函数,其原型为intRunCmd(constchar*cmd);
如果要hook这个函数,可以按照以下几步来做:
a)include声明这个函数的头文件
b)定义指向这个函数的函数指针,int(*RealRunCmd)(constchar*)=RunCmd;
c)定义detour函数,例如:intDetourRunCmd(constchar*);
d)实现detour函数,如:
IntDetourRunCmd(constchar*cmd)
{
//extendthefunction,addwhatyouwant:)
ReturnRealRunCme(cmd);
}
这样就完成了hookRunCmd函数的定义,所需要的就是调用DetourAttack
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
DetourAttach(&(PVOID&)RealRunCmd,DetourRunCmd);
if(DetourTransactionCommit()==NO_ERROR)
{
//error
}
2.3hook类成员函数
Hook类成员函数通过在static函数指针来实现还是举例说明,假如有个类定义如下:
classCData
{
public:
CData(void);
virtual~CData(void);
intRun(constchar*cmd);
};
现在需要hookintCData::Run(constchar*)这个函数,可以按照以下几步:
a)声明用于hook的类
classCDataHook
{
public:
intDetourRun(constchar*cmd);
staticint(CDataHook::*RealRun)(constchar*cmd);
};
b)初始化类中的static函数指针
int(CDataHook::*CDataHook::RealRun)(constchar*cmd)=(int(CDataHook::*)(constchar*))&CData::Run;
c)定义detour函数
intCDataHook::DetourRun(constchar*cmd)
{
//添加任意你想添加的代码
intiRet=(this->*RealRun)(cmd);
returniRet;
}
e)调用detourAttach函数
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
DetourAttach(&(PVOID&)CDataHook::RealRun,(PVOID)(&(PVOID&)CDataHook::DetourRun));
if(DetourTransactionCommit()==NO_ERROR)
{
//error
}
2.4DetourCreateProcessWithDll
使用这个函数相当于用CREATE_SUSPENDED
标志调用函数
CreateProcess.新进程的主线程处于暂停状态,因此DLL能在函数被运行钱被注入。注意:被注入的DLL最少要有一个导出函数.如用testdll.dll注入到notepad.exe中:
#undefUNICODE
#include<cstdio>
#include<windows.h>
#include<detours/detours.h>
intmain()
{
STARTUPINFOsi;
PROCESS_INFORMATIONpi;
ZeroMemory(&si,sizeof(STARTUPINFO));
ZeroMemory(&pi,sizeof(PROCESS_INFORMATION));
si.cb=sizeof(STARTUPINFO);
char*DirPath=newchar[MAX_PATH];
char*DLLPath=newchar[MAX_PATH];//testdll.dll
char*DetourPath=newchar[MAX_PATH];//detoured.dll
GetCurrentDirectory(MAX_PATH,DirPath);
sprintf_s(DLLPath,MAX_PATH,"%s//testdll.dll",DirPath);
sprintf_s(DetourPath,MAX_PATH,"%s//detoured.dll",DirPath);
DetourCreateProcessWithDll(NULL,"C://windows//notepad.exe",NULL,
NULL,FALSE,CREATE_DEFAULT_ERROR_MODE,NULL,NULL,
&si,&pi,DetourPath,DLLPath,NULL);
delete[]DirPath;
delete[]DLLPath;
delete[]DetourPath;
return0;
}
2.5DetouringbyAddress
假如出现这种情况怎么办?我们需要hook的函数既不是一个标准的WIN32API,也不是导出函数。这时我们需要吧我们的程序和被所要注入的程序同事编译,或者,把函数的地址硬编码:#undefUNICODE
#include<cstdio>
#include<windows.h>
#include<detours/detours.h>
typedefvoid(WINAPI*pFunc)(DWORD);
voidWINAPIMyFunc(DWORD);
pFuncFuncToDetour=(pFunc)(0x0100347C);//Setitataddresstodetourin
//theprocess
INTAPIENTRYDllMain(HMODULEhDLL,DWORDReason,LPVOIDReserved)
{
switch(Reason)
{
caseDLL_PROCESS_ATTACH:
{
DisableThreadLibraryCalls(hDLL);
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
DetourAttach(&(PVOID&)FuncToDetour,MyFunc);
DetourTransactionCommit();
}
break;
caseDLL_PROCESS_DETACH:
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
DetourDetach(&(PVOID&)FuncToDetour,MyFunc);
DetourTransactionCommit();
break;
caseDLL_THREAD_ATTACH:
caseDLL_THREAD_DETACH:
break;
}
returnTRUE;
}
voidWINAPIMyFunc(DWORDsomeParameter)
{
//Somemagiccanhappenhere
}
相关文章推荐
- Detours使用说明 【转载】
- Detours使用说明
- Detours使用说明
- Detours使用说明
- Detours使用说明
- Detours使用说明
- Detours使用说明
- Detours使用说明
- Detours使用说明
- Detours使用说明
- Detours使用说明
- Detours使用说明
- Detours使用说明
- SQLHelper使用说明
- pjsip编译及使用说明
- vbs中对于getobject使用WMI的使用说明
- junit4使用说明
- jsdoc-toolkit文档工具使用说明
- Android Studio 2.2.3 科大讯飞语音合成接口 案例使用说明
- node.js中的path.normalize方法使用说明