50.破坏性更小的代码跳转功能完善(无敌+秒杀)

免责声明:内容仅供学习参考,请合法利用知识,禁止进行违法犯罪活动!

完整代码地址:下载名为: htdHook2.0.zip 的文件

链接:https://pan.baidu.com/s/17_aXbMCyexGIlP3Yz_ajIA

提取码:ilbw

--来自百度网盘超级会员V4的分享

上一个内容:49.实现调试器HOOK机制

以 49.实现调试器HOOK机制 它的代码为基础进行修改
48.破坏性更小的代码跳转(异常)(异常拦截说明在它里面)

辅助核心文件说明:

CWndMain(辅助窗口主要由OnBnClickedButton2函数开始)

调用SetHook函数就开始进行拦截了,拦截(SetHook函数)中实现了游戏代码修改、还原、拦截地址与拦截之后的处理函数关联功能。

HOOKPOINT.h文件里的内容:

// 当前文件是用来关联拦截点与拦截之后处理函数、游戏代码修改、还原的 HOOKPOINT.h 文件里的函数
#pragma once
#define _HTDHOOK2_

typedef struct CPUINFO {
    unsigned EFlags;
    unsigned Edi;
    unsigned Esi;
    unsigned Ebp;
    unsigned Esp;
    unsigned Ebx;
    unsigned Edx;
    unsigned Ecx;
    unsigned Eax;
    unsigned Eip;
}*PCPUINFO;

// 下面代码不删的原因是,记录一下c语言写法(玩法)
//#ifdef _HTDHOOK2_
//#define HOOKREFS PCONTEXT val
//#else 
//#define HOOKREFS PCPUINFO val
//#endif // _HTDHOOK2_

#define HOOKREFS2 PCONTEXT val
#define HOOKREFS PCONTEXT val



typedef bool (*HOOKBACK)(PCPUINFO);
typedef bool (*HOOKBACK2)(PCONTEXT);

#define _ESI val->Esi
#define _EDI val->Edi
#define _EBP val->Ebp
#define _ESP val->Esp
#define _EBX val->Ebx
#define _EDX val->Edx
#define _ECX val->Ecx
#define _EAX val->Eax
#define _EIP val->Eip

typedef  unsigned char uchar;


typedef class HOOKPOINT
{
private:
    // Address表示在哪进入外挂代码,也就是在什么地方做hook
    LPVOID Address;
    HOOKPOINT* NextPoint;
    HOOKPOINT* BackPoint;
    // 外挂代码的地址
    HOOKBACK DestCall;

public:

    // 修复区代码
    char* CodeFix;
    LPVOID AddressRet;
public:
    HOOKPOINT();
    ~HOOKPOINT();
    HOOKPOINT(LPVOID, LPVOID, LPVOID _HOOKBACK, uchar lenth, HOOKPOINT*, HOOKPOINT* _NextPoint = NULL);
    HOOKPOINT* AddPonit(LPVOID, LPVOID, LPVOID _HOOKBACK, uchar lenth);
    HOOKPOINT* FindPoint(LPVOID);

    HOOKBACK2 GetHookBack2();
    HOOKBACK GetHookBack();
}*PHOOKPOINT;

HOOKPOINT.cpp文件里的内容:

#include "pch.h"
#include "HOOKPOINT.h"

unsigned GetJMPCode(unsigned distance, unsigned eip);

HOOKPOINT::HOOKPOINT()
{
}

HOOKPOINT::~HOOKPOINT()
{
    delete CodeFix;
}

HOOKPOINT::HOOKPOINT(LPVOID _adr, LPVOID _adrRet, LPVOID _hbk, uchar lenth, HOOKPOINT* _BackP, HOOKPOINT* _NextPoint):
    Address(_adr), AddressRet(_adrRet), DestCall((HOOKBACK)_hbk), BackPoint{ _BackP }, NextPoint{ _NextPoint }
{
    DWORD offcount;

    /**
        下面是修复 call(硬编码是E8) JMP(硬编码是E9)
        _adr是要做hook的地方, 假设做hook的地方是call xxxx
        call 后面的地址是通过
         它是有一个公式要跳转到的目标地址 - 执行jmp指令的内存地址(eip) - 5 这个公式算出来的
         只单纯的对它修复,地址是原来的,但是这个代码被我们的辅助代码进行了修复也就是它的内存地址
         进入了辅助代码的内存空间里,这就导致要跳转的位置不正确,所以对call或者jmp这种跳转做修复时
         它们后面跟的地址也要使用 要跳转到的目标地址 - 执行jmp指令的内存地址(eip) - 5 这个公式计算
         公式里的值全都要用辅助代码给它的哪个地址才可以
         
         下面只实现了长跳的jmp与call
    */
    char* code = (char*)(_adr);
    unsigned* u = (unsigned*)(code + 1);
    unsigned dest = u[0] + (unsigned)_adr + 5;
    bool fix{};

    /**
       switch的case用的是int类型,然后code[0]是一个char类型然后switch会做一个隐形的类型转换
       所以要把code[0]的值当做int类型来写
    */
    switch (code[0])
    {
    case 0xFFFFFFE8: {
    }
    case 0xFFFFFFE9:{
        fix = true;
        break;
    }
    default:
        break;
    }

    CodeFix = new char[lenth + 0x5];
    memcpy(CodeFix, _adr, lenth);

    if (fix) {
        AfxMessageBox(L"非借壳是否会卡拉和监考老师");
        u = (unsigned*)(CodeFix + 1);
        u[0] = GetJMPCode(dest, (unsigned)CodeFix);
    }

    /**
      下面是之前分析剑侠情缘用来无敌的代码
      mov [esi + 10], edi   
      mov eax, [esi+10]
      jmp Address+lenth // 这个是执行完剑侠情缘原有代码让它再跳回去

      CodeFix长度是 lenth+0x5,lenth是要进行hook位置的指令长度,0x5是执行完指令之后让他跳回去

    */
    DWORD dOld;
    CodeFix[lenth] = 0xE9;
    unsigned* adr = (unsigned*)(CodeFix + lenth + 1);
    adr[0] = GetJMPCode((unsigned)_adr + lenth, (unsigned)&CodeFix[lenth]);

    VirtualProtect(CodeFix, lenth+0x5, PAGE_EXECUTE_READWRITE, &dOld);
}

HOOKPOINT* HOOKPOINT::AddPonit(LPVOID _adr,LPVOID _adrRet, LPVOID _hbk, uchar lenth)
{
    NextPoint = new HOOKPOINT(_adr, _adrRet, _hbk, lenth, this);
    return NextPoint;
}

HOOKPOINT* HOOKPOINT::FindPoint(LPVOID _adr)
{
    PHOOKPOINT _point = this;
    do {
        if (_point->Address == _adr)return _point;
        _point = _point->NextPoint;
    }while(_point);
    return nullptr;
}

HOOKBACK2 HOOKPOINT::GetHookBack2()
{
    HOOKBACK2 _rt = (HOOKBACK2)DestCall;
    return _rt;
}

HOOKBACK HOOKPOINT::GetHookBack()
{
    return DestCall;
}

htdHook2.cpp文件里面的内容:

#include "pch.h"
#include "htdHook2.h"
htdHook2* htdHook2Ptr;

LONG _stdcall PvectoredExceptionHandler(PEXCEPTION_POINTERS val) {
    //CString wTxt;
    //wTxt.Format(L"111----%X", val->ContextRecord->Eip);
    //AfxMessageBox(wTxt);
    //return EXCEPTION_CONTINUE_SEARCH;

    /**
        call指令执行时会让eip指向下一条指令的位置,
        这里减去0x5是让他回到call的位置,也就是得到从哪来的
    */
    unsigned _eip = val->ContextRecord->Eip;

    PHOOKPOINT point = htdHook2Ptr->Points.FindPoint((LPVOID)_eip);
    if (point) {
        if (point->GetHookBack2()(val->ContextRecord)) {
            // 继续执行原有代码
            val->ContextRecord->Eip = (unsigned)point->CodeFix;
        }
        else {
            // 调转到指定位置执行
            val->ContextRecord->Eip = (unsigned)point->AddressRet;
        }
        // 拦截异常不让当前异常往后传递
        return EXCEPTION_CONTINUE_EXECUTION;
    }
    // 拦截异常让当前异常往后传递(表示当前异常不是我们要拦截的异常)
    else return EXCEPTION_CONTINUE_SEARCH;

}

htdHook2::htdHook2()
{
    PPointLast = &Points;
    htdHook2Ptr = this;
    AddVectoredExceptionHandler(1, PvectoredExceptionHandler);
}

void htdHook2::SetHook(LPVOID Address, uchar len, HOOKBACK2 hookBack, LPVOID AddressRet)
{
    DWORD dOld;
    DWORD dNew;

    // 更改内存权限让它可读可写
    VirtualProtect(Address, 0x1, PAGE_EXECUTE_READWRITE, &dOld);

    PPointLast = PPointLast->AddPonit(Address, AddressRet, hookBack, len);

    char* code = (char*)Address;
    code[0] = 0xCC;

    VirtualProtect(Address, 0x1, dOld, &dNew);
}

htdHook2.h文件里面的内容:

// 当前文件是用来关联拦截点与拦截之后处理函数、游戏代码修改、还原的 HOOKPOINT.h 文件里的函数
#pragma once
#include "HOOKPOINT.h"
class htdHook2
{
private:
    PHOOKPOINT PPointLast{};
public:
    HOOKPOINT Points;
public:
    htdHook2();
    void SetHook(LPVOID Address, uchar len, HOOKBACK2 hookBack, LPVOID AddressRet=0);
};


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值