Hey,
This code show the param used when the target program use WriteProcessMemory.
Create an new Console project, add BlackMagic in your reference.
Code:
Code:
internal class Program
{
private static readonly BlackMagic Memory = new BlackMagic();
[DllImport("kernel32", CharSet = CharSet.Ansi)]
public static extern int GetProcAddress(int hwnd, string procedureName);
[DllImport("kernel32")]
public static extern int LoadLibrary(string librayName);
[StructLayout(LayoutKind.Explicit, Size = 0x14)]
private struct WriteProcessMemoryDump
{
[FieldOffset(0x0)]
public uint hProcess;
[FieldOffset(0x4)]
public uint lpBaseAddress;
[FieldOffset(0x8)]
public uint lpBuffer;
[FieldOffset(0xC)]
public uint nSize;
[FieldOffset(0x10)]
public uint lpNumberOfBytesWritten;
}
private static void Main(string[] args)
{
Console.WriteLine("By RivaL");
Console.WriteLine("What is the process name (without .exe)?");
string processName = Console.ReadLine();
if (Process.GetProcessesByName(processName).Count() <= 0)
{
Console.WriteLine("Process " + processName + " not found.");
Console.ReadKey();
return;
}
Memory.OpenProcessAndThread(Process.GetProcessesByName(processName)[0].Id);
var baseAddressWriteProcessMemory = (uint) GetProcAddress(LoadLibrary("Kernel32"), "WriteProcessMemory");
uint codeCaveHook = Memory.AllocateMemory(0x2000);
uint codeCaveDump = Memory.AllocateMemory(0x10000000);
Memory.WriteUInt(codeCaveDump, codeCaveDump + 0x4);
Memory.Asm.Clear();
Memory.Asm.AddLine("mov edi, edi");
Memory.Asm.AddLine("push ebp");
Memory.Asm.AddLine("mov ebp, esp");
Memory.Asm.AddLine("pushfd");
Memory.Asm.AddLine("pushad");
// Write hProcess
Memory.Asm.AddLine("mov eax, [ebp+8]"); // hProcess to eax
Memory.Asm.AddLine("mov edi, [" + (codeCaveDump) + "]");
Memory.Asm.AddLine("mov [edi], eax");
// Write lpBaseAddress
Memory.Asm.AddLine("mov eax, [ebp+12]"); // lpBaseAddress to eax
Memory.Asm.AddLine("mov edi, [" + (codeCaveDump) + "]");
Memory.Asm.AddLine("add edi, 4");
Memory.Asm.AddLine("mov [edi], eax");
// Write lpBuffer
Memory.Asm.AddLine("mov eax, [ebp+16]"); // lpBuffer to eax
Memory.Asm.AddLine("mov edi, [" + (codeCaveDump) + "]");
Memory.Asm.AddLine("add edi, 8");
Memory.Asm.AddLine("mov [edi], eax");
// Write nSize
Memory.Asm.AddLine("mov eax, [ebp+20]"); // nSize to eax
Memory.Asm.AddLine("mov edi, [" + (codeCaveDump) + "]");
Memory.Asm.AddLine("add edi, 12");
Memory.Asm.AddLine("mov [edi], eax");
// Write lpNumberOfBytesWritten
Memory.Asm.AddLine("mov eax, [ebp+24]"); // lpNumberOfBytesWritten to eax
Memory.Asm.AddLine("mov edi, [" + (codeCaveDump) + "]");
Memory.Asm.AddLine("add edi, 16");
Memory.Asm.AddLine("mov [edi], eax");
// Write new base address of dump
Memory.Asm.AddLine("mov edi, [" + (codeCaveDump) + "]");
Memory.Asm.AddLine("add edi, " + Marshal.SizeOf(typeof(WriteProcessMemoryDump)));
Memory.Asm.AddLine("mov [" + (codeCaveDump) + "], edi");
Memory.Asm.AddLine("popad");
Memory.Asm.AddLine("popfd");
Memory.Asm.AddLine("jmp " + (baseAddressWriteProcessMemory + 0x5));
Memory.Asm.Inject(codeCaveHook);
Memory.Asm.Clear();
// Jump to the Hook
Memory.Asm.AddLine("jmp " + codeCaveHook);
Memory.Asm.Inject(baseAddressWriteProcessMemory);
Console.WriteLine("WriteProcessMemory Hooked.");
Console.WriteLine("Dump List:");
// First address dump
uint addressCurrent = codeCaveDump + 0x4;
while (true)
{
if (Memory.ReadUInt(codeCaveDump) >= addressCurrent + Marshal.SizeOf(typeof(WriteProcessMemoryDump)))
{
// Read result
var dump = (WriteProcessMemoryDump)Memory.ReadObject(addressCurrent, typeof(WriteProcessMemoryDump));
// Write result:
Console.WriteLine("hProcess = 0x" + dump.hProcess.ToString("X") +
" - lpBaseAddress = 0x" + dump.lpBaseAddress.ToString("X") +
" - lpBuffer = 0x" + dump.lpBuffer.ToString("X") +
" - nSize = 0x" + dump.nSize.ToString("X") +
" - lpNumberOfBytesWritten = 0x" + dump.lpNumberOfBytesWritten.ToString("X")
);
Console.WriteLine("");
// New base address of the dump codecave
addressCurrent = addressCurrent + (uint)Marshal.SizeOf(typeof(WriteProcessMemoryDump));
}
}
}
}