分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow

也欢迎大家转载本篇文章。分享知识,造福人民,实现我们中华民族伟大复兴!

[原创/讨论]Windows核心编程研究系列之二:

读取指定物理内存地址中的内容

关键字:windows内核,物理内存

大家知道在windows NT中,如果已知虚拟地址可以通过

进程页表或者内核提供的MmGetPhysicalAddress来取得对应的

物理地址。

现在我们反过来看一下,如果已知一个物理内存地 址 (假设地址有效),如何取得物理地址中的内容呢?经过一番思考后,我发现一个方法,但我这里先卖个关子,为什么呢?

因为我觉得这个方法有些繁琐。经过和csdn的各位高手讨论

之后,加上本人的一共总结出3种方法,现在想和大家分享一下,

下面不再废话,立即进入正题J

[方法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

invokePsGetCurrentProcessId

mov   cid.UniqueProcess,eax

mov   cid.UniqueThread,0

invokeInitObjAttrs,addr ObjAttrsP,0

;取得本进程句柄

Invoke     ZwOpenProcess,addr hp,PROCESS_DUP_HANDLE,/

addr ObjAttrsP,addr cid

invokeInitObjAttrs,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

;释放资源

invokeZwUnmapViewOfSection,hp,addr dwbase

invokeZwClose,hpmem

invokeZwClose,hp

mov   eax,dwret

ret

GetValByPhyAddr  endp

;***************************************************************************

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

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

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

mov    eax,cr0

and    eax,7fffffffh

mov    cr0,eax

打开分页同样很简单:

mov eax,cr0

oreax,80000000h

mov cr0,eax

既然这么简单,为什么我在前面说这个方法有些繁琐呢?原因之一是如果仅仅关闭分页就会使原来依赖于分页的windows变得一团糟,马上会发生著名的蓝屏现象,不爽哦!L

那要怎么做呢?经过我的尝试,发现有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:  19796174@qq.com

QQ:    19796174

最后“预告”一下我的第3篇文章:

<<Windows核心编程研究系列之三:突破windows共享文件打开限制>>

主要内容:

很多用No_Share打开的文件,正常情况下不能在其他进程用

CreateFile打开,或者是仅仅用FILE_SHARE_READ打开的

文件不能再以写入目而打开,那么如何绕过windows的这种保护呢?敬请期待。J

感谢观赏,拜拜!

Mydo(侯佩|hopy|福信克|FreeThink)

2006年12月19日晚于合肥温馨的家中J

给我老师的人工智能教程打call!http://blog.csdn.net/jiangjunshow

Windows 核心编程研究系列之二 读取指定物理内存地址中的内容相关推荐

  1. 插入DLL和挂接API——Windows核心编程学习手札之二十二

    插入DLL和挂接API --Windows核心编程学习手札之二十二 如下情况,可能要打破进程的界限,访问另一个进程的地址空间: 1)为另一个进程创建的窗口建立子类时: 2)需要调试帮助时,如需要确定另 ...

  2. 窗口消息——Windows核心编程学习手札之二十六

    窗口消息 --Windows核心编程学习手札之二十六 Windows允许一个进程至多建立10000个不同类型的用户对象(user object):图符.光标.窗口类.菜单.加速键表等,当一个线程调用一 ...

  3. 未处理异常和C++异常——Windows核心编程学习手札之二十五

    未处理异常和C++异常 --Windows核心编程学习手札之二十五 当一个异常过滤器返回EXCEPTION_CONTINUE_SEARCH标识符时是告诉系统继续上溯调用树,寻找另外的异常过滤器,但当每 ...

  4. 异常处理程序和软件异常——Windows核心编程学习手札之二十四

    异常处理程序和软件异常 --Windows核心编程学习手札之二十四 CPU负责捕捉无效内存访问和用0除一个数值这种错误,并相应引发一个异常作为对错误的反应,CPU引发的异常称为硬件异常(hardwar ...

  5. 结束处理程序——Windows核心编程学习手札之二十三

    结束处理程序 --Windows核心编程学习手札之二十三 使用SEH可以只关注程序要完成任务,而运行中发生的错误,系统将会发现并通知.Windows引入SHE是为了便于操作系统的开发,使用SHE所造成 ...

  6. 线程本地存储器——Windows核心编程学习手札之二十一

    线程本地存储器 --Windows核心编程学习手札之二十一 C/C++运行期库使用线程本地存储器,运行期库是在多线程应用程序出现前设计的,因此运行期库里的大多数函数是用于单线程应用程序的.函数strt ...

  7. DLL的高级操作技术——Windows核心编程学习手札之二十

    DLL的高级操作技术 --Windows核心编程学习手札之二十 显示加载DLL模块: HINSTANCE LoadLibrary(PCTSTR pszDLLPathName); HINSTANCE L ...

  8. Unicode——Windows核心编程学习手札之二

    Unicode --Windows核心编程学习手札之二 处理软件本地化的核心在于处理不同的字符集.文本串一直作为一系列单字节字符进行编码,并在结尾处放上一个零,当调用strlen函数时,获取以/0结尾 ...

  9. 《Windows核心编程》读书笔记二十五章 未处理异常,向量化异常处理与C++异常

    第二十五章  未处理异常,向量化异常处理与C++异常 本章内容 25.1 UnhandledExceptionFilter函数详解 25.2 即时调试 25.3 电子表格示例程序 25.4 向量化异常 ...

最新文章

  1. 机器阅读理解(MRC)零基础入门级综述(一)
  2. python数据分析需要数据库吗_python数据分析|使用python操作MySQL数据库
  3. 2019 课程设计个人报告
  4. 10个数冒泡排序流程图_C语言 | 冒泡排序
  5. 做事情一定要从小事情着手
  6. 如果拿到私钥的话,https会被攻击吗?
  7. 最受欢迎中文机器学习课程,台大李宏毅老师公开课2019版上线!
  8. rfid在高速公路管理中的应用_RFID亮灯电子标签在仓储管理中的应用
  9. 基于ipv6的socket通信(TCP)
  10. TCP四次握手断开连接(图解)
  11. 专题详解-5G接入控制(1)
  12. MySQL中的BETWEEN...AND的用法
  13. 爱情故事:追忆似水流年 回味永恒的爱恋
  14. java如何用雪花算法批量生成唯一编码(保证位数不过长)?
  15. java中mapper层作用_Java的MyBatis框架中Mapper映射配置的使用及原理解析
  16. centos7 ceph 集群部署
  17. 【最优化方法】【矩阵分析】标量、向量、矩阵之间的求导关系
  18. 中科院计算所培训中心--2019年三季度课程新鲜出炉啦!
  19. 做为程序员 给大家推荐不很错的淘宝店
  20. pull 仓库 设置docker_docker镜像上传到阿里仓库,并在服务器pull拉取运行

热门文章

  1. centos下安装cmake
  2. 智能化多规则油液综合故障这段理论及方法的研究
  3. 关于手游网络协议的简单分析
  4. 健身耳机什么牌子好,抗汗能力好的运动耳机推荐
  5. Android基于XMPP Smack Openfire下学习开发IM(二)对分组、好友和头像等一些操作
  6. HTML个人相册(3d旋转)
  7. 快速学习制作类似《部落冲突》的等距游戏
  8. 十年建模师带你学习3D建模,次时代游戏建模人物制作经验分享!越努力越幸运
  9. (6)理解事务处理、事务处理的隔离级别,和使用JDBC进行事务处理||抛弃框架,如何实现分层架构下JDBC事务的控制
  10. 外国人眼中的珍珠奶茶是啥?