首页
社区
课程
招聘
[求助]inline hook 的问题,帮忙看下
发表于: 2009-12-10 04:54 7272

[求助]inline hook 的问题,帮忙看下

2009-12-10 04:54
7272
论坛搜索了很多inline hook的例子了,很多说的不是太清楚,没办法了,请大家帮下

inline hook的操作流程我大致清楚了,具体操作有点不明.

void  HookObReferenceObjectByHandle()

{
  
  KIRQL Irql;
  RtlCopyMemory(OriginalBytes,(BYTE *)ObReferenceObjectByHandle,5);
  *(ULONG *)(JmpAddress+1)=(ULONG)DetourMyObReferenceObjectByHandle-((ULONG)ObReferenceObjectByHandle+5);
  _asm
   
  {
    push eax
      
      mov eax, cr0
      mov CR0VALUE, eax
      and eax, 0fffeffffh  
      mov cr0, eax
      pop eax
  }
  

Irql=KeRaiseIrqlToDpcLevel();
RtlCopyMemory((BYTE *)ObReferenceObjectByHandle,JmpAddress,5);
KeLowerIrql(Irql);  
  __asm
   
  {      
   
    push eax
      
      mov eax, CR0VALUE
      
      mov cr0, eax
      
      pop eax
      
  }
  
}

本论坛竹君帖子里的
*(ULONG *)(JmpAddress+1)=(ULONG)DetourMyObReferenceObjectByHandle-((ULONG)ObReferenceObjectByHandle+5);
JmpAddress这个是数组E9 00 00 00 00 跳转到自身语句的下一句,没什么意义,*(ULONG *)(JmpAddress+1)肯定是改E9后的4个字节了,问题就来了(ULONG)DetourMyObReferenceObjectByHandle-((ULONG)ObReferenceObjectByHandle+5);新函数的地址减去(原函数+5)有什么意义?能指向新函数的地址?
为什么不直接 jmp [DetourMyObReferenceObjectByHandle]

还有篇是sudami介绍的标准inline hook例子

__declspec(naked) my_function_detour_seaccesscheck()
{
        __asm
        {               
                // exec missing instructions
                push        ebp
                mov                ebp, esp
                push        ebx
                xor                ebx, ebx
                cmp                [ebp+24], bl

                // jump to re-entry location in hooked function
                // this gets 'stamped' with the correct address
                // at runtime.
                //
                // we need to hard-code a far jmp, but the assembler
                // that comes with the DDK will not poop this out
                // for us, so we code it manually
                // jmp FAR 0x08:0xAAAAAAAA
                _emit 0xEA
                _emit 0xAA
                _emit 0xAA
                _emit 0xAA
                _emit 0xAA
                _emit 0x08
                _emit 0x00
        }
}

这个应该是自己建的新函数了,补齐前面几字节后跳回原函数
           _emit 0xEA
                _emit 0xAA
                _emit 0xAA
                _emit 0xAA
                _emit 0xAA
                _emit 0x08
                _emit 0x00

这堆是什么来路?难道还会自动寻地不成?
请会的朋友直接回答,感谢之,我想肯定要些朋友要劝我从基础开始学,我也感谢之,我收到你的心意了.

[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

收藏
免费 0
支持
分享
最新回复 (16)
雪    币: 213
活跃值: (147)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
所谓InlineHook就是改变API函数体的前几个字节,进而跳转到自己的函数
IATHook就是改变导入表里的函数地址

给你个Hook MeesageBox的例子
BOOL InlineHookMessageBox()
{
	//生成新的跳转代码
	BYTE szNew8Bytes[8] = {0xB8, 0x0F, 0x10, 0x40, 0x00, 0xFF, 0xE0};
	memcpy(m_szNew8Bytes, szNew8Bytes, 8);
	*(DWORD*)(m_szNew8Bytes + 1) = (DWORD)pfnHook;

	//加载user32.dll模块,得到MessageBoxA的真实地址
	HMODULE hMod = LoadLibrary(_T("user32.dll"));
	if (hMod == NULL)
	{
		g_pfnReal = NULL;
		return FALSE;
	}

	g_pfnReal = (PFUNMESSAGEBOX)GetProcAddress(hMod, "MessageBoxW");
	if (g_pfnReal != NULL)
	{
		//MessageBoxA()的地址0x77d5058a
		//printf("%x\n", g_pfnReal);

		//修改原API函数的前8个字节,跳转到我们的自定义函数
		DWORD dwOldProtect = 0;
		MEMORY_BASIC_INFORMATION mbi;
		VirtualQuery(g_pfnReal, &mbi, sizeof(mbi));
		VirtualProtect(g_pfnReal, 8, PAGE_READWRITE, &dwOldProtect);

		//保存原来的执行代码
		memcpy(m_szOld8Bytes, g_pfnReal, 8);

		//写入新的执行代码
		WriteProcessMemory(GetCurrentProcess(), (void*)g_pfnReal, m_szNew8Bytes, sizeof(DWORD) * 2, NULL);

		//恢复页面属性
		VirtualProtect(g_pfnReal, 8, mbi.Protect, &dwOldProtect);//最后一个参数不能是0,否则出错
		return true;
	}

	return FALSE;
}

BOOL UnInlineHookMessageBox()
{
	if (g_pfnReal != NULL)
	{
		//恢复原API函数的前8个字节
		DWORD dwOldProtect = 0;
		MEMORY_BASIC_INFORMATION mbi;
		VirtualQuery(g_pfnReal, &mbi, sizeof(mbi));
		VirtualProtect(g_pfnReal, 8, PAGE_READWRITE, &dwOldProtect);

		//写入原来的执行代码
		WriteProcessMemory(GetCurrentProcess(), (void*)g_pfnReal, m_szOld8Bytes, sizeof(DWORD) * 2, NULL);

		//恢复页面属性
		VirtualProtect(g_pfnReal, 8, mbi.Protect, &dwOldProtect);//最后一个参数不能是0,否则出错

		return TRUE;
	}

	return FALSE;
}
2009-12-10 14:47
0
雪    币: 1
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
多谢LS回答,大致流程我是知道的
比如,你的这个BYTE szNew8Bytes[8] = {0xB8, 0x0F, 0x10, 0x40, 0x00, 0xFF, 0xE0};
jmp eax 这eax的值是怎么来的?我的问题是想知道这个,跳到新函数的哪个地方,那个地址是怎么得来的
2009-12-10 15:24
0
雪    币: 213
活跃值: (147)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
[QUOTE=野仔与狗;724954]多谢LS回答,大致流程我是知道的
比如,你的这个BYTE szNew8Bytes[8] = {0xB8, 0x0F, 0x10, 0x40, 0x00, 0xFF, 0xE0};
jmp eax 这eax的值是怎么来的?我的问题是想知道这个,跳到新函数的哪个地方,那个地址是怎么得来的[/QUOTE]

要跳转到的函数指针
2009-12-10 15:26
0
雪    币: 213
活跃值: (147)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
也就是这一句:*(DWORD*)(m_szNew8Bytes + 1) = (DWORD)pfnHook;
2009-12-10 15:29
0
雪    币: 1
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
没错是这个pfnHook的地址,关键是这个pfnHook怎么来的,在新函数的哪一个部分,是开头呢,还是有些偏移,我先第一个恭喜LS的换头像成功!
2009-12-10 15:32
0
雪    币: 213
活跃值: (147)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
直接jump过去,当然是开头了
2009-12-10 16:03
0
雪    币: 1
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
所以回到原来问的问题(ULONG)DetourMyObReferenceObjectByHandle-((ULONG)ObReferenceObjectByHandle+5);
DetourMyObReferenceObjectByHandle是我的过滤函数,我的函数减掉系统API地址为什么是指向了我自己的函数地址,我相当费解.
2009-12-10 16:12
0
雪    币: 245
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
^费解啊,费解

为什么 跳转不能用
sprintf(asmcode,"jmp %p", pfunc);

__asm asmcode

呢?
2009-12-10 17:15
0
雪    币: 522
活跃值: (10)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
10
5字节Jmp是相对跳  要以当前地址为基础记算的

7字节的是远跳 直接跳到某地址的

还有个6字节jmp 和远跳差不多 不过是个地址指针

小弟也有个问题弄不明白
7字节的Jmp 在一些地方Hook时会蓝 换成5字节就好了
看不懂dmp文件 不知是什么原因  所以俺现在只敢用5字节跳来hook...
2009-12-10 17:46
0
雪    币: 1
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
11
LS的你还算好了,我都不理解是怎么算来的,A函数-(B函数+5)=A函数?
void  Hook()
{
  ULONG JmpAddress[5]={0xE9,0,0,0,0};
  ULONG i;
  //KIRQL LEVEL;   
  RtlCopyMemory(OriginalBytes,ObReferenceObjectByHandle,5);  //把函数前5个字节复制出来
  *(ULONG *)(JmpAddress+1)=(ULONG)myone-((ULONG)ObReferenceObjectByHandle+5);
  for(i=0;i<5;i++)
  {
  DbgPrint("0x%x",JmpAddress[i]);
  }
  DbgPrint("myone地址0x%x",myone);
  DbgPrint("ObReferenceObjectByHandle地址0x%x",(ULONG)ObReferenceObjectByHandle);
  DbgPrint("ObReferenceObjectByHandle+5地址0x%x",(ULONG)ObReferenceObjectByHandle+5);

我打印出结果了
00000047        388.65960693        0xe9       
00000048        388.65960693        0x79a4fa1f       
00000049        388.65960693        0x0       
00000050        388.65960693        0x0       
00000051        388.65960693        0x0       
00000052        388.65963745        myone地址0xfa000580       
00000053        388.65963745        ObReferenceObjectByHandle地址0x805b0b5c       
00000054        388.65969849        ObReferenceObjectByHandle+5地址0x805b0b61
}

我完全不理解这样减有什么关系,希望明眼人来帮解答下,等待作者来看看
2009-12-10 23:54
0
雪    币: 522
活跃值: (10)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
12
已经说的很明白了
5字节是相对跳 地址以当前指令地址为基础记算得来 你所谓的“这样减” 只不过是它的记算公式  
你如果觉得费解 可以用6字节 或者7字节跳
要么也可以去问问inter为什么5字节的jmp要“这样减” ^__^
2009-12-11 04:13
0
雪    币: 1
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
13
就算地址是动态的也要个理由吧,不要嫌我罗嗦啊,人人都这样写,应该也有说法为什么这样写.
这也不像构造个重定位结构一摆出来自己就加载了,这个自己JMP的地址,总该有个说法的,我自己用打印出来的值减,得到的东西也不在我函数的领空,这样直接就JMP过去不是等蓝吗,你说的7字跳6字跳我还没学到,不知道是不是mov eax,xxxx  push eax这样的或者jmp [eax]?
还请赐教!不好意思啊,我这人对学习执着点,以前高中时期为一些题几天不睡觉,现在为这个东西饭都吃不下,觉也睡不好!
2009-12-11 04:54
0
雪    币: 522
活跃值: (10)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
14
钻牛角尖可不代表执着

5字节Jmp的地址只不过是相对地址罢了
就好象相对路径一样  以当前位置为基础在原有地址上再进行跳转的

至于为什么要用相对地址  可能这样cpu寻址起来更快吧 (个人猜测 )

如果还理解不了 就先打好基础吧  要么今后可真得多注意身体了^____^
2009-12-11 14:00
0
雪    币: 1
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
15
嗯,有道理,这个自动寻址应该怎么构造,能不能它的结构写一下,汇编代码即可,总不能在这里例子里我知道这样操作能构造一个自动寻址,在别的地方就瞎子鸡了.
2009-12-11 16:02
0
雪    币: 227
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
16
http://bbs.pediy.com/showthread.php?t=30746
2009-12-11 21:34
0
雪    币: 1
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
17
多谢啊,这样一说就明了了,太感谢了
2009-12-12 00:41
0
游客
登录 | 注册 方可回帖
返回