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

Delphi 實作 Shell 執行鉤子:攔截記錄系統外殼操作完整指南

     編輯:Delphi

原理:IShellExecuteHook 介面

實作 IShellExecuteHook 的進程內 COM 物件,註冊至系統後,可攔截所有 ShellExecute/ShellExecuteEx 呼叫。Windows 98/2000 原生支援,95/NT4 需安裝 IE 4.01+ (Active Desktop)。

呼叫流程與攔截點

  1. 解析目標可執行檔路徑。
  2. 檢查使用者執行權限 (NT)。
  3. 啟動所有已註冊的 IShellExecuteHook(攔截點)。
  4. 所有擴展同意且權限通過 → 建立進程返回。

資源管理器幾乎所有操作(雙擊開啟、列印、編輯、屬性、右鍵選單、開始→執行)均經由上述 API,故可廣泛監控使用者行為。

COM 物件實作步驟

1. 專案建立

  • File → New → ActiveX Library
  • New → COM Object,類別名 TShellExecuteHook,介面 IShellExecuteHook。

2. 介面宣告 (ShlObj 單元)

type
  TTShellExecuteHook = class(TComObject, IShellExecuteHook)
  protected
    function Execute(var ShellExecuteInfo: TShellExecuteInfo): HResult; stdcall;
  end;

const
  Class_TShellExecuteHook: TGUID = '{935FA400-243D-11D3-B06E-857B2AE2BE64}';

3. 核心 Execute 方法

function TTShellExecuteHook.Execute(var ShellExecuteInfo: TShellExecuteInfo): HResult;
var
  FileName: string;
  fs: TFileStream;
  s: string;
begin
  Result := S_FALSE; // 預設繼續預設任務
  with ShellExecuteInfo do begin
    // 記錄:動作 + 目標檔案 + 時間
    fs := TFileStream.Create('C:\ShellExecuteHook.log', fmOpenWrite or fmShareDenyNone);
    try
      fs.Seek(0, soFromEnd);
      s := Format('%s:%s %s%s', [lpVerb, lpFile, DateTimeToStr(Now), #13#10]);
      fs.Write(PChar(s)^, Length(s));
    finally
      fs.Free;
    end;

    // 範例:禁止記事本執行
    FileName := UpperCase(ExtractFileName(lpFile));
    if Pos('NOTEPAD', FileName) = 1 then begin
      Result := S_OK; // 取消預設執行
      hInstApp := 32; // 模擬錯誤碼
      MessageBox(Wnd, '不允許記事本運行!', '錯誤', MB_OK or MB_ICONERROR);
    end;
  end;
end;

關鍵結構 TShellExecuteInfo 關注欄位

  • lpVerb:操作動詞 (open/print/edit/explore/properties/find 等)
  • lpFile:目標檔案/程式路徑
  • nShow:視窗顯示狀態(可修改)
  • 回傳 S_FALSE 繼續、S_OK 攔截阻止、錯誤碼則彈出系統錯誤訊息。

避坑:勿在 Execute 內呼叫 ShellExecute/Ex

會觸發遞迴攔截導致死循環。需啟動外部程序請用 CreateProcess 或 WinExec。

註冊機制:元件工廠覆寫 UpdateRegistry

type
  TShellExComObjectFactory = class(TComObjectFactory)
  public
    procedure UpdateRegistry(Register: Boolean); override;
  end;

procedure TShellExComObjectFactory.UpdateRegistry(Register: Boolean);
const
  HooksKey = 'SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\ShellExecuteHooks';
var
  hKey: HKEY; Status, Disp: Integer; ClassID: string;
begin
  ClassID := GUIDToString(Class_TShellExecuteHook);
  if Register then begin
    Status := RegCreateKeyEx(HKEY_LOCAL_MACHINE, HooksKey, 0, '', REG_OPTION_NON_VOLATILE,
      KEY_READ or KEY_WRITE, nil, hKey, @Disp);
    if Status = 0 then begin
      RegSetValueEx(hKey, PChar(ClassID), 0, REG_SZ, PChar(Description), Length(Description)+1);
      RegCloseKey(hKey);
    end;
  end else begin
    Status := RegOpenKeyEx(HKEY_LOCAL_MACHINE, HooksKey, 0, KEY_READ or KEY_WRITE, hKey);
    if Status = 0 then begin
      RegDeleteValue(hKey, PChar(ClassID));
      RegCloseKey(hKey);
    end;
  end;
  if Status <> 0 then raise EOleError.Create('建立註冊表項失敗');
  inherited UpdateRegistry(Register);
end;

initialization
  TShellExComObjectFactory.Create(ComServer, TTShellExecuteHook, Class_TShellExecuteHook,
    'TShellExecuteHook', 'ShellExecute Hook Sample', ciMultiInstance, tmApartment);

限制與注意

  • 僅攔截 ShellExecute/Ex,不保證捕獲所有外殼行為(如右鍵→屬性可能走其他路徑)。
  • 多鉤子按安裝順序調用,優先級難控制。
  • 謹慎用於生產環境,確認確切符合需求再部署。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved