VC++可不可以直接对内存进行修改?

VC++可不可以直接对内存进行修改?,第1张

一、结论:

只可以间接修改

二、原因:

32位字长的Windows 环境是一个“多任务单用户” *** 作系统,运行在X86或者兼容CPU的保护模式上,此模式使每个正在运行的程序(准确的叫法是“进程”,即Windows所调度的“任务”)都有自己独立的4GB逻辑内存空间,所谓保护就是每个进程的4GB内存地址逻辑上彼此独立,CPU和Windows保护每个独立进程的4GB逻辑内存空间不被其他用户进程直接修改。

而且4GB中只有2GB属于本进程专有地址,另外2GB属于Windows系统保护的系统内存空间,受windows系统严格保护,不允许用户进程直接读写只能通过“内核对象”间接访问。

所以您通过某个软件看到了内存地址0x0467A618的内容并试图用自编的VC程序修改时,实际上只能修改自编VC程序运行实例(即“进程”)的同编号进程地址的内容,而不能修改原来的那个进程的内存地址内容。

三、解决方案:

1)思路:

a.启动您希望修改其内容的进程,记下您希望修改的地址的内容;

b.编写一个VC程序,先按照进程名字获取进程ID,然后搜索这个ID的进程中,非系统内存区域中匹配这个内容的内存地址(注意:从Windows 2000/XP开始的版本,系统保留区域为64K~2GB,2GB以上的才是用户进程内存区域)

c.找到内容匹配的内存地址后,将其修改为你希望的值。

2)具体编程方法:

a.建立一个名字为MemRepair的VC工程(选择32位控制台工程,使用预编译头)

b.陆续加入以下三个文件:

MemRepair.h MemRepair.cpp MainProg.cpp,分别键入以下源代码:

/*(完整VC工程源代码,已经在WinXP+VC2008Express环境调试通过)*/

/* *************** 新文件 ********************* */

/* ******************************************** */

//StdAfx.h

#if !defined(AFX_STDAFX_H__7438D592_DA27_443E_824E_D280AF259D3F__INCLUDED_)

#define AFX_STDAFX_H__7438D592_DA27_443E_824E_D280AF259D3F__INCLUDED_

#if _MSC_VER >1000

#pragma once

#endif // _MSC_VER >1000

// TODO: reference additional headers your program requires here

#include "MemRepair.h"

//{{AFX_INSERT_LOCATION}}

// Microsoft Visual C++ will insert additional declarations immediately before the previous line.

#endif // !defined(AFX_STDAFX_H__7438D592_DA27_443E_824E_D280AF259D3F__INCLUDED_)

/* **************新文件**************** */

/* ************************************ */

//MemRepair.h

#ifndef __MEMFINDER_H__

#define __MEMFINDER_H__

#include <windows.h>

class CMemFinder

{

public:

CMemFinder(DWORD dwProcessId)

virtual ~CMemFinder()

// 属性

public:

BOOL IsFirst() const { return m_bFirst}

BOOL IsValid() const { return m_hProcess != NULL}

int GetListCount() const { return m_nListCnt}

DWORD operator [](int nIndex) { return m_arList[nIndex]}

// *** 作

virtual BOOL FindFirst(DWORD dwValue)

virtual BOOL FindNext(DWORD dwValue)

virtual BOOL WriteMemory(DWORD dwAddr, DWORD dwValue)

// 实现

protected:

virtual BOOL CompareAPage(DWORD dwBaseAddr, DWORD dwValue)

DWORD m_arList[1024]// 地址列表

int m_nListCnt // 有效地址的个数

HANDLE m_hProcess// 目标进程句柄

BOOL m_bFirst // 是不是第一次搜索

}

#endif // __MEMFINDER_H__

/* ************** 新文件 ************** */

/* ************************************ */

//MemRepair.cpp

#include "MemRepair.h"

#include "StdAfx.h"

