ReadProcessMemory与WriteProcessMemory用例分析「建议收藏」

ReadProcessMemory与WriteProcessMemory用例分析「建议收藏」首先介绍一个函数VirtualProtectEx,它用来改变一个进程的虚拟地址中特定页里的某一区域的保护属性,这句话有些咬嘴,直接从MSDN中翻译过来的,简单来说就是改变某一进程中虚拟地址的保护属性,如果以前是只读的,那改变属性为PAGE_EXECUTE_READWRITE后,就

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE稳定放心使用

首先介绍一个函数VirtualProtectEx,它用来改变一个进程的虚拟地址中特定页里的某一区域的保护属性,这句话有些咬嘴,直接从MSDN中翻译过来的,简单来说就是改变某一进程中虚拟地址的保护属性,如果以前是只读的,那改变属性为PAGE_EXECUTE_READWRITE后,就可以更改这部分内存了。

具体看它的实现

BOOL WINAPI VirtualProtectEx(
  __in   HANDLE hProcess,
  __in   LPVOID lpAddress,
  __in   SIZE_T dwSize,
  __in   DWORD flNewProtect,
  __out  PDWORD lpflOldProtect
);

第一个参数是进程的句柄,这个句柄可以使用由CreateProcess()函数得到的PROCESS_INFORMATION结构中的hProcess成员,CreateProcess()这个函数相信大家用的很多了,我就不详细介绍了。如果仅仅知道hProcess的ID,那么可以通过OpenProcess()函数得到,OpenProcess()有三个参数,最后一个参数就是进程的ID,它的返回值为进程的句柄。如果想得到线程的句柄,同样可以采用这两种方式,利用结构体PROCESS_INFORMATION重的hThread成员或使用函数OpenThread()。

第二个参数lpAddress就是页中要改变保护属性的地址。第三个参数dwSize改变保护属性区域的大小,以字节为单位。通过这两个变量就可以确定要改变包括属性的区域了。

第四个参数fNewProtect是要改变的保护属性。包含PAGE_EXECUTE_READWRITE,PAGE_READONLY等,但先看第五个参数lpfOldProtect,是用来保存为改变之前的内存区域的保护属性,也就是说我们可以先备份之前的保护属性,然后将属性更改为PAGE_EXECUTE_READWRITE,然后对内存区域进行一些操作,然后再将内区域更改回来。

 

接下来看ReadProcessMemory()函数

BOOL WINAPI ReadProcessMemory(
  __in   HANDLE hProcess,
  __in   LPCVOID lpBaseAddress,
  __out  LPVOID lpBuffer,
  __in   SIZE_T nSize,
  __out  SIZE_T *lpNumberOfBytesRead
);

第一个参数hProcess为进程的句柄,第二个参数lpBaseAddress为要读取内容的基地址,当然你事先要了解你要读取内容的基地址。第三个参数lpBuffer为接收所读取内容的基地址。第四个参数为要读取内容的大小,以字节为单位。最后一个参数lpNumberOfBytesRead为接收读取内容的buffer中收到的字节数。一般都设为NULL,这个该参数将被忽略掉。

使用ReadProcessMemory()函数,可以获得该进程内存空间中的信息,或是用于监测进程的执行情况,或是将进程内的数据备份,然后调用writeProcessMemory()进行修改,必要时再还原该进程的数据。

BOOL WINAPI WriteProcessMemory(
  __in   HANDLE hProcess,
  __in   LPVOID lpBaseAddress,
  __in   LPCVOID lpBuffer,
  __in   SIZE_T nSize,
  __out  SIZE_T *lpNumberOfBytesWritten
);

该函数与readProcessMemory的参数基本相同,只不过第三个参数lpBuffer为要写入进程的内容。

将内存的内容更改后,别忘了调用VirtualProtectEx()恢复内存原来的保护属性。

下面看个例子,该例子是用于如何设置和移除断点的,类似调试器的功能。

//****************************************************************************
// Function : BOOL SetBreakPoint(HANDLE hProcess, LPVOID lpAddr, UINT nNum)
// DESCRIPTION : Use for setting a break point.
// PARAMETERS :
//               hProcess – The current process handle
//               lpAddr – The address of break point
//               nNum – the index of the break point
//*****************************************************************************

