हुकिंग: Difference between revisions

From Vigyanwiki
m (8 revisions imported from alpha:हुकिंग)
 
(One intermediate revision by one other user not shown)
Line 447: Line 447:
[[Category:Templates that add a tracking category]]
[[Category:Templates that add a tracking category]]
[[Category:Templates that generate short descriptions]]
[[Category:Templates that generate short descriptions]]
[[Category:Vigyan Ready]]

Latest revision as of 10:17, 1 December 2023

कंप्यूटर प्रोग्रामिंग में हुकिंग शब्द मॉड्यूलर प्रोग्रामिंग के बीच कॉल फ़ंक्शन या इवेंट (कंप्यूटिंग) को इंटरसेप्ट करके ऑपरेटिंग सिस्टम, एप्लिकेशन या अन्य सॉफ़्टवेयर कॉम्पोनेंट के प्रोग्राम को परिवर्तित या इंटरसेप्ट करने के लिए उपयोग की जाने वाली तकनीकों की एक टेबल सम्मिलित होती है। ऐसे कोड जो इंटरसेप्टेड कॉल फ़ंक्शन ईवेंट या प्रोग्रामों को सुरक्षित रखते हैं उन्हे 'हुक' कहा जाता है।

हुकिंग का उपयोग कई उद्देश्यों के लिए किया जाता है जिसमें डिबगिंग और फंक्शन का विस्तार सम्मिलित है। उदाहरणों में किसी एप्लिकेशन के लिए कीबोर्ड या माउस ईवेंट संदेशों को इंटरसेप्ट करना या किसी एप्लिकेशन के अन्य कॉम्पोनेंट के फ़ंक्शन को संशोधित करने के लिए ऑपरेटिंग सिस्टम मे कॉल फ़ंक्शन को इंटरसेप्ट करना सम्मिलित हो सकता है। इसका व्यापक रूप से बेंचमार्किंग प्रोग्राम में भी उपयोग किया जाता है। उदाहरण के लिए 3डी गेम में फ्रेम दर को आउटपुट और इनपुट हुकिंग के माध्यम से प्राप्त किया जाता है।

हुकिंग का उपयोग मॉलिसियस कोड द्वारा भी किया जा सकता है। उदाहरण के लिए हुकिंग प्रोग्राम रूटकिट सॉफ़्टवेयर के एपीआई कॉल फ़ंक्शन के आउटपुट द्वारा स्वयं को इंविसिबल (अस्पष्ट) बनाने का प्रयास करते हैं और उनके आउटपुट को प्रदर्शित कर सकते हैं, जिसमे सामान्यतः हुकिंग तकनीकों का उपयोग किया जाता है।

प्रकार

सामान्यतः हुक को तब प्रयुक्त किया जाता है जब सॉफ़्टवेयर पहले से ही प्रारम्भ हो, क्योकि हुकिंग एक ऐसा फ़ंक्शन है जिसे एप्लिकेशन प्रारम्भ होने से पहले भी प्रयुक्त किया जा सकता है। इन दोनों तकनीकों का निम्नलिखित रूप से वर्णन किया गया है।

सोर्स कोड संशोधन

किसी एप्लिकेशन के प्रारम्भ होने से पहले रिवर्स इंजीनियरिंग तकनीकों के माध्यम से संचालित कोड या लाइब्रेरी के सोर्स कोड को संशोधित करके हुकिंग प्राप्त की जा सकती है। इसका उपयोग सामान्यतः कॉल फ़ंक्शन को मॉनिटर करने या उन्हें पूर्ण रूप से परिवर्तित करने के लिए या इंटरसेप्ट करने के लिए किया जाता है।

उदाहरण के लिए एक डिस्सेबलर का उपयोग करके मॉड्यूल मे किसी फ़ंक्शन के इंटरपॉइंटर को प्राप्त किया जा सकता है और इसे किसी अन्य लाइब्रेरी मॉड्यूल मे डायनामिक रूप से लोड करने के लिए परिवर्तित किया जा सकता है। पुनः लोड की गई लाइब्रेरी के डिजायर प्रोग्राम को निष्पादित किया जा सकता है। यदि प्रयुक्त हो तो एक अन्य संबंधित एप्रोच प्रोग्राम जिसके द्वारा हुकिंग प्राप्त की जा सकती है। जिसमे सामान्यतः एक्सेक्यूट प्रोग्राम की इम्पॉर्ट टेबल को परिवर्तित किया जा सकता है। इस इम्पॉर्ट टेबल को किसी भी अतिरिक्त लाइब्रेरी मॉड्यूल मे लोड करने के लिए संशोधित किया जा सकता है और साथ ही यह भी परिवर्तित किया जा सकता है कि जब एप्लिकेशन द्वारा किसी फ़ंक्शन को कॉल किया जाता है तब इसमे कौन सा एक्सटर्नल कोड प्रयुक्त होता है। फ़ंक्शन हुकिंग प्राप्त करने का एक वैकल्पिक प्रकार रैपर लाइब्रेरी के माध्यम से कॉल फ़ंक्शन को इंटरसेप्ट करना है। रैपर एक लाइब्रेरी का एक फ़ंक्शन है जिसे एक एप्लिकेशन लोड करता है, जिसमें मूल लाइब्रेरी के सभी समान फ़ंक्शन होते हैं जिसे वह प्रतिस्थापित करता है। अर्थात् सभी फ़ंक्शन जो एक्सेक्यूटेबल हैं और प्रतिस्थापन के बीच अनिवार्य रूप से समान हैं। इस रैपर लाइब्रेरी को मूल लाइब्रेरी के किसी भी फ़ंक्शन को कॉल करने के लिए डिज़ाइन किया जा सकता है या इस लॉजिक कोड के एक नए फ़ंक्शन के साथ परिवर्तित किया जा सकता है।

रनटाइम संशोधन

ऑपरेटिंग सिस्टम और सॉफ़्टवेयर रनटाइम पर सामान्यतः इवेंट हुक इन्सर्ट करने के फ़ंक्शन उपलब्ध होते है क्योकि हुक इन्सर्ट करने की प्रक्रिया को ऐसा करने के लिए पर्याप्त रूप से स्वीकृति दी जाती है। उदाहरण के लिए माइक्रोसॉफ्ट विंडोज़ उपयोगकर्ताओं को हुक इन्सर्ट करने की स्वीकृति देता है जिसका उपयोग सिस्टम इवेंट और डायलॉग, स्क्रॉल बार और मेनू के साथ-साथ अन्य आइटम के लिए एप्लिकेशन इवेंट को संसाधित या संशोधित करने के लिए किया जा सकता है। यह हुक को कीबोर्ड और माउस (कंप्यूटिंग) इवेंट को सम्मिलित करने, हटाने, संसाधित करने या संशोधित करने की भी स्वीकृति देता है। लिनक्स एक और उदाहरण प्रदान करता है जहां नेटफ़िल्टर के माध्यम से कर्नेल (ऑपरेटिंग सिस्टम) मे नेटवर्क इवेंट को संसाधित करने के लिए हुक का उपयोग सामान्य रूप से किया जा सकता है। जब ऐसे फ़ंक्शनों को इन्सर्ट नहीं किया जा सकता है तब हुकिंग का एक फ़ंक्शन विशेष प्रक्रिया द्वारा लाइब्रेरी कॉल फ़ंक्शन को इंटरसेप्ट करने का कार्य करता है। फ़ंक्शन हुकिंग को एक इंजेक्टेड कोड पर जाने के लिए टार्गेट फ़ंक्शन के पहले कुछ कोड इंस्ट्रक्शन को परिवर्तित करने निष्पादित (एक्सेक्यूट) किया जाता है। वैकल्पिक रूप से लाइब्रेरी फ़ंक्शन का उपयोग करने वाले सिस्टम पर इंटरप्ट वेक्टर टेबल या इंपोर्ट डिस्क्रिप्टर टेबल को मेमोरी में संशोधित किया जा सकता है। सामान्यतः ये फ़ंक्शन सोर्स कोड संशोधन के समान प्रोग्रामों को कंपाइल करते हैं लेकिन इसके अतिरिक्त किसी प्रोग्राम की मेमोरी में स्थित इंस्ट्रक्शन और संरचनाओं को परिवर्तित किया जा सकता है।

सैंपल कोड

वर्चुअल मेथड टेबल हुकिंग (वीएमटी हुकिंग)

जब क्लास किसी वर्चुअल फ़ंक्शन (या मेथड) को इनहेरिट करती है तो कंपाइलर क्लास में एक हिडेन मेंबर वेरिएबल को प्रयुक्त किया जाता है जो वर्चुअल मेथड टेबल (वीएमटी या वीटेबल) की ओर संकेत देता है। प्रायः कंपाइलर क्लास के प्रत्येक उदाहरण के पहले 4 बाइट पर हिडेन वीएमटी पॉइंटर को रखते हैं। वीएमटी पॉइंटर मूल रूप से सभी वर्चुअल फ़ंक्शन के लिए पॉइंटर्स की एक टेबल है जिसे क्लास मे इंस्टेंस कॉल कर सकते हैं। रनटाइम पर ये पॉइंटर्स सही फ़ंक्शन को इंगित करने के लिए प्रयुक्त किए जाते हैं क्योंकि कंपाइलर रनटाइम अभी तक ज्ञात नहीं है कि क्या बेस फ़ंक्शन को कॉल किया जाना है या किसी डेरिवेड क्लास से फ़ंक्शन का ओवरराइड प्रोग्राम को कॉल किया जाना है। इसलिए वर्चुअल फ़ंक्शन को किसी भी वीएमटी पॉइंटर को प्रतिस्थापित करके हुक किया जा सकता है जो वे प्रायः प्रदर्शित होते हैं। नीचे दिया गया कोड माइक्रोसॉफ़्ट विंडोज़ में एक विशिष्ट वीएमटी हुक का उदाहरण प्रदर्शित करता है जिसे C++ में लिखा गया है।[1]

#include <iostream>
#include "windows.h"
 
using namespace std;
 
class VirtualClass
{
public:
 
    int number;
 
    virtual void VirtualFn1() //This is the virtual function that will be hooked.
    {
        cout << "VirtualFn1 called " << number++ << "\n\n";
    }
};
 
 
 
 
using VirtualFn1_t = void(__thiscall*)(void* thisptr); 
VirtualFn1_t orig_VirtualFn1;
 

void __fastcall hkVirtualFn1(void* thisptr, int edx) //This is our hook function which we will cause the program to call instead of the original VirtualFn1 function after hooking is done.
{
    cout << "Hook function called" << "\n";
 
    orig_VirtualFn1(thisptr); //Call the original function.
}
 
 
 
 
int main()
{
    VirtualClass* myClass = new VirtualClass(); //Create a pointer to a dynamically allocated instance of VirtualClass.
 
    void** vTablePtr = *reinterpret_cast<void***>(myClass); //Find the address that points to the base of VirtualClass' VMT (which then points to VirtualFn1) and store it in vTablePtr.
 
    DWORD oldProtection;
    VirtualProtect(vTablePtr, 4, PAGE_EXECUTE_READWRITE, &oldProtection); //Removes page protection at the start of the VMT so we can overwrite its first pointer.
 
    orig_VirtualFn1 = reinterpret_cast<VirtualFn1_t>(*vTablePtr); //Stores the pointer to VirtualFn1 from the VMT in a global variable so that it can be accessed again later after its entry in the VMT has been 
                                                                  //overwritten with our hook function.
 
    *vTablePtr = &hkVirtualFn1; //Overwrite the pointer to VirtualFn1 within the virtual table to a pointer to our hook function (hkVirtualFn1).
 
    VirtualProtect(vTablePtr, 4, oldProtection, 0); //Restore old page protection.
 
    myClass->VirtualFn1(); //Call the virtual function from our class instance. Because it is now hooked, this will actually call our hook function (hkVirtualFn1).
    myClass->VirtualFn1();
    myClass->VirtualFn1();
 
    delete myClass;
 
    return 0;
}

यह ध्यान रखना महत्वपूर्ण है कि सभी वर्चुअल फ़ंक्शन क्लास के कॉम्पोनेंट फ़ंक्शन होते हैं और सभी नॉन-स्टैटिक क्लास के फ़ंक्शन को _thiscall कॉलिंग कन्वेंशन के साथ कॉल किया जाता है जब तक कि फ़ंक्शन एक वेरिएबल संख्या नहीं लेता है जिसे केस _cdecl के साथ _thiscall कॉलिंग कन्वेंशन ईसीएक्स रजिस्टर कहा जाता है। x86 आर्किटेक्चर के माध्यम से कॉलिंग क्लास इंस्टेंस को सामान्यतः इस पॉइंटर के रूप में संदर्भित करने के लिए एक पॉइंटर पास करता है। इसलिए हुक फ़ंक्शन द्वारा प्रयुक्त किए गए इस पॉइंटर को सही से इंटरसेप्ट करने और इसे एक फ़ंक्शन के रूप में उपयोग करने के लिए ईसीएक्स रजिस्टर में देखा जा सकता है। उपरोक्त उदाहरण में यह _fastcall कॉलिंग कन्वेंशन फ़ंक्शन का उपयोग करने के लिए हुक फ़ंक्शन (hkVirtualFn1) को प्रयुक्त करके किया जाता है जो कि हुक फ़ंक्शन को उसके एक लॉजिक फ़ंक्शन के लिए ईसीएक्स रजिस्टर में देखने का कारण बनता है।

यह भी ध्यान दें कि उपरोक्त उदाहरण में हुक फ़ंक्शन (hkVirtualFn1) स्वयं एक फ़ंक्शन नहीं है। इसलिए यह _thiscall कॉलिंग कन्वेंशन फ़ंक्शन का उपयोग नहीं कर सकता है। इसके अतिरिक्त _fastcall फ़ंक्शन का उपयोग करता है क्योंकि यह एक अन्य कॉलिंग कन्वेंशन फ़ंक्शन है जो किसी लॉजिक फ़ंक्शन के लिए ईसीएक्स रजिस्टर लॉजिक फ़ंक्शन को प्रदर्शित करता है।

सी# कीबोर्ड इवेंट हुक

निम्न उदाहरण माइक्रोसॉफ्ट नेट फ्रेमवर्क का उपयोग करके माइक्रोसॉफ़्ट विंडोज़ में कीबोर्ड ईवेंट को प्रदर्शित करता है।

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 */
    static private 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);
        }
    }
}

एपीआई/फ़ंक्शन हुकिंग/इंटरसेप्शन जेएमपी इंस्ट्रक्शन या ​​स्प्लिसिंग का उपयोग

निम्नलिखित सोर्स कोड एक एपीआई/फ़ंक्शन हुकिंग विधि का उदाहरण है जो एक डेस्टिनेशन फ़ंक्शन के पहले 6 बाइट को जेएमपी (x86 इंस्ट्रक्शन) के साथ एक नए फ़ंक्शन पर ओवरराइट करके हुक करता है। कोड को एक डायनामिक-लिंक लाइब्रेरी फ़ाइल में कंपाइल किया जाता है और फिर डायनामिक-लिंक लाइब्रेरी इंजेक्शन की किसी भी एक विधि का उपयोग करके प्रोग्राम को लोड किया जा सकता है। मूल फ़ंक्शन के बैकअप का उपयोग करके पहले 6 बाइट को पुनर्स्थापित किया जा सकता है, जिससे कॉल फ़ंक्शन इंटरप्ट न हो। सामान्यतः इस उदाहरण में विंडोज 32 एपीआई फ़ंक्शन एसएमएस बॉक्स से संबद्ध है।[2]

