使用IDA反汇编系统NTReadVirtualMemory函数,模拟实现里边的部分函数
2013-10-25 10:56
495 查看
首先是IDA的]使用,打开VMware虚拟机,找到C:\Windows\system32\ntkrnlpa.exe,考到本地电脑,用IDA打开。
配置symbol标志文件:找到IDA文件下边的cfg\pdb.cfg,使用UltraEdit打开,第8行有个_NT_SYMBOL_PATH字符串,记住之后配置系统环境变量,计算机---属性---高级系统设置---高级---环境变量---系统变量---新建---变量名填写_NT_SYMBOL_PATH,变量值填写你的symbol标志文件的路径,比如:D:\vmsysbolxp,OK。
在左边的Functions window里边找到NtReadVirtualMemory,双击进入IDA View - A,这部分就是NtReadVirtualMemory对应的汇编代码,它以push开头,按F5进入Pseudocode-F,这个就是经过系统优化后反汇编出来的C语言代码,与原本的代码会有不同,主要是编译器优化的原因,不过功能几乎是一样的。在这里就可以进行反汇编的学习了。
通过IDA View - A,Pseudocode-F两部分去“猜测”原代码。
补充:
有一个文件包是微软那些函数的实现代码:WindowsResearchKernel-WRK.tar,网上好多,自己找一下,我用的是48.6MB的,使用Source Insight 3.5打开,在里边可以查看核代码的实现。
测试:看看自己实现的代码是否与刚才找到的代码实现的功能是一致的。
使用的常用快捷键:
F5:进入反汇编代码,使用:在汇编代码上按下F5就能到需要的返汇编位置:
![](https://img-blog.csdn.net/20131203174957093?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvZHVoYW9taW4=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
![](https://img-blog.csdn.net/20131203175033859?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvZHVoYW9taW4=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
想回到上一步,使用的是Esc键
学习流程:
在Pseudocode-F中将里边涉及到的函数找到,之后开始菜单中点开Windows Driver Kits \ WDK 6000 \ HELP \ WDK Documentation.exe,寻找一下该函数是否有实现,如果有则不需要实现了,可以学一下人家怎么实现的,如果没有实现,则双击Pseudocode-F中该函数,则会自动跳转到该函数反汇编的代码,本次的主要任务就是去看该代码,实现它。
001:MmHighestUserAddress
找到了signed int __stdcall NtReadVirtualMemory(HANDLE Handle , int a2 , char *Address, SIZE_T Length,unsigned int a5)
{......................}
按顺序看代码,前边是局部变量的声明,之后看if(AccessMode[0])里边,有个MmHighestUserAddress,显然它应该是代表的用户可以使用的最高内存地址,而系统初始化的时候,它被初始化为 :0x7fff0000,具体的资料引用如下:
MmInit1(…)
{
……
MmUserProbeAddress = 0x7fff0000;
MmHighestUserAddress = (PVOID)0x7ffeffff;
……
}
很显然,MmUserProbeAddress = MmHighestUserAddress + 1
摘自:漫谈兼容内核之二十一:Windows进程的用户空间 毛德操 , 兼容内核之二十一:Windows进程的用户空间(第一部分)
002:ARGUMENT_PRESENT([in] CHAR *ArgumentPointer)
he ARGUMENT_PRESENT macro takes an argument pointer and returns FALSE if the pointer is NULL. Otherwise, it returns TRUE.
003:在程序中尽量不要自己new [],而使用局部变量之类的,因为一旦系统因为某些内部或者外部原因导致进程停止之类的,该申请的内存将永远不能被释放,找不到该地址了。
首先更加深刻的了解一下句柄:
一个句柄,只有当唯一地确定了一个项目的时候,它才开始有意义。句柄对应着项目表中的一项,而只有WINDOWS本身才能直接存取这个表,应用程序只能通过API函数来处理不同的句柄。举个例子来说吧,比如:我们可以为我们的应用程序申请一块内存块,通过调用API函数GlobalAlloc,来返回一个句柄值:
hMem=GlobalAlloc(......);
其实现在hMem的值只是一个索引值,不是物理地址,应用程序还不能直接存取这块内存。这儿还有一句题外话,是关于操作系统的内存管理的。一般情况下操作系统给应用程序分配的内存块都是可以被移动的或者是可以丢弃的,这样能使有限的内存资源得到充分利用。所以,我们刚开始分配到的那块内存的地址是不确定的,因为它是可以被移动的,所以得先锁定那块内存块,这里应用程序需要调用API函数GlobalLock函数来锁定句柄。如下:
lpMem=GlobalLock(hMem);
这样应用程序才能存取这块内存。
配置symbol标志文件:找到IDA文件下边的cfg\pdb.cfg,使用UltraEdit打开,第8行有个_NT_SYMBOL_PATH字符串,记住之后配置系统环境变量,计算机---属性---高级系统设置---高级---环境变量---系统变量---新建---变量名填写_NT_SYMBOL_PATH,变量值填写你的symbol标志文件的路径,比如:D:\vmsysbolxp,OK。
在左边的Functions window里边找到NtReadVirtualMemory,双击进入IDA View - A,这部分就是NtReadVirtualMemory对应的汇编代码,它以push开头,按F5进入Pseudocode-F,这个就是经过系统优化后反汇编出来的C语言代码,与原本的代码会有不同,主要是编译器优化的原因,不过功能几乎是一样的。在这里就可以进行反汇编的学习了。
通过IDA View - A,Pseudocode-F两部分去“猜测”原代码。
补充:
有一个文件包是微软那些函数的实现代码:WindowsResearchKernel-WRK.tar,网上好多,自己找一下,我用的是48.6MB的,使用Source Insight 3.5打开,在里边可以查看核代码的实现。
测试:看看自己实现的代码是否与刚才找到的代码实现的功能是一致的。
使用的常用快捷键:
F5:进入反汇编代码,使用:在汇编代码上按下F5就能到需要的返汇编位置:
想回到上一步,使用的是Esc键
学习流程:
在Pseudocode-F中将里边涉及到的函数找到,之后开始菜单中点开Windows Driver Kits \ WDK 6000 \ HELP \ WDK Documentation.exe,寻找一下该函数是否有实现,如果有则不需要实现了,可以学一下人家怎么实现的,如果没有实现,则双击Pseudocode-F中该函数,则会自动跳转到该函数反汇编的代码,本次的主要任务就是去看该代码,实现它。
001:MmHighestUserAddress
找到了signed int __stdcall NtReadVirtualMemory(HANDLE Handle , int a2 , char *Address, SIZE_T Length,unsigned int a5)
{......................}
按顺序看代码,前边是局部变量的声明,之后看if(AccessMode[0])里边,有个MmHighestUserAddress,显然它应该是代表的用户可以使用的最高内存地址,而系统初始化的时候,它被初始化为 :0x7fff0000,具体的资料引用如下:
MmInit1(…)
{
……
MmUserProbeAddress = 0x7fff0000;
MmHighestUserAddress = (PVOID)0x7ffeffff;
……
}
很显然,MmUserProbeAddress = MmHighestUserAddress + 1
摘自:漫谈兼容内核之二十一:Windows进程的用户空间 毛德操 , 兼容内核之二十一:Windows进程的用户空间(第一部分)
002:ARGUMENT_PRESENT([in] CHAR *ArgumentPointer)
he ARGUMENT_PRESENT macro takes an argument pointer and returns FALSE if the pointer is NULL. Otherwise, it returns TRUE.
003:在程序中尽量不要自己new [],而使用局部变量之类的,因为一旦系统因为某些内部或者外部原因导致进程停止之类的,该申请的内存将永远不能被释放,找不到该地址了。
首先更加深刻的了解一下句柄:
一个句柄,只有当唯一地确定了一个项目的时候,它才开始有意义。句柄对应着项目表中的一项,而只有WINDOWS本身才能直接存取这个表,应用程序只能通过API函数来处理不同的句柄。举个例子来说吧,比如:我们可以为我们的应用程序申请一块内存块,通过调用API函数GlobalAlloc,来返回一个句柄值:
hMem=GlobalAlloc(......);
其实现在hMem的值只是一个索引值,不是物理地址,应用程序还不能直接存取这块内存。这儿还有一句题外话,是关于操作系统的内存管理的。一般情况下操作系统给应用程序分配的内存块都是可以被移动的或者是可以丢弃的,这样能使有限的内存资源得到充分利用。所以,我们刚开始分配到的那块内存的地址是不确定的,因为它是可以被移动的,所以得先锁定那块内存块,这里应用程序需要调用API函数GlobalLock函数来锁定句柄。如下:
lpMem=GlobalLock(hMem);
这样应用程序才能存取这块内存。
相关文章推荐
- 使用C/C++编写函数,实现字符串反转,要求不使用任何系统函数,且时间复杂度最小
- 1 秒杀系统模拟基础实现,使用DB实现
- 使用库函数API和C代码中嵌入汇编代码两种方式实现对sysinfo的系统调用
- linux 系统下使用C程序实现时钟的函数
- 使用 XForms 和 Ruby on Rails 开发小型门诊管理系统,第 3 部分:实现护士和医生 XForm
- 新手上路系列5:部分字符串使用函数的程序实现
- 使用" 参数化基类" 和" 成员函数指针" 模拟实现虚函数--在实际中的应用
- c++使用sendinput函数实现模拟键盘按键操作
- 使用 XForms 和 Ruby on Rails 开发小型门诊管理系统,第 3 部分:实现护士和医生 Xform
- 使用" 参数化基类" 和" 成员函数指针" 模拟实现虚函数--在实际中的应用
- 如何在不使用系统函数的情况下实现PHP中数组系统函数的功能
- 使用仿函实现函数参数的部分自动填充
- 汇编总结-第二部分_3_使用函数
- 习题8-5 使用函数实现字符串部分复制(20 分)
- 不调用具有"协程特性"的系统API函数而使用汇编实现协程
- 对于日期指定部分的加减 使用DATEADD函数就可以轻松实现
- 6-1 使用函数实现字符串部分复制(20 分)
- 6-1 使用函数实现字符串部分复制(20 分)
- GEM5中模拟的系统调用(部分没实现)
- 2 秒杀系统模拟基础实现,使用Redis实现