勾點編程

勾點編程

虛擬函式表掛鉤

編輯

C++使用虛擬函式,因此可在執行時直接修改虛擬函式表的內容來掛鉤。 Window上很多軟體庫以COM方式提供的(如DirectX), 所以有需求攔截COM呼叫的COM Hook。COM里的介面是C++虛表的形式提供的,所以COM的Hook其實就是虛表(vtable)的Hook。ATL就是用介面替代的方式來除錯和記錄COM介面參照計數的次數

class VirtualTable { // example class

public:

virtual void VirtualFunction01( ticket );

};

void VirtualTable::VirtualFunction01( ticket ) {

printf("VirtualFunction01 called");

}

typedef void ( __thiscall* VirtualFunction01_t )( ticket* thisptr );

VirtualFunction01_t g_org_VirtualFunction01;

//our detour function

void __fastcall hk_VirtualFunction01( ticket* thisptr, int edx ) {

printf("Custom function called");

//call the original function

g_org_VirtualFunction01(thisptr);

}

int _tmain(int argc, _TCHAR* argv[]) {

DWORD oldProtection;

VirtualTable* myTable = new VirtualTable();

void** base = *(void***)myTable;

VirtualProtect( &base[0], 4, PAGE_EXECUTE_READWRITE, &oldProtection );

//save the original function

g_org_VirtualFunction01 = (VirtualFunction01_t)base[0];

//overwrite

base[0] = &hk_VirtualFunction01;

VirtualProtect( &base[0], 4, oldProtection, 0 );

//call the virtual function (now hooked) from our class instance

myTable->VirtualFunction01();

return 0;

}

C#鍵盤事件勾點

編輯

using System.Runtime.InteropServices;

namespace Hooks

{

public class KeyHook

{

/* Member variables */

protected static int Hook;

protected static LowLevelKeyboardDelegate Delegate;

protected static readonly object Lock = new object();

protected static bool IsRegistered = false;

/* DLL imports */

[DllImport("user32")]

private static extern int SetWindowsHookEx(int idHook, LowLevelKeyboardDelegate lpfn,

int hmod, int dwThreadId);

[DllImport("user32")]

private static extern int CallNextHookEx(int hHook, int nCode, int wParam, KBDLLHOOKSTRUCT lParam);

[DllImport("user32")]

private static extern int UnhookWindowsHookEx(int hHook);

/* Types & constants */

protected delegate int LowLevelKeyboardDelegate(int nCode, int wParam, ref KBDLLHOOKSTRUCT lParam);

private const int HC_ACTION = 0;

private const int WM_KEYDOWN = 0x0100;

private const int WM_KEYUP = 0x0101;

private const int WH_KEYBOARD_LL = 13;

[StructLayout(LayoutKind.Sequential)]

public struct KBDLLHOOKSTRUCT

{

public int vkCode;

public int scanCode;

public int flags;

public int time;

public int dwExtraInfo;

}

/* Methods */

private static int LowLevelKeyboardHandler(int nCode, int wParam, ref KBDLLHOOKSTRUCT lParam)

{

if (nCode == HC_ACTION)

{

if (wParam == WM_KEYDOWN)

System.Console.Out.WriteLine("Key Down: " + lParam.vkCode);

else if (wParam == WM_KEYUP)

System.Console.Out.WriteLine("Key Up: " + lParam.vkCode);

}

return CallNextHookEx(Hook, nCode, wParam, lParam);

}

public static bool RegisterHook()

{

lock (Lock)

{

if (IsRegistered)

return true;

Delegate = LowLevelKeyboardHandler;

Hook = SetWindowsHookEx(

WH_KEYBOARD_LL, Delegate,

Marshal.GetHINSTANCE(

System.Reflection.Assembly.GetExecutingAssembly().GetModules()[0]

).ToInt32(), 0

);

if (Hook != 0)

return IsRegistered = true;

Delegate = null;

return false;

}

}

public static bool UnregisterHook()

{

lock (Lock)

{

return IsRegistered = (UnhookWindowsHookEx(Hook) != 0);

}

}

}

}

使用跳轉指令的API/函式勾點攔截

編輯

下述例子使用JMP(英語:JMP (x86 instruction))指令,修改windows API中的MessageBoxW函式的前6個位元組執行其他代碼。這段代碼編譯為DLL檔案,採用DLL注入技術讓應用程式使用。[1]微軟提供了封裝好的Detours庫用於此目的。

/*

This idea is based on chrom-lib approach, Distributed under GNU LGPL License.

Source chrom-lib: https://github.com/linuxexp/chrom-lib

Copyright (C) 2011 Raja Jamwal

*/