CMemFinder::CMemFinder(DWORD dwProcessId)

{

m_nListCnt = 0

m_bFirst = TRUE

m_hProcess = ::OpenProcess(PROCESS_VM_READ|PROCESS_VM_WRITE|PROCESS_VM_OPERATION, FALSE, dwProcessId)

}

CMemFinder::~CMemFinder()

{

if(m_hProcess != NULL)

::CloseHandle(m_hProcess)

}

BOOL CMemFinder::FindFirst(DWORD dwValue)

{

const DWORD dwOneGB = 1024*1024*1024// 1GB

const DWORD dwOnePage = 4*1024 // 4KB

if(m_hProcess == NULL)

return FALSE

// 查看 *** 作系统类型,以决定开始地址

DWORD dwBase

OSVERSIONINFO vi = { sizeof(vi) }

::GetVersionEx(&vi)

if (vi.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS)

dwBase = 4*1024*1024 // Windows 98系列,4MB

else

dwBase = 640*1024 // Windows NT系列,64KB

// 在开始地址到2GB的地址空间进行查找

for(dwBase <2*dwOneGBdwBase += dwOnePage)

{

// 比较1页大小的内存

CompareAPage(dwBase, dwValue)

}

m_bFirst = FALSE

return TRUE

}

BOOL CMemFinder::CompareAPage(DWORD dwBaseAddr, DWORD dwValue)

{

// 读取1页内存

BYTE arBytes[4096]

if(!::ReadProcessMemory(m_hProcess, (LPVOID)dwBaseAddr, arBytes, 4096, NULL))

return FALSE// 此页不可读

// 在这1页内存中查找

DWORD* pdw

for(int i=0i<(int)4*1024-3i++)

{

pdw = (DWORD*)&arBytes[i]

if(pdw[0] == dwValue) // 等于要查找的值?

{

if(m_nListCnt >= 1024)

return FALSE

// 添加到全局变量中

m_arList[m_nListCnt++] = dwBaseAddr + i

}

}

return TRUE

}

BOOL CMemFinder::FindNext(DWORD dwValue)

{

// 保存m_arList数组中有效地址的个数,初始化新的m_nListCnt值

int nOrgCnt = m_nListCnt

m_nListCnt = 0

// 在m_arList数组记录的地址处查找

BOOL bRet = FALSE// 假设失败

DWORD dwReadValue

for(int i=0i<nOrgCnti++)

{

if(::ReadProcessMemory(m_hProcess, (LPVOID)m_arList[i], &dwReadValue, sizeof(DWORD), NULL))

{

if(dwReadValue == dwValue)

{

m_arList[m_nListCnt++] = m_arList[i]

bRet = TRUE

}

}

}

return bRet

}

BOOL CMemFinder::WriteMemory(DWORD dwAddr, DWORD dwValue)

{

return ::WriteProcessMemory(m_hProcess, (LPVOID)dwAddr, &dwValue, sizeof(DWORD), NULL)

}

/* ************** 新文件 ************** */

/* ************************************ */

//主程序mainprog.cpp

#include "stdafx.h"

#include "windows.h"

#include "stdio.h"

#include <iostream>

using namespace std

BOOL FindFirst(DWORD dwValue)// 在目标进程空间进行第一次查找

BOOL FindNext(DWORD dwValue)// 在目标进程地址空间进行第2、3、4……次查找

DWORD g_arList[1024] // 地址列表

int g_nListCnt // 有效地址的个数

HANDLE g_hProcess // 目标进程句柄

//////////////////////

BOOL WriteMemory(DWORD dwAddr, DWORD dwValue)

void ShowList()

int main(int argc, char* argv[])