BOOL SetBreakPoint(HANDLE hProcess, LPVOID lpAddr, UINT nNum)
{

    if (nNum >= sizeof(g_bpData) / sizeof(BPDATA)) return FALSE;
    BYTE byTemp;
    DWORD dwNewProt, dwOldProt;
    VirtualProtectEx(hProcess, lpAddr, 1, PAGE_EXECUTE_READWRITE, &dwOldProt);
    BOOL bOK = ReadProcessMemory(hProcess, lpAddr, &byTemp, 1, NULL);
    if (bOK)
 {
  g_bpData[nNum].lpAddr = lpAddr;             // 备份原地址的内容,然后替换为断点指令int3,当程序运行到这时,就会执行断点 
  g_bpData[nNum].byData = byTemp;         // 如果继续执行,那么就将EIP指针减一,然后还原原指令,程序能正常执行
  g_bpData[nNum].nCount = 0;
  byTemp = 0xcc;  // int3 断点指令
  bOK = WriteProcessMemory(hProcess, lpAddr, &byTemp, 1, NULL);   
    }

    VirtualProtectEx(hProcess, lpAddr, 1, dwOldProt, &dwNewProt);
    return bOK;
}

//****************************************************************************
// Function : BOOL RemoveBreakPoint(HANDLE hProcess, UINT nNum)
// DESCRIPTION : Use for removing a break point.
// PARAMETERS :
//               hProcess – The current process handle
//               nNum – the index of the break point
//*****************************************************************************

BOOL RemoveBreakPoint(HANDLE hProcess, UINT nNum)
{
 
    if (nNum >= sizeof(g_bpData) / sizeof(BPDATA)) return FALSE;
    BYTE byTemp;
    DWORD dwNewProt, dwOldProt;
    LPVOID lpAddr = g_bpData[nNum].lpAddr;
    VirtualProtectEx(hProcess, lpAddr, 1, PAGE_EXECUTE_READWRITE, &dwOldProt);
    BOOL bOK = ReadProcessMemory(hProcess, lpAddr, &byTemp, 1, NULL);
    bOK = (byTemp == 0xcc);
    if (bOK)
 {

  
  bOK = WriteProcessMemory(hProcess, lpAddr, &g_bpData[nNum].byData, 1, NULL);   // 还原原指令
  
  if (bOK) ZeroMemory(g_bpData + nNum, sizeof(BPDATA));   // 清空
 }
    VirtualProtectEx(hProcess, lpAddr, 1, dwOldProt, &dwNewProt);
    return bOK;
}

 

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/185948.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • 一个新的敲诈者病毒

    一个新的敲诈者病毒

  • java时间计数_java计算方法耗时

    java时间计数_java计算方法耗时java时间计数

  • vue父子组件传值方法_vue父组件向子组件传递对象

    vue父子组件传值方法_vue父组件向子组件传递对象前言在业务场景中经常会遇到子组件向父组件传递数值,或是父组件向子组件传递数值,下面将结合vue富文本框一起来了解一下父与子组件之间的传值业务场景在vue项目中创建了一个可以重复使用的富文本编辑器(可参考【vue】vue富文本编辑器(可重复使用组件)vue-quill-editor),由于是新闻编辑页面,首先需要把已经保存好的新闻内容展示在富文本编辑器中(父组件向子组件传值),其次需要把更新后的新闻内容保存到数据库中(子组件向父组件传值)父组件向子组件传值(v-bind:child.

  • asp.net mvc实现文件下载「建议收藏」

    asp.net mvc实现文件下载「建议收藏」前段时间一直对如何解决文件下载的问题比较困惑,对文件下载的问题一直都是用的前端的方式解决的,代码如下//下载functiondownload(filePath){window.open(filePath);}但是这个方法有他的缺陷:1.下载的文件后缀必须为iis程序池中存在的文件2.此方法是通过浏览器打开服务器文件,无法直接下载近期看了asp.net下载文件几种方式…

  • [译文]三重缓冲:为什么我们爱它

    [译文]三重缓冲:为什么我们爱它
    文章来源:http://www.anandtech.com/video/showdoc.aspx?i=3591&p=1
    文章标题:TripleBuffering:WhyWeLoveIt
    文章作者:DerekWilson
    文章时间:2009年6月26日

    引子

    我们往往不愿过多讨论哪些选项在游戏中应该开启。相反,我们往往把重点放在我们的评测内容上。老实说,我们对玩游戏的建议设置与我们的评测设置非常相似,除

  • 手机怎么复制网页上不能复制的文字_如何复制网页上收费文档的文字

    手机怎么复制网页上不能复制的文字_如何复制网页上收费文档的文字们在浏览网页的时候,时常会觉得有的内容不错,想复制下来,却发现有的网页内容不能复制,今天就教大家如何解决这个问题。虽然可以通过禁用脚本或是“查看源文件”,在源文件代码中复制需要的文章。不过复制文章的时候会有很多用不着的符号和代码。这样的操作方法其实都不如使用八爪鱼方便快捷。下面就给大家介绍一下如何利用八爪鱼采集网页上不能复制。步骤一、下载八爪鱼软件并登陆1、打开htt…

    2022年10月13日

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号