#include

#define SIZE 6

typedef int (WINAPI *pMessageBoxW)(HWND, LPCWSTR, LPCWSTR, UINT); // Messagebox prototype

int WINAPI MyMessageBoxW(HWND, LPCWSTR, LPCWSTR, UINT); // Our detour

void BeginRedirect(LPVOID);

pMessageBoxW pOrigMBAddress = NULL; // address of original

BYTE oldBytes[SIZE] = {0}; // backup

BYTE JMP[SIZE] = {0}; // 6 byte JMP instruction

DWORD oldProtect, myProtect = PAGE_EXECUTE_READWRITE;

INT APIENTRY DllMain(HMODULE hDLL, DWORD Reason, LPVOID Reserved)

{

switch(Reason)

{

case DLL_PROCESS_ATTACH: // if attached

pOrigMBAddress = (pMessageBoxW)

GetProcAddress(GetModuleHandle("user32.dll"), // get address of original

"MessageBoxW");

if(pOrigMBAddress != NULL)

BeginRedirect(MyMessageBoxW); // start detouring

break;

case DLL_PROCESS_DETACH:

memcpy(pOrigMBAddress, oldBytes, SIZE); // restore backup

case DLL_THREAD_ATTACH:

case DLL_THREAD_DETACH:

break;

}

return TRUE;

}

void BeginRedirect(LPVOID newFunction)

{

BYTE tempJMP[SIZE] = {0xE9, 0x90, 0x90, 0x90, 0x90, 0xC3}; // 0xE9 = JMP 0x90 = NOP 0xC3 = RET

memcpy(JMP, tempJMP, SIZE); // store jmp instruction to JMP

DWORD JMPSize = ((DWORD)newFunction - (DWORD)pOrigMBAddress - 5); // calculate jump distance

VirtualProtect((LPVOID)pOrigMBAddress, SIZE, // assign read write protection

PAGE_EXECUTE_READWRITE, &oldProtect);

memcpy(oldBytes, pOrigMBAddress, SIZE); // make backup

memcpy(&JMP[1], &JMPSize, 4); // fill the nop's with the jump distance (JMP,distance(4bytes),RET)

memcpy(pOrigMBAddress, JMP, SIZE); // set jump instruction at the beginning of the original function

VirtualProtect((LPVOID)pOrigMBAddress, SIZE, oldProtect, NULL); // reset protection

}

int WINAPI MyMessageBoxW(HWND hWnd, LPCWSTR lpText, LPCWSTR lpCaption, UINT uiType)

{

VirtualProtect((LPVOID)pOrigMBAddress, SIZE, myProtect, NULL); // assign read write protection

memcpy(pOrigMBAddress, oldBytes, SIZE); // restore backup

int retValue = MessageBoxW(hWnd, lpText, lpCaption, uiType); // get return value of original function

memcpy(pOrigMBAddress, JMP, SIZE); // set the jump instruction again

VirtualProtect((LPVOID)pOrigMBAddress, SIZE, oldProtect, NULL); // reset protection

return retValue; // return original return value

}

Netfilter勾點

編輯

使用Netfilter勾點修改Linux核心的網路交通。

#include

#include

#include

#include

#include

#include

#include

#include

/* Port we want to drop packets on */

static const uint16_t port = 25;

/* This is the hook function itself */

static unsigned int hook_func(unsigned int hooknum,

struct sk_buff **pskb,

const struct net_device *in,

const struct net_device *out,

int (*okfn)(struct sk_buff *))

{

struct iphdr *iph = ip_hdr(*pskb);

struct tcphdr *tcph, tcpbuf;

if (iph->protocol != IPPROTO_TCP)

return NF_ACCEPT;

tcph = skb_header_pointer(*pskb, ip_hdrlen(*pskb), sizeof(*tcph), &tcpbuf);

if (tcph == NULL)

return NF_ACCEPT;

return (tcph->dest == port) ? NF_DROP : NF_ACCEPT;

}

/* Used to register our hook function */

static struct nf_hook_ops nfho = {

.hook = hook_func,

.hooknum = NF_IP_PRE_ROUTING,

.pf = NFPROTO_IPV4,

.priority = NF_IP_PRI_FIRST,

};

static __init int my_init(void)

{

return nf_register_hook(&nfho);

}

static __exit void my_exit(void)

{

nf_unregister_hook(&nfho);

}

module_init(my_init);

module_exit(my_exit);

內部IAT勾點

編輯

下例展示通過修改可執行程式的輸入位址表(IAT),把勾點函式替代原函式。

#include

typedef int(__stdcall *pMessageBoxA) (HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType); //This is the 'type' of the MessageBoxA call.

