// 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(GetModuleHandleA("user32.dll"), // get address of original "MessageBoxW"); if (pOrigMBAddress != NULL) BeginRedirect(MyMessageBoxW); // start detouring break; case DLL_PROCESS_DETACH: VirtualProtect((LPVOID)pOrigMBAddress, SIZE, myProtect, &oldProtect); // assign read write protection memcpy(pOrigMBAddress, oldBytes, SIZE); // restore backup VirtualProtect((LPVOID)pOrigMBAddress, SIZE, oldProtect, &myProtect); // reset protection 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, &myProtect); // reset protection } int WINAPI MyMessageBoxW(HWND hWnd, LPCWSTR lpText, LPCWSTR lpCaption, UINT uiType) { VirtualProtect((LPVOID)pOrigMBAddress, SIZE, myProtect, &oldProtect); // 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, &myProtect); // reset protection return retValue; // return original return value } Netfilter hook This example shows how to use hooking to alter network traffic in the Linux kernel using Netfilter. #include <linux/module.h> #include <linux/kernel.h> #include <linux/skbuff.h> #include <linux/ip.h> #include <linux/tcp.h> #include <linux/in.h> #include <linux/netfilter.h> #include <linux/netfilter_ipv4.h> /* 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); }