首页
社区
课程
招聘
[加一篇外传!][添加工具下载!]Windows 核心编程研究系列之二:读取指定物理内存地址中的内容
2006-12-19 21:52 18524

[加一篇外传!][添加工具下载!]Windows 核心编程研究系列之二:读取指定物理内存地址中的内容

2006-12-19 21:52
18524
[原创/讨论] Windows 核心编程研究系列之二:
读取指定物理内存地址中的内容
关键字:windows内核,物理内存

大家知道在windows NT中,如果已知虚拟地址可以通过
进程页表或者内核提供的MmGetPhysicalAddress来取得对应的
物理地址。
现在我们反过来看一下,如果已知一个物理内存地 址 (假设地址有效),如何取得物理地址中的内容呢?经过一番思考后,我发现一个方法,但我这里先卖个关子,为什么呢?
因为我觉得这个方法有些繁琐。经过和csdn的各位高手讨论
之后,加上本人的一共总结出3种方法,现在想和大家分享一下,
下面不再废话,立即进入正题 

[方法1]:使用内核提供的MmMapIoSpace函数
原来内核早就提供了很简单的接口,就是MmMapIoSpace函数,不过在DDK文档中看到该函数的说明如下:

PVOID MmMapIoSpace(
    IN PHYSICAL_ADDRESS  PhysicalAddress,
    IN ULONG  NumberOfBytes,
IN MEMORY_CACHING_TYPE  CacheType );

它只有3个形参,这和实际Masm32v9.0声明的4个形参有所
不同,为了确定,我通过 IDA 反汇编证实该函数确实有4个形参。经过测试,我猜测中间的ULONG  NumberOfBytes参数实际由64位字节的(两个双字)高低两部分组成,即在Masm32v9.0中有:

PVOID MmMapIoSpace(
    IN PHYSICAL_ADDRESS  PhysicalAddress,
IN ULONG  NumberOfBytesHighPart,
IN ULONG  NumberOfBytesLowPart,
IN MEMORY_CACHING_TYPE  CacheType );

这样的话调用就很简单了:
invoke        MmMapIoSpace,_phyaddr,0,4,MmNonCached
若成功该函数返回影射后的虚拟地址,否则返回NULL。这样就可以间接达到读取物理地址中内容的第一个方法。但可能我对参数功能的猜测也有错误,如果有误请指出。不胜感谢。

[方法2]:通过操作物理内存对象来完成到虚拟地址的影射
简单的说这个方法的基本思想如下:

a :        取得本进程句柄;
b :        取得物理内存对象的句柄;
c :        将物理内存地址影射到进程的虚拟地址空间中。

下面是我从C改写后的汇编关键代码:

;***************************************************************************
GetValByPhyAddr        proc uses esi edi ebx _phyaddr
        local        hpmem:dword
        local        hp:dword
        local        dwsize:dword
        local        dwbase:dword
        local        dwret:dword
        local        cid:CLIENT_ID
        local        stLR:LARGE_INTEGER
        local        ObjAttrsMem:OBJECT_ATTRIBUTES
        local        ObjAttrsP:OBJECT_ATTRIBUTES

        mov        dwbase,0
        mov        dwsize,4
        push        _phyaddr
        pop        stLR.LowPart
        mov        stLR.HighPart,0

        invoke        PsGetCurrentProcessId
        mov        cid.UniqueProcess,eax
        mov        cid.UniqueThread,0

        invoke        InitObjAttrs,addr ObjAttrsP,0
        ;取得本进程句柄
        Invoke         ZwOpenProcess,addr hp,PROCESS_DUP_HANDLE,\
                         addr ObjAttrsP,addr cid

        invoke         InitObjAttrs,addr ObjAttrsMem,addr devphymem

        ;取得物理对象的句柄
        Invoke         ZwOpenSection,addr hpmem,\
                                SECTION_MAP_READ or SECTION_MAP_WRITE,\
                                addr ObjAttrsMem

        ;将物理内存地址影射到进程的虚拟地址空间中
       

invoke                ZwMapViewOfSection,hpmem,hp,addr dwbase,\
                                0,4,addr stLR,addr dwsize,1,\
                                MEM_TOP_DOWN,PAGE_READWRITE

mov        edx,dwbase
        mov        eax,[edx]        ;取得影射后对应虚拟地址中的内容
        mov        dwret,eax

        ;释放资源
        invoke        ZwUnmapViewOfSection,hp,addr dwbase
        invoke        ZwClose,hpmem
        invoke        ZwClose,hp

        mov        eax,dwret
        ret
GetValByPhyAddr        endp
;***************************************************************************

[方法3]:关闭CPU分页机制达到直接读取物理地址的目的

第3种方法就是我前面卖关子的方法  ,这种方法不依赖于OS,了解保护模式的朋友都知道:进入保护模式后如果关闭分页机制则CPU就会将线形地址直接解释成物理地址。

关闭分页很简单,只需3行汇编代码:

mov     eax,cr0
and     eax,7fffffffh
mov     cr0,eax       

打开分页同样很简单:

mov        eax,cr0
or        eax,80000000h       
mov        cr0,eax

既然这么简单,为什么我在前面说这个方法有些繁琐呢?原因之一是如果仅仅关闭分页就会使原来依赖于分页的windows变得一团糟,马上会发生著名的蓝屏现象,不爽哦!
那要怎么做呢?经过我的尝试,发现有3点非常重要:

1 :        要保证windows处在较高的IRQL级别,防止关闭分页后
                被打断;
2 :        要将处理分页、读取物理地址的指令块放到线形地址等于
                物理地址的页中;
3 :        要做好数据的恢复工作。

第1点和第3点都容易理解,可能有人会疑问第2点,为什么要放到线形地址等于物理地址的空间中呢?原因其实也很简单,就是一旦关闭分页,所有地址都将以物理地址来解释,如果先前的
虚拟地址和物理地址不相同那么很可能就会发生执行错误指令流的问题。(当然也可以不相同,只要你能保证关分页后能执行正确指令即可。)

那么如何将物理地址和虚拟地址设置为相同呢?我的方法是将虚拟地址对应地页表PTE中的物理页基址改为包容即可。
我随机选择了一个虚拟地址 0x1c00000 ,为了简单它正好是页面的一个基址。下面我构造了它的PTE使得其中的物理也帧指向它:

mov        edx,0ffdf0000h
        mov        eax,[edx]
        mov        tmp0,eax                        ; 保存原始值
        ;mov        dword ptr [edx],1c00027h
        mov        dword ptr [edx],1c00007h

        ;初始化PTE
        mov        edx,0c03ff7c0h
        mov        eax,[edx]
        and        eax,0fffff000h
        or        eax,7h
        mov        edx,0c030001ch
        mov        ebx,[edx]
        mov        tmp1,ebx                                ; 保存原始值
        mov        dword ptr [edx],eax
        ;刷新TLB
        mov        eax,cr3
        mov        cr3,eax

                        最后两句指令在我前一篇: <<Windows内核编程研究一:改变进程PTE>> 中有过说明,这里就不解释了。

结束了PTE的设置后,下面就是将指令块拷贝到指定位置,代码如下:

mov        ecx,slen
mov        esi,subasm
mov        edi,1c00000h
cld
rep                movsb

而subasm指令块完成的就是实际设置分页和读取物理地址内容的工作,如下:

subasm:
                mov     eax,cr0
                and     eax,7fffffffh                        ;关闭分页机制
                mov     cr0,eax       
                jmp     SHORT PageC
PageC:
                mov        edx,[ecx]

mov        eax,cr0
                or        eax,80000000h                        ;打开分页机制
                mov        cr0,eax
               
jmp        SHORT PageO
PageO:
               
jmp        edi
slen        =        $ - subasm

借用一句话作为结尾“…一切都那么清楚明白,然而却无法透彻理解。理解就是改变,就是超越自己已有的认识。”
感谢CSDN热心朋友提供的方法和意见,给我很好的启发。
                末尾,感谢各位观赏,如有误谬之处请不吝指出,不胜感谢。希望有同好的朋友能够一起讨论,一起交流。

Email:        kf2b@hotmail.com
                        Kf2b@msn.com
QQ:                411987378

最后“预告”一下我的第3篇文章:
<<Windows核心编程研究系列之三:突破windows共享文件打开限制>>

主要内容:
很多用No_Share打开的文件,正常情况下不能在其他进程用
CreateFile打开,或者是仅仅用FILE_SHARE_READ打开的
文件不能再以写入目而打开,那么如何绕过windows的这种保护呢?敬请期待。

感谢观赏,拜拜!

Mydo(侯佩|hopy|福信克|FreeThink)
2006年12月19日晚于合肥温馨的家中

[培训]《安卓高级研修班(网课)》月薪三万计划,掌 握调试、分析还原ollvm、vmp的方法,定制art虚拟机自动化脱壳的方法

收藏
点赞7
打赏
分享
最新回复 (26)
雪    币: 442
活跃值: (107)
能力值: ( LV9,RANK:350 )
在线值:
发帖
回帖
粉丝
hopy 8 2006-12-19 21:56
2
0
第一篇文章 Windows 核心编程研究系列之一(改变进程 PTE)
的观赏地址:

http://bbs.pediy.com/showthread.php?s=&threadid=34158

也可以到我的博客观赏:

http://blog.csdn.net/mydo/
http://hopy.blogchina.com
雪    币: 442
活跃值: (107)
能力值: ( LV9,RANK:350 )
在线值:
发帖
回帖
粉丝
hopy 8 2006-12-19 22:11
3
0
在csdn的观赏连接:

http://community.csdn.net/Expert/topic/5242/5242379.xml?temp=.6433374
雪    币: 441
活跃值: (149)
能力值: ( LV9,RANK:170 )
在线值:
发帖
回帖
粉丝
rockhard 4 2006-12-20 00:00
4
0
[方法3]:关闭CPU分页机制达到直接读取物理地址的目的
=======================

在window中关闭分页机制,佩服呀。有空试试代码

雪    币: 196
活跃值: (135)
能力值: ( LV10,RANK:170 )
在线值:
发帖
回帖
粉丝
thinkSJ 4 2006-12-20 02:40
5
0
En,写得很不错,用KUSER_SHARED_DATA所在的物理页的TEB来初始化
0x1c00000的TEB,并映射为用户页,怎么写都不会当掉,,
期待下一篇:
雪    币: 442
活跃值: (107)
能力值: ( LV9,RANK:350 )
在线值:
发帖
回帖
粉丝
hopy 8 2006-12-20 12:52
6
0
多谢各位捧场
雪    币: 214
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
colboy 2006-12-20 13:15
7
0
强人.....能不能发个demo出来?~
雪    币: 196
活跃值: (135)
能力值: ( LV10,RANK:170 )
在线值:
发帖
回帖
粉丝
thinkSJ 4 2006-12-20 15:28
8
0
有点不足的就是不支持/PAE,这样转换出来的地址就是错误的
雪    币: 222
活跃值: (10)
能力值: ( LV8,RANK:130 )
在线值:
发帖
回帖
粉丝
drwch 3 2006-12-20 16:34
9
0
没错,传入的_phyaddr参数最好连高位一并带上
雪    币: 442
活跃值: (107)
能力值: ( LV9,RANK:350 )
在线值:
发帖
回帖
粉丝
hopy 8 2006-12-21 10:18
10
0
谢谢楼上几位的启发,我会考虑进去的:)
另外过会会在博客中会放出我编写的观察系统中任意
进程虚拟地址的PTE工具,敬请关注。
雪    币: 442
活跃值: (107)
能力值: ( LV9,RANK:350 )
在线值:
发帖
回帖
粉丝
hopy 8 2006-12-22 13:14
11
0
观察系统进程特定虚拟地址页PTE的工具

关键词:虚拟地址,PTE

为了便于研究windows内核,我写了一个察看系统中特定进程虚拟地址页的PTE工具,

CPP v1.0(Check Process PTE),界面图1所示:


                                                                                   

                                  图1

值得注意的是,在 PDE Virtual Addr At 一栏中要输入16位数字,比如0x8000A000,只要

直接输入:8000a000即可。另外我考虑到了windows内存影射中的4MB大页,

见图2所示:



                                                                                      图2

由于是即兴之作,可能有很多错误的和未考虑到的地方,请各位多多提意见和建议,多谢了。

直接运行,绿色软件。

测试环境:

windows 2000 sp4 , windows XP sp2 。(9x 和 2003 未测试)

