程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 更多編程語言 >> Delphi >> 用hook實現dll注入詳解

用hook實現dll注入詳解

編輯:Delphi

  需要一個用來注入的dll(inject.dll)及一個調用程序(caller.exe)
  流程:
   
  caller.exe
  procedure TestHook;
  var pwnd,hChild, hwndInject :hwnd;
      msg:tmsg;
  begin
     //通過窗口標題用FindWindow找到要注入的程序的主窗口句柄pwnd
     pwnd := findwindow('Progman',nil);
     //用FindwindowEx(hMain,0,nil,nil)找到要處理的子窗口句柄hChild
     hChild := findWindowEx(pwnd,0,nil,nil);
     //用getwindowThreadProcessid(hChild,nil)找到要注入的線程
     dwThreadID := getwindowThreadProcessid(hChild,nil);
     //調用 inject.dll的SetInjectHook方法
     SetInjectHook(dwThreadID);
     //等待消息返回
     getmessage(msg,0,0,0);
     //找到注入的窗口
     hwndInject:= findwindow(nil,'InjectForm');
     //發送控制消息,將目標窗體的句柄作為wparam,控制參數以lparam傳入
     sendMessage( hwndInject, wm_app,hChild,integer(true));
     //關閉注入的窗口
     sendMessage( hwndInject,wm_close,0,0);
     //等待窗口關閉
     sleep(500);
     //檢查是否成功關閉
     assert(not iswindow( hwndInject));
     //去掉掛鉤
     setDipsHook(0);
  end;  

  //下面說明 Inject.dll的SetInjectHook的具體操作
  在全局定義以下變量
   var
     g_hhook :Hhook=0;
     g_dwThreadidInject :dWord=0;
     g_hInjectfrm:hwnd;

  
  function SetInjectHook(dwThreadid:DWord):boolean;
  begin
    result := false;
    //如果線程標志為0則用於去掉鉤子,否則進行動態庫注入
    if dwThreadid<>0 then
    begin
      assert(g_hhook=0);
      //保存當前線程的ID到 g_dwThreadidInject
      g_dwThreadidInject := getCurrentThreadid;
      //下一個GetMessage的鉤子到目標線程
      //GetMsgProc是在下面定義的一個函數,在第一次調用時將自定義的form在目標線程中創建出來
      //這樣就能通過這個自定義的form對目標線程進行進程內控制了
      g_hhook := setWindowsHookEx(wh_getMessage,GetMsgProc,hInstance,dwThreadid);
      result := g_hhook <> null;
      if result then
        //發一個空的信息以便於立即創建這個自定義form
        result := postThreadMessage(dwThreadid, wm_Null,0,0);
      //等待半秒鐘,以保證調用者可以找到這個剛創建的form
      sleep(500);
    end else
    begin
      assert(g_hhook<>0);
      //去掉鉤子
      result := unHookWindowsHookEx(g_hhook);
      g_Hhook := 0;
    end;
  end;

  //定義一個全局的是否第一個消息的標志
  var
    fFirstTime:boolean = true;
  //這個函數用於在收到第一個消息時創建自定義窗體,以便於遠程控制
  function GetMsgProc(code: Integer; wparam: WPARAM; lparam: LPARAM): LRESULT; stdcall;
  begin
    //如果是第一次
    if fFirstTime then
    begin
      fFirstTime := false;
      //創建窗體
      InjectFrm := TinjectFrm.create(nil);
      //保存窗體句柄
      g_hInjectfrm := InjectFrm.handle;
    end;
    //調用默認處理,這一句可不能忘記
    result := callNexthookEx(g_hhook,code,wparam,lparam);
  end;

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved