I'm trying to call a win api function in an external process.
Basic rundown:
- Get base address of user32.dll from putty.exe (or any 32 bit proc)
- Get base address of MessageBoxA from user32.dll
- Populate MessageBoxA struct with data, and allocate data locally.
- Allocate struct in putty
- Write struct to putty.
- CreateRemoteThread to execute messageboxA.
All WinAPI calls succeed, and no error is thrown, nor does the putty process crash. Simply does not show messagebox.
Any help is greatly appreciated.
Thanks!
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
namespace remote_api_call
{
class Program
{
#region API
[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
public static extern IntPtr GetModuleHandle(string lpModuleName);
[DllImport("kernel32", CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)]
static extern IntPtr GetProcAddress(IntPtr hModule, string procName);
[DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)]
static extern IntPtr VirtualAllocEx(IntPtr hProcess, IntPtr lpAddress,
uint dwSize, uint flAllocationType, uint flProtect);
[DllImport("kernel32.dll", SetLastError = true)]
static extern bool WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, byte[] lpBuffer, uint nSize, out UIntPtr lpNumberOfBytesWritten);
[DllImport("kernel32.dll")]
static extern IntPtr CreateRemoteThread(IntPtr hProcess,
IntPtr lpThreadAttributes, uint dwStackSize, IntPtr lpStartAddress, IntPtr lpParameter, uint dwCreationFlags, IntPtr lpThreadId);
#endregion
[DllImport("kernel32.dll", SetLastError = true)]
static extern bool WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, IntPtr lpBuffer, uint nSize, out UIntPtr lpNumberOfBytesWritten);
// privileges
const int PROCESS_CREATE_THREAD = 0x0002;
const int PROCESS_QUERY_INFORMATION = 0x0400;
const int PROCESS_VM_OPERATION = 0x0008;
const int PROCESS_VM_WRITE = 0x0020;
const int PROCESS_VM_READ = 0x0010;
// used for memory allocation
const uint MEM_COMMIT = 0x00001000;
const uint MEM_RESERVE = 0x00002000;
const uint PAGE_READWRITE = 4;
[StructLayout(LayoutKind.Sequential)]
struct MessageBoxA
{
public IntPtr HWND;
[MarshalAs(UnmanagedType.LPStr)]
public string lpText;
[MarshalAs(UnmanagedType.LPStr)]
public string lpCaption;
[MarshalAs(UnmanagedType.U4)]
public uint type;
}
[DllImport("kernel32.dll")]
public static extern IntPtr OpenProcess(int dwDesiredAccess, bool bInheritHandle, int dwProcessId);
static void Main(string[] args)
{
Process putty = Process.GetProcessesByName("putty")[0];
IntPtr user32Calc = ModuleAddr(calc, "user32.dll");
Console.WriteLine("User32.dll addr from putty.exe: " + user32Calc.ToInt32());
IntPtr MessageBoxA = GetProcAddress(user32Calc, "MessageBoxA");
Console.WriteLine("MessageBoxA addr from putty.exe: " + MessageBoxA.ToInt32());
IntPtr procHandle = OpenProcess(PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION | PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_VM_READ, false, putty.Id);
MessageBoxA rtp = new MessageBoxA();
rtp.HWND = IntPtr.Zero;
rtp.lpText = "Hey mate!";
rtp.lpCaption = "Caption";
rtp.type = 16;
UIntPtr bytesWritten;
// allocate mem locally
IntPtr iptrtoparams = Marshal.AllocHGlobal(Marshal.SizeOf(rtp));
// copy data to structure
Marshal.StructureToPtr(rtp, iptrtoparams, false);
// allocate mem in other process for params
IntPtr allocMemAddress = VirtualAllocEx(procHandle, IntPtr.Zero, (uint)Marshal.SizeOf(rtp), MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
if (allocMemAddress != IntPtr.Zero)
Console.WriteLine("allocmem success");
if (WriteProcessMemory(procHandle, allocMemAddress, iptrtoparams, (uint)Marshal.SizeOf(rtp), out bytesWritten))
Console.WriteLine("wpm success");
// Marshal.FreeHGlobal(iptrtoparams);
if (CreateRemoteThread(procHandle, IntPtr.Zero, 0, MessageBoxA, allocMemAddress, 0, IntPtr.Zero) != IntPtr.Zero)
Console.WriteLine("CreateRemoteThread success");
Console.Read();
}
private static IntPtr ModuleAddr(Process p, string moduleName)
{
foreach (ProcessModule pMod in p.Modules)
{
if (pMod.ModuleName.ToLower() == moduleName.ToLower())
return pMod.BaseAddress;
}
return IntPtr.Zero;
}
}
}