【发布时间】:2016-01-21 03:11:51
【问题描述】:
我正在尝试在外部进程中调用 win api 函数。
基本纲要:
- 从 putty.exe(或任何 32 位 proc)获取 user32.dll 的基地址
- 从user32.dll中获取MessageBoxA的基地址
- 用数据填充 MessageBoxA 结构,并在本地分配数据。
- 在腻子中分配结构
- 将结构写入腻子。
- CreateRemoteThread 以执行 messageboxA。
所有 WinAPI 调用都成功,不会抛出错误,putty 进程也不会崩溃。根本不显示消息框。
非常感谢任何帮助。
谢谢!
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;
}
}
}
【问题讨论】:
-
struct MessageBoxA没有意义。 -
您不执行错误检查,因此您不知道函数调用是否成功。请在提问前更正。除此之外,
MessageBoxA的线程进程签名错误。你的方法注定要失败。它永远不会起作用。 -
@DavidHeffernan 结构的正确签名是什么?
-
线程过程不是结构。这是一个程序。
CreateRemoteThread的文档中清楚地描述了它的签名。你仔细阅读了吗?为什么不检查错误? -
我在每次使用 Marshal.GetLastWin32Error() 调用 win api 后检查了错误,但没有发现任何错误。 @大卫赫弗南