青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

旅途

如果想飛得高,就該把地平線忘掉

跨進程API Hook(初稿)


跨進程API Hook(初稿)

什么是“跨進程 API Hook”?
眾所周知Windows應用程序的各種系統功能是通過調用API函數來實現。API Hook就是給系統的API附加上一段小程序,它能監視甚至控制應用程序對API函數的調用。所謂跨進程也就是讓自己的程序來控制別人程序的API調用了。

API Hook 理論
通 過對Win32 PE文件的分析(如果你還不熟悉PE文件格式,可以看看Iczelion的PE教程或者LUEVELSMEYER的<>)。 我們知道在PE文件中的IMPORT TABLE內存儲著API函數的很多信息。其中包括API的函數名,調用地址等等。而操作系統在執行PE文件時會先 將其映射到內存中。在映射的同時還會把當前版本操作系統中API函數的入口地址寫入IMPORT TABLE中一組與API調用相關的結構體內,用于該應 用程序的API調用。 當應用程序調用API時,他會在自己內存映像里尋找API的入口地址,然后執行CALL指令。如此一來,我們通過修改應用程序內存 映像的IMPORT TABLE中API函數的入口地址,就可以達到重定向API的目的。將API地址改為我們自己函數的地址,這樣我們的函數就可以完成 對API的監視和控制了。

API Hook 的實現
/* 1 */HANDLE hCurrent = GetModuleHandle(NULL);
/* 2 */IMAGE_DOS_HEADER *pidh;
/* 3 */IMAGE_NT_HEADERS *pinh;
/* 4 */IMAGE_DATA_DIRECTORY *pSymbolTable;
/* 5 */IMAGE_IMPORT_DESCRIPTOR *piid;
 
/* 6 */pidh = (IMAGE_DOS_HEADER *)hCurrent; 
/* 7 */pinh = (IMAGE_NT_HEADERS *)((DWORD)hCurrent + pidh->e_lfanew);
/* 8 */pSymbolTable = &pinh->OptionalHeader.DataDirectory[1];
/* 9 */piid =(IMAGE_IMPORT_DESCRIPTOR *)((DWORD)hCurrent +  pSymbolTable->VirtualAddress);
/*10 */do {
/*11 */    IMAGE_THUNK_DATA *pitd,*pitd2;
/*12 */    pitd = (IMAGE_THUNK_DATA *)((DWORD)hCurrent + piid->OriginalFirstThunk);
/*13 */    pitd2 = (IMAGE_THUNK_DATA *)((DWORD)hCurrent + piid->FirstThunk);
/*14 */    do {
/*15 */ IMAGE_IMPORT_BY_NAME *piibn;
/*16 */ piibn = (IMAGE_IMPORT_BY_NAME *)((DWORD)hCurrent +  *((DWORD *)pitd));
/*17 */ PROC *ppfn = (PROC *)(pitd2->u1.Function);
/*18 */ if (!strcmp("MessageBoxW",(char *)piibn->Name)) {
/*19 */     oldMsg = (MsgBoxType)(ppfn);
/*20 */     DWORD addr = (DWORD)MyMessage;
/*21 */     DWORD written = 0;
      /* 改變內存讀寫狀態 */
/*22 */     DWORD oldAccess;
/*23 */     VirtualProtect(&pitd2->u1.Function,sizeof(DWORD),PAGE_WRITECOPY,&oldAccess);
/*24 */     APIAddress = (DWORD)&pitd2->u1.Function;
      /* 向內存映像寫入數據 */
/*25 */     WriteProcessMemory(GetCurrentProcess(),&pitd2->u1.Function, &addr,sizeof(DWORD), &written);
/*26 */ }
/*27 */ pitd++;pitd2++;
/*28 */    } while (pitd->u1.Function);
 
/*29 */    piid++;
/*30 */} while (piid->FirstThunk + piid->Characteristics 
  + piid->ForwarderChain + piid->Name + piid->TimeDateStamp);
分析:
尋覓IMPORT TALBE
在/*1*/ 中我們使用GetModuleHandle(NULL)來返回當前進程在內存中映像的基地址。但這個值在文檔中僅僅被描述為 "a module handle for the specified module",雖然他確實是進程內存映像的基地址。如果你不太放心的話也可以 使用,GetModuleInformation函數來獲得基地址,只不過你要額外包含psapi.h和psapi.lib了(這個庫在VC6里沒有,所 以我就沒有用這個函數了)。在/* 6 */里我們先找到IMAGE_DOS_HEADER結構,他的起始地址就是映像的基地址。/*7*/通過 IMAGE_DOS_HEADER給出的PE文件頭的偏移量,找到IMAGE_NT_HEADERS結構。順藤摸瓜,IMAGE_NT_HEADERS里 的OptionalHeader中的DataDirectory數組里的第二個元素正是指向我們想要的IMPORT TABLE的地址。在/*9*/中我們將其轉化為一個IMAGE_IMPORT_DESCRIPTOR的結構指針存入piid中。

替換的API函數入口地址
在/*12*/ 和/*13*/中我們分別取得OriginalFirstThunk和FirstThunk結構,用于以后得到API函數的名稱和入口地址。/*10*/ 的do循環讓我們遍歷每一個IMAGE_IMPORT_DESCRIPTOR結構也就是應用程序引用的每個DLL。在/*14*/的循環中我們遍歷DLL 中的IMAGE_THUNK_DATA結構來一一查詢API的信息。/*16*/中我們將OriginalFirstThunk轉換為 IMAGE_IMPORT_BY_NAME結構用于獲得API函數的名稱進行比對。在/*18*/我們找到MessageBoxW函數之后,在 /*19*/保存其原始入口地址便于以后恢復時使用。在/*23*/我們需要用VirtualProtect改變一下內存區域的讀寫性,因為一般應用程序 的映像都是只讀的,直接寫入會造成一個非法訪問的異常出現。在/*25*/我們寫入自己函數的地址。

這樣就基本完成一個API函數的重定向。

其他
恢復函數的API入口地址相對比較簡單。只要把保存的值再寫回去就可以了。上面的程序中/*24*/我用APIAddress保存了存有MessageBoxW入口地址的地方的地址,便于以后調用WriteProcessMemory恢復時使用。

跨進程理論
我 們要用自己的函數來替代別人程序里的API函數,但我們的函數與別人的程序處于不同的進程空間內啊。不同的進程空間是不能相互調用函數的。因此我們要想辦 法把自己的函數放入別人的進程空間去。這時我們就需要使用DLL injection技術了。如果你對她還不是十分熟悉的話,建議看看 Jeffrey Richter大師的< >,也可以參考陳寬達先生的<>。

簡 而言之,DLL injection就是想辦法讓對方的進程加載我們的一個DLL程序,把需要替換的函數放在我們這個DLL里。如此一來,我們的函數就進 入了別人的進程空間了。DLL injection方法很多,Richter大師在書中對各方法利弊有詳細解釋,陳寬大先生的書中也有深入的分析。我在這 里使用SetWindowsHookEx函數來達到目的。主要有這幾個原因: 1, 不用重新啟動系統,調試方便。2, 可以利用消息循環機制進行兩個進 程之間的通信,可以較好的掌握Hook的狀態。便于安裝與卸載。

SetWindowsHookEx之所以能完成 DLL injection是因為它要給一個應用程序某個環節加上一個Hook,而Hook就要有Hook Procedure也就是Hook函數。如果 這個Hook函數在一個DLL中,那么系統就會把這個DLL加載到SetWindowsHookEx的目標進程上。從而也就達到了我們 DLL injection的目的了。當然這里我們會用WH_GETMESSAGE的Hook進行injection,因為這個Hook可以用來監視目標 進程的消息循環方便我們的進程與目標進程通信。 

跨進程的實現和幾點注意
/* DllPart.Dll */
#include 
#include 
#include 
#include 
typedef (WINAPI *MsgBoxType)(HWND,LPCWSTR,LPCWSTR,UINT); 
MsgBoxType oldMsg;  /*API原入口地址*/
DWORD APIAddress; /*存儲API入口地址的地方的地址*/
int WINAPI  MyMessage(HWND hWnd ,LPCWSTR M1,LPCWSTR M2, UINT M3) {
 /* 這是用來替換的函數 */
 return oldMsg(hWnd,buf,M2,MB_OK);
}
const char szApp[] = "DllPart.dll";
HHOOK hHook; /*Hook的句柄*/
HMODULE hInst; /*DLL 模塊句柄,用于SetWindowsHookEx函數*/
HWND hTarget; /*目標窗口句柄*/
/*DLL 入口*/
BOOL WINAPI DllMain(HINSTANCE inst, DWORD reason, LPVOID lpvReserved)
{
    hInst = inst;
    switch (reason) {
 case DLL_PROCESS_ATTACH:
     /*調試信息,表示DLL已經加載*/
     MessageBox(NULL,"DLL_PROCESS_ATTACH",szApp,MB_OK);
     break;
 case DLL_PROCESS_DETACH:
     /*調試信息,表示DLL已經卸載*/
     MessageBox(NULL,"DLL_PROCESS_DETACH",szApp,MB_OK);
     break;
    }
    return true;
}
/*顯示GetLastError的信息*/
void showerr(const char *m) {
    char message[255];
    FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,0,GetLastError()
 ,MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),message,255, 0);
    MessageBox(NULL,message,m,MB_OK);
}
//-----------------------
void UnHookApi() {
 /*卸載API Hook用*/
}
void HookApi() {
 /*加載API Hook同上面介紹的函數一樣*/
}
//-----------------------
/*用于WH_GETMESSAGE的Hook Procedure*/
LRESULT CALLBACK GetMsgProc(int nCode,WPARAM wParam, LPARAM lParam) {
 if (nCode == HC_ACTION) {
     MSG *msg = (MSG *)lParam;
&n
  if (msg->message == WM_CHAR) {
      if (msg->wParam == 'h') HookApi();
      if (msg->wParam == 'u') UnHookApi();
     }
 }
    return CallNextHookEx(hHook,nCode,wParam,lParam);
}
extern "C" __declspec(dllexport) SetAPIHook(HWND handle) {
    DWORD ThreadId = GetWindowThreadProcessId(handle, NULL);
    hTarget = handle;
    MessageBox(NULL, "Enabling CallWndProc Hook", szApp, MB_OK);
    hHook = SetWindowsHookEx(WH_GETMESSAGE,GetMsgProc,hInst,ThreadId); 
    if (hHook) {
 MessageBox(NULL,"Hook OK!", szApp, MB_OK);
    } else {
 showerr("SetWindowsHookEx");
    }
}
extern "C" __declspec(dllexport) UnHookAPIHook() {
    MessageBox(NULL, "Disenabling CallWndProc Hook", szApp, MB_OK);
    if (UnhookWindowsHookEx(hHook)) {
        MessageBox(NULL,"UnHook OK!", szApp, MB_OK); 
    } else {
 showerr("UnHookWindowsHookEx");
    }
}
分析
幾個需要注意的問題
SetAPIHook 和UnHookAPIHook是我們自己進程調用的用來加載WH_GETMESSAGE Hook的函數。由于我們的程序要用LoadLibrary加載 這個Dll因此這兩個函數要用__declspec(dllexport)修飾,使其成為導出函數,才能被GetAddressProc函數找到。加上  extern "C"是讓編譯器使用C語言編碼方式。因為C++編譯器會進行Dynamic Binding(C++函數重載的實現),將函數的參數類 型附加到名稱上。是函數的導出名看起來像SetAPIHook@XYTZX之類的,不利于GetAddressProc進行引用。因此使用 extern "C"讓編譯器不使用Dynamic Binding,自然使用extern"C"的函數也就不能被重載了。

不要忘記在GetMsgProc最后要調用CallNextHookEx函數,保證Hook鏈的完整性。

一 定要在Hook Procedure中調用HookApi和UnHookApi函數,因為保存API入口地址的地方在目標進程中,你必須在目標進程的進程 空間內完成卸載操作,不能在UnHookAPIHook或是SetAPIHook函數中調用,因為UnHookAPIHook是我們的進程調用的,因此在 我們的進程空間中。在這里使用UnHookApi會造成一個非法訪問的錯誤。而使用HookApi會給自己的DLL加上API Hook。

SetWindowsHookEx的最后參數是ThreadId不是Handle,因此要通過調用GetWindowThreadProcessId轉換一下。 

在跨進程API HOOK時可能用到的其他技術
主進程與目標進程的信息交互和共享
由 于使用了WH_GETMESSAGE鉤子我們可以利用Windows消息機制實現進程間通訊。需要注意的是應該使用PostThreadMessage來 發送讓WH_GETMESSAGE得到的消息而不是SendMessage或者PostMessage,因為后兩個是用來給窗口發送消息的。而我們的 WH_GETMESSAGE是Hook在線程上面的,因此需使用PostThreadMessage.

傳遞不太大的數據可以使用 WM_COPYDATA消息來進行。同樣也應該注意,如果使用MFC的窗口過程獲得消息就需要用SendMessage發送了。WM_COPYDATA的 使用相對簡單可以參考MSDN的文檔。也可以參考附錄里的程序Hook.cpp的showerr函數部分。

如果傳遞較大的數據或者希望數據共享比較方便可以開辟共享內存來進行數據共享。這里簡單分析一下使用共享內存的代碼 

HANDLE hMap;
switch (reason) {
    case DLL_PROCESS_ATTACH:
    /*創建/打開共享內存區域*/
    hMap = CreateFileMapping((HFILE *)0xFFFFFFFF,NULL,PAGE_READWRITE,0,sizeof(GLOBALDATA),ID_MAP);
    pg_data = (GLOBALDATA*)MapViewOfFile(hMap,FILE_MAP_ALL_ACCESS,0 ,0 ,0);
    if (!pg_data) {
 MessageBox(NULL,"無法建立共享內存,程序終止!",szApp,MB_OK);
 if (hMap) {
     CloseHandle(hMap);
     hMap = NULL;
     return 0;
       }
    }
    pg_data->hInst = hInst;
    showerr("共享內存映像文件");
    showerr("DLL裝載中...",FALSE);
    break;
    case DLL_PROCESS_DETACH:
    if (pg_data) {
        UnmapViewOfFile(pg_data);
 pg_data = NULL;
    }
    if (hMap) {
 CloseHandle(hMap);
 hMap = NULL;
     }
    break;
}

上 面的代碼通過CreateFileMapping建立共享區域。將其第一個參數設置為0xFFFFFFFF使其能創建一個內存共享區域而不是文件。并標記 為可讀寫的(PAGE_READWRITE).其大小為我們定義的結構體GLOBALDATA的大小。最后的ID_MAP是一個用來標示這個區域的字符 串。打開或者創建完共享區域后,我們用MapViewOfFile來獲得這個區域的地址。之后就可以直接使用pg_data來操作共享區域了。不要忘記在 DLL退出的時候安全的刪除共享區域釋放內存。 
消息等待與安全卸載
在我們卸載WH_GETMESSAGE鉤子之前必須先把目標程序的 API調用恢復正常。我們不能再調用UnHookApi之后就立刻調用UnhookWindowsHookEx,因為很有可能UnHookApi還沒來得 急完成API入口地址的恢復操作,WH_GETMESSAGE鉤子就已經被卸載了。因此需要等待一段時間,等UnHookApi完成了恢復操作在調用 UnhookWindowsHookEx。以防錯誤發生。

extern "C" __declspec(dllexport) void UnHookAPIHook() {
    /*向目標線程發送消息進行API UNHOOK*/
    PostThreadMessage(pg_data->idTarget,WM_DISABLEAPIHOOK,(WPARAM)GetCurrentThreadId(),0);
    showerr("WM_DISABLEAPIHOOK");
    /*等待目標進程返回WM_UNHOOKOK消息,確認可以將WH_GETMESSAGE的HOOK去掉*/
    
    MSG Msg;
    do {
        GetMessage(&Msg,NULL,0,0);
    }while(Msg.message !=  WM_UNHOOKOK);
    UnhookWindowsHookEx(pg_data->hHook);
    PostThreadMessage(pg_data->idTarget,WM_DISABLEAPIHOOKOK,(WPARAM)GetCurrentThreadId(),0);
    showerr("UnHookWindowsHookEx");
}
上面的代碼中我們使用一個含有GetMessage的循環來等待消息的到達,一旦UnHookApi完成他就會發送WM_UNHOOKOK消息。等我們接收到消息確認一切安全了在來卸載WH_GETMESSAGE鉤子。 
弄清消息對象
我 們一定要清楚代碼是在主程序進程空間中執行的還是在目標程序進程空間中執行的。像上面的UnHookAPIHook函數就是通過主程序調用的,因此在主程 序進程空間中執行。這樣一來用來恢復目標程序API信息的UnHookApi完成后就應該向主程序發送消息,而不是目標程序。

目標進程加載了其他DLL
如果目標進程動態加載了其他的DLL文件,我們必須監視LoadLibrary函數。保證DLL中的API入口地址也被正確修改。防止出現混亂的情況。我從LoadLibrary獲得DLL的路徑用于GetModuleHandle來取得他的ImageBase的地址。

不知道文章寫的如何,希望大家能多給些批評意見。發現問題我馬上改正
Email: detrox@yang.com.cn

參考資料
< >, Jeffrey Richter, Microsoft Press

<>,陳寬達,華中科大出版社

<>, LUEVELSMEYER

<>, Iczelion

附:跨進程APIHook的例子
先打開一個記事本程序并輸入幾個字符,運行下面的程序,加載APIHook.之后在記事本的文件菜單中選擇新建就會看到API Hook將MessageBoxW 函數Hook的結果了.
代碼在WinXP SP1 + VC6.0測試成功。

下載源代碼

(特別感謝老羅的代碼著色器,比我自己那個好多了)

這是DLL的程序,Hook.dll
#include 
#include 
#include 
#include 
#include "mydef.h"

const char szApp[] = "Hook.dll"; /*應用程序名稱*/
HANDLE hMap;/*在共享內存映像的句柄*/
GLOBALDATA *pg_data; /*在共享內存中的全局數據*/
LRESULT CALLBACK GetMsgProc(int,WPARAM, LPARAM);

/*顯示GetLastError指出的錯誤*/
void showerr(const char *m, BOOL GetError = TRUE) {
    char message[127];
    char buf[255];
    COPYDATASTRUCT cds;
    if (GetError) 
        FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,0
  ,GetLastError(),MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),message,127, 0);
    else 
        *message = 0;
    if (Get
CurrentThreadId() != pg_data->idMain)
        sprintf(buf,"目標程序空間DLL: %-30s [%-40s]",m, message);
    else
        sprintf(buf,"主程序空間DLL  : %-30s [%-40s]",m, message);
    cds.lpData = buf;
    cds.cbData = sizeof(buf);
    cds.dwData = 0;
 
    SendMessage(pg_data->hWndMain,WM_COPYDATA,(WPARAM)pg_data->hWndTarget,(LPARAM)&cds);
  
    SetLastError(0);
}
int WINAPI MyMessageBoxW(HWND hWnd ,LPCWSTR M1,LPCWSTR M2, UINT M3) {
    wchar_t buf[255];
    swprintf(buf,L"!!這個窗口的API被Hook了!! HWND: 0x%08X Message: %s Caption: %s"
        ,(DWORD *)hWnd
        , M1
        , M2);
    pg_data->oldAPIFunction(hWnd,buf,M2,MB_OK);
    return pg_data->oldAPIFunction(hWnd,M1,M2,M3);
}

/*DLL 入口函數*/
BOOL WINAPI DllMain(HINSTANCE hInst, DWORD reason,LPVOID lpvReserved)
{
    switch (reason) {
    case DLL_PROCESS_ATTACH:
        /*創建/打開共享內存區域*/
        hMap = CreateFileMapping((HFILE *)0xFFFFFFFF,NULL,PAGE_READWRITE,0,sizeof(GLOBALDATA),ID_MAP);
        pg_data = (GLOBALDATA*)MapViewOfFile(hMap,FILE_MAP_ALL_ACCESS,0 ,0 ,0);
        if (!pg_data) {
           MessageBox(NULL,"無法建立共享內存,程序終止!",szApp,MB_OK);
           if (hMap) {
               CloseHandle(hMap);
               hMap = NULL;
               return 0;
            }
        }
        pg_data->hInst = hInst;
        showerr("共享內存映像文件");
        showerr("DLL裝載中...",FALSE);
        break;
    case DLL_PROCESS_DETACH:
        showerr("DLL卸載中...",FALSE);
        if (pg_data) {
            UnmapViewOfFile(pg_data);
            pg_data = NULL;
        }
        if (hMap) {
            CloseHandle(hMap);
            hMap = NULL;
        }
        break;
    }

 return true;
}
/*卸載API Hook*/
void UnHookApi() {
    DWORD written = 0;
    DWORD oldaddrAPIFunction = (DWORD)pg_data->oldAPIFunction;
    WriteProcessMemory(GetCurrentProcess(),(DWORD *)pg_data->addrAPIEntryPoint
        , &oldaddrAPIFunction,sizeof(DWORD), &written);
    showerr("WriteProcessMemory on UnHook");
    /*向主線程發送 API UNHOOK 處理完畢的消息*/
    PostThreadMessage(pg_data->idMain,WM_UNHOOKOK,0,0);
}

/*加載API Hook*/
void HookApi(const char* szApiName, tAPIFunction newAddr, DWORD ImageBase) {
    /*這段代碼請參考文章中的分析*/
    IMAGE_DOS_HEADER *pidh;
    IMAGE_NT_HEADERS *pinh;
    IMAGE_DATA_DIRECTORY *pSymbolTable;
    IMAGE_IMPORT_DESCRIPTOR *piid;
  
    pidh = (IMAGE_DOS_HEADER *)ImageBase;    
    pinh = (IMAGE_NT_HEADERS *)((DWORD)ImageBase + pidh->e_lfanew);
    pSymbolTable = &pinh->OptionalHeader.DataDirectory[1];
    piid =(IMAGE_IMPORT_DESCRIPTOR *)((DWORD)ImageBase +  pSymbolTable->VirtualAddress);

    do {
        IMAGE_THUNK_DATA *pitd_org,*pitd_1st;
        pitd_org = (IMAGE_THUNK_DATA *)((DWORD)ImageBase + piid->OriginalFirstThunk);
        pitd_1st = (IMAGE_THUNK_DATA *)((DWORD)ImageBase + piid->FirstThunk);
        do {
            IMAGE_IMPORT_BY_NAME *piibn;
            piibn = (IMAGE_IMPORT_BY_NAME *)((DWORD)ImageBase +  *((DWORD *)pitd_org));
            PROC *pAPIFunction = (PROC *)(pitd_1st->u1.Function);
            if (!strcmp(szApiName,(char *)piibn->Name)) {
                DWORD addrNewAPIFunction = (DWORD)MyMessageBoxW;
                DWORD written = 0;
                DWORD oldAccess;

                pg_data->oldAPIFunction = (tAPIFunction)(pAPIFunction);
                /*Change Memeory State*/
                VirtualProtect(&pitd_1st->u1.Function,sizeof(DWORD),PAGE_WRITECOPY,&oldAccess);
                showerr("VirtualProtect");
                pg_data->addrAPIEntryPoint = (DWORD)&pitd_1st->u1.Function;
                /*Write Process Memory*/
                WriteProcessMemory(GetCurrentProcess(),&pitd_1st->u1.Function
                    , &addrNewAPIFunction,sizeof(DWORD), &written);
                showerr("WriteProcessMemory on Hook");
            }
            pitd_org++;
            pitd_1st++;
        } while (pitd_1st->u1.Function);
       
        piid++;
    } while (piid->FirstThunk + piid->Characteristics 
 + piid->ForwarderChain + piid->Name + piid->TimeDateStamp);
}

//-----------------------
extern "C" __declspec(dllexport) BOOL SetAPIHook(HWND _target) {
    pg_data->hHook = SetWindowsHookEx(WH_GETMESSAGE,GetMsgProc,pg_data->hInst,pg_data->idTarget);    
    showerr("SetWindowsHookEx");
    /*向目標線程發送消息進行API HOOK*/
    if (pg_data->hHook) {
        PostThreadMessage(pg_data->idTarget,WM_ENABLEAPIHOOK,0,0);
    } else {
        return FALSE;
    }
    showerr("WM_ENABLEAPIHOOK");
    return TRUE;
}

extern "C" __declspec(dllexport) void UnHookAPIHook() {
    /*向目標線程發送消息進行API UNHOOK*/
    PostThreadMessage(pg_data->idTarget,WM_DISABLEAPIHOOK,(WPARAM)GetCurrentThreadId(),0);
    showerr("WM_DISABLEAPIHOOK");
    /*等待目標進程返回WM_UNHOOKOK消息,確認可以將WH_GETMESSAGE的HOOK去掉*/
    MSG Msg;
    do {
        GetMessage(&Msg,NULL,0,0);
    }while(Msg.message !=  WM_UNHOOKOK);

    UnhookWindowsHookEx(pg_data->hHook);
    PostThreadMessage(pg_data->idTarget,WM_DISABLEAPIHOOKOK,(WPARAM)GetCurrentThreadId(),0);
    showerr("UnHookWindowsHookEx");
}

LRESULT CALLBACK GetMsgProc(int nCode,WPARAM wParam, LPARAM lParam) {
    if (nCode == HC_ACTION) {
        MSG *msg = (MSG *)lParam;
     
        if (msg->message == WM_ENABLEAPIHOOK) {
            HookApi("MessageBoxW",MyMessageBoxW,(DWORD)GetModuleHandle(NULL));
        }
        if (msg->message == WM_DISABLEAPIHOOK) {
            UnHookApi();
  ;      }
        if (msg->message == WM_DESTROY) {
            showerr("目標進程退出!",FALSE);
        }
    }
    return CallNextHookEx(pg_data->hHook,nCode,wParam,lParam);
}
 
這個是主程序的關鍵部分 HookGui.cpp
用MFC建立一個窗口程序,包含兩個按鈕和一個ListBox

typedef void (*PUnHookAPIHook)();
typedef BOOL (*PSetAPIHook)(HWND);
HMODULE hDll = NULL;
HWND hNotePad = NULL;
PSetAPIHook SetAPIHook;
PUnHookAPIHook UnHookAPIHook;
GLOBALDATA *pg_data; /*在共享內存中的全局數據*/
HANDLE hMap; /*在共享內存映像的句柄*/
int CHookGUIDlg::showerr(const char* m) {
    char message[127];
    char buf[255];
    int errId = GetLastError();
    FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,0
 ,errId,MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),message,127, 0);
    sprintf(buf,"主程序         : %-30s [%-40s] ",m, message);
    c_List1.InsertString(c_List1.GetCount(),buf);
    UpdateData(FALSE);
    return errId;
}

void CHookGUIDlg::OnSetapihook() 
{
    // TODO: Add your control notification handler code here
    hDll = LoadLibrary("Hook.dll");
    showerr("LoadLibrary");
    hMap = OpenFileMapping(FILE_MAP_ALL_ACCESS,false,ID_MAP);
    showerr("OpenFileMapping");    
    pg_data = (GLOBALDATA *)MapViewOfFile(hMap,FILE_MAP_ALL_ACCESS,0,0,0);
    showerr("MapViewOfFile");    
    if (!pg_data) {
        MessageBox("不能打開共享內存程序終止!");
        return;
    }
    SetAPIHook = (PSetAPIHook)GetProcAddress(hDll,"SetAPIHook");
    showerr("GetProcAddress-SetAPIHOOK");
   
    pg_data->hWndTarget = ::FindWindow("NotePad",NULL);
    pg_data->hWndMain = m_hWnd;
    pg_data->idMain = GetWindowThreadProcessId(m_hWnd,NULL);
    pg_data->idTarget = GetWindowThreadProcessId(pg_data->hWndTarget,NULL);
    if (!showerr("FindWindow")) {
        if (SetAPIHook) { 
            if (SetAPIHook(hNotePad))
                PostThreadMessage(pg_data->idTarget
   , WM_SETCALLERID,(LPARAM)GetCurrentThreadId(),0);
            else {
                MessageBox("SetWindowHookEx時出錯,程序終止!");
                return;
            }
  &n } else {
            MessageBox("無法取得SetAPIHook函數!程序終止!");                    
        }
    } else {
            MessageBox("內存中沒有找到NOTEPAD.EXE");            
    }
    c_SetApiHook.EnableWindow(FALSE);
    c_UnsetApiHook.EnableWindow();
}

void CHookGUIDlg::OnUnsetapihook() 
{
    // TODO: Add your control notification handler code here
    if (hDll) {
        if ( !IsWindow(pg_data->hWndTarget)) {
            MessageBox("目標進程不在內存中");
            return;
        }
        UnHookAPIHook = (PUnHookAPIHook)GetProcAddress(hDll,"UnHookAPIHook");
        showerr("GetProcAddress-UnHookAPIHook");
        if (UnHookAPIHook) 
            UnHookAPIHook();
        FreeLibrary(hDll);
        showerr("FreeLibrary");
        hDll = NULL;
    } else {
        MessageBox("請先加載DLL");
    }
    c_SetApiHook.EnableWindow();
    c_UnsetApiHook.EnableWindow(FALSE);
}

void CHookGUIDlg::OnOK() 
{
    // TODO: Add extra validation here
    if (hDll) {
        OnUnsetapihook();
    }
    CDialog::OnOK();
}

BOOL CHookGUIDlg::OnCopyData(CWnd* pWnd, COPYDATASTRUCT* pCopyDataStruct) 
{
    // TODO: Add your message handler code here and/or call default
    c_List1.InsertString(c_List1.GetCount(),(char *)pCopyDataStruct->lpData);
    return CDialog::OnCopyData(pWnd, pCopyDataStruct);
}

posted on 2007-07-29 11:08 旅途 閱讀(1332) 評論(0)  編輯 收藏 引用 所屬分類: 深入windows

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            欧美伊人久久| 亚洲欧洲综合另类在线| 中文av一区特黄| 亚洲欧美日韩精品| 曰韩精品一区二区| 99国产精品| 国产精品一区久久久久| 欧美成人免费在线观看| 欧美日韩国产高清| 久久天堂av综合合色| 欧美日本网站| 六月婷婷一区| 国产精品视频免费| 亚洲第一毛片| 国产日产欧美a一级在线| 亚洲激情电影中文字幕| 激情久久久久久| 亚洲综合国产精品| 一区二区三区四区国产精品| 久久亚洲国产精品一区二区 | 一本色道**综合亚洲精品蜜桃冫 | 亚洲视频欧美在线| 亚洲乱码一区二区| 久久久精品性| 欧美一区亚洲二区| 欧美午夜不卡视频| 亚洲看片免费| 亚洲精品三级| 欧美v国产在线一区二区三区| 性刺激综合网| 欧美婷婷在线| 亚洲国产成人porn| 亚洲第一区在线| 欧美在线综合| 久久精品国产99精品国产亚洲性色| 欧美日韩国产小视频| 亚洲成人资源网| 国产午夜精品理论片a级大结局| 一本高清dvd不卡在线观看| 亚洲靠逼com| 欧美激情一区二区三区不卡| 欧美成人免费小视频| 亚洲国产精品一区二区久| 久久日韩精品| 欧美寡妇偷汉性猛交| 亚洲福利视频在线| 久热综合在线亚洲精品| 蜜月aⅴ免费一区二区三区| 欧美大尺度在线观看| 久久先锋资源| 猛男gaygay欧美视频| 狠狠色狠狠色综合人人| 久久gogo国模啪啪人体图| 久久精品日韩欧美| 国产主播精品| 另类激情亚洲| 亚洲国产欧美日韩精品| 亚洲精品久久久久久久久久久| 蜜月aⅴ免费一区二区三区 | 国产欧美日韩精品一区| 亚洲欧美日韩国产精品| 新狼窝色av性久久久久久| 国产一区二区三区无遮挡| 久久久久久久999精品视频| 欧美成人综合一区| 亚洲毛片在线免费观看| 欧美日韩中文字幕日韩欧美| 亚洲婷婷免费| 久久夜色精品国产噜噜av| 亚洲高清资源| 欧美视频专区一二在线观看| 亚洲一卡久久| 久久免费精品日本久久中文字幕| 亚洲成人在线视频播放| 欧美绝品在线观看成人午夜影视| 这里只有精品丝袜| 久热这里只精品99re8久| 99成人在线| 国产乱理伦片在线观看夜一区| 久久精品国产清自在天天线| 亚洲电影在线免费观看| 亚洲欧美日本日韩| 黄色国产精品| 欧美三级午夜理伦三级中视频| 欧美在线啊v| 亚洲欧洲精品一区二区| 欧美一区二区三区在线播放| 亚洲高清久久久| 国产精品视频精品| 欧美成人精品1314www| 亚洲欧美日韩在线高清直播| 亚洲国产高清自拍| 久久久久久**毛片大全| 中文精品视频| 亚洲国产精品一区在线观看不卡| 国产精品久久综合| 欧美电影免费| 久久久国产精品一区二区中文| 夜夜嗨av色综合久久久综合网| 久久综合网络一区二区| 午夜精品久久久久久久| 新狼窝色av性久久久久久| 国产伦精品一区二区| 欧美成人精品在线| 久久国产欧美精品| 亚洲一区二区精品视频| 亚洲国产三级| 蜜桃av久久久亚洲精品| 欧美在线一级va免费观看| 99精品国产高清一区二区| 激情久久五月| 国产欧美在线看| 欧美午夜宅男影院在线观看| 欧美成人r级一区二区三区| 欧美永久精品| 亚洲欧美日韩综合一区| 夜夜精品视频一区二区| 亚洲三级毛片| 亚洲福利久久| 亚洲福利视频一区二区| 欧美肥婆bbw| 欧美三区在线视频| 久久青草久久| 欧美一区二区三区日韩视频| 亚洲一级在线观看| 亚洲午夜在线观看| 亚洲视频网在线直播| 日韩午夜激情av| 亚洲精品女人| 亚洲大胆美女视频| 欧美大片第1页| 欧美成人资源| 亚洲黄色精品| 亚洲欧洲在线视频| 亚洲精品视频在线观看免费| 亚洲日产国产精品| 亚洲精品国产精品国自产观看浪潮| 亚洲成人在线免费| 亚洲一区二区三区三| 99热这里只有成人精品国产| 亚洲精品视频在线观看免费| 亚洲黄色高清| 亚洲每日更新| 亚洲午夜伦理| 午夜视频在线观看一区二区| 欧美一级欧美一级在线播放| 欧美一区二区三区在线免费观看 | 欧美午夜无遮挡| 国产精品美女午夜av| 国产欧美三级| 伊人色综合久久天天| 亚洲人永久免费| 99这里有精品| 校园激情久久| 麻豆精品91| 亚洲经典视频在线观看| 99热精品在线观看| 亚洲欧美一区二区在线观看| 久久精品一区二区三区中文字幕 | 亚洲日本黄色| 亚洲一区免费观看| 久久久久成人精品| 欧美精品三级日韩久久| 国产精品美女在线| 伊伊综合在线| av成人手机在线| 欧美在线观看视频一区二区三区| 久久只精品国产| 亚洲激情自拍| 欧美一级成年大片在线观看| 欧美成人免费观看| 国产精品一区在线观看你懂的| 在线观看欧美成人| 亚洲午夜精品久久久久久浪潮 | 国产日韩欧美在线视频观看| 亚洲成人资源网| 亚洲在线视频观看| 美女91精品| 一区二区三区四区精品| 久久久久久久高潮| 国产精品国产三级国产| 在线看视频不卡| 亚洲欧美日韩爽爽影院| 欧美大尺度在线| 午夜精品久久久久久久99黑人| 免费欧美电影| 国产欧美日韩不卡| 夜夜夜久久久| 免费日本视频一区| 午夜日韩在线观看| 欧美日韩一区成人| 亚洲国产高清视频| 久久精品日产第一区二区| 99re热精品| 亚洲人成网站777色婷婷| 欧美一级视频一区二区| 亚洲国产欧洲综合997久久| 欧美在线日韩在线| 国产精品99免费看| 99re这里只有精品6|