内存修改

内存修改

    在应用程序A中读取和修改进程B的内存的方法有很多,这里介绍使用API函数(ReadProcessMemory和WriteProcessMemory)来实现的方法。只需你了解Windows的内存管理机制,再了解几个Windows API 函数,就可以做到。对于Windows的内存机制,网络上有很多的文章介绍这方面的内容,在此我不赘述。下面开始实例讲解。

1.  思路:

      修改其他进程的内存,因为进程使用独立的进程空间,所以必须使用API函数调用实现此功能。读指定进程的内存使用API函数ReadProcessMemory,写则使用WriteProcessMemory函数。

     具体算法:例如要修改游戏中的金钱值,首先先玩游戏,然后挣到A数量的金钱值,然后输入这个值,搜索,因为第一次搜索,可能在进程内存中有很多其他变量的值与此金钱值变量的值相同,所以记录下所有搜索到的值,然后继续玩游戏使得金钱值增加到B,然后输入B值,在上次搜索到的地址中再匹配与B值相等的地址,如此循环,直到找到唯一的地址,则完成了内存的定位,接下来就可以进行改写了。下面开始编程:

 #include <stdio.h>

#include <iostream>

using namespace std;

#include <Windows.h>

 

HWND destWnd;    //存储目标进程的窗口句柄

DWORD destThreadID=0; //存放目标进程的线程ID号

DWORD destProcessID=0;  //存放目标进程的进程ID好

DWORD g_arList[1024]; //地址列表,用来记录搜索到的地址

int g_nListCnt; //搜索到的有效地址的个数

HANDLE g_hProcess; //目标进程句柄

/*

提升权限,如果不提升权限,无法打开系统安全进程或服务进程为了提升权

限,要用到RaisePrivileges()中所示的3个API函数,具体函数介绍参考MSDN

*/

void RaisePrivileges(){

HANDLE hToken;    //

TOKEN_PRIVILEGES tkp;

tkp.PrivilegeCount=1;

tkp.Privileges[0].Attributes=SE_PRIVILEGE_ENABLED;

       //获得该进程访问令牌的句柄

if (OpenProcessToken(GetCurrentProcess(),TOKEN_ALL_ACCESS,&hToken))

{

               //得到一个唯一的GUID值

if (LookupPrivilegeValue(NULL,SE_DEBUG_NAME,&tkp.Privileges[0].Luid))

{

                         //修改访问令牌,获得权限

AdjustTokenPrivileges(hToken,FALSE,&tkp,0x10,(PTOKEN_PRIVILEGES)NULL,0);

}

}

if(hToken)

{

printf("Success Raise Privilege\n");

CloseHandle(hToken);

}

}

 

/////   读进程空间   //////////////////

 

//搜索并比较目标进程中一页大小的内存

BOOL cmpApage(DWORD dwBaseAddr,DWORD dwValue){

//读取一页内存

BYTE arBytes[4096];

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

{

return FALSE;

}

//在这一页内存中查找

DWORD *pwd;

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

{

pwd=(DWORD*)&arBytes[i];

//如果等于要查找的值,且已经搜索的到和目标值相等的值的个数(即g_nListCnt的大小)小于1024,则将其记录下来

if (pwd[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;

const DWORD dwOnePage=4*1024;

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;   //Win98系列,4MB

else

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

for (;dwBase<2*dwOneGB;dwBase+=dwOnePage)

{

cmpApage(dwBase,dwValue);    //比较1页大小的内存

}

return TRUE;

}

 

//下面的函数在第一次搜索的结果集上继续搜索

BOOL FindNext(DWORD dwValue){

int nOrgCnt=g_nListCnt;

g_nListCnt=0;

BOOL bret=FALSE;

DWORD dwReadValue;

for (int i=0;i<nOrgCnt;i++)

{

if (::ReadProcessMemory(g_hProcess,(LPCVOID)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=0;i<g_nListCnt;i++)

{

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

}

if(g_nListCnt<1)

cout<<"Failed Read\n";

}

 

 

////////写进程空间////////////////

//找到变量的地址后,就可以改变它的值了

BOOL WriteMemory(DWORD dwAddr,DWORD dwValue){

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

}

 

int main(){

 

RaisePrivileges(); //提升权限

       // //第一个参数为“窗口类名”,第二个参数为"窗口名"。可以用VC中的TOOL中的

    //SPY++查看。当然,也可以通过编程如拍快照等找到目标进程的ID

destWnd=FindWindowA(NULL,"超级玛丽");   //找到目标进程的窗口句柄

if(destWnd!=NULL)

{

                   //根据窗口句柄找到进程ID,存储在destProcessID中

destThreadID=::GetWindowThreadProcessId(destWnd,&destProcessID);

}else

cout<<"Failed FindWnd and get ProcessID\n";

cout<<"Dest ThreadID:   "<<(int)destThreadID<<"\nDest ProcessID:   "<<(int)destProcessID<<endl;

 

//

int doRead=0,doWrite=0; //两个变量都默认为0,即默认不对目标进程进行读操作和写操作

int iVal;

g_hProcess=OpenProcess(PROCESS_ALL_ACCESS,FALSE,destProcessID); //获得目标进程的句柄

if(g_hProcess!=NULL){

cout<<"will you read process?  0:no,  !0:yes\n";

cin>>doRead;

if(doRead!=0){

printf("Input var=");

scanf("%d",&iVal);

FindFirst(iVal);

showList();

int x=0;

while(g_nListCnt>1){

printf("input iVal=");

scanf("%d",&iVal);

FindNext(iVal);

showList();

x++;

if(x>10); break;

}

}

//write memorry

if (g_nListCnt==1)

{

cout<<"will you write process?  0:no  !0:yes\n";

cin>>doWrite;

}

if (doWrite!=0)

{

printf("New Value=");

scanf("%d",&iVal);

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

printf("Success write\n");

else

printf("Failed Write\n");

}

 

CloseHandle(g_hProcess); //如果打开了句柄,必须关闭

}

else

cout<<"Failed OpenHandle()\n";

return 0;

 

你可能感兴趣的:(职场,休闲,内存修改,C++编程,游戏修改器)