首页
社区
课程
招聘
问一个API hook的问题,有没有通用的解决方法?!
发表于: 2007-5-8 17:16 8809

问一个API hook的问题,有没有通用的解决方法?!

2007-5-8 17:16
8809
最近在编一个小工具。想用API hook技术。因为以前没有弄过,就搜了一下。然后发现麻烦大了:系统中似乎没有这方面的应用(1.本人想要一个高度兼容的方法!2.不是指那些message hooks)。本人以前钟爱masm,不过现在都用C和C++,因为用他们能写出保持执行效率的同时代码与平台无关......结果,自己弄API hook,却发现网上给的方法似乎都有问题(也许是我不懂?!i don't think so...):
1. hook 系统DLL,这个不想。我编写的程序要求针对某个指定的应用程序,而对以外的所有程序完全无关(而不是绕过或屏蔽),那些不安全的方法我想微软不会在以后的OS里‘容忍’多久,而且我不喜欢,略过。
2. hook 指定的应用程序。这个对我来说最理想了。可是仔细查找,发现居然要分析文件格式,这本身倒不是难事。可如果哪天有新文件格式咋办?如果是P-code文件呢?要是文件加了壳呢?好像还是不行,略过。
3. hook 指定的应用程序DLL。这个对我来也比较理想。然而问题来了:我从网上下了个APIHOOK的例子,里面有对user32.dll::MessageBoxA挂钩的代码。大家知道user32.dll是链接库,如果其它程序也在用,对其代码段修改,会不会也影响到这些程序?理论上会影响,试验时发现并不影响(我故意修改代码使程序对MessageBoxA处的代码段扰乱)!难道系统会对每一个进程维持一份独立的DLL拷贝不成?我记得9x是进程间共享的啊。
    反正总结起来要求如下:程序用CreateProcess加载被hook进程为暂停模式,挂钩;涉及的代码,有平台相关的,尽量用MS定义的符号或/和API代理;CreateProcess加载的程序应该不限制格式(只要是能用鼠标点开的非虚拟的可执行文件都适用);hook应该只对被加载进程有效(最多只允许影响到程序自己。);最好9x/NT/longhorn内核的OS都通用。有可能实现吗?

[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

收藏
免费 0
支持
分享
最新回复 (13)
雪    币: 218
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
NaX
2
不是我打击你,你的问题非常白痴
很多东西没实践就在这里想当然
2007-5-8 18:58
0
雪    币: 114
活跃值: (16)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
嗯,你是当老师的材料,理论大把,没有动手实践。
2007-5-8 19:08
0
雪    币: 218
活跃值: (129)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
楼上的,讲话那么刻薄也不能让人家当你是高手,搞人身攻击。几天搞搞这明天搞搞那。我会了还来问你干什么?!自己不看清楚就贴了条子了是,大家看谁白痴,这种人就是既没责任心又自私的人。你若是高手那充其量也就是人家捧的自己吹的,没什么真本事,改天MS贴个补丁你就又得瞎忙。基础没打好却喜欢搞小聪明。你这种“高手”我看不当也罢。
2007-5-8 21:04
0
雪    币: 189
活跃值: (56)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
5
3. hook 指定的应用程序DLL。这个对我来也比较理想。然而问题来了:我从网上下了个APIHOOK的例子,里面有对user32.dll::MessageBoxA挂钩的代码。大家知道user32.dll是链接库,如果其它程序也在用,对其代码段修改,会不会也影响到这些程序?理论上会影响,试验时发现并不影响(我故意修改代码使程序对MessageBoxA处的代码段扰乱)!难道系统会对每一个进程维持一份独立的DLL拷贝不成?我记得9x是进程间共享的啊。
_________________________________________-

现在还有人用9X吗?NT下进RING0,修改CR0的WP位才会影响其他进程的。
HOOKAPI的办法太多了~~~现在传来传去的那些都不够好,我以前看过一个,带着简单的反汇编模块的,很稳定。代码找不到了,好象是个病毒来的。带着EPO的HOOK。
2007-5-9 03:45
0
雪    币: 218
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
NaX
6
第一、第三个问题,你不知windows的Copy on Write机制
第二个问题 Hook API当然是针对可执行文件,还没有听说要先分析文件格式才能HOOK,Hook一个进程跟加不加壳没太大关系,除非壳能自己实现系统API

你先认真看完《windows核心编程》,再看看你的问题是不是。。。
2007-5-9 08:47
0
雪    币: 218
活跃值: (129)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
Osris:我找了那个病毒的源代码,正在研究中...另外我爱好兼容,不能兼容总感觉放不下心。有没可能实现手动分页切换(无驱)的方法?(这个问题可能太傻...
NaX:多谢赐教!我正在看的一本书。问题2我看过有通过解析PE跳到其导入表打内存补丁的例子,这个文章的一部分(来源我忘了):
“API Hook 理论
通过对Win32 PE文件的分析(如果你还不熟悉PE文件格式,可以看看Iczelion的PE教程或者LUEVELSMEYER的<<The PE File Format>>)。我们知道在PE文件中的IMPORT TABLE内存储着API函数的很多信息。其中包括API的函数名,调用地址等等。而操作系统在执行PE文件时会先将其映射到内存中。在映射的同时还会把当前版本操作系统中API函数的入口地址写入IMPORT TABLE中一组与API调用相关的结构体内,用于该应用程序的API调用。当应用程序调用API时,他会在自己内存映像里寻找API的入口地址,然后执行CALL指令。如此一来,我们通过修改应用程序内存映像的IMPORT TABLE中API函数的入口地址,就可以达到重定向API的目的。将API地址改为我们自己函数的地址,这样我们的函数就可以完成对API的监视和控制了。

API Hook 的实现
/* 1 */HANDLE hCurrent = GetModuleHandle(NULL);
/* 2 */IMAGE_DOS_HEADER *pidh;
/* 3 */IMAGE_NT_HEADERS *pinh;
/* 4 */IMAGE_DATA_DIRECTORY *pSymbolTable;
/* 5 */IMAGE_IMPORT_DESCRIPTOR *piid;

/* 6 */pidh = (IMAGE_DOS_HEADER *)hCurrent;
/* 7 */pinh = (IMAGE_NT_HEADERS *)((DWORD)hCurrent + pidh->e_lfanew);
/* 8 */pSymbolTable = &pinh->OptionalHeader.DataDirectory[1];
/* 9 */piid =(IMAGE_IMPORT_DESCRIPTOR *)((DWORD)hCurrent +  pSymbolTable->VirtualAddress);
/*10 */do {
/*11 */    IMAGE_THUNK_DATA *pitd,*pitd2;
/*12 */    pitd = (IMAGE_THUNK_DATA *)((DWORD)hCurrent + piid->OriginalFirstThunk);
/*13 */    pitd2 = (IMAGE_THUNK_DATA *)((DWORD)hCurrent + piid->FirstThunk);
/*14 */    do {
/*15 */ IMAGE_IMPORT_BY_NAME *piibn;
/*16 */ piibn = (IMAGE_IMPORT_BY_NAME *)((DWORD)hCurrent +  *((DWORD *)pitd));
/*17 */ PROC *ppfn = (PROC *)(pitd2->u1.Function);
/*18 */ if (!strcmp("MessageBoxW",(char *)piibn->Name)) {
/*19 */     oldMsg = (MsgBoxType)(ppfn);
/*20 */     DWORD addr = (DWORD)MyMessage;
/*21 */     DWORD written = 0;
      /* 改变内存读写状态 */
/*22 */     DWORD oldAccess;
/*23 */     VirtualProtect(&pitd2->u1.Function,sizeof(DWORD),PAGE_WRITECOPY,&oldAccess);
/*24 */     APIAddress = (DWORD)&pitd2->u1.Function;
      /* 向内存映像写入数据 */
/*25 */     WriteProcessMemory(GetCurrentProcess(),&pitd2->u1.Function, &addr,sizeof(DWORD), &written);
/*26 */ }
/*27 */ pitd++;pitd2++;
/*28 */    } while (pitd->u1.Function);

/*29 */    piid++;
/*30 */} while (piid->FirstThunk + piid->Characteristics
  + piid->ForwarderChain + piid->Name + piid->TimeDateStamp);
分析:
寻觅IMPORT TALBE
在/*1*/中我们使用GetModuleHandle(NULL)来返回当前进程在内存中映像的基地址。但这个值在文档中仅仅被描述为"a module handle for the specified module",虽然他确实是进程内存映像的基地址。如果你不太放心的话也可以使用,GetModuleInformation函数来获得基地址,只不过你要额外包含psapi.h和psapi.lib了(这个库在VC6里没有,所以我就没有用这个函数了)。在/* 6 */里我们先找到IMAGE_DOS_HEADER结构,他的起始地址就是映像的基地址。/*7*/通过IMAGE_DOS_HEADER给出的PE文件头的偏移量,找到IMAGE_NT_HEADERS结构。顺藤摸瓜,IMAGE_NT_HEADERS里的OptionalHeader中的DataDirectory数组里的第二个元素正是指向我们想要的IMPORT TABLE的地址。在/*9*/中我们将其转化为一个IMAGE_IMPORT_DESCRIPTOR的结构指针存入piid中。

替换的API函数入口地址
在/*12*/和/*13*/中我们分别取得OriginalFirstThunk和FirstThunk结构,用于以后得到API函数的名称和入口地址。/*10*/的do循环让我们遍历每一个IMAGE_IMPORT_DESCRIPTOR结构也就是应用程序引用的每个DLL。在/*14*/的循环中我们遍历DLL中的IMAGE_THUNK_DATA结构来一一查询API的信息。/*16*/中我们将OriginalFirstThunk转换为IMAGE_IMPORT_BY_NAME结构用于获得API函数的名称进行比对。在/*18*/我们找到MessageBoxW函数之后,在/*19*/保存其原始入口地址便于以后恢复时使用。在/*23*/我们需要用VirtualProtect改变一下内存区域的读写性,因为一般应用程序的映像都是只读的,直接写入会造成一个非法访问的异常出现。在/*25*/我们写入自己函数的地址。

这样就基本完成一个API函数的重定向。

其他......”
2007-5-13 12:27
0
雪    币: 242
活跃值: (14)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
8
LZ还是该补下基础。你的问题好像都不是问题
2007-5-14 01:15
0
雪    币: 79
活跃值: (35)
能力值: ( LV2,RANK:150 )
在线值:
发帖
回帖
粉丝
9
楼主要求太苛刻了,一般来说,我们所作的软件的兼容,只是列举一些系统,在某些地方针对不同系统写不同的代码,如果你想写一份兼容所有系统的代码,并且还要兼容未来的(貌似你有点这方面的意思),那么,你太强了。
2007-5-14 10:09
0
雪    币: 218
活跃值: (129)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
nnhy:对了。我就是这个意思。
whtyy:多谢了!我并不是说这些都不能。只是想知道有没有表述上更“通用”的方法...比如下个断点,我可以写相应地址0xcc,但也可以写setbreak(lpAddrTo),这样就不必考虑移植mips/ia64(自己编那些函数就免了,劳而无功...)
此前我修改过很多代码尝试移植,反正发现只要不涉及代码段读写的都不是难事
2007-5-14 12:28
0
雪    币: 846
活跃值: (221)
能力值: (RANK:570 )
在线值:
发帖
回帖
粉丝
11
Detours 就是API HOOK的库,包括所有现行的API HOOK函数,而且考虑到各种情况。
MS官方发布的,免费的。自己到MS的网站找,找不到我也帮不了你

LZ说的东西象天书一样让人看不懂,用外行人的话来跟内行人说,难免会被BS
2007-5-14 12:48
0
雪    币: 242
活跃值: (14)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
12
Detours 也现在也还不支持LZ想要的移植性
现在也应该只是支持X86/IA64/x64而已,而LZ好像是要“能运行WINDOWS的CPU都能用的HOOK”方法

HOOK API本身是改变CPU的指令流,但你又不想让你自己的程序直接操作指令流。还是等操作系统厂商的“HOOK 接口”吧
2007-5-14 20:20
0
雪    币: 79
活跃值: (35)
能力值: ( LV2,RANK:150 )
在线值:
发帖
回帖
粉丝
13
其实,我觉得应该不存在万能的写法的
2007-5-14 21:50
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
14
还有一个地方可以去看看 MSR
2007-5-16 13:34
0
游客
登录 | 注册 方可回帖
返回
//