📜 ⬆️ ⬇️

Search and edit values ​​in the memory of a third-party C ++ program

What is not satisfied with ArtMoney



Often there is a need to find and change any lines / numbers in another program. This task is best done by ArtMoney. For those who do not know how or do not want to use debuggers, this is probably the only option today, since there are simply no normal analogues. Although ArtMoney supports a lot of possibilities for working with memory, the whole process is done manually, without the possibility of creating actions using an algorithm. If there are many values ​​and they need to be changed, for example, each time the program is started, then the time spent on this work exceeds any permissible limits. Only one way out - to write your own memory editor!

We are looking for sources



At one time, I had a task that required modification of the values ​​in the memory of another program constantly during its operation. One of the conditions was that the program would work on other machines, which means that the option of writing to memory at predetermined addresses would not work: the addresses for different machines will be different and it is necessary to implement the search for addresses in memory.
')
I started writing a bootloader and started looking for information on this issue. Unfortunately, I do not own Delphi, and when it was discovered that most of the source code is in this language, I was a little confused. I didn’t have time or opportunity to rewrite a huge amount of code in C ++. Another discovery was that none of the sources I found worked correctly: the program either hung or worked with errors. In addition, the work of all these search programs in memory took much longer than it should (15–20 times longer than ArtMoney).

Searching the forums (including English) was also not joyful: in the topics related to the subject in C ++ there were snippets of code (obviously without the necessary functionality). I do not remember where the author would have successfully solved his question. Nevertheless, I made some knowledge about the device memory in Windows and learned about the functions used in the work.

After several days of torment, I found one useful topic . The author gives quite a working program in C ++, unfortunately it worked very slowly. The solution is there in the penultimate post. It remains only to link the two codes and provide them with comments. I think the program below will help many people to solve the problem of searching through the process memory, well, and learn something new.

Search and edit values ​​in the program memory



Test program


#include <windows.h>

char szText[] = "Hello world.",
szTitle[] = "Information";

main()
{
while(TRUE)
MessageBox(NULL, szText, szTitle, MB_ICONINFORMATION);
return EXIT_SUCCESS;
}
/* , */


Editor himself


#include <stdio.h>
#include <windows.h>
#include <tlhelp32.h>
#define PROC_NAME "n00b.exe"
#define MAX_READ 128

int fMatchCheck (char *mainstr, int mainstrLen, char *checkstr, int checkstrLen)
{
/*
.
""
.
*/
BOOL fmcret=TRUE;
int x,y;

for (x=0; x<mainstrLen; x++) {
fmcret=TRUE;

for (y=0; y<checkstrLen; y++) {
if (checkstr[y]!=mainstr[x+y]) {
fmcret=FALSE;
break;
}
}

if (fmcret)
return x+checkstrLen;
}
return -1;
}

char *getMem(char *buff, size_t buffLen, int from, int to)
{
/*
,
.
*/
size_t ourSize = buffLen*2;
char *ret = (char*)malloc(ourSize);

memset(ret, 0, ourSize);

memcpy(ret, &buff[from], buffLen-from);
memset(&ret[to-from], 0, to-from);

return ret;
}

char *delMem(char *buff, size_t buffLen, int from, int to)
{
/*
.
*/
size_t ourSize = buffLen*2;
char *ret = (char*)malloc(ourSize);
int i,x=0;

memset(ret, 0, ourSize);

for (i=0; i<buffLen; i++) {
if (!(i>=from&&i<to)) {
ret[x]=buff[i];
x++;
}
}

return ret;
}

char *addMem(char *buff, size_t buffLen, char *buffToAdd, size_t addLen, int addFrom)
{
/*
.
*/
size_t ourSize = (buffLen+addLen)*2;
char *ret = (char*)malloc(ourSize);
int i,x=0;

memset(ret, 0, ourSize);

memcpy(ret, getMem(buff, buffLen, 0, addFrom), addFrom);

x=0;
for (i=addFrom; i<addLen+addFrom; i++) {
ret[i]=buffToAdd[x];
x++;
}

x=0;
for (i; i<addFrom+buffLen; i++) {
ret[i]=buff[addFrom+x];
x++;
}

return ret;
}

char *replaceMem(char *buff, size_t buffLen, int from, int to, char *replaceBuff, size_t replaceLen)
{
/*
"" .
*/
size_t ourSize = (buffLen)*2;
char *ret = (char*)malloc(ourSize);

memset(ret, 0, ourSize);

memcpy(ret, buff, buffLen); // copy 'buff' into 'ret'

ret = delMem(ret, buffLen, from, to); // delete all memory from 'ret' betwen 'from' and 'to'
ret = addMem(ret, buffLen-to+from, replaceBuff, replaceLen, from);

return ret;
}

DWORD fGetPID( char *szProcessName )
{
PROCESSENTRY32 pe = {sizeof(PROCESSENTRY32)};
HANDLE ss;
DWORD dwRet = 0;

ss = CreateToolhelp32Snapshot (TH32CS_SNAPPROCESS, 0);

if (ss) {
if (Process32First(ss, &pe))
while (Process32Next(ss, &pe)) {
if (!strcmp(pe.szExeFile, szProcessName)) {
dwRet = pe.th32ProcessID;
break;
}
} CloseHandle( ss );
}
return dwRet;
}

BOOL DoRtlAdjustPrivilege()
{
/*
. .

.
*/
#define SE_DEBUG_PRIVILEGE 20L
#define AdjustCurrentProcess 0
BOOL bPrev = FALSE;
LONG (WINAPI *RtlAdjustPrivilege)(DWORD, BOOL, INT, PBOOL);
*(FARPROC *)&RtlAdjustPrivilege = GetProcAddress(GetModuleHandle("ntdll.dll"), "RtlAdjustPrivilege");
if(!RtlAdjustPrivilege) return FALSE;
RtlAdjustPrivilege(SE_DEBUG_PRIVILEGE, TRUE, AdjustCurrentProcess, &bPrev);
return TRUE;
}

main()
{
/*** VARIABLES ***/
HANDLE hProc;

MEMORY_BASIC_INFORMATION mbi;
SYSTEM_INFO msi;
ZeroMemory(&mbi, sizeof(mbi));
GetSystemInfo(&msi);
/*
.
*/

DWORD dwRead=0;

char *lpData = (VOID*)GlobalAlloc(GMEM_FIXED, MAX_READ),
lpOrig[] = "Information", //
lpReplacement[] = "habrahabr.ru"; //

int x,at;
/*****************/

if (!lpData)
return -1;

ZeroMemory(lpData, MAX_READ);

//
do {
hProc = OpenProcess (PROCESS_ALL_ACCESS,
FALSE,
fGetPID(PROC_NAME));
if (!hProc) {
Sleep(500);
puts ("Cant open process!\n"
"Press any key to retry.\n");
getch();
}
} while(!hProc);

if(DoRtlAdjustPrivilege()){
/*
.
*/

puts ("Process opened sucessfully\n"
"Scanning memory...\n");

for(LPBYTE lpAddress = (LPBYTE)msi.lpMinimumApplicationAddress;
lpAddress <= (LPBYTE)msi.lpMaximumApplicationAddress;
lpAddress += mbi.RegionSize){
/*
,
. Windows "".
: - ,
- . .

. ArtMoney.
*/

if(VirtualQueryEx(fGetPID(PROC_NAME), lpAddress, &mbi, sizeof(mbi))){
/*
.
*/

if((mbi.Protect & PAGE_READWRITE) || (mbi.Protect & PAGE_WRITECOPY)){
/*
, .
*/

for (lpAddress;
lpAddress<(lpAddress + dwSize);
lpAddress+=0x00000100) {
/*
,
, .
*/

dwRead=0;
if (ReadProcessMemory (hProc,
(LPCVOID)lpAddress,
lpData,
MAX_READ,
&dwRead) == TRUE) {
/*
128
, .
*/

if (fMatchCheck(lpData, dwRead, lpOrig, sizeof(lpOrig)-1)!=-1) {
/*, .*/
printf ("MEMORY ADDRESS: 0x00%x\n"
"DATA:\n", lpAddress);
for (x=0;x<dwRead;x++) {
printf("%c", lpData[x]);
} puts("\n");

at = fMatchCheck (lpData,
dwRead,
lpOrig,
sizeof(lpOrig)-1);

if (at!=-1) {
at-=sizeof(lpOrig)-1;

lpData = replaceMem (lpData,
dwRead,
at,
at+sizeof(lpOrig)-1,
lpReplacement,
/*sizeof(lpReplacement)-1*/sizeof(lpOrig)-1);

puts("REPLACEMENT DATA:");
for (x=0;x<dwRead-sizeof(lpOrig)-1+sizeof(lpReplacement)-1;x++) {
printf("%c", lpData[x]);
} puts("\n");

puts("Replacing memory...");
if (WriteProcessMemory (hProc,
(LPVOID)lpAddress,
lpData,
/*dwRead-sizeof(lpOrig)-1+sizeof(lpReplacement)-1*/dwRead,
&dwRead)) {
puts("Success.\n");
} else puts("Error.\n");
} else puts("Error.\n");

}

}
}

}else puts("Error.\n");
}else puts("Error.\n");
}
}else puts("Error.\n");

// // // // //
// Cleanup
if (hProc)
CloseHandle(hProc);
if (lpData)
GlobalFree(lpData);
///////////////

puts ("Done. Press any key to quit...");
return getch();
}


In custody



The code is damp, there is a lot of work to do, but this is apparently the only ready-made example of solving a C ++ problem in runet. I intentionally did not make all the corrections here and cover all the nuances, because this would greatly inflate the article (and it is not so small as it turned out). In any case, it will be useful as a framework for writing a memory editor to fit your needs, as well as giving an insight into how to search in memory so that it takes a few seconds, not minutes.

Once again I will mention a topic from which source codes and principles of work are taken.

PS Thank you for donnerjack13589 for an invite

Source: https://habr.com/ru/post/93437/


All Articles