サードパーティのC ++プログラムのメモリ内の値を検索および編集する

ArtMoneyに適さないもの





多くの場合、外部プログラムの行/番号を見つけて変更する必要があります。 このタスクは、ArtMoneyが最適に処理します。 デバッガーの使用方法がわからない、またはデバッガーを使用したくない場合、通常の類似物は存在しないため、これがおそらく今日の唯一のオプションです。 ArtMoneyはメモリを操作する多くの機会をサポートしていますが、プロセス全体は手動で行われ、アルゴリズムに従ってアクションを作成する可能性はありません。 多くの値があり、たとえばプログラムを起動するたびに値を変更する必要がある場合、この作業に費やされる時間は考えられるすべての制限を超えます。 唯一の方法があります-独自のメモリエディタを作成してください!



ソースを探しています





かつて、別のプログラムのメモリ内の値を操作中に常に変更する必要があるタスクがありました。 条件の1つは、プログラムが他のマシンで動作することでした。つまり、所定のアドレスでメモリに書き込むオプションは適切ではありません。異なるマシンのアドレスは異なり、メモリ内のアドレスの検索を実装する必要がありました。



ブートローダーの記述を開始し、この問題に関する情報の検索を開始しました。 残念ながら、私はDelphiを所有していません。ソースコードのほとんどがその言語であることが判明したとき、私は少し混乱していました。 膨大な量のC ++コードを書き直す時間も機会もありませんでした。 別の発見は、私が見つけたソースコードがどれも正しく動作しないことでした。プログラムはハングするか、エラーで動作しました。 さらに、これらすべてのプログラムのメモリ内での検索作業は、必要以上に時間がかかりました(ArtMoneyの15〜20倍ごと)。



フォーラム(英語のフォーラムを含む)の検索も楽しいものではありませんでした:C ++の主題に関連するトピックにコードのスニペットがありました(明らかに必要な機能はありません)。 著者が彼の質問をどこでうまく解決できたか覚えていない。 それにもかかわらず、私はWindowsのRAMデバイスに関する知識をいくらか取り、作業で使用される機能について学びました。



数日間の苦痛の後、1つの有用なトピックが見つかりました。 著者はC ++で非常に機能するプログラムを提供していますが、残念ながら非常にゆっくり動作しました。 解決策は最後から2番目の投稿にあります。 2つのコードを作成し、それらにコメントを提供するだけです。 以下のプログラムは、多くの人がプロセスの記憶を検索する問題を解決し、新しいことを学ぶのに役立つと思います。



プログラムメモリ内の値を検索および編集する





テストプログラム




#include <windows.h> char szText[] = "Hello world.", szTitle[] = "Information"; main() { while (TRUE) MessageBox(NULL, szText, szTitle, MB_ICONINFORMATION); return EXIT_SUCCESS; } /*  ,       */
      
      







編集者自身




 #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 20 L# 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(); }
      
      







結論として





コードは湿っていて、作業が必要ですが、これはRuNetのC ++で問題を解決する唯一の既製の例です。 私は意図的にここですべての修正を行い、すべてのニュアンスをカバーしませんでした。 これは記事を大きく膨らませます(とにかくそれほど小さくはありませんでした)。 いずれにせよ、それはあなたのニーズに合うようにメモリエディタを書くためのフレームワークとして有用であり、また数分ではなく数秒かかるようにメモリ内で検索する方法を理解します。



もう一度、ソースコードと作業の原則が採用されているトピックに言及します



PS donnerjack13589招待していただきありがとうございます



All Articles