首页
社区
课程
招聘
[原创]物理HOOK
发表于: 2012-7-8 16:04 35368

[原创]物理HOOK

2012-7-8 16:04
35368
物理HOOK
                             物理HOOK
/**************************************
/* 作者:半斤八兩
/* 博客:http://hi.baidu.com/bjblcracked
/* 日期:2012-07-07  19:30
/**************************************

////////////测试环境//////////////////////////////
// 操作系统:    Windows XP Professional Service Pack 2
// CPU :        AMD Athlon II X3 450
// 物理内存:    523.752KB
// 小内存分页:  10/10/12模式
////////////////////////测试环境//////////////////

本文只是拿 int3 指令演示.
只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!

  昨天晚上发现一个很有意思的东西.
吾敢独享,于是把它写出来,与大家一起分享~
  相信大家都知道,我们系统上每个进程都独享4G虚拟内存空间.
如图(1)


 
                                                             图(1)

  每个进程都互不干扰.哪怕是哪个进程产生了致使的错误.如果程序没有异常处理,那么操作系统也能提前捕获,并弹一个很友好的错误提示.如图(2)
 


                               图(2)
  前面说了那么多,就是为了说明,每个进程都是独立的.互不干扰.
可是,就在昨天,我发现,他们并不是互不干扰的.这个问题也很困扰我,如果有哪位大侠知道原因的,希望能告之.~~

  下面,大家请观看屏幕上的VCR,跟随我们的镜头,来看看事件回放.

  为了方便事件回放,我们就用系统自带的计算器(calc.exe)的关于窗口来演示.

VCR回放:

1. 首先我们开启虚拟机(Debug模式),用OD载入计算器.
2. 在OD反汇编窗口中, 我们按CTRL+G组合键,输入ShellAboutW

7743F8EB >  8BFF            mov edi,edi    // ShellAboutW Entry
7743F8ED    55              push ebp
7743F8EE    8BEC            mov ebp,esp

我们把ShellAboutW入口函数,修改成 int3.然后单击计算器的关于按钮.
(这里大家要注意了,我们要用海风大侠的StrongOD插件,
将OD与计算器脱离关系. 因为OD的异常处理的关系,如果不这么做的话,我们单击计算器的关于,这个异常会被计算器的异常处理给接管了.
当我们脱离OD,在单击关于,才会产生一个int3中断.)

修改后:

7743F8EB >  CC              int3    // ShellAboutW Entry
7743F8EC    90              nop
7743F8ED    55              push ebp
7743F8EE    8BEC            mov ebp,esp

3. 在物理机,打开WinDbg调试器.就能看到虚拟机系统,正好中断在刚刚我们写的int3断点处.

4. 我们将ShellAboutW对应的线性地址0x7743F8EB,转换成物理地址.

  转换公式,我们就按照虚拟机的小内存(10/10/12)的方式来转换.

我们在WinDbg上,输入命令 .formats 0x7743F8EB

返回:

Break instruction exception - code 80000003 (first chance)
001b:7743f8eb cc              int     3
kd> .formats 0x7743F8EB
Evaluate expression:
  Hex:     7743f8eb
  Decimal: 2000943339
  Octal:   16720774353
  Binary:  01110111 01000011 11111000 11101011
  Chars:   wC..
  Time:    Sun May 29 09:35:39 2033
  Float:   low 3.97479e+033 high 0
  Double:  9.88597e-315

重点看二进制. Binary:  01110111 01000011 11111000 11101011

我们将这32位线性地址,按10/10/12 方式拆分为.

01110111   01000011   11111000   11101011   // 拆分前
0111011101   0000111111   100011101011      // 拆分后

0001 1101 1101   // 前10位重组后为  0x1DD
0000 0011 1111   // 中10位重组后为  0x3F
1000 1110 1011   // 后12位重组后为  0x8EB

拆分完后,紧接着,我们在WinDbg上输入 !dd cr3 + 0x1dd * 4

返回PDE:

kd> !dd cr3 + 0x1dd * 4
#1e966774 1a869867 0f3c2867 14483867 00000000
#1e966784 00000000 00000000 00000000 00000000
#1e966794 00000000 00000000 00000000 00000000
#1e9667a4 00000000 00000000 00000000 00000000
#1e9667b4 00000000 00000000 00000000 00000000
#1e9667c4 00000000 1fb00867 00000000 00000000
#1e9667d4 00000000 00000000 00000000 00000000
#1e9667e4 00000000 00000000 00000000 00000000

我们将返回的PDE &= 0xFFFFF000; 将低3字节清零.

然后再输入 !dd 1a869000 + 0x3f * 4

返回PTE:
kd> !dd 1a869000 + 0x3f * 4
#1a8690fc 128f6025 14424025 183c5025 1b73e025
#1a86910c 1f21e025 1f2e7025 1f1c8025 1f1a1025
#1a86911c 1f2b2025 1f2cb025 1f254025 1f26d025
#1a86912c 1f326025 1f3df025 1f2c8025 1f299025
#1a86913c 07853025 0784c025 1f42b025 1f3bc025
#1a86914c 1f3c5025 1f38e025 1f447025 0784d025
#1a86915c 18c64025 18cd5025 15e76025 1fd5f025
#1a86916c 15660025 175f9025 187e2025 18993025

再将返回的PTE &= 0xFFFFF000; 将低3字节清零.

最后再输入 !db 128f6000 + 0x8eb l4

返回PA:

kd> !db 128f6000 + 0x8eb l4
#128f68eb cc 90 55 8b ..U.........+C0.

我们注意观察物理地址0x128f68eb 对应的线性地址 0x7743F8EB
他们的数据前两字节都是显示的是 0xCC90  .说明我们物理地址找对了.

我们再打开一个计算器,观察ShellAboutW,这个地址处的数据,并没有修改,还是之前的默认数据mov edi, edi.这是理所当然的.因为每个进程是隔离的嘛,所以我们修改第一个计算器int3 ,根本不会影响到其它的进程.

下面,我们可以再多开几个计算器.重复 1 至 4  这四个步骤.(此略...)
我们可以发现,每一个计算器的线性地址都是一样的,但是对应的物理地址不一样.(这是因为每个进程分配的CR3不一样,所以对应的物理地址不一样,这一切似乎都很正常.)
下面,我们再来做一个小实验.下面的小实验,也正是本章的正文,物理HOOK.

首先,我们要将虚拟机里面的计算器全部关闭.

然后重新打开一个计算器.

1. 然后我们切回物理机,打开WinDbg,按Ctrl+Pause Break,让虚拟机系统中断.
2. 输入 !Process 0 0 命令,列出当前虚拟机系统所有进程(需下载符号)

返回所有进程如图3:
 

                                         图(3)

从图3中,我们能看出,系统的Cr3是3900.
下面,我们把cr3切换到计算器中.

输入命令 .process -i 0x81c89278

返回:

kd> .process -i 0x81c89278
You need to continue execution (press 'g' <enter>) for the context
to be switched. When the debugger breaks in again, you will be in
the new process context.

再输入g ,开始切换

返回:

kd> g
Break instruction exception - code 80000003 (first chance)
nt!RtlpBreakWithStatusInstruction:
804e40d9 cc              int     3

切换成功,看一下cr3值如图4:
 

                   图(4)

切换成功后.我们再将最开始纪录的ShellAboutW 的线性地址,转换成物理地址.

01110111   01000011   11111000   11101011   // 拆分前
0111011101   0000111111   100011101011      // 拆分后

0001 1101 1101   // 前10位重组后为  0x1DD
0000 0011 1111   // 中10位重组后为  0x3F
1000 1110 1011   // 后12位重组后为  0x8EB

剩下的,和前面的操作一样,直到找到对应的物理地址.此处省略...

kd> !dd cr3 + 1dd * 4
# c272774 18d83867 117ac867 1f2e5867 00000000
# c272784 00000000 00000000 00000000 00000000
# c272794 00000000 00000000 00000000 00000000
# c2727a4 00000000 00000000 00000000 00000000
# c2727b4 00000000 00000000 00000000 00000000
# c2727c4 00000000 14052867 00000000 00000000
# c2727d4 00000000 00000000 00000000 00000000
# c2727e4 00000000 00000000 00000000 00000000

kd> !dd 18d83000 + 3f * 4
#18d830fc 1c7eb025 00000000 00000000 00000000
#18d8310c 00000000 00000000 00000000 00000000
#18d8311c 00000000 00000000 00000000 00000000
#18d8312c 00000000 00000000 00000000 00000000
#18d8313c 00000000 00000000 00000000 00000000
#18d8314c 00000000 00000000 00000000 00000000
#18d8315c 00000000 00000000 00000000 00000000
#18d8316c 00000000 00000000 00000000 00000000

kd> !db 1c7eb000 + 8eb l4
#1c7eb8eb 8b ff 55 8b ..U.........+C0.

我们找到物理地址为 0x1c7eb8eb , 对应的数值为 0x8bff558b
我们来修改它...

kd> !ed 0x1c7eb8eb 8b5590cc

无返回值.我们可以敲入命令查看.

!db 1c7eb000 + 8eb l4

返回:

kd> !db 1c7eb000 + 8eb l4
#1c7eb8eb cc 90 55 8b ..U.........+C0.

修改成功...

最后再输入 g ,让操作系统跑起来.我们来单击计算器的关于看看...如图(5)


                                                     图(5)

系统中断下来了,我们修改了数据了,能中断下来是很正常的.如果不中断,反而不正常了...
这一切,似乎都是很正常的...

但是,当我们再打开一个计算器,点击关于的时候,神奇的事情发生了.它也中断了...
好吧,有可能是之前的计算器干扰了,我们把记算器全部关掉,重新打开,再点关于.

它仍然中断了...

就不信邪了...

我们再来打开.记事本,扫雷,纸牌,黑桃王,翻转棋,红心大战...

它全部都中断下来了...

最后结论,但凡调用shellapi!Shellaboutw的函数,都会中断下来...

Physical Hook~~

End...

DOC文档
物理HOOK.doc

演示视频在43楼.

[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

上传的附件:
收藏
免费 0
支持
分享
最新回复 (69)
雪    币: 292
活跃值: (153)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
2
.................可以用在 外挂上。。。。。
2012-7-8 16:10
0
雪    币: 1708
活跃值: (586)
能力值: ( LV15,RANK:670 )
在线值:
发帖
回帖
粉丝
3
ssdt hook ???
在 x64 下已经没用了。
2012-7-8 16:30
0
雪    币: 1919
活跃值: (901)
能力值: ( LV9,RANK:490 )
在线值:
发帖
回帖
粉丝
4
参考参考
2012-7-8 16:36
0
雪    币: 2
活跃值: (199)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
1:一个dll,在当前计算机系统中只被映射一次,我理解为只为提交到物理内存一次,其他使用这个dll的程序,pe加载器在load的时候会把这个dll映射到这个程序的虚拟地址里面来。虽然dll在各个使用它的程序的虚拟地址空间的线程地址不同,但他们对应的物理地址应该是一致的。
2:所以,shell32!ShellAbout的物理地址代码头部被修改,那么可能所有使用这个函数的都受影响。
3:所以,kernel32!BaseProcessStart的物理地址头部被修改,那么可能程序都跑不起来。

我的的菜鸟理解,楼主肯定都知道的,俺班门弄斧一下,不对的指正下哈
2012-7-8 17:17
0
雪    币: 223
活跃值: (516)
能力值: ( LV13,RANK:520 )
在线值:
发帖
回帖
粉丝
6
zgyknight,很高兴你回贴.

我当时有测试过的.
如果我直接让计算器中断,修改shell32!shellaboutw对应的物理地址数据.并不影响其它进程.

但是,我从系统中断,CR3为 39000, 再切换到计算器的cr3. 然后再修改,这样,其它的进程,全部受影响.

我也是感觉很奇怪,所以发出来,与大家分享一下..
2012-7-8 17:51
0
雪    币: 223
活跃值: (516)
能力值: ( LV13,RANK:520 )
在线值:
发帖
回帖
粉丝
7
那如果换成大内存 2/9/9/12 下,应该也一样的效果吧?
我当时只测试了 10/10/12, 没有测试过 2/9/9/12.
2012-7-8 17:53
0
雪    币: 2
活跃值: (199)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
(1)如果我直接让计算器中断,修改shell32!shellaboutw对应的物理地址数据.并不影响其它进程.
(2),我从系统中断,CR3为 39000, 再切换到计算器的cr3. 然后再修改,这样,其它的进程,全部受影响

这两处修改的地方地址一样吗?这个很关键,如果不一致,说明XXXX,如果一致,就有点灵异了,可能还有未知的系统机制

正好我也有虚拟机,我也来试试
2012-7-8 18:14
0
雪    币: 223
活跃值: (516)
能力值: ( LV13,RANK:520 )
在线值:
发帖
回帖
粉丝
9
每个进程分配的CR3值都不相等, 那么他的物理地址,怎么可能一致呢?
2012-7-8 18:26
0
雪    币: 2
活跃值: (199)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
如果这个dll在系统里只有一份,那么这个地址怎么会不一样呢?

如果都是指向那个函数头部,那么cr3可能不同,但虚拟地址也不同

如果这个只有一份,那么转换后的物理地址应该是指向同一个地方,这个函数的头部
2012-7-8 18:37
0
雪    币: 2
活跃值: (199)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
11
下vmware---ing,俺也跟牛X楼主一起学习下这个
2012-7-8 18:45
0
雪    币: 2700
活跃值: (63)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
12
楼主 的 桌面 背景 图 那个MM 好性感哦,不知道可否 共享 给 哥们个。
2012-7-8 18:46
0
雪    币: 2
活跃值: (199)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
13
估计是楼猪女朋友  你猜他会给你吗
2012-7-8 18:51
0
雪    币: 2700
活跃值: (63)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
14
不会吧!这么有艳福?!!
2012-7-8 18:52
0
雪    币: 223
活跃值: (516)
能力值: ( LV13,RANK:520 )
在线值:
发帖
回帖
粉丝
15
这个就是它怪异的地方了.

线性-->物理  之间的转换,本来就受CR3控制.

我们来两个假设.

假设1.
shell32!shellaboutw 的物理地址,都是相同的.

那么,这就奇怪了, 我直接在OD里面,修改shellaboutw,为什么其它进程不受影响?

假设2.
shell32!shellaboutw 的物理地址,都不相同的.

这个更奇怪了.我直接让虚拟机操作系统中断,然后切换到计算器的Cr3.
计算出物理地址. 修改数据. 那么,只要是当前系统已经运行的,并且加载了 shell32的,完全不受影响.

但是,我再重新打开加载了shell32.dll模块的程序,就全部修改了.
2012-7-8 19:04
0
雪    币: 223
活跃值: (516)
能力值: ( LV13,RANK:520 )
在线值:
发帖
回帖
粉丝
16
你好,她不是我女朋友,
是我在网上下载的.来源于网络.
2012-7-8 19:04
0
雪    币: 3116
活跃值: (1269)
能力值: ( LV8,RANK:120 )
在线值:
发帖
回帖
粉丝
18
囧。

假设1里面你还不知道啊,原因是你用OD改会触发COW
2012-7-8 19:33
0
雪    币: 2
活跃值: (199)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
19
copy on write  复制出来一份改 是不
2012-7-8 19:36
0
雪    币: 223
活跃值: (516)
能力值: ( LV13,RANK:520 )
在线值:
发帖
回帖
粉丝
21
COW,引用计数.  学习了.感谢.

我想再请教一下.

是不是所有的进程的低2G中的系统模块.抛开COW, 都是相同的物理地址?
2012-7-8 19:48
0
雪    币: 223
活跃值: (516)
能力值: ( LV13,RANK:520 )
在线值:
发帖
回帖
粉丝
22
[QUOTE=xouou;1085751]哥回的不是贴,是寂寞,字数补丁,颜色补丁,闪人补丁...[/QUOTE]

小弟愚昧,  

字数补丁,颜色补丁,闪人补丁...

是什么意思?
2012-7-8 19:50
0
雪    币: 1141
活跃值: (789)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
23
之前写的OD驱动插件一直有个BUG, 找不到原因
在WINAPI下INT3断点会导致所有进程的模块中该WINAPI入口都被改为0xCC

直到看到这篇文章
去检查了下驱动源码
才发现...我的保护写反了...造成CR0保护一直都是关闭的状态

CR0保护关闭时,OD下断,其他进程的同一模块内存都会被影响...
2012-7-8 19:51
0
雪    币: 135
活跃值: (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
24
系统的Copy On Write机制。
系统DLL只load一次,新进程加载时只是map过去。这些系统DLL的虚拟地址对应的物理地址是一样的。
2012-7-8 19:53
0
雪    币: 223
活跃值: (516)
能力值: ( LV13,RANK:520 )
在线值:
发帖
回帖
粉丝
25
感谢,原来是这样子.学习了.
2012-7-8 19:58
0
游客
登录 | 注册 方可回帖
返回
//