有時需要開發「查看密碼」工具,讀取其他程式密碼方塊(或任何文字方塊)的真實內容。C# 雖屬管理式語言,但透過 P/Invoke 呼叫 Windows API,即可跨進程讀取視窗文字。本文示範完整實作步驟與代碼。
public static class NativeMethods
{
[DllImport("user32.dll")]
public static extern IntPtr WindowFromPoint(POINT lpPoint);
[DllImport("user32.dll")]
public static extern int GetCursorPos(out POINT lpPoint);
[DllImport("kernel32.dll")]
public static extern IntPtr VirtualAllocEx(
IntPtr hProcess, IntPtr lpAddress, int dwSize,
uint flAllocationType, uint flProtect);
[DllImport("user32.dll")]
public static extern IntPtr SendMessage(
IntPtr hWnd, int Msg, IntPtr wParam, IntPtr lParam);
[DllImport("kernel32.dll")]
public static extern int ReadProcessMemory(
IntPtr hProcess, IntPtr lpBaseAddress,
byte[] lpBuffer, int nSize, out int lpNumberOfBytesRead);
}
[StructLayout(LayoutKind.Sequential)]
public struct POINT { public int X; public int Y; }
public static IntPtr GetControlUnderCursor()
{
POINT pt;
NativeMethods.GetCursorPos(out pt);
return NativeMethods.WindowFromPoint(pt);
}
public static string ReadControlText(IntPtr hWnd)
{
const int WM_GETTEXT = 0x000D;
const int MAX_LEN = 256;
// 1. 在目標進程配置記憶體
IntPtr hProcess = Process.GetCurrentProcess().Handle; // 同進程簡化,跨進程需 OpenProcess
IntPtr remotePtr = NativeMethods.VirtualAllocEx(
hProcess, IntPtr.Zero, MAX_LEN, 0x1000, 0x04); // MEM_COMMIT | PAGE_READWRITE
// 2. 發送 WM_GETTEXT 要求控制項將文字複製到遠端記憶體
NativeMethods.SendMessage(hWnd, WM_GETTEXT, new IntPtr(MAX_LEN), remotePtr);
// 3. 讀取遠端記憶體到本地陣列
byte[] buffer = new byte[MAX_LEN];
int bytesRead;
NativeMethods.ReadProcessMemory(hProcess, remotePtr, buffer, MAX_LEN, out bytesRead);
// 4. 釋放遠端記憶體 (略,實際應呼叫 VirtualFreeEx)
return Encoding.Default.GetString(buffer, 0, bytesRead).TrimEnd('\0');
}
protected override void WndProc(ref Message m)
{
const int WM_HOTKEY = 0x0312;
if (m.Msg == WM_HOTKEY && m.WParam.ToInt32() == 1001)
{
OnHotKeyV();
}
base.WndProc(ref m);
}
private void RegisterHotKey()
{
// 在 Form Load 中註冊
RegisterHotKey(this.Handle, 1001, KeyModifiers.Windows, Keys.V);
}
private void OnHotKeyV()
{
IntPtr hWnd = GetControlUnderCursor();
string text = ReadControlText(hWnd);
MessageBox.Show($"控制項文字:{text}");
}
| 步驟 | API | 說明 |
|---|---|---|
| 定位控制項 | GetCursorPos + WindowFromPoint | 取得滑鼠座標下的視窗句柄 |
| 配置跨進程記憶體 | VirtualAllocEx | 在目標進程位址空間保留緩衝區 |
| 請求文字 | SendMessage(WM_GETTEXT) | 控制項將文字複製到指定位址 |
| 讀回資料 | ReadProcessMemory | 將遠端記憶體複製到本地陣列 |
OpenProcess(PROCESS_VM_READ | PROCESS_VM_OPERATION),目標進程若以管理員權限執行,本程式亦需提權。WM_GETTEXT 依視窗建立時的字元集決定回傳編碼,建議搭配 WM_GETTEXTLENGTH 先取得長度。透過 P/Invoke 組合 VirtualAllocEx、SendMessage、ReadProcessMemory,C# 即可實作跨進程文字讀取工具。搭配全域熱鍵,可做成實用的「密碼顯示器」或自動化測試輔助程式。