////////////测试环境//////////////////////////////
// 操作系统: 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...
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课