首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> VC >> 關於VC++

VC++ 密碼編輯框防竊取:原理剖析與自訂控件實戰

     編輯:關於VC++

前言:為什麼 ES_PASSWORD 不夠安全?

Windows 編輯控件設定 ES_PASSWORD 樣式後,螢幕顯示為星號,但記憶體中仍保存明文。任何進程若取得該視窗控制代碼(HWND),即可透過 WM_GETTEXT 或 EM_GETLINE 直接讀取密碼。這是眾多「顯密碼」工具的核心原理。

攻擊向量還原

  1. 滑鼠掃描取得目標視窗座標 → WindowFromPoint() 獲取 HWND
  2. GetClassName() 確認為 EDIT 類別
  3. GetWindowLong(GWL_STYLE) 驗證 ES_PASSWORD 位元
  4. SendMessage(hwnd, WM_GETTEXT, ...) 讀取明文

全程無身分驗證,任何進程皆可為之。

防禦策略:訊息級身分驗證

核心思路:在 DefWindowProc 中攔截敏感訊息,僅允許自家進程合法呼叫。

步驟 1:建立衍生類別

class CPasswordEdit : public CEdit {
    DECLARE_DYNAMIC(CPasswordEdit)
public:
    static BOOL g_bSenderIdentity; // 全域身分旗標
protected:
    virtual LRESULT DefWindowProc(UINT msg, WPARAM wp, LPARAM lp);
};
BOOL CPasswordEdit::g_bSenderIdentity = FALSE;

步驟 2:攔截與驗證

LRESULT CPasswordEdit::DefWindowProc(UINT msg, WPARAM wp, LPARAM lp) {
    if (msg == WM_GETTEXT || msg == EM_GETLINE) {
        if (!g_bSenderIdentity) {
            AfxMessageBox(_T("偵測到非法讀取密碼嘗試!"));
            return 0; // 拒絕服務
        }
        g_bSenderIdentity = FALSE; // 一次性授權
    }
    return CEdit::DefWindowProc(msg, wp, lp);
}

步驟 3:對話方塊整合

// 成員變數
CPasswordEdit m_edtPassword;

// OnInitDialog 子類化
m_edtPassword.SubclassDlgItem(IDC_EDIT_PASSWORD, this);

// DoDataExchange 僅在合法取值時置旗
void CDlgInput::DoDataExchange(CDataExchange* pDX) {
    if (pDX->m_bSaveAndValidate) // UpdateData(TRUE) 時
        CPasswordEdit::g_bSenderIdentity = TRUE;
    CDialog::DoDataExchange(pDX);
    DDX_Text(pDX, IDC_EDIT_PASSWORD, m_sPassword);
}

進階話題:繞過自訂視窗程序的對抗

若惡意程式同樣子類化並過濾 WM_GETTEXT,防禦方可動態替換視窗程序:

// 建立標準 EDIT 取得原始 WndProc
HWND hTmp = CreateWindow(_T("EDIT"), NULL, WS_CHILD|ES_PASSWORD, 
    0,0,0,0, GetParent(hTarget), (HMENU)123, 
    (HINSTANCE)GetWindowLong(hTarget, GWL_HINSTANCE), NULL);
LONG_PTR pStdProc = GetWindowLongPtr(hTmp, GWLP_WNDPROC);
DestroyWindow(hTmp);

// 熱換目標視窗程序
LONG_PTR pOld = SetWindowLongPtr(hTarget, GWLP_WNDPROC, pStdProc);
SendMessage(hTarget, WM_GETTEXT, size, (LPARAM)buf); // 讀取成功
SetWindowLongPtr(hTarget, GWLP_WNDPROC, pOld); // 還原

此技術屬「核武級」對抗,僅在遭遇主動反偷窺時啟用,平時保持輕量。

跨語言部署建議

  • VB/Delphi:打包上述邏輯為 ActiveX 控件(OCX)供拖放使用
  • .NET:參考相同原理撰寫 TextBox 衍生類,重寫 WndProc

結語

密碼編輯框防護的本質是「訊息來源驗證」。透過 MFC 子類化與全域旗標配合 DDX 機制,可在幾十行程式碼內構建有效防線。面對進階對抗,動態視窗程序替換提供最後防禦手段。

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