.NET remote process manipulation library for x86 / x64 written in C++/CLI.
Note : Your program architecture must match the remote process architecture. If you want to manipulate x64 process, compile MyMemory as x64 !
This also apply to WOW64 process, x86 process on x64 OS, MyMemory need to be compiled as x86.
- Mercury because that's mainly because of you I fall in this world.
- Apoc for it's MarshalCache class and many clean win32 implementation.
- DrakeFish as you did the first version of VEH in assembly for me.
- Cypher for being awesome and helped me with many undocumented stuff (and because he like yelling at everyone).
- Shynd because he is a wizard doing black magic.
- Master674 you helped me in many differents area, unrelated to this project, but had to put your name.
- ZenLulz for good implementation in it's MemorySharp project that gave me many ideas.
- Nesox's cat.
- Cromon because I had some fun time reading you on Skype group while coding.
#Simple documentation :
- 1 - Basic memory maniputation
- 1.1 - Initialize a RemoteProcess
- 1.2 - Reading memory
- 1.3 - Writing memory
- 1.4 - Protect memory
- 1.5 - Allocate memory
- 2 - Modules informations
- 2.1 - Enumerate modules
- 3 - Threads informations
- 3.1 - Enumerate threads
- 3.2 - Manipulate thread context
- 4 - Assembly
- 4.1 - Use Yasm
- 4.2 - Assemble mnemonics
- 4.3 - Inject mnemonics
- 4.4 - Execute mnemonics
##1.1 Initialize a RemoteProcess
Simply make a new instance of MyMemory.RemoteProcess and call RemoteProcess.Open(uint processId) :
var process = new MyMemory.RemoteProcess();
bool processOpened = process.Open(1234); // adjust process id
var result = process.MemoryManager.Read<int>(new IntPtr(0xDEADBEEF));
var writeSuccess = process.MemoryManager.Write<int>(new IntPtr(0xDEADBEEF), 1234);
Change the memory protection of a specific region, the RemoteMemoryProtection class implement IDisposable so it can be used in an using block :
using (var protection = process.MemoryManager.ProtectMemory(new IntPtr(0x9A0000), 0x1000, Enumerations.MemoryProtectionFlags.ExecuteReadWrite))
{
// Protect the memory at address 0x9A0000 with a length 0x1000
// ProtectMemory return an RemoteMemoryProtection instance
// The memory protection is restored when .Dispose() is called
}
Allocate memory in the process, the RemoteAllocatedMemory class implement IDisposable so it can be used in an using block :
using (var allocatedMemory = process.MemoryManager.AllocateMemory(1000))
{
Console.WriteLine("BaseAddress : 0x{0}", allocatedMemory.Pointer.ToInt64());
// You can also get chunk from this allocated memory
var chunk1 = allocatedMemory.AllocateOfChunk("chunkName1", 4);
var chunk2 = allocatedMemory.AllocateOfChunk("chunkName2", 4);
// And write in them
allocatedMemory.Write<int>("chunkName1", 123);
// Or read them
int value = allocatedMemory.Read<int>("chunkName1");
}
foreach (var remoteModule in process.ModulesManager.Modules)
{
Console.WriteLine("Name : {0}", remoteModule.BaseName);
Console.WriteLine("BaseAddress : 0x{0:X}", remoteModule.BaseAddress.ToInt64());
Console.WriteLine("Size : 0x{0:X}", remoteModule.Size);
}
foreach (var remoteThread in process.ThreadsManager.Threads)
{
Console.WriteLine("ThreadId : {0}", remoteThread.ThreadId);
}
var mainThread = process.ThreadsManager.MainThread;
if (mainThread.SuspendThread())
{
MyMemory.Structures.ThreadContext ctx;
if (mainThread.GetThreadContext(out ctx))
{
ctx.Eip = 0; // Don't do that for real, just proof of concept !
mainThread.SetThreadContext(ref ctx);
}
mainThread.ResumeThread();
}
MyMemory embedd Yasm assembler to assemble mnemonics on the fly. It support 32 and 64 bits.
First, you need to create a new instance of Yasm :
var yasm32 = new MyMemory.Assembly.Yasm(process, 1024, 32);
// Create a new Yasm instance with a 1024 bytes buffer, for 32 bits
var yasm64 = new MyMemory.Assembly.Yasm(process, 1024, 64);
// Create a new Yasm instance with a 1024 bytes buffer, for 64 bits
You can also use the already instanced Yasm property in RemoteProcess class :
var yasm = process.Yasm;
Note : the RemoteProcess.Yasm by default match the current process architecture.
That's pretty simple, the Yasm.Assemble function take the mnemonics as a string array, and return the result as byte array :
string[] mnemonics = { "mov rax, 1", "retn" };
byte[] opcodes = process.Yasm.Assemble(mnemonics);
// Output : 48 C7 C0 01 00 00 00 C3
var mnemonics = new[] {"mov eax, 123", "retn"};
var allocatedMemory = process.MemoryManager.AllocateMemory(1000);
bool injected = process.Yasm.Inject(mnemonics, allocatedMemory.Pointer);
Note : Yasm will automatically change absolute address to relative one using the allocated memory pointer.
var mnemonics = new[] {"mov eax, 123", "retn"};
var result = process.Yasm.InjectAndExecute(mnemonics);
// result = 123
Note : InjectAndExecute will return the value contained in EAX/RAX at the end of the call automatically.