在开始之前,还是简单介绍下hook技术吧,HOOK技术:在windows系统下编程,应该会接触到api函数的使用,常用的api函数大概有2000个左右。
windows自带的api有SetWindowsHookEx,那么这个函数使用虽然是非常不错,不过这家伙早已经被一般杀毒软件干死了啊,你要是用了这个函数360第一个报毒。所以我还是用本站讲的mook吧,隐藏的很深入,嘿嘿……
开始干吧,首先创建一个mfc工程,然后申明以下变量
上面是一些准备工作,先把系统的send和recv 2个函数地址取到,然后通过socket描述创建一个我们自己的socket套接字,这样就可以用自己的socket发包啦,定义的类型如下
接下来就是初始hook要用的变量,代码如下:
以上代码就是创建一个套接字,这个套接字属于我们自己,其目的就是为了克隆目标连接的套接字,后面套接字只用socket了,中文打的慢!
完成了这步之后,我们就要加载mk.dll,这个动态链接库封装了mhook中的2个方法,一个是t001,t002,名字随便取的。之前是为了不让别人知道是干嘛的,是不是很坏?看代码:
这点对C++编程稍微熟点的人应该能看懂吧,t001就是hook函数,和windows的SetWindowsHookEx其实是一样的。另外一个就不用说了吧,看申明:
开始HOOK之后,我们还要处理send和recv函数,这个是系统自动调用的,因为它是系统函数嘛!
先说send,变量g_bIsDuplicated是为了判断是否已经为一个共享套接口创建一个新的描述字,如果已经创建就不需要再创建。创建目的是为了把游戏的socket共享给我们前面创建的socket。我在第二个if判断了数据库长度大于3并且第四个字节是0x24,之所以要判断是为了确定已经进入游戏了,不然可能就Hook错了目标,因为你打开游戏的时候可能会产生其它的http信息,比如说广告,游戏首页的HTTP请求。
处理完了send函数再看下recv函数,这个函数基本上不用处理,你只需要把数据解密拿来分析。
以上步骤才算是第一步,因为还要处理接收的数据,大部分游戏肯定会加密,我们还要破解加密算法才能正确处理接收到的数据。后面再讲处理数据包的流程,本文至此结束!
HOOK存在的意义
最初有些人对某些api函数的功能不太满意,就产生了如何修改这些api,使之更好的服务于程序的想法,这样api hook就自然而然的出现了。我们可以通过api hook,改变一个系统api的原有功能。windows自带的api有SetWindowsHookEx,那么这个函数使用虽然是非常不错,不过这家伙早已经被一般杀毒软件干死了啊,你要是用了这个函数360第一个报毒。所以我还是用本站讲的mook吧,隐藏的很深入,嘿嘿……
分析:
1.首先创建一个自己的socket,然后通过hook系统的send和recv函数,在send函数被调用的时候利用WSADuplicateSocket函数把游戏的socket共享给自己的socket,相当于你拿到了发包的权限,可以这么理解。然后之后就可以用我们自己的socket去调用send函数了,也就是发数据包了,这样不会掉线。否则直接掉线喽!这也是要hook的原因。开始干吧,首先创建一个mfc工程,然后申明以下变量
WSAPROTOCOL_INFO LocalProtocolInfo; _send g_trueSend = (_send)GetProcAddress(GetModuleHandleA("Ws2_32"),"send"); _recv g_trueRecv = (_recv)GetProcAddress(GetModuleHandleA("Ws2_32"),"recv"); SOCKET g_socket = NULL; bool g_bIsInitWSA = false; bool g_bIsDuplicated = false; ghook_recv g_recv = NULL;
上面是一些准备工作,先把系统的send和recv 2个函数地址取到,然后通过socket描述创建一个我们自己的socket套接字,这样就可以用自己的socket发包啦,定义的类型如下
//////////////封包函数////////////// typedef int (WINAPI *_send)(SOCKET s, const char *buf, int len, int flags); int WINAPI hook_send(SOCKET s, const char *buf, int len, int flags); typedef int (WINAPI *_recv)(SOCKET s, char *buf, int len, int flags); int WINAPI hook_recv(SOCKET s, char *buf, int len, int flags); //用来其它地方处理recv数据 typedef void (WINAPI *ghook_recv)(char *buf, int len);
接下来就是初始hook要用的变量,代码如下:
void InitHookApi() { WORD wVersionRequested; WSADATA wsaData; int err; wVersionRequested = MAKEWORD(2,2); err = WSAStartup(wVersionRequested, &wsaData); if ( err != 0 ) { return ; } if (LOBYTE( wsaData.wVersion ) != 2 || HIBYTE( wsaData.wVersion ) != 2 ) { WSACleanup( ); return ; } //创建自己的socket g_socket = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP,&LocalProtocolInfo,0,0); g_bIsInitWSA = true; }
以上代码就是创建一个套接字,这个套接字属于我们自己,其目的就是为了克隆目标连接的套接字,后面套接字只用socket了,中文打的慢!
完成了这步之后,我们就要加载mk.dll,这个动态链接库封装了mhook中的2个方法,一个是t001,t002,名字随便取的。之前是为了不让别人知道是干嘛的,是不是很坏?看代码:
/////////////////hook api///////////////////// BOOL StartHook() { if (m_hook == NULL || m_unhook == NULL) { //实现HOOK函数 hModule = LoadLibrary("mk.dll"); if(hModule == NULL) { AfxMessageBox("模块加载失败"); return FALSE; } m_hook = (t001)GetProcAddress(hModule,"t001"); m_unhook = (t002)GetProcAddress(hModule,"t002"); if (m_hook == NULL || m_unhook == NULL) { AfxMessageBox("error."); return FALSE; } } BOOL ret_send = m_hook((LPVOID*)&g_trueSend,hook_send); BOOL ret_recv = m_hook((LPVOID*)&g_trueRecv,hook_recv); return ret_send && ret_recv; } BOOL StopHook() { if(m_unhook != NULL) { BOOL ret_send = m_unhook((LPVOID*)&g_trueSend); BOOL ret_recv = m_unhook((LPVOID*)&g_trueRecv); g_bIsDuplicated = false;//停止,重新复制socket g_bIsInitWSA = false;//需要重新创建socket return ret_send && ret_recv; } return FALSE; }
这点对C++编程稍微熟点的人应该能看懂吧,t001就是hook函数,和windows的SetWindowsHookEx其实是一样的。另外一个就不用说了吧,看申明:
typedef BOOL (*t001)(PVOID *ppSystemFunction, PVOID pHookFunction); typedef BOOL (*t002)(PVOID *ppHookedFunction); t001 m_hook = NULL; t002 m_unhook = NULL; HMODULE hModule = NULL;
开始HOOK之后,我们还要处理send和recv函数,这个是系统自动调用的,因为它是系统函数嘛!
int WINAPI hook_send(SOCKET s, const char *buf, int len, int flags) { if (!g_bIsDuplicated) { //为一个共享套接口创建一个新的描述字LocalProtocolInfo,自己的套接口 if(buf != NULL && len >= 3 && (buf[3]&0xFF) == 0x24)//0x24点击主城返回的数据包 { //83是socket信息,非HTTP int wRet = WSADuplicateSocket(s,GetCurrentProcessId(),&LocalProtocolInfo); if(wRet == 0) { //若无错误发生,WSADuplicateSocket()返回0 //可以封包了 g_bIsDuplicated = true; AfxGetApp()->GetMainWnd()->GetDlgItem(IDC_BTN_DATA_DEBUG)->EnableWindow(); } } } return g_trueSend(s,buf,len,flags); }
先说send,变量g_bIsDuplicated是为了判断是否已经为一个共享套接口创建一个新的描述字,如果已经创建就不需要再创建。创建目的是为了把游戏的socket共享给我们前面创建的socket。我在第二个if判断了数据库长度大于3并且第四个字节是0x24,之所以要判断是为了确定已经进入游戏了,不然可能就Hook错了目标,因为你打开游戏的时候可能会产生其它的http信息,比如说广告,游戏首页的HTTP请求。
处理完了send函数再看下recv函数,这个函数基本上不用处理,你只需要把数据解密拿来分析。
int WINAPI hook_recv(SOCKET s, char *buf, int len, int flags) { int ret = g_trueRecv(s,buf,len,flags); //调用系统recv 让游戏自己处理; return ret; }
以上步骤才算是第一步,因为还要处理接收的数据,大部分游戏肯定会加密,我们还要破解加密算法才能正确处理接收到的数据。后面再讲处理数据包的流程,本文至此结束!
收藏的用户(0) X
正在加载信息~
推荐阅读
最新回复 (0)
站点信息
- 文章2300
- 用户1336
- 访客10858883
每日一句
Challenges spark life; conquering them gives purpose.
挑战点亮生活,征服赋予意义。
挑战点亮生活,征服赋予意义。
语法错误: 意外的令牌“标识符”
全面理解Gradle - 定义Task
Motrix全能下载工具 (支持 BT / 磁力链 / 百度网盘)
谷歌Pixel正在开始起飞?
获取ElementUI Table排序后的数据
Run-Time Check Failure #0 - The value of ESP was not properly saved across a function call. This is
亲测!虚拟机VirtualBox安装MAC OS 10.12图文教程
华为手机app闪退重启界面清空log日志问题
android ndk开发之asm/page.h: not found
手机屏幕碎了怎么备份操作?
免ROOT实现模拟点击任意位置
新手必看修改DSDT教程
thinkpad t470p装黑苹果系统10.13.2
新会员