古老的钩子艺术

导入地址表钩子

// Rint3Hook.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <iostream>
#include <windows.h>
using namespace std;

/*
    获取PE头相对于文件的偏地址 基地址偏移3c 为PE头
    module 基地址
    */
DWORD getPEHeader(DWORD module)
{
    return *(DWORD*)(module + 0x3c) + module;
}

/*
    获取导入表地址
    */
DWORD getImportAddress(DWORD PEHeader, DWORD module)
{
    DWORD ImportDataDirectory = PEHeader + 0x80;
    return *(DWORD*)(ImportDataDirectory)+module;
}

//MessageBoxA源地址
void *msgbox = NULL;
//指向 IAT MessageBoxA函数指针
LPVOID ptr = NULL;
//MyMessageBoxA 值大小
DWORD func = 0;
/*
    Import Address Table hooking
    导入表钩子

    修改导入表中地址指向自己的函数即可如

    call CreateFileA   call [导入表中的地址]

    自己的代码执行完毕之后跳转到我们需要的代码即可!
    */

int WINAPI MyMessageBoxA(_In_opt_ HWND hWnd,
    _In_opt_ LPCSTR lpText,
    _In_opt_ LPCSTR lpCaption,
    _In_ UINT uType)
{
    //hook进入之后修改之前的函数地址否则调用不了MessageBoxA
    VirtualProtectEx(GetCurrentProcess(), ptr, 4, PAGE_READWRITE, 0);
    DWORD temp = (DWORD)msgbox;
    WriteProcessMemory(GetCurrentProcess(), ptr, &temp, 4, 0);

    //调用
    int result=MessageBoxA(NULL, "Hook", "Hook", 0);

    //记住一定要写回去不然下次就不能hook了
    WriteProcessMemory(GetCurrentProcess(), ptr, &func, 4, 0);
    return result;
}

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

    HANDLE MyHandle = GetModuleHandleA(NULL);
    DWORD PEHeader = getPEHeader((DWORD)MyHandle);
    DWORD ImportTableAddress = getImportAddress(PEHeader, (DWORD)MyHandle);
    IMAGE_IMPORT_DESCRIPTOR *iid = (IMAGE_IMPORT_DESCRIPTOR *)ImportTableAddress;
    while (true)
    {
        if (strcmp((char*)(iid->Name + (DWORD)MyHandle), "USER32.dll") == 0)
        {
            cout << (char*)(iid->Name + (DWORD)MyHandle) << endl;
            //INT
            IMAGE_THUNK_DATA *functionArr = (IMAGE_THUNK_DATA *)(iid->OriginalFirstThunk + (DWORD)MyHandle);
            //IAT
            IMAGE_THUNK_DATA *functionArr2 = (IMAGE_THUNK_DATA *)(iid->FirstThunk + (DWORD)MyHandle);
            cout << hex << functionArr << endl;
            while (functionArr->u1.AddressOfData != NULL)
            {

                char *str = NULL;

                DWORD temp = (functionArr->u1.AddressOfData + 2 + (DWORD)MyHandle);
                cout << hex << functionArr->u1.AddressOfData << endl;
                str = (char*)temp;
                if (strcmp(str, "MessageBoxA") == 0){
                    DWORD dwOld;
                    SIZE_T dwW;
                    ptr = &(functionArr2->u1.Function);
                    msgbox = (void*)functionArr2->u1.Function;
                    BOOL isOpen = VirtualProtectEx(GetCurrentProcess(), ptr, 4, PAGE_READWRITE, &dwOld);
                    func = (DWORD)MyMessageBoxA;
                    bool isOpen1 = WriteProcessMemory(GetCurrentProcess(), ptr, &func, 4, &dwW);
                    MessageBoxA(NULL, "qwe", "qwe", 0);
                    return 0;
                }
                functionArr++;
                functionArr2++;
            }
            break;
        }
        else
            iid += 1;
    }
    return 0;
}


内联函数钩子

// 内敛函数钩子.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <windows.h>
#include <iostream>
using namespace std;

//老函数的字节
byte oldCode[5];
//新的函数的字节
byte newCode[5];

//MessageBoxA地址
void *msgbox;

/*
    将MessageBoxA的前五个字节改为
    jmp MyMessageBoxA


    修改完毕之后调用MessageBoxA之前需要将前五个字节修改回来

    调用完毕需要将五个字节改回去 这样形成不断hook
*/

//修改函数前5个字节
void CaptureFunction(){
    VirtualProtectEx(GetCurrentProcess(), msgbox, 5, PAGE_READWRITE, 0);
    memcpy(oldCode, MessageBoxA, 5);
    WriteProcessMemory(GetCurrentProcess(), msgbox, newCode, 5, 0);
}

//恢复函数前5个字节
void UnCaptureFunction(){
    VirtualProtectEx(GetCurrentProcess(), msgbox, 5, PAGE_READWRITE, 0);
    WriteProcessMemory(GetCurrentProcess(), msgbox, oldCode, 5, 0);
}

typedef int(WINAPI *MSGBOX)(_In_opt_ HWND hWnd,
    _In_opt_ LPCSTR lpText,
    _In_opt_ LPCSTR lpCaption,
    _In_ UINT uType);

int WINAPI MyMessageBoxA(_In_opt_ HWND hWnd,
    _In_opt_ LPCSTR lpText,
    _In_opt_ LPCSTR lpCaption,
    _In_ UINT uType){
    UnCaptureFunction();
    int res=MessageBoxA(NULL,"Hook","Hook",0);
    CaptureFunction();
    return res;

}



int _tmain(int argc, _TCHAR* argv[])
{
    HMODULE user32= LoadLibraryA("user32.dll");
    msgbox=GetProcAddress(user32,"MessageBoxA");

    /*
        将前五个字节保存起来
    */
    DWORD funcAddrress = (DWORD)MyMessageBoxA - (DWORD)(MessageBoxA)-5;
    newCode[0] = 0xe9;
    byte *temp = &newCode[1];
    memcpy(temp,&funcAddrress,4);

    CaptureFunction();
    MessageBoxA(NULL,"f","f",0);
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
编译原理是计算机专业的一门核心课程,旨在介绍编译程序构造的一般原理和基本方法。编译原理不仅是计算机科学理论的重要组成部分,也是实现高效、可靠的计算机程序设计的关键。本文将对编译原理的基本概念、发展历程、主要内容和实际应用进行详细介绍编译原理是计算机专业的一门核心课程,旨在介绍编译程序构造的一般原理和基本方法。编译原理不仅是计算机科学理论的重要组成部分,也是实现高效、可靠的计算机程序设计的关键。本文将对编译原理的基本概念、发展历程、主要内容和实际应用进行详细介绍编译原理是计算机专业的一门核心课程,旨在介绍编译程序构造的一般原理和基本方法。编译原理不仅是计算机科学理论的重要组成部分,也是实现高效、可靠的计算机程序设计的关键。本文将对编译原理的基本概念、发展历程、主要内容和实际应用进行详细介绍编译原理是计算机专业的一门核心课程,旨在介绍编译程序构造的一般原理和基本方法。编译原理不仅是计算机科学理论的重要组成部分,也是实现高效、可靠的计算机程序设计的关键。本文将对编译原理的基本概念、发展历程、主要内容和实际应用进行详细介绍编译原理是计算机专业的一门核心课程,旨在介绍编译程序构造的一般原理和基本

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值