+ 1

Process memory writing with c#

Is it possible to write with c# to other adress than the process code adress and what i mean by that is that there is 2 adresse codes in one adress "Something.exe+1234567" and "7A23456" ihave to write over the process to the first example but i cant.. I use winapi and kernel32 on c#. Example using System; using System.Diagnostics; using System.Runtime.InteropServices; using System.Text; public class MemoryRead { const int PROCESS_WM_READ = 0x0010; [DllImport("kernel32.dll")] public static extern IntPtr OpenProcess(int dwDesiredAccess, bool bInheritHandle, int dwProcessId); [DllImport("kernel32.dll")] public static extern bool ReadProcessMemory(int hProcess, int lpBaseAddress, byte[] lpBuffer, int dwSize, ref int lpNumberOfBytesRead); public static void Main() { Process process = Process.GetProcessesByName("notepad")[0]; IntPtr processHandle = OpenProcess(PROCESS_WM_READ, false, process.Id); int bytesRead = 0; byte[] buffer = new byte[24]; //'Hello World!' takes 12*2 bytes because of Unicode // 0x0046A3B8 is

12th Jun 2019, 6:37 PM
Syss
Syss - avatar
2 Answers
+ 1
My guess is because you're using PROCESS_VM_READ as desired access, this only gives you access to well, reading. If you want to write as well you should ask for that PROCESS_VM_WRITE is there for writing, however sometimes this still prevents you from writing to the process and you should use PROCESS_VM_OPERATION as well. ( You can just or them together ) I don't really write in C# often, but the process is pretty much the same so I'm gonna give you an example in C++. This is gonna be the program that we're targeting: SetConsoleTitle( "test" ); // Easier to find the window int c = 0; int prev = c; std::cout << &c << '\n' << c << '\n'; while( true ) { if( prev != c ) { std::cout << c << '\n'; prev = c; } } All it does is print out the memory address of c and its value. It prints the value of c every time it detects a change. Now we use a 2nd program to change the value of c: int* ptr = (int*)0x22FE48; // c's address HWND hwnd = FindWindow( 0, "test" ); if( !hwnd ) return -1; DWORD processId; GetWindowThreadProcessId( hwnd, &processId ); HANDLE proc = OpenProcess( PROCESS_VM_READ | PROCESS_VM_WRITE | PROCESS_VM_OPERATION, FALSE, processId ); if( !proc ) return -2; int value; ReadProcessMemory( proc, (LPVOID)ptr, &value, sizeof( value ), NULL ); value += 5; WriteProcessMemory( proc, (LPVOID)ptr, &value, sizeof( value ), NULL ); We store the memory address of c in a pointer, find the window and then get its ID. Next we request access to it with OpenProcess, we want read and write access We read the value at the location of 0x22FE48 in this case with ReadProcessMemory and store it in value. value is then incremented by 5 and stored back at that address with WriteProcessMemory. Now the target program detects the change and prints the new value.
12th Jun 2019, 7:36 PM
Dennis
Dennis - avatar
0
Also, to resolve something like "Something.exe+15BA" you'd use a function like: uintptr_t getBaseAddress( const std::string& processName, DWORD id ) { HANDLE hSnapShot = CreateToolhelp32Snapshot( TH32CS_SNAPMODULE, id ); uintptr_t base = 0; MODULEENTRY32 me32 = {0}; me32.dwSize = sizeof( MODULEENTRY32 ); if( Module32First( hSnapShot, &me32 ) ) { do { if( strcmp( me32.szModule, processName.c_str() ) == 0 ) { base = (uintptr_t)me32.modBaseAddr; break; } }while( Module32Next( hSnapShot, &me32 ) ); } return base; } Then you can call it like: auto base = getBaseAddress( "Something.exe", processId ); char v = '\x75'; WriteProcessMemory( proc, (LPVOID)base + 0x15BA, &v, sizeof( v ), NULL ); and now the instruction 74 F8 ( "je bla.exe+15B4" ) changes into 75 F8 ( "jne bla.exe+15B4" ) which pretty much removed the detection change from the first post.
12th Jun 2019, 8:03 PM
Dennis
Dennis - avatar