Windows下的函數hook技術

都是很成熟的東西了,這幾天看了看,總結一下而已。

討論了Windows下hook函數的幾種方法。提供了一個hook TextOutA的完整例子。通過CreateRemoteThread的方法把hook dll注入到一個普通的應用程序中。Hooking Imported Functions by name調用

imported functions'時的步驟/實現

在程序中調用從其它模塊引入的函數的方法和普通的函數調用有所不同。對于普通的函數調用,直接使用

call address來調用即可,但是對于

imported functions

,在編譯的時候

compiler/link

並不知道實際的函數實現會被加載到那個地址,函數實現在那個地址在運行的時候才會確定。對于

imported functions

,首先是

call

引入表中的一個函數,在運行時再初始化引入表,使用

jmp

跳轉到真實的函數實現。

引入表:

The PE file

IMAGE_IMPORT_DESCRipTOR

strUCture, which holds all the information about functions imported from a specific DLL, has pointers to two arrays in the executable. These arrays are called import address tables (IATs), or sometimes thunk data arrays. The first pointer references the real IAT, which the PRogram loader fixes up when the executable is loaded. The second pointer references the original IAT, which is untouched by the loader and lists the imported functions.

實現原理

找到

PE

文件的

Image_Import_Descriptor

結構

找到

Original LAT

Real LAT.

通過要

hook

的函數的名字在

Original LAT

找到要

hook

imported function

在數組中的

index.

保存並修改

Real LAT

在相應

index

function address

(refer to John Robbins, BugsLayerUtil.dll)

Hooking Imported Functions by ordinal

原理和

Hook Imported functions by name

一樣,只是是通過要

hook

的函數的

ordinal

original LAT

中找到

index.

Hooking a function in this dll

當一個

DLL

是通過

LoadLibrary

載入的時候,我們無法通過

hook imported function

的方法的

hook

它中的

function

。有兩種可能的辦法處理這種情況:

第一種方法,遍曆進程空間,發現

call

指定函數的地方替換爲

call hookFunction.

太麻煩,而且不安全。

第二種方法,改寫要

hook

的函數

FuncA

。比較好的方法

實現

HookFuncA

,最後的實現墊入

n

nop.

找到要

hook

的函數

FuncA

的絕對地址,改寫前

5

個字節爲

jmp hookFuncA(

假定前

5

個字節爲

n

個完整的指令

)

FuncA

的前

5

個字節拷貝到

hookFuncA

的後面,在加上一條指令

jmp funcA+5.

----Code of HookDLL.dll, 可以通過CreateRemoteThread的方法把hook dll注入到一個普通的應用程序中。

// HookDLL.cpp : Defines the entry point for the DLL application.

//

#include "stdafx.h"

#include "HookDLL.h"

#include "Log.h"

//forward declare.

LRESULT WINAPI InstallTextoutHook();

LRESULT WINAPI UninstallTextoutHook();

BOOL APIENTRY DllMain( HANDLE hModule,

DWord ul_reason_for_call,

LPVOID lpReserved

)

{

switch (ul_reason_for_call)

{

case DLL_PROCESS_ATTACH:

if (InstallTextoutHook())

{

WriteLog("Install hook success.\n");

}else

{

WriteLog("Intall hook failed.\n");

}

break;

case DLL_THREAD_ATTACH:

break;

case DLL_THREAD_DETACH:

break;

case DLL_PROCESS_DETACH:

if (UninstallTextoutHook())

{

WriteLog("Uninstall hook success.\n");

}else

{

WriteLog("Unintall hook failed.\n");

}

break;

}

return TRUE;

}

#define DWORD_PTR DWORD*

#define __LOCAL_SIZE 40h

#define NAKED_PROLOG() \

DWORD_PTR dwRet ; \

DWORD_PTR dwESI ; \

{ \

__asm PUSH EBP /* Set up the standard frame.*/\

__asm MOV EBP , ESP \

__asm SUB ESP , __LOCAL_SIZE /* Save room for the local */\

/* variables. */\

__asm MOV EAX , EBP /* EBP has the stack coming */\

/* into the fn. in it. */\

__asm ADD EAX , 4 /* Account for PUSH EBP */\

__asm MOV EAX , [EAX] /* Get return address. */\

__asm MOV [dwRet] , EAX /* Save return address. */\

__asm MOV [dwESI] , ESI /* Save ESI so chkesp in dbg */\

/* builds works. */\

}// The common epilog part that can be shared between the stdcall and

// cdecl hook functions.

#define EPILOG_COMMON() \

{ \

__asm MOV ESI , [dwESI] /* Restore ESI. */\

__asm ADD ESP , __LOCAL_SIZE /* Take away local var space */\

__asm MOV ESP, EBP /* Restore standard frame. */\

__asm POP EBP \

}

#define COPY_CODE_LENGTH 5

BYTE g_abOriCode[COPY_CODE_LENGTH];

BYTE g_abJmpCode[COPY_CODE_LENGTH];

PROC g_oriTextout;

BOOL g_blHooked = FALSE;

LRESULT WINAPI InstallTextoutHook()

{

if (g_blHooked)

return TRUE;

//Get TextOutA's address.

HMODULE hGdi32 = ::LoadLibrary(_T("Gdi32.dll"));

g_oriTextout = GetProcAddress(hGdi32, _T("TextOutA"));

if (NULL == g_oriTextout)

return FALSE;

//Get the hook'a address.

HMODULE hModule = GetModuleHandle(_T("HookDLL.dll"));

if (NULL == hModule)

return FALSE;

DWORD dwHookAddr = NULL;

__asm

{

mov esi, offset HookLabel;

mov edi, 0x10000000;//0x10000000 is the dll's base address.

sub esi, edi;

add esi, hModule;

mov [dwHookAddr], esi;

}

//Get the NOP's address.

DWORD dwNOPAddr = NULL;

__asm

{

mov esi, offset NOPLabel;

mov edi, 0x10000000;//0x10000000 is the dll's base address.

sub esi, edi;

add esi, hModule;

mov [dwNOPAddr], esi;

}

//Save the first 5 byte of TextOutA to g_abOriCode

__asm

{

mov esi, g_oriTextout;

lea edi, g_abOriCode;

cld;

movsd;

movsb;

}

//Generate the jmp Hook function.

g_abJmpCode[0] = 0xe9;

__asm

{

mov eax, dwHookAddr;

mov ebx, g_oriTextout;

add ebx, 5;

sub eax, ebx;

mov dword ptr[g_abJmpCode+1], eax;

}

//Write the jump instruction to the textoutA.

DWORD dwProcessId = GetCurrentProcessId();

HANDLE hProcess = OpenProcess (PROCESS_ALL_access,

FALSE, dwProcessId);

if (NULL == hProcess)

return FALSE;

DWORD dwOldFlag;

VirtualProtectEx(hProcess, g_oriTextout, 5, PAGE_READWRITE, &dwOldFlag);

WriteProcessMemory(hProcess, g_oriTextout, g_abJmpCode, sizeof(g_abJmpCode), NULL);

VirtualProtectEx(hProcess, g_oriTextout, 5, dwOldFlag, NULL);

//Write g_abOriTextout to the end of Hook function(NOP addr), then write the jmp instruction.

VirtualProtectEx(hProcess, (LPVOID)dwNOPAddr, 10, PAGE_READWRITE, &dwOldFlag);

WriteProcessMemory(hProcess, (LPVOID)dwNOPAddr, g_abOriCode, sizeof(g_abOriCode), NULL);

//Generate the jmp TextoutA + 5

__asm

{

mov eax, g_oriTextout;

mov ebx, dwNOPAddr;

add ebx, 5;

sub eax, ebx;

mov dword ptr[g_abJmpCode+1], eax;

}

WriteProcessMemory(hProcess, (LPVOID)(dwNOPAddr+5), g_abJmpCode, sizeof(g_abJmpCode), NULL);

VirtualProtectEx(hProcess, (LPVOID)dwNOPAddr, 10, dwOldFlag, NULL);

g_blHooked = TRUE;

if(TRUE)

return TRUE;

HookLabel:

NAKED_PROLOG ( ) ;

int nx, ny;

LPCSTR lp;

lp = NULL;

_asm

{

mov esi, ebp;

add esi, 0Ch;

lea edi, nx;

movsd;

lea edi, ny;

movsd;

lea edi, lp;

movsd;

}

WriteLog_F("Try to ouput \"%s\" at (%d,%d)\n", lp, nx, ny);

// Do the common epilog.

EPILOG_COMMON ( ) ;

NOPLabel:

_asm NOP

_asm NOP

_asm NOP

_asm NOP

_asm NOP

_asm NOP

_asm NOP

_asm NOP

_asm NOP

_asm NOP

_asm NOP

}

