1 目的:
获得系统中打开的程序。所以我这里选择HCBT_ACTIVATE来判断。
2 将要处理的信息 我用log方式写入到本地文件
3 代码:(Google 浏览器居然没有高亮代码的工具栏)
{Dll加载时调用}
{因为在主程序中有对该DLL引用,故应该先执行}procedure OnDllProcessAttach;
var
  title: array[0..255] of Char;
  M1: TMemoryStream;
begin
  if GetModuleFileName(0, title, 256) <> 0 then //获得加载Dll的程序进程名
  begin
    CreateGameShareData; //创建共享数据块    ProcessName := ExtractFileName(title);
  {$IFDEF Dll_log}
    logFileName := 'c:\log\' + ProcessName + '.log';
    logFile('1:dll is in the process:' + ProcessName);
  {$ENDIF}
    IsMainProc := (CompareText('TestRunCapture.exe', ProcessName) = 0) or
      (CompareText('YOYO.exe', ProcessName) = 0);    IsSpecialProcess := IsInterSpecialProc; //是否是特殊进程    if IsSpecialProcess then
    {$IFDEF Dll_log}
      logFile('2:' + ProcessName + ' is a special process')
    {$ENDIF}
    else
    if IsMainProc then //如果是宿主程序,则将共享数据初始化
    begin
    {$IFDEF Dll_log}
      logFile('2:' + ProcessName + ' is a main process');
    {$ENDIF}      
    end
    else
    begin
    {$IFDEF Dll_log}
      logFile('2:' + ProcessName + ' is a other process');
    {$ENDIF}
      M1 := TMemoryStream.Create;
      M1.Position := 0;
      M1.Write(GameShareData^.Buf[0], GameShareData^.BufSize);
      M1.Position := 0;
      M1.ReadComponent(Lib);
      M1.Free;
    end;
  end
  else
  begin
    IsMainProc := False;
    IsSpecialProcess := False;
    CurGameID := 0;
    HaveCheck := True;
  end;
end;procedure OnDllProcessDetach;
begin
{$IFDEF Dll_log}
  logFile('100:dll detach');
{$ENDIF}
  if MapHandle <> 0 then //关闭共享内存块
  begin
    UnmapViewOfFile(GameShareData);
    CloseHandle(mapHandle);
    mapHandle := 0;
  end;
end;回调函数:
function HookCbtProc(nCode: integer; wParam: WPARAM; lParam: LPARAM): HRESULT; stdcall;
var
  title: array[0..256] of Char;
  WndCaption, WndClassName: string;
label 1;
begin
  Result := 0;
  if nCode < 0 then
    goto 1;
  case nCode of
    HCBT_ACTIVATE:
      begin
      {$IFDEF Dll_log}
        logFile('3:Get CBT_Active,wParam' + IntToStr(wParam));
      {$ENDIF}
        if HaveCheck then goto 1;
        if IsSpecialProcess or IsMainProc then goto 1;
      {$IFDEF Dll_log}
        logFile('4:进程没有被过滤掉');
        logFile('5:process name is ' + ProcessName);
      {$ENDIF}
        if Lib.IsSpecialNode(ProcessName) then //说明为特殊进程,下面不进行
          IsSpecialProcess := True
        else //
        begin
        {$IFDEF Dll_log}
          logFile('6:start Judging Process');
        {$ENDIF}
          FillChar(title, 257, 0);
          GetWindowText(wParam, title, 257);          WndCaption := title;
          FillChar(title, 257, 0);
          GetClassName(wParam, title, 257);
          WndClassName := title;
        {$IFDEF Dll_log}
          logFile(Format('7:ProcessName:%S,Caption:%S,ClassName:%S', [ProcessName, WndCaption, WndClassName]));
        {$ENDIF}
          Node := Lib.FindGameDef(ProcessName, WndCaption, WndClassName);
          if Node <> nil then
          begin
            CurGameID := Node.GameID;
            HaveCheck := True;
            TopHandle := wParam;
            GameShareData^.GameHwnd := TopHandle;
          {$IFDEF Dll_log}
            logFile('8:' + ProcessName + ' is a game ,now send msg to main Process。TopHandle:' + IntToStr(TopHandle));
          {$ENDIF}            
            SendMessage(GameShareData^.AppHandle, WM_CBT_CREATEWND, Node.GameID, wParam); //这个时候wParam为HWND
          end;
        end;
      end;
    HCBT_DESTROYWND:
      begin
      {$IFDEF Dll_log}
        logFile('a3:Get CBT_DestroyWnd,wParam' + IntToStr(wParam));
      {$ENDIF}        
        if IsSpecialProcess or IsMainProc then goto 1;
        if not Assigned(Node) then
          goto 1;
        if (not IsWindow(wParam))then
          goto 1;
        if Node.GameExitJudge and (Cardinal(wParam) <> GameShareData^.GameHwnd) then
          goto 1;
      {$IFDEF Dll_log}
        logFile(Format('a4:Wparam:%D,TopHandle:%D', [wParam, TopHandle]));
      {$ENDIF}
        if not HaveCheck then goto 1;
        if (CurGameID <> 0) then
        begin
        {$IFDEF Dll_log}
          logFile('a5:Game Process is about to Destroy,notifying Main Process');
        {$ENDIF}
          SendMessage(GameShareData^.AppHandle, WM_CBT_DESTROYWND, CurGameID, wParam);
          CurGameID := 0; //避免发送多次
        end;
      end;
  else ;
  end;
  1:
  Result := CallNextHookEx(CbtHk, nCode, wParam, lParam)
end;4 问题描述:
一般情况下正常,每个程序激活就会在C:\log\进程名.log的文件。
现在问题是 在某些特定的进程,如大话西游,如果我先开程序和钩子,然后大话西游,ok,什么都没有,log不会写,而且后续开的其他所有程序都没有log了,我觉得钩子死掉了。
可能有人觉得 大话西游 卸钩子了。ok,先开大话西游,它运行起来,然后开钩子,激活大话西游,log又出来了 程序一切正常。后续其他程序钩子也注入了。5 问题总结
某些特定的进程在钩子先开的情况下,钩子会失效 但是 钩子后开 运行正常。我在这里想问下 大家 觉得 是什么原因?
调试dll都有些什么方法。。