迷ったんですが・・・
こういう方法もある、という、あくまで情報としてだけ提供しておきます。
特にこの件については答える気は無いので、必要であれば自分の力で調べてください。
別プロセスの仮想メモリ内アドレス(ポインタ)経由で
OpenProcess、WriteProcessMemoryを使用することで
値の書き変えをするという方法を、一応、例という形でだけ示してはおきます。
(ビルド環境:Windows7、VS2013update3)
Process1.cpp
- コード[C++]: 全て選択
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91
| #include <windows.h> #include <iostream> using namespace std; typedef struct stKid { char str1[128]; char str2[256]; } stKid_t; typedef struct stPrnt { stKid_t *strSt; } stPrnt_t; DWORD GetProcessID(); int main() { DWORD idProcess = GetProcessID(); cout << "idProcess: " << idProcess << endl; HANDLE hProcess = OpenProcess(PROCESS_VM_READ | PROCESS_VM_WRITE | PROCESS_VM_OPERATION, FALSE, idProcess); if (!hProcess){ cerr << "OpenProcess(): " << GetLastError() << endl; cin.ignore(); return -1; } LPVOID pInterProcessSharedPointer = VirtualAllocEx(hProcess, NULL, 0x1000, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); if (!pInterProcessSharedPointer){ cerr << "VirtualAllocEx(): " << GetLastError() << endl; cin.ignore(); return -1; } stKid_t stK = { "hello", "world" }; stPrnt_t stP = { &stK }; DWORD len = 0; BOOL res = 0; if (!WriteProcessMemory(hProcess, pInterProcessSharedPointer, &stP, sizeof(stPrnt_t), &len)){ cerr << "WriteProcessMemory(): " << GetLastError() << endl; cin.ignore(); return -1; } printf("pInterProcessSharedPointer: 0x%p\n", pInterProcessSharedPointer); cout << endl; cout << stP.strSt->str1 << endl; cout << stP.strSt->str2 << endl; cout << endl; cout << "このタイミングで Process2のプログラムの pInterProcessSharedPointer を、こちらの pInterProcessSharedPointer で書き換えてビルドしてください。" << endl; cout << "その後、Process2の実行を開始し、止まったらEnterを押下してください。" << endl; cin.ignore(); cout << stP.strSt->str1 << endl; cout << stP.strSt->str2 << endl; cout << endl; cout << "Enterを押下するとプロセスを終了します。"; cin.ignore(); VirtualFreeEx(hProcess, pInterProcessSharedPointer, 0, MEM_RELEASE); CloseHandle(hProcess); return 0; } DWORD GetProcessID() { DWORD idProcess = NULL; char name[512] = { 0 }; GetConsoleTitle(name, sizeof(name)); cout << name << endl; string cosole_name(name); DWORD idThread = GetWindowThreadProcessId(FindWindow(NULL, cosole_name.data()), &idProcess); if (!idThread || !idProcess) { cerr << "GetWindowThreadProcessId(): " << GetLastError() << endl; cin.ignore(); return -1; } return idProcess; } |
Process2.cpp
- コード[C++]: 全て選択
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108
| #include <windows.h> #include <iostream> using namespace std; typedef struct stKid { char str1[128]; char str2[256]; } stKid_t; typedef struct stPrnt { stKid_t *strSt; } stPrnt_t; DWORD GetProcessID(const char name[]); DWORD GetProcessID(); int main() { //Process1.exe のパス char name[512] = { "C:\\Process1.exe" }; //注意: ビルド&実行前に、相手プロセスのPIDを指定する必要がある。 DWORD idProcess = GetProcessID(name); cout << "idProcess: " << idProcess << endl; HANDLE hProcess = OpenProcess(PROCESS_VM_READ | PROCESS_VM_WRITE | PROCESS_VM_OPERATION, FALSE, idProcess); if (!hProcess){ cerr << "OpenProcess(): " << GetLastError() << endl; cin.ignore(); return -1; } DWORD len = 0; stKid_t stK_clone = { 0 }; stPrnt_t stP_clone = { 0 }; stP_clone.strSt = &stK_clone; //注意: // Process2が止まったら、Process1画面で表示されている相手プロセスの pInterProcessSharedPointer と // 同じ値にハードコーティングで書き換えた後、ビルドして実行してください。 LPVOID pInterProcessSharedPointer = (LPVOID)0x001C0000; stKid_t *strSt; if (!ReadProcessMemory(hProcess, (LPCVOID)pInterProcessSharedPointer, &strSt, sizeof(strSt), &len)) { cerr << "ReadProcessMemory(): " << GetLastError() << endl; cin.ignore(); return -1; } // (LPCVOID)strSt->str1 は、相手プロセスの仮想メモリ空間内のメモリアドレスを指しているだけで、こちらのプロセスで直接中身が参照できるわけではない。 if (!ReadProcessMemory(hProcess, (LPCVOID)strSt->str1, stP_clone.strSt->str1, sizeof(stP_clone.strSt->str1), &len)) { cerr << "ReadProcessMemory(): " << GetLastError() << endl; cin.ignore(); return -1; } // (LPCVOID)strSt->str2 は、相手プロセスの仮想メモリ空間内のメモリアドレスを指しているだけで、こちらのプロセスで直接中身が参照できるわけではない。 if (!ReadProcessMemory(hProcess, (LPCVOID)strSt->str2, stP_clone.strSt->str2, sizeof(stP_clone.strSt->str2), &len)) { cerr << "ReadProcessMemory(): " << GetLastError() << endl; cin.ignore(); return -1; } //★相手プロセスの仮想メモリ空間内の値を書き換える char str1[128] = "good evening"; if (!WriteProcessMemory(hProcess, (LPVOID)strSt->str1, str1, sizeof(str1), &len)){ cerr << "WriteProcessMemory(): " << GetLastError() << endl; cin.ignore(); return -1; } cout << stP_clone.strSt->str1 << endl; cout << stP_clone.strSt->str2 << endl; cout << endl; cout << "Process1でEnterを押下して、stP.strSt->str1 の内容が書き換わったか確認してください。" << endl; cout << endl; cout << "Enterを押下するとプロセスを終了します。"; cin.ignore(); CloseHandle(hProcess); return 0; } DWORD GetProcessID(const char name[]) { DWORD idProcess = NULL; cout << name << endl; DWORD idThread = GetWindowThreadProcessId(FindWindow(NULL, name), &idProcess); if (!idThread || !idProcess) { cerr << "GetWindowThreadProcessId(): " << GetLastError() << endl; cin.ignore(); return -1; } return idProcess; } |
Process1 で確保したヒープメモリの内容を
Process2 側でアドレス(ポインタ)のみの参照から 相手プロセスのヒープメモリの内容を書き換えています。
例を示すために
共有メモリにセットされたローカルアドレス(ポインタ)を
相手プロセスのヒープメモリのアドレス(ポインタ)で見立てて代用してます。
説明用に書き殴ったものなので、コードを短くするために
めんどうな実行方法を取らなければ実行できないようになってます。
準備
-----------------------------------------------------------------------------------------------------------
Process2.cpp の 27行目
- コード[C++]: 全て選択
1
| char name[512] = { "C:\\Process1.exe" }; |
を、Process1.cpp をビルドして完成した実行ファイルのパスに書き換えておきます。
-----------------------------------------------------------------------------------------------------------
実行方法
-----------------------------------------------------------------------------------------------------------
① Process1 起動
→ Process1 が途中で止まり、メッセージが表示されるので指示にしたがう。
② Process2 の コード 49行目 を指示どおり、Process1の pInterProcessSharedPointer で直に書き換え、ビルドして起動。
- コード[C++]: 全て選択
1
| LPVOID pInterProcessSharedPointer = (LPVOID)0x001C0000; |
③ Process2の動作が止まったら、Process1側の画面でEnterキーを押して確認。
→ Process1側の stP.strSt->str1 が "hello" から "good evening" に書き換わっている。
④ Process1、Process2 共に終了。
-----------------------------------------------------------------------------------------------------------
ただ、折角の仮想メモリ空間を超えてまで、こんなことをする必要があるかは疑問です。