/*
 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 <windows.h>  
#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(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
 }

नेटफ़िल्टर हुक

यह उदाहरण प्रदर्शित करता है कि नेटफिल्टर का उपयोग करके लिनक्स कर्नेल में नेटवर्क ट्रैफ़िक को परिवर्तित करने के लिए हुकिंग का उपयोग कैसे करें।

#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);
}

module_init(my_init);
module_exit(my_exit);

इंटर्नल आईएटी हुकिंग

निम्नलिखित कोड दर्शाता है कि किसी अन्य मॉड्यूल प्रोग्राम से डेमोंस्ट्रेट फ़ंक्शन को कैसे हुक किया जाए। इसका उपयोग कॉलिंग फ़ंक्शन से भिन्न प्रोग्राम में फ़ंक्शन को हुक करने के लिए किया जा सकता है। इसके लिए कोड को एक डायनामिक-लिंक लाइब्रेरी फ़ाइल में कंपाइल किया जाना चाहिए और फिर डायनामिक-लिंक लाइब्रेरी इंजेक्शन की किसी भी विधि का उपयोग करके प्रोग्राम में लोड किया जाना चाहिए। इस फ़ंक्शन का लाभ यह है कि यह एंटीवायरस सॉफ्टवेयर या एंटी-चीट सॉफ़्टवेयर द्वारा एक्सेस किया जा सकता है। कोई भी इसे एक्सटर्नल हुक में बना सकता है जो किसी भी मॉलिसियस कॉल का उपयोग नहीं करता है। पोर्टेबल एक्ज़ीक्यूटेबल हेडर (पीईएच) में इम्पोर्ट एड्रेस टेबल (आईएटी) सम्मिलित होती है जिसे परिवर्तित किया जा सकता है जैसा कि नीचे दिए गए सोर्स कोड में दिखाया गया है। नीचे दिया गया सोर्स कोड माइक्रोसॉफ़्ट विंडोज़ के अंतर्गत कंपाइल होता है।

#include <windows.h>

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 though
	*funcptr = newfunction;

	//Restore the old memory protection flags.
	VirtualProtect(funcptr, sizeof(LPVOID), oldrights, &newrights);
}

यह भी देखें

संदर्भ

  • Jonathan Daniel (2013-11-27). "Hooking explained: detouring library calls and vtable patching in Windows/Linux/MAC-OSX". Retrieved 2014-01-01.
  • Binh Nguyen (2004-08-16). "Hacking-Lexicon / Linux Dictionary V 0.16". Retrieved 2008-02-23. Hook
  • [2012-06-29: Link appears to be dead] Author: Holy Father (2002-06-10). "Hooking Windows API - Technics of hooking API functions on Windows 1.1 english" (PDF). Archived from the original (PDF) on 2009-12-29. Retrieved 2008-02-21. {{cite web}}: |author= has generic name (help)

बाहरी संबंध

विंडोज़

  • आयात पता टेबल फ़ंक्शन हुकिंग पर जानकारी।
  • हुकिंग पर माइक्रोसॉफ्ट से जानकारी
  • x86 हुकिंग के संबंध में जानकारी और विभिन्न तकनीकें।
  • APISpy32 एक एप्लिकेशन है जिसका उपयोग Win32 API को हुक करने के लिए किया जाता है।
  • Detours माइक्रोसॉफ्ट रिसर्च द्वारा बनाई गई एक सामान्य प्रयोजन फ़ंक्शन हुकिंग लाइब्रेरी है जो C/C++ में काम करती है।
  • [2] किसी अन्य प्रक्रिया में कोड डालने के तीन तरीके।
  • HookTool SDK (ACF SDK) एपीआई हुकिंग और कोड इंजेक्शन पर एक व्यापक अवलोकन प्रदान करता है। एक व्यावसायिक उत्पाद भी उपलब्ध है.
  • [3] C++ और डेल्फ़ी के लिए एक व्यावसायिक x86 और x64 API हुकिंग और डायनामिक-लिंक लाइब्रेरी इंजेक्शन लाइब्रेरी है।
  • EasyHook एक ओपन सोर्स हुकिंग इंजन है जो विंडोज़ में उपयोगकर्ता और कर्नेल भूमि दोनों में x86 और x64 का समर्थन करता है।
  • SpyStudio एप्लिकेशन ट्रेस SpyStudio एक एप्लिकेशन ट्रेसर है जो कॉल को हुक करता है, परिणामों को संरचित तरीके से प्रदर्शित करता है।
  • rohitab.com एपीआई मॉनिटर एक फ्रीवेयर एप्लिकेशन है जो 32-बिट और 64-बिट एप्लिकेशन और सेवाओं में 10,000+ विंडोज एपीआई और COM इंटरफेस को हुक और प्रदर्शित कर सकता है।
  • डेविएरे एपीआई हुक डेविएरे एक फ्रीवेयर इंटर-प्रोसेस हुक फ्रेमवर्क है जिसका उपयोग अन्य प्रक्रियाओं के एपीआई कॉल को इंटरसेप्ट करने और पूर्ण दिखाने के लिए किया जा सकता है। पैरामीटर जानकारी या एपीआई मॉनिटर बनाएं।
  • WinAPIOverride WinAPIOverride गैर व्यावसायिक उपयोग के लिए एक फ्रीवेयर है। यह Win32 API, COM, OLE, ActiveX, .NET को 32-बिट और 64-बिट प्रक्रियाओं में हुक कर सकता है। इसमें पोस्ट विश्लेषण टूल की निगरानी सम्मिलित है।
  • urmem मेमोरी (हुक, पैच, पॉइंटर रैपर, सिग्नेचर स्कैनर आदि) के साथ काम करने के लिए C++11 क्रॉस-प्लेटफॉर्म लाइब्रेरी (x86)

लिनक्स

  • [4] एक छात्र अनुसंधान परियोजना जो उपयोग करती है हुकिंग.
  • [5] कार्यक्षमता जो सॉफ़्टवेयर के एक टुकड़े को किसी अन्य प्रक्रिया के निष्पादन को देखने और नियंत्रित करने की स्वीकृति देती है .
  • [6] साझा लाइब्रेरी कॉल को हुक करने के लिए LD_PRELOAD का उपयोग।

Emacs

  • Emacs Hooks Emacs के अनुकूलन के लिए हुक एक महत्वपूर्ण तंत्र हैं। हुक एक लिस्प वैरिएबल है जिसमें कुछ अच्छी तरह से परिभाषित अवसरों पर बुलाए जाने वाले कार्यों की एक सूची होती है। (इसे हुक चलाना कहते हैं।)

ओएस एक्स और आईओएस

  • Cydia Substrate जेलब्रेक किए गए iOS उपकरणों के लिए एक ढांचा है जो डेवलपर्स को किसी अन्य ढांचे या एप्लिकेशन से जुड़ने की स्वीकृति देता है।
  • harpoon रनटाइम फ़ंक्शन हुकिंग के लिए एक OS

गहराई में एपीआई हुकिंग

  • x86 API Hooking Demystified x86 आर्किटेक्चर के लिए विभिन्न एपीआई हुकिंग विधियों पर लेख।