{

// 启动02testor进程

char szFileName[] = "..\\02testor\\debug\\02testor.exe"

STARTUPINFO si = { sizeof(si) }

PROCESS_INFORMATION pi

::CreateProcess(NULL, szFileName, NULL, NULL, FALSE,

CREATE_NEW_CONSOLE, NULL, NULL, &si, &pi)

// 关闭线程句柄,既然我们不使用它

::CloseHandle(pi.hThread)

g_hProcess = pi.hProcess

// 输入要修改的值

int iVal

printf(" Input val = ")

scanf("%d", &iVal)

// 进行第一次查找

FindFirst(iVal)

// 打印出搜索的结果

ShowList()

while(g_nListCnt >1)

{

printf(" Input val = ")

scanf("%d", &iVal)

// 进行下次搜索

FindNext(iVal)

// 显示搜索结果

ShowList()

}

// 取得新值

printf(" New value = ")

scanf("%d", &iVal)

// 写入新值

if(WriteMemory(g_arList[0], iVal))

printf(" Write data success \n")

::CloseHandle(g_hProcess)

return 0

}

BOOL CompareAPage(DWORD dwBaseAddr, DWORD dwValue)

{

// 读取1页内存

BYTE arBytes[4096]

if(!::ReadProcessMemory(g_hProcess, (LPVOID)dwBaseAddr, arBytes, 4096, NULL))

return FALSE// 此页不可读

// 在这1页内存中查找

DWORD* pdw

for(int i=0i<(int)4*1024-3i++)

{

pdw = (DWORD*)&arBytes[i]

if(pdw[0] == dwValue) // 等于要查找的值?

{

if(g_nListCnt >= 1024)

return FALSE

// 添加到全局变量中

g_arList[g_nListCnt++] = dwBaseAddr + i

}

}

return TRUE

}

BOOL FindFirst(DWORD dwValue)

{

const DWORD dwOneGB = 1024*1024*1024// 1GB

const DWORD dwOnePage = 4*1024 // 4KB

if(g_hProcess == NULL)

return FALSE

// 查看 *** 作系统类型,以决定开始地址

DWORD dwBase

OSVERSIONINFO vi = { sizeof(vi) }

::GetVersionEx(&vi)

if (vi.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS)

dwBase = 4*1024*1024 // Windows 98系列,4MB

else

dwBase = 640*1024 // Windows NT系列,64KB

// 在开始地址到2GB的地址空间进行查找

for(dwBase <2*dwOneGBdwBase += dwOnePage)

{

// 比较1页大小的内存

CompareAPage(dwBase, dwValue)

}

return TRUE

}

BOOL FindNext(DWORD dwValue)

{

// 保存m_arList数组中有效地址的个数,初始化新的m_nListCnt值

int nOrgCnt = g_nListCnt

g_nListCnt = 0

// 在m_arList数组记录的地址处查找

BOOL bRet = FALSE// 假设失败

DWORD dwReadValue

for(int i=0i<nOrgCnti++)

{

if(::ReadProcessMemory(g_hProcess, (LPVOID)g_arList[i], &dwReadValue, sizeof(DWORD), NULL))

{

if(dwReadValue == dwValue)

{

g_arList[g_nListCnt++] = g_arList[i]

bRet = TRUE

}

}

}

return bRet

}

// 打印出搜索到的地址

void ShowList()

{

for(int i=0i<g_nListCnti++)

{

printf("%08lX \n", g_arList[i])

}

}

BOOL WriteMemory(DWORD dwAddr, DWORD dwValue)

{

return ::WriteProcessMemory(g_hProcess, (LPVOID)dwAddr, &dwValue, sizeof(DWORD), NULL)

}

1将默认堆栈值设大些,可以设定2g以上。

2优化程序,全局变量开数组,到2g左右也是极限了,可以考虑自己管理内存,先保留很大一片内存,分批提交内存,不用的释放掉,这样处理上t的数据都没问题

3设置windows大内存选项,最大3gb

4换成64比特系统


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/tougao/11323568.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-15
下一篇 2023-05-15

发表评论

登录后才能评论

评论列表(0条)

保存