@xiongmin
2017-12-06T12:50:48.000000Z
字数 1797
阅读 591
APIHOOK
WIN32API
应用程序启动的时候出现启动界面毫无疑问,他肯定是加载了图片资源,这通常会有两种做法,要么在本地确实存在这样一张图片,要么这张图片已经被编译到了dll中,启动的时候再把dll中的资源给解析出来,Revit显然是用了第二种做法。我已经做过测试,再本地找到这张图片,删掉或者改名字都不会影响Revit的启动界面。由于最近在研究HOOK技术,所以也就产生了一个直接也最有效的方法,那就是直接拦截WIN32API,因为无论你是以何种方式去加载图片,终究是会去调用WIN32API,那么这条API就是
HANDLE LoadImage(
HINSTANCE hinst,
LPCTSTR lpszName,
UINT uType,
int cxDesired,
int cyDesired,
UINT fuLoad
);
需要准备的工具
- Detours 这是微软的一个库,但是官方只提供32位源码,所以说如果要HOOK像Reivt这样的64位的应用程序,得修改源码,自己编译一个64位的库,关于这个Detour源码的编译也有很多坑,有许多地方需要修改大多是类型的转换,我就不多叙述了,这需要各位亲自实践一下,我建议有兴趣的都把源码和例子编译一遍,如果你都编译过了那么这个库的原理也就能明白了,下面贴出关键代码
HANDLE(WINAPI *Real_LoadImageW)(HINSTANCE a0,
LPCWSTR a1,
UINT a2,
int a3,
int a4,
UINT a5)
= LoadImageW;
HANDLE WINAPI my_LoadImageW(HINSTANCE a0,
LPCWSTR a1,
UINT a2,
int a3,
int a4,
UINT a5)
{
return Real_LoadImageW(NULL,
L"C:\\Users\\xiong\\Desktop\\war3.bmp",
IMAGE_BITMAP,
0, 0,
LR_LOADFROMFILE);
}
__declspec(dllexport) VOID ExportFunc(VOID)
{
OutputDebugStringA("ExportFunc");
}
void AttachMiFlash()
{
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
DetourAttach(&(PVOID&)Real_LoadImageW, my_LoadImageW);
DetourTransactionCommit();
}
void DetachMiFlash()
{
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
DetourDetach(&(PVOID&)Real_LoadImageW, my_LoadImageW);
DetourTransactionCommit();
}
针对这段代码有几个坑跟大家说明一下
- 首先你的dll中得有一个导出函数,detours官方文档中有说明
- 关于LoadImage这个函数也比较奇怪,也是经过大量调试搜索资源才调用成功,有两点值得说明的是,一图片地址最好是绝对路径,二是图片一定要是真正的bitmap,需要注意的是有时候虽然Geterror()返回的是0,但是返回的HANDLE任然是NULL
DLL注入
当我们写好了dll但是怎么才能让Revit加载我们的dll呢,这个时候就需要用到dll的注入技术,关于这块也是比较复杂的一块技术,但是detours已经给我们提供了注入的源码,我们只需要编译一下就好了,当然在编译的过程中还是有一些地方需要我们手动去修改源码,这就需要大家去实践了。
扩展
当然我们要做的远远不止时候要修改Revit的启动界面,这只是一个基础,这说明我们在Revit这样的一个进程中是可以实现APIHOOK的,有了这个基础之后,我们就可以实现更复杂的功能,比如说:
- 代替操作系统来指挥Revit
- 更方便的分析Revit的文件格式
- 诸如禁止拷贝,HOOK加密等此类不过多关注RevitApi本身的功能