首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

SendMessage WM_SETTEXT 修改他程序灰色 EditBox 失敗?消息攔截與權限隔離分析

     編輯:程式設計綜合問答

用 SendMessage(hwnd, WM_SETTEXT, 0, (LPARAM)str) 修改他程序灰色(禁用)EditBox,內容被清空但新文本未寫入。自寫程序同樣操作卻成功。這涉及UIPI(用戶界面權限隔離)、控制項子類化攔截、只讀/禁用狀態處理差異。

現象分析

  • 目標 EditBox:灰色(WS_DISABLED 或 ES_READONLY)
  • SendMessage(WM_SETTEXT) → 原文本清空,新文本未顯示
  • 自寫程序同樣灰色 EditBox → 成功

核心原因排查

1. UIPI(User Interface Privilege Isolation)

  • Vista+ 系統:低完整性進程不能向高完整性進程發送大多數消息
  • 若目標程序以「管理員身份運行」,而你的程序普通權限 → SendMessage 被攔截/過濾
  • 驗證:雙方以相同權限運行測試

2. 目標程序子類化攔截 WM_SETTEXT

  • 某些安全軟體、加密鍵盤、輸入法保護會 SetWindowSubclass 或 SetWindowLong(GWL_WNDPROC) 掛鉤
  • 攔截 WM_SETTEXT、WM_CHAR、EM_REPLACESEL 等消息
  • 表現:DefWindowProc 未被調用,或調用前清空內容、調用後恢復

3. 禁用/只讀狀態下的內部邏輯

  • 標準 Edit 控制項:ES_READONLY 仍接受 WM_SETTEXT;WS_DISABLED 也接受
  • 但自繪/子類化控制項可能在 WM_SETTEXT 中判斷狀態拒絕更新
  • 自寫程序用標準 Edit,目標程序可能用自定義控制項

調試與繞過方案

方案一:啟用控制項再設置


EnableWindow(hEdit, TRUE);
SendMessage(hEdit, WM_SETTEXT, 0, (LPARAM)newText);
EnableWindow(hEdit, FALSE);

若目標程序在 WM_ENABLE 中重繪,可能閃爍但通常有效。

方案二:模擬鍵盤輸入(繞過 WM_SETTEXT)


// 先全選
SendMessage(hEdit, EM_SETSEL, 0, -1);
// 發送每個字符
for (int i = 0; newText[i]; i++) {
    PostMessage(hEdit, WM_CHAR, newText[i], 0);
}

或用 SendInput / keybd_event 全域模擬(需前台焦點)。

方案三:內存寫入(終極方案,需調試器權限)

  1. OpenProcess(PROCESS_VM_WRITE | PROCESS_VM_OPERATION, FALSE, pid)
  2. VirtualQueryEx 定位 Edit 控制項內存緩衝區
  3. WriteProcessMemory 直接寫入字串
  4. 發送 WM_PAINT / InvalidateRect 觸發重繪

風險:極不穩定,目標程序更新即失效,可能觸發反作弊/防篡改。

方案四:Spy++ / API Monitor 追蹤消息流

  1. 用 Spy++ 監控目標 EditBox 消息
  2. 發送 WM_SETTEXT 觀察:是否到達?是否被 DefWindowProc 處理?返回值?
  3. 用 API Monitor 監控 SetWindowText、SendMessage 調用堆疊

代碼級調試技巧


// 發送前獲取窗口信息
TCHAR className[256];
GetClassName(hEdit, className, 256); // 確認是否 "Edit" 或自定義類
LONG style = GetWindowLong(hEdit, GWL_STYLE);
BOOL enabled = IsWindowEnabled(hEdit);
BOOL readonly = (style & ES_READONLY);
TRACE(_T("Class: %s, Style: 0x%X, Enabled: %d, ReadOnly: %d\n"), className, style, enabled, readonly);

// 發送後檢查返回值
LRESULT lr = SendMessage(hEdit, WM_SETTEXT, 0, (LPARAM)newText);
TRACE(_T("WM_SETTEXT returned: %d\n", lr));
DWORD err = GetLastError();
if (err) TRACE(_T("LastError: %d\n", err));

總結

灰色 EditBox WM_SETTEXT 失敗,優先檢查 UIPI 權限隔離(以同權限運行)、目標程序子類化攔截(Spy++ 追蹤)、自定義控制項邏輯。繞過方案依序:EnableWindow 切換 → 模擬 WM_CHAR → 內存寫入(最後手段)。切記:操作他程序 UI 屬灰色地帶,穩定性無保障,盡量尋找官方 API/自動化接口替代。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved