【问题标题】:How to Recognize that an Application Intends to Execute \ Run a File?如何识别应用程序打算执行\运行文件?
【发布时间】:2010-08-15 22:17:15
【问题描述】:

当应用程序将要执行或运行文件时,我需要识别并触发事件。我知道我可以通过挂钩 windows 程序来做到这一点,但我不知道 windows 的哪些程序或事件会触发。 例如,当一个自动运行文件要执行时,我的应用程序应该能够识别它,就像防病毒应用程序一样。

我不确定挂钩是否对我的目的有用,如果解决方案不能挂钩,请给我一个真正的解决方案。

【问题讨论】:

    标签: windows delphi winapi hook


    【解决方案1】:

    尝试使用PsSetCreateProcessNotifyRoutine,此函数将驱动程序提供的回调例程添加到或从例程列表中删除,以便在创建或删除进程时调用。

    你可以在这个用 c++ 编写的链接中找到一个非常好的示例

    Detecting Windows NT/2K process execution

    更新

    另一个选项是使用 WMI 事件,检查 Win32_Process 类、ExecNotificationQuery 方法和 SWbemEventSource.NextEvent 函数。

    检查这个在 delphi 7 和 Windows 7 中测试的示例,你必须从 Delphi IDE 外部运行这个应用程序或禁用 EOleException 异常的异常通知(检查这个link),以避免EOleException 至极被 IDE 拦截。

    program GetWMI_InstanceCreationEvent;
    
    {$APPTYPE CONSOLE}
    
    uses
      SysUtils
      ,Windows
      ,ComObj
      ,ActiveX
      ,Variants;
    
    
    Function KeyPressed:boolean; //detect if an key is pressed
    var
    NumEvents   : DWORD;
    ir          : _INPUT_RECORD;
    bufcount    : DWORD;
    StdIn       : THandle;
    begin
    Result:=false;
    StdIn := GetStdHandle(STD_INPUT_HANDLE);
    NumEvents:=0;
    GetNumberOfConsoleInputEvents(StdIn,NumEvents);
        if NumEvents<> 0 then
        begin
            PeekConsoleInput(StdIn,ir,1,bufcount);
            if bufcount <> 0 then
            begin
                if ir.EventType = KEY_EVENT then
                begin
                  if ir.Event.KeyEvent.bKeyDown then
                  result:=true
                  else
                  FlushConsoleInputBuffer(StdIn);
                end
                else
                FlushConsoleInputBuffer(StdIn);
            end;
        end;
    end;
    
    
    function VarStrNUll(VarStr:OleVariant):string;//dummy function to handle null variants
    begin
      Result:='';
      if not VarIsNull(VarStr) then
      Result:=VarToStr(VarStr);
    end;
    
    function GetWMIObject(const objectName: String): IDispatch; //create a wmi object instance
    var
      chEaten: Integer;
      BindCtx: IBindCtx;
      Moniker: IMoniker;
    begin
      OleCheck(CreateBindCtx(0, bindCtx));
      OleCheck(MkParseDisplayName(BindCtx, StringToOleStr(objectName), chEaten, Moniker));
      OleCheck(Moniker.BindToObject(BindCtx, nil, IDispatch, Result));
    end;
    
    Procedure  GetWin32_InstanceCreationEvent;
    var
      objWMIService              : OLEVariant;
      colMonitoredProcesses      : OLEVariant;
      objLatestProcess           : OLEVariant;
    begin
      objWMIService := GetWMIObject('winmgmts:\\localhost\root\cimv2');
      colMonitoredProcesses      := objWMIService.ExecNotificationQuery('Select * From __InstanceCreationEvent Within 1 Where TargetInstance ISA ''Win32_Process'''); //Get the event listener
      while not KeyPressed do
      begin
        try
         objLatestProcess := colMonitoredProcesses.NextEvent(100);//set the max time to wait (ms)
        except
         on E:EOleException do
         if EOleException(E).ErrorCode=HRESULT($80043001) then //Check for the timeout error wbemErrTimedOut 0x80043001
         objLatestProcess:=Null
         else
         raise;
        end;
    
        if not VarIsNull(objLatestProcess) then
        begin
          Writeln('Process Started '+VarStrNUll(objLatestProcess.TargetInstance.Name));
          Writeln('CommandLine     '+VarStrNUll(objLatestProcess.TargetInstance.CommandLine));
          Writeln('PID             '+VarStrNUll(objLatestProcess.TargetInstance.ProcessID));
        end;
      end;
    end;
    
    
    
    begin
     try    
        CoInitialize(nil);
        try
          Writeln('Press Any key to exit');
          GetWin32_InstanceCreationEvent;
        finally
        CoUninitialize;
        end;
    
     except
        on E:Exception do
        Begin
            Writeln(E.Classname, ': ', E.Message);
            Readln;
        End;
      end;
    end.
    

    【讨论】:

    • 非常感谢 PRUZ 它非常有用,但是有一个问题!当自动运行文件 (Autorun.inf) 试图执行命令或运行文件时,我们可以获得进程执行地址,但我怎样才能获得自动运行文件地址?换句话说,我想获取进程的地址和执行进程的对象……非常感谢……
    • @Mahmood_N,检查此链接msdn.microsoft.com/en-us/library/aa394372%28VS.85%29.aspx 以查看您可以使用的所有属性,ParentProcessId 返回父进程的 PID。当您获得 pid 时,您可以使用 Windows API 或 WMI 本身检索任何信息。
    猜你喜欢
    • 1970-01-01
    • 2013-05-02
    • 2020-02-22
    • 2020-07-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多