LRESULT WINAPI UninstallTextoutHook()

{

if (!g_blHooked)

return FALSE;

//Restore the first 5 bytes code of TextOutA

DWORD dwProcessId = GetCurrentProcessId();

HANDLE hProcess = OpenProcess (PROCESS_ALL_ACCESS,

FALSE, dwProcessId);

if (NULL == hProcess)

return FALSE;

DWORD dwOldFlag;

VirtualProtectEx(hProcess, g_oriTextout, 5, PAGE_READWRITE, &dwOldFlag);

WriteProcessMemory(hProcess, g_oriTextout, g_abOriCode, sizeof(g_abOriCode), NULL);

VirtualProtectEx(hProcess, g_oriTextout, 5, dwOldFlag, NULL);

g_blHooked = FALSE;

return TRUE;

}

Windows下的函數hook技術
更多內容請看Windows操作系統安全集 Windows操作系統安裝 Windows頻道專題,或

Windows下的函數hook技術
  都是很成熟的東西了,這幾天看了看,總結一下而已。 討論了Windows下hook函數的幾種方法。提供了一個hook TextOu...查看完整版>>Windows下的函數hook技術
 
Windows中Hook的使用——Hook函數篇
Windows中Hook的使用——Hook函數篇 提起HOOK,已經不是什麽新的話題了。在Windows的進程監控和消息監控等方面,HOOK機制都給予了強有力的支持,使得上述應用變得易于實現。本文旨在介紹一下HOOK函數的使用方法,函數...查看完整版>>Windows中Hook的使用——Hook函數篇
 
WINDOWS下的低級音頻函數介紹
在WINDOWS下,音頻函數有多種類型,如MCI、多媒體OLE控制、高級音頻等,使用方法都比較簡單。但如果想編寫一個功能較強大的音頻處理程序,那就必須使用低級音頻函數和多媒體文件I/O來控制音頻設備的輸入和輸出。因爲...查看完整版>>WINDOWS下的低級音頻函數介紹
 
Windows下的個人防火牆-網絡數據包攔截技術概覽
  隨著網絡安全問題日益嚴重,網絡安全産品也被人們重視起來。防火牆作爲最早出現的網絡安全産品和使用量最大的安全産品,也受到用戶和研發機構的青睐。從防火牆的應用角度來看基本上可以分爲兩種:網絡級的防火牆...查看完整版>>Windows下的個人防火牆-網絡數據包攔截技術概覽
 
用HOOK函數自動關閉IE廣告窗口
  在用IE浏覽某些網站的時候,網站主頁會彈出一些廣告網頁。所以每當打開這樣的網頁時,總得手動關閉廣告頁,感覺比較麻煩。那麽,是否可以編寫程序來判定打開的網頁是否是彈出廣告,然後自動關閉這些廣告,避免每...查看完整版>>用HOOK函數自動關閉IE廣告窗口
 
對于HOOK函數的一點認識 iBreathe(收藏)
一、序言對大多數的Windows開發者來說,如何在Win32系統中對API函數的調用進行攔截一直是項極富挑戰性的課題,因爲這將是對你所掌握的計算機知識較爲全面的考驗,尤其是一些在如今使用RAD進行軟件開發時並不常用的知...查看完整版>>對于HOOK函數的一點認識 iBreathe(收藏)
 
Windows中Filter-Hook驅程
Windows中Filter-Hook驅動程序在Windows 2000和Windows XP中,System32\drivers目錄下的ipfltdrv.sys是Microsoft提供的ip協議過濾驅動程序。它允許用戶注冊自己的ip數據報處理函數。在MSDN中有關于這方面內容的簡短說...查看完整版>>Windows中Filter-Hook驅程
 
Windows HOOK 說明(1)
HOOKS 說明(1)hook是WINDOWS提供的一種消息處理機制,它使得程序員可以使用子過程來監視系統消息,並在消息到達目標過程前得到處理。下面將介紹WINNDOWS HOOKS並且說明如何在WINDOWS 程序中使用它。================...查看完整版>>Windows HOOK 說明(1)
 
使用HOOK隨心監視Windows
每個程序都有自己的生存空間,在Windows系統中你可以在任何時候讓你的程序執行一些操作,還可以觸發消息,觸發的消息分爲三種,一是操作你程序的界面,onClick,onMouseMove等等,另外一個可以使用Windows的消息機制...查看完整版>>使用HOOK隨心監視Windows
 
 
回到王朝網路移動版首頁