(软件下载地址: http://download.csdn.net/source/160347)
雪    币: 196
活跃值: (135)
能力值: ( LV10,RANK:170 )
在线值:
发帖
回帖
粉丝
thinkSJ 4 2006-12-22 16:03
12
0
多谢,收藏了!
雪    币: 214
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
colboy 2006-12-22 17:50
13
0
最初由 hopy 发布
观察系统进程特定虚拟地址页PTE的工具

关键词:虚拟地址,PTE


........


....源代码可以发出来不?
雪    币: 442
活跃值: (107)
能力值: ( LV9,RANK:350 )
在线值:
发帖
回帖
粉丝
hopy 8 2006-12-22 18:49
14
0
最初由 colboy 发布
....源代码可以发出来不?


谢谢关注,最后应该会发出来。
雪    币: 442
活跃值: (107)
能力值: ( LV9,RANK:350 )
在线值:
发帖
回帖
粉丝
hopy 8 2006-12-22 18:50
15
0
接上一篇 Windows 核心编程研究系列之一(改变进程 PTE) 内容

上一篇观赏地址 :
http://community.csdn.net/Expert/topic/5124/5124747.xml?temp=.2832453

当然系统保证不让访问地址0出于一种保护的目的,是防止未初始化的指针读取数据。我说的访问地址0只是出于一种纯实现的目的,也不提倡大家这样做。说白了
只是好玩罢了。

大家都知道在 windows 中读取/写入地址0的指令肯定会出错:

// 写 0 地址的内容
xor edx,edx
mov [edx],eax

这是为什么呢?是不是windows在内核做了什么判断?其实这是愚蠢和低效的。
windows只是借助于PM的一个自然属性---页表属性,通过将0xc000_0000置null
来完成。

知道原理解决也就很简单了,就是将0xc000_0000 赋予一个有效的页表属性,
通过观察发现 0xc000_0040 是一个有效的值,我们只需:

mov edx,0c0000040h
mov eax,[edx]
mov edx,0c0000000h
mov [edx],eax

然后执行访问0地址的任何指令,就不会发生所谓的无效地址访问的问题了,
呵呵......希望有相同兴趣的朋友来聊聊吧。
雪    币: 398
活跃值: (343)
能力值: (RANK:650 )
在线值:
发帖
回帖
粉丝
shoooo 16 2006-12-22 19:39
16
0
csdn的强人啊, 膜拜+学习+收藏
雪    币: 603
活跃值: (617)
能力值: ( LV12,RANK:660 )
在线值:
发帖
回帖
粉丝
prince 16 2006-12-22 23:53
17
0
最初由 shoooo 发布
csdn的强人啊, 膜拜+学习+收藏
雪    币: 258
活跃值: (230)
能力值: ( LV12,RANK:770 )
在线值:
发帖
回帖
粉丝
qiweixue 19 2006-12-23 17:42
18
0
支持侯佩兄....

两篇文章都不错!!!!

学习!

雪    币: 214
活跃值: (70)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
仙剑太郎 2 2006-12-24 09:17
19
0
Originally posted by hopy
接上一篇 Windows 核心编程研究系列之一(改变进程 PTE) 内容

上一篇观赏地址 :
http://community.csdn.net/Expert/topic/5124/5124747.xml?temp=.2832453

........

强贴!!留名!
雪    币: 442
活跃值: (107)
能力值: ( LV9,RANK:350 )
在线值:
发帖
回帖
粉丝
hopy 8 2007-1-13 19:20
20
0
已经解决在ring3中读写物理地址的问题(不借助驱动),其实
也算老生常谈了。通过注册一个callgate即可实现ring3中
无驱进入ring0,即可为所欲为了:)

会开新贴谈谈细节,先预告一下,呵呵。
雪    币: 796
活跃值: (370)
能力值: ( LV9,RANK:380 )
在线值:
发帖
回帖
粉丝
Winker 8 2007-1-14 01:59
21
0
"很多用No_Share打开的文件,正常情况下不能在其他进程用
CreateFile打开,或者是仅仅用FILE_SHARE_READ打开的
文件不能再以写入目而打开,那么如何绕过windows的这种保护呢?敬请期待。?"

无限期待
这样的突破方式,貌似也可以用在以FILE_MAP_READ的方式MapViewOfFile一个文件,但是却绕过windows对文件共享内存进行写的访问
雪    币: 156
活跃值: (23)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
sbright 2 2007-1-14 02:10
22
0
最初由 hopy 发布
已经解决在ring3中读写物理地址的问题(不借助驱动),其实
也算老生常谈了。通过注册一个callgate即可实现ring3中
无驱进入ring0,即可为所欲为了:)

会开新贴谈谈细节,先预告一下,呵呵。

雪    币: 442
活跃值: (107)
能力值: ( LV9,RANK:350 )
在线值:
发帖
回帖
粉丝
hopy 8 2007-1-14 13:13
23
0
最初由 Winker 发布
"很多用No_Share打开的文件,正常情况下不能在其他进程用
CreateFile打开,或者是仅仅用FILE_SHARE_READ打开的
文件不能再以写入目而打开,那么如何绕过windows的这种保护呢?敬请期待。?"

无限期待
........


这个会在晚些时候贴出来,在这之前先上几道甜点...
雪    币: 560
活跃值: (309)
能力值: ( LV13,RANK:1370 )
在线值:
发帖
回帖
粉丝
laomms 34 2007-1-14 13:37
24
0
只能学习!
雪    币: 442
活跃值: (107)
能力值: ( LV9,RANK:350 )
在线值:
发帖
回帖
粉丝
hopy 8 2007-2-28 20:01
25
0
向大家申明一下:

很多朋友看了本人的拙作后,给我发电子邮件询问细节,虽然
我都作了回应,但是最好还是QQ或msn联系比较方便:

qq:411987378
msn:kf2b@hotmail.com

谢谢大家支持!

侯佩|hopy
游客
登录 | 注册 方可回帖
返回