分享一个编写传奇封外挂(反外挂)系统的完成过程 - API检测篇[原创]

分享一个编写传奇封外挂(反外挂)系统的完成过程[原创]


正文

        游戏外挂的编写离不开对API的操作调用。通过逆向思维思考,我们要反外挂第一个要保护和监测的就是游戏进程的API函数。比如ws2_32.dll里面的send、recv,WSASend,WSARecv ,connect是必须要监测的,外挂程序可能会通过hook这些函数来达到监听和篡改游戏封包的目的。

   hook API函数常用的方法有使用微软提供的detours库或者使用inline hook 来修改。下面我们来了解一下hook api函数的方法。


一、detours库的使用

detours下载   比较简单,直接上演示代码,下面是hook connect函数的演示:

#pragma once
#include "pch.h"
#include "detours.h"
#include <Windows.h>
#include <WinSock2.h>

#pragma comment (lib,"detours.lib")

typedef int (WINAPI* type_connect)(
	_In_ SOCKET s,
	_In_reads_bytes_(namelen) const struct sockaddr FAR* name,
	_In_ int namelen
	);

type_connect g_fnconnect_real = ::connect;

HANDLE g_thread_hook = NULL;

void HookApi(LPVOID *trueFunction, LPVOID newFunction, bool install)
{
	 
	if (install)
	{
		g_thread_hook = GetCurrentThread();

		//装载Hook
		DetourRestoreAfterWith();
		DetourTransactionBegin();
		DetourUpdateThread(g_thread_hook);
		DetourAttach(trueFunction, newFunction);
		DetourTransactionCommit();
	}
	else
	{
		//卸载
		DetourTransactionBegin();
		DetourUpdateThread(g_thread_hook);
		DetourDetach(trueFunction, newFunction);
		DetourTransactionCommit();
	}
}
  

//调用函数 hook connect
HookApi(&(LPVOID&)g_fnconnect_real, (LPVOID)&Hook_connect, true);  

//hook 后会,每当执行connect函数时会首先执行转向本函数
int WINAPI Hook_connect(
    _In_ SOCKET s,
    _In_reads_bytes_(namelen) const struct sockaddr FAR* name,
    _In_ int namelen
)
{
    //编写你的处理过程
    ...

    return g_fnconnect_real  (s,name,namelen;
}

二、inline hook的使用

    inline hook 其实就是通过直接修改可行代码,使之转向到执行我们的函数的过程。理论上inline hook 可以在任意位置进行hook转向 ,只要保证好堆栈平衡就行。

    inline hook的原理就是修改一条跳转代码(jmp xxxxx) ,机器码为 E9 。比如我们要 hook connect ,代码如下

//1、保存真实connect的地址
type_connect g_fnconnect_real = ::connect;

//2、保存connect 函数开头5字节
char g_first5chars[5];
memcpy(g_first5chars,0,sizeof(g_first5chars));

//修改机器码使之跳转到 Hook_connect
//这里如果代码不可写,需要先调用 VirtualProtect 修改为可写属性
*(BYTE*)g_fnconnect_real = 0xe9 ; 
*(DWORD*)((BYTE*)g_fnconnect_real +1) = (DWORD)Hook_connect - (DWORD)g_fnconnect_real  - 5;


//hook 后会,每当执行connect函数时会首先执行转向本函数
int WINAPI Hook_connect(
    _In_ SOCKET s,
    _In_reads_bytes_(namelen) const struct sockaddr FAR* name,
    _In_ int namelen
)
{
    //编写你的处理过程
    ...

    //还原原始函数头5字节
    memcpy(g_fnconnect_real ,g_first5chars,sizeof(g_first5chars));


    return connect_real (s,name,namelen;
}

三、监测API是否被hook

    我们已经了解外挂作者可能会如何 hook 我们的函数了,总之要hook API 必定会修改到我们的可执行代码。对应的版本有两个:一是不停地覆盖还原原始的代码,让hook失效。二是检测代码是否被修改,如果修改了就告知服务器(注意:一般封挂都不是在客户端直接弹出提示,让破解者轻易找到应对办法),由服务器端处理发送消息、断开连接、记录日志等。

    一般可使用crc校验法或者自己编写累加和算法校验。可随意设计,下面是自己编写的校验和例子:

DWORD game_memory::calc_checksum(BYTE* pBuffer, DWORD dwCheckLen, DWORD dwStartSum )
{
    DWORD dwSUM = dwStartSum;
    WORD* pWord = (WORD*)pBuffer;
    while (dwCheckLen >= 2)
    {
        dwSUM += *pWord;
        if (dwSUM >= 0xffffffff - 0xffff * 2)
        {
            dwSUM = (dwSUM & 0xffff) + (dwSUM >> 16);
        }
        pWord++;
        dwCheckLen -= 2;
    }

    pBuffer = (BYTE*)pWord;
    while (dwCheckLen > 0)
    {
        dwSUM += *pBuffer;
        pBuffer++;
        dwCheckLen--;
    }
    return dwSUM;
}

如果你也有这方面兴趣爱好交流欢迎加扣58085250与我直接沟通交流指正。


总结

      本文是介绍HOOK API的常见方法,以及通过校验API函数是否被非法HOOK 来判断玩家是否使用了外挂的方法。具体编写实现方法可自行设计,尽量让设计隐晦一些不那么容易被发现和破解,程序设计时尽量不要有API参考和字符串产考、尽量不要使用静态全局变量保存重要数据,指针层数越深越好。不要通过本地检测之后直接得出结论并弹出提示。 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

二楼の五号

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值