pMessageBoxA RealMessageBoxA; //This will store a pointer to the original function.

void DetourIATptr(const char* function, void* newfunction, HMODULE module);

int __stdcall NewMessageBoxA(HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType) { //Our fake function

printf("The String Sent to MessageBoxA Was : %s\n", lpText);

return RealMessageBoxA(hWnd, lpText, lpCaption, uType); //Call the real function

}

int main(int argc, CHAR *argv[]) {

DetourIATptr("MessageBoxA",(void*)NewMessageBoxA,0); //Hook the function

MessageBoxA(NULL, "Just A MessageBox", "Just A MessageBox", 0); //Call the function -- this will invoke our fake hook.

return 0;

}

void **IATfind(const char *function, HMODULE module) { //Find the IAT (Import Address Table) entry specific to the given function.

int ip = 0;

if (module == 0)

module = GetModuleHandle(0);

PIMAGE_DOS_HEADER pImgDosHeaders = (PIMAGE_DOS_HEADER)module;

PIMAGE_NT_HEADERS pImgNTHeaders = (PIMAGE_NT_HEADERS)((LPBYTE)pImgDosHeaders + pImgDosHeaders->e_lfanew);

PIMAGE_IMPORT_DESCRIPTOR pImgImportDesc = (PIMAGE_IMPORT_DESCRIPTOR)((LPBYTE)pImgDosHeaders + pImgNTHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);

if (pImgDosHeaders->e_magic != IMAGE_DOS_SIGNATURE)

printf("libPE Error : e_magic is no valid DOS signature\n");

for (IMAGE_IMPORT_DESCRIPTOR *iid = pImgImportDesc; iid->Name != NULL; iid++) {

for (int funcIdx = 0; *(funcIdx + (LPVOID*)(iid->FirstThunk + (SIZE_T)module)) != NULL; funcIdx++) {

char *modFuncName = (char*)(*(funcIdx + (SIZE_T*)(iid->OriginalFirstThunk + (SIZE_T)module)) + (SIZE_T)module + 2);

const uintptr_t nModFuncName = (uintptr_t)modFuncName;

bool isString = !(nModFuncName & (sizeof(nModFuncName) == 4 ? 0x80000000 : 0x8000000000000000));

if (isString) {

if (!_stricmp(function, modFuncName))

return funcIdx + (LPVOID*)(iid->FirstThunk + (SIZE_T)module);

}

}

}

return 0;

}

void DetourIATptr(const char *function, void *newfunction, HMODULE module) {

void **funcptr = IATfind(function, module);

if (*funcptr == newfunction)

return;

DWORD oldrights, newrights = PAGE_READWRITE;

//Update the protection to READWRITE

VirtualProtect(funcptr, sizeof(LPVOID), newrights, &oldrights);

RealMessageBoxA = (pMessageBoxA)*funcptr; //Some compilers require the cast like "MinGW" not sure about MSVC

*funcptr = newfunction;

//Restore the old memory protection flags.

VirtualProtect(funcptr, sizeof(LPVOID), oldrights, &newrights);

}

Windows API提供的掛鉤函式

編輯

SetWinEventHook:基本沒有權限問題,也就是說這個API可以Hook到高權限程式的事件,同時支援行程內(WINEVENT_INCONTEXT)和行程外(WINEVENT_OUTOFCONTEXT)2種Hook方式,可以行程外的方式Hook到64位元程式的事件。

SetWindowsHookEx:64位元編程情形,32位元DLL沒法直接注入到64位元的應用程式裡面, 因為位址空間完全不一樣。UAC打開的情況下低權限程式沒法Hook高權限程式。對於64位元問題,解決方法是提供2個DLL,分別可以Hook32和64位元程式。對於權限問題,通過註冊系統服務,由服務行程建立工作行程。因為Windows Vista開始有了Session隔離機制,服務行程執行在Session 0,使用者程式執行在Session 1, Session 2等,如果直接在服務程式里幹活,我們就只能在Session 0里工作。通過建立行程,可以在DuplicateTokenEx後將Token的SessionID設定成目標Session,並且在CreateProcessAsUser時指定目標WinStation和Desktop, 這樣就獲得了System權限,並且也可以和當前桌面行程互動。

相关文章

bat365官方网页版 蛞蝓怎么彻底消灭干净?实测鼻涕虫最怕三种药有这些!
bat365官方网页版 图片大小裁剪

图片大小裁剪

⏱️ 06-27 👁️ 6253
365直播网网络电视台下载 PRJ 文件:它是什么?

PRJ 文件:它是什么?

⏱️ 07-03 👁️ 9068