封包协议,加密解密,线程发包,recv,明文收包

封包协议,加密解密,线程发包,recv,明文收包本文详细介绍了网络通信中的封包 协议概念 以及收发包流程 强调了心跳包的作用

大家好,欢迎来到IT知识分享网。

一.封包,协议

什么是封包?封包就是按照某种协议组成的一段字节集.这个很容易理解

那为什么要按照某种协议呢?这个我们一会再说

所有联网的软件,包括网络游戏,客户端和服务端进行通信都是通过封包进行的.

大家可以想象成2个人打电话,封包就是说话的内容.

而协议呢?就是封包的语种, 2个人打电话一个用日语,一个用英文

もしもし、韓さんです。 那边接电话 What are you talking? 这怎么交流啊?

好,那么我们定好协议,本通电话我们全部采用中文,这样就可以正常交流了对吧?

这就是协议

一句话概括, 联网软件,客户端和服务端通过约定好的协议用封包来进行通信.

二.收发包

上面了解了什么是封包协议,我们来看下什么是收发包

网络游戏和单机游戏的区别就在于时刻要和服务器进行通信,也就是收发包.我们发给服务器的叫做发包, 我们收到服务器发给我们的叫做收包,

当然这是相当于我们而言.反之一样.

来一个简单的例子:

我们进入游戏说一句:你好! 为什么别的玩家可以看到?

通过这个流程我们就会了解收发包以及服务器的作用.

首先我们发送要和周围人说你好的封包给服务器,

服务器收到我们的封包以后, 一般会给我们回一个封包,说OK没问题,当然也可能高冷的不回啊.

然后服务器会执行代码判断我周围都有哪些玩家,然后对这些玩家逐个发包

这些玩家收到服务器的封包以后,就会看到我们的喊话内容了.

了解了什么是收发包

我们就要知道调用什么函数来实现.

这里的三大快递公司

就是三个发包函数 send sendto WSASend 以及对应的 3个收包函数 recv recvfrom WSARecv

用哪一组都是可以的.

例如 口袋西游是 send recv

幻想神域是 WSASend WSARecv

三.心跳包

上面了解了封包协议,收发包,我们来看下什么是心跳包?

心跳包也是封包,只是一种比较特殊的封包.

他可以证明我们的客户端还活着,顾名思义,有心跳就是活着.

举个简单的例子:

2个人打电话, A: 喂在吗? B:… A:在吗? B….A:挂了. 多次没得到回应直接就挂断了.

心跳包也一样,当服务器给我们发包,我们没有回复的时候,服务器就有可能把我们强制踢下线. 当然也有可能我们定时主动发送

1-2次服务器可能会认为偶尔丢包,如果2个以上应该就会直接认为我们掉线,直接强制踢下线了.

心跳包有很多好处:

1.一定程度防止脱机外挂

2.掉线立刻下线, 比如以前的老游戏,电脑蓝屏关机了,由于没有自然下线, 心跳也特别少,人物可能还在上面很长一段时间,这是不安全的,比如传奇2

3.可以隐藏一些数据在心跳包中.

四.针对发包函数的保护方法

了解了封包的概念,我们发现发包函数非常重要,

监听了发包函数就相当于掌握了所有功能实现的方法,可以替代所有call.监听了收包函数就相当于掌握了所以数据信息.因为数据本质来源于服务器

同时通过调用关系我们还知道,可以通过发包函数返回到所有的功能函数.

这是连新手的都知道的2点,所以一定要进行防护

针对这2点我们可以做什么防护呢?

那么第一件事,当然是把这个函数给尽量的隐藏起来

有的时候我们会发现,三大发包函数都不断!

那么是不是这个游戏不用这3个函数发包呢?当然不是,我们只能用这三个发包函数发包,没有其他的方法。

那就是重新实现发包函数,自己重新写一个发包函数,不用系统提供的成品函数了。

说的简单点就是,代码还是这三个发包函数的代码,只是换了个位置,搬家了,不直接调用这3个函数了。

知道这个原理以后就很容易处理了

方法一

既然还是之前的代码,那么我们到他的更内层函数下断就可以了

既WSPSend,相当于用内层函数当特征码。

函数体内的虚函数

封包协议,加密解密,线程发包,recv,明文收包

封包协议,加密解密,线程发包,recv,明文收包

X64结构不一样,但是一样是虚函数进去 找到WSPSend

方法二

通过三个函数的特征码到对应模块中进行搜索,这里注意的是这个重新实现的发包函数,可能在原来的模块中ws2_32,也可能在游戏自己的某个模块中。

所以搜索的时候要注意.

特征码比如头部这一段

封包协议,加密解密,线程发包,recv,明文收包

可能会有微小变化,所以我们要尝试

同时也可能搜索到多个位置,全部下断,测试即可.

总之两种方法思路是一致的,都是找原代码的特征而已。

对发包函数第二个保护方案就是加密

如果不加密,直接监听发包函数就可以获得所有的信息了.

比如直接hook send函数

例如WPE等简单工具就是hook的发包函数

所以必须进行加密

加密也一定要进行动态加密,就是同样的结果加密后内容是不同的.那么以上方法也就没有任何作用了.

五.对发包函数第三个保护方案就是线程发包

正常的游戏调用流程是

功能函数1—》功能函数2—》组包过程—》明文封包—》加密—》发包函数

所谓组包过程就是把功能函数的参数按照格式组成一个字节集

明文封包就是组装完成但是没有进行加密的封包

最后一步加密发送.

通过上面的调用关系,我们能看出来

这样只要找到发包函数,所以功能函数以及加密解密函数随意返回,随意分析

那怎么样避免呢?线程发包!

线程发包原理

就是说用2条线程来控制以上流程,让逆向者不能直接返回

第一条线程

功能函数1—》功能函数2—》组包—》明文封包—》封包写到某一个地址中

第二条线程

得到那个地址中的内容—》加密—》发包函数

当然两条线程分工不一定是严格这样写的,也可能明文封包在第二条线程中

这样的发包会有什么的特征呢?

1.无论什么功能,堆栈返回都是一样的,因为第二条线程的调用过程,什么功能都一样了

2.第二条线程由于不断循环,断的可能会比较频繁

六.线程发包跳出循环线程

先不管线程通信都有哪些方法,我们先来一个锻炼,然后我们再详细分析原理.

上面我们知道了线程发包的原理,那么这2条线程唯一的关联就是封包内容

所以我们直接追封包内容来源即可.就有线索从第二条线程返回到第一条线程了.

1.包内容地址如果是固定的,我们直接下断就能跳出去了,相当于用全局变量做线程之间通信

这里是变化的

那么我们追其来源

封包协议,加密解密,线程发包,recv,明文收包

edi+2888 开始不发生变化了

根据我们的思路,要找变化的值来源, 那么我们在该地址上下写入断,

封包协议,加密解密,线程发包,recv,明文收包

找到写入来源以后 我们看是否跳出了线程

发现并未跳出线程,还在原来的线程里.

2.那么我们还要继续追其来源

封包协议,加密解密,线程发包,recv,明文收包

edx开始不变化了,对EDX下断

封包协议,加密解密,线程发包,recv,明文收包

跳出了线程,我们可以通过这里下断,断到功能函数了

返回就是明文发包call

而这里就可以当成我们的”send”了

七.整理完全线程发包流程

1.跳出线程在这个位置,我们来整理下整体流程

封包协议,加密解密,线程发包,recv,明文收包

线程1将ebp写入一个地址.

ebp 是会变的是动态申请的,存放的封包结构

这个地址是全局类对象指向封包结构的指针

封包协议,加密解密,线程发包,recv,明文收包

线程2将线程1写入的 封包结构取出来

edi+2880就是全局类对象指向封包结构的指针

取出来给edx,我们依然写ebp 为了知道是线程1断出去的ebp

[[ebp]+8] 又写入 全局类型对象 +2888的位置

封包协议,加密解密,线程发包,recv,明文收包

全局类对象+2888的位置 取出来给ebx

取出来的就是前面的 [[ebp]+8]

[[ebp+8]+4] 就是是封包内容

八.验证发包内容

我们下断可以验证一下 里面的封包内容是否是最后发送的内容,这个必须验证,防止中间又有多次加密

如果不相同,我们还要在这里对封包下访问断,追踪他经历了什么

方法很简单:

我们同时在这个位置下断 和WSASend 下断

对比两个位置封包是否一样

分别下条件断

byte ptr[[[EBP+8]+4]] != 0x0F

喊话11对比

2B771F00 C2C70011

2B771F04 C0105E58

2B771F08 D805FBB8

2B771F0C 910B1805

2B771F10 6F043A08

$ ==> >C2C70011

$+4 >C0105E58

$+8 >D805FBB8

$+C >910B1805

$+10 >6F043A08

$+14 >404B0000

发现是一样的那么我们在这里继续分析即可

九.明文发包call 和锁定加密call

我们现在跳出的位置 其实就是相当于”send”

正常可以返回到各种功能call, 如果使用call的话,我们现在已经足够了

如果想自己加密自己send发送封包,那么我们还需要分析加密解密过程,分析加密算法.

返回一层层看看 是否有明文内容,喊话是最容易看到明文的位置

返回的第一个call里面就看到了明文

封包协议,加密解密,线程发包,recv,明文收包

那么说明 从这个call的头部 到第二次跳出的位置 中间就有加密call

如果这层发现不了明文,我们继续返回

当然我们也可以从ebp 一句一句逆向来源也是可以的

这个地方同样需要条件断 byte ptr[[[esp]+4]]!=0f

封包协议,加密解密,线程发包,recv,明文收包

那么这地方就是明文发包call

找到了明文发包call,我们可以直接调用或则调用更外层功能函数实现各种功能,这之前我们都已经讲过了,这节课我们想用更好的方法

就是找到加密函数,我们自己加密封包,然后通过发包函数发送

十.加密call

加密函数的位置我们已经锁定了,就是在返回的call到我们断的位置之间

那么可以进行分析了

从call 断下以后 F7单独执行即可

封包协议,加密解密,线程发包,recv,明文收包

发现了加密calll

以及分析出来加密call的参数

封包协议,加密解密,线程发包,recv,明文收包

00B92266 2BF8 sub edi, eax

00B92268 83C5 02 add ebp, 2

00B9226B 55 push ebp ; 加密的地址

00B9226C 83C3 02 add ebx, 2

00B9226F 53 push ebx ; 加密的地址

00B92270 83C7 FE add edi, -2

00B92273 8D46 54 lea eax, dword ptr [esi+54]

00B92276 57 push edi ; 加密的长度

00B92277 50 push eax ; 秘钥 往上追 [[[[[00f84ba4]]+4]+0xC+8]]+54

00B92278 E8 call 00B94700 ; 加密call

00B9227D 8B9E mov ebx, dword ptr [esi+2880]

全过程:

功能call参数进行组包,调用明文发包call, 明文发包call内部进行加密, 写入到一个全局类对象的属性中

线程2访问该属性,进行发包

十一.偷功能

偷功能很容易就是把程序的汇编代码复制到我们的程序内进行使用

我们自己组包,自己加密,自己发送封包

好处是,彻底不走游戏的任何代码.

复制出来的汇编代码需要进行初步处理才能写到内联汇编中

1.常数全部要加上0x

2.如果有call 还要自己分析出来继续执行内容 否则还是要以来原有程序

3.mov eax,[0x] 类似这种容易错误的汇编代码也要转一下

4.跳转都标注出来

例如 jnz 他是要跳转到目的代码地址执行的,我们偷出来的代码已经不是原来的地址了

所以要通过标签修改跳转的地址。

我们把加密call的代码全部偷出来

 push ebp push ebx push esi push edi mov edi, dword ptr [esp+0x14] mov edx, dword ptr [esp+0x18] mov esi, dword ptr [esp+0x1C] mov ebp, dword ptr [esp+0x20] xor eax, eax xor ebx, ebx cmp edx, 0 je Label1 ========================================= mov al, byte ptr [edi] mov bl, byte ptr [edi+4] add edi, 8 lea ecx, dword ptr [esi+edx] sub ebp, esi mov dword ptr [esp+0x18], ecx inc al cmp dword ptr [edi+0x100], -1 je Label2================================================ mov ecx, dword ptr [edi+eax*4] and edx, 0xFFFFFFFC je Label3=============================================== lea edx, dword ptr [esi+edx-4] mov dword ptr [esp+0x1C], edx mov dword ptr [esp+0x20], ebp Label4: add bl, cl mov edx, dword ptr [edi+ebx*4] mov dword ptr [edi+ebx*4], ecx mov dword ptr [edi+eax*4], edx add edx, ecx inc al and edx, 0x0FF mov ecx, dword ptr [edi+eax*4] mov ebp, dword ptr [edi+edx*4] add bl, cl mov edx, dword ptr [edi+ebx*4] mov dword ptr [edi+ebx*4], ecx mov dword ptr [edi+eax*4], edx add edx, ecx inc al and edx, 0x0FF ror ebp, 8 mov ecx, dword ptr [edi+eax*4] or ebp, dword ptr [edi+edx*4] add bl, cl mov edx, dword ptr [edi+ebx*4] mov dword ptr [edi+ebx*4], ecx mov dword ptr [edi+eax*4], edx add edx, ecx inc al and edx, 0x0FF ror ebp, 8 mov ecx, dword ptr [edi+eax*4] or ebp, dword ptr [edi+edx*4] add bl, cl mov edx, dword ptr [edi+ebx*4] mov dword ptr [edi+ebx*4], ecx mov dword ptr [edi+eax*4], edx add edx, ecx inc al and edx, 0x0FF ror ebp, 8 mov ecx, dword ptr [esp+0x20] or ebp, dword ptr [edi+edx*4] ror ebp, 8 xor ebp, dword ptr [esi] cmp esi, dword ptr [esp+0x1C] mov dword ptr [ecx+esi], ebp lea esi, dword ptr [esi+4] mov ecx, dword ptr [edi+eax*4] jb Label4============================================ cmp esi, dword ptr [esp+0x18] je Label5=================================== mov ebp, dword ptr [esp+0x20] Label3: add bl, cl mov edx, dword ptr [edi+ebx*4] mov dword ptr [edi+ebx*4], ecx mov dword ptr [edi+eax*4], edx add edx, ecx inc al and edx, 0x0FF mov edx, dword ptr [edi+edx*4] xor dl, byte ptr [esi] lea esi, dword ptr [esi+1] mov ecx, dword ptr [edi+eax*4] cmp esi, dword ptr [esp+0x18] mov byte ptr [ebp+esi-1], dl jb Label3========================================== jmp Label5======================================== Label2: movzx ecx, byte ptr [edi+eax] Label6: add bl, cl movzx edx, byte ptr [edi+ebx] mov byte ptr [edi+ebx], cl mov byte ptr [edi+eax], dl add dl, cl movzx edx, byte ptr [edi+edx] add al, 1 xor dl, byte ptr [esi] lea esi, dword ptr [esi+1] movzx ecx, byte ptr [edi+eax] cmp esi, dword ptr [esp+0x18] mov byte ptr [ebp+esi-1], dl jb Label6============================================= Label5: dec al mov byte ptr [edi-4], bl mov byte ptr [edi-8], al Label1: pop edi pop esi pop ebx pop ebp retn

最终代码

 __declspec(naked) void 加密call(DWORD 秘钥,DWORD 加密长度,DWORD 加密地址,DWORD 加密地址2) { __asm { push ebp push ebx push esi push edi mov edi, dword ptr [esp+0x14] mov edx, dword ptr [esp+0x18] mov esi, dword ptr [esp+0x1C] mov ebp, dword ptr [esp+0x20] xor eax, eax xor ebx, ebx cmp edx, 0 je Label1 mov al, byte ptr [edi] mov bl, byte ptr [edi+4] add edi, 8 lea ecx, dword ptr [esi+edx] sub ebp, esi mov dword ptr [esp+0x18], ecx inc al cmp dword ptr [edi+0x100], -1 je Label2 mov ecx, dword ptr [edi+eax*4] and edx, 0xFFFFFFFC je Label3 lea edx, dword ptr [esi+edx-4] mov dword ptr [esp+0x1C], edx mov dword ptr [esp+0x20], ebp Label4: add bl, cl mov edx, dword ptr [edi+ebx*4] mov dword ptr [edi+ebx*4], ecx mov dword ptr [edi+eax*4], edx add edx, ecx inc al and edx, 0x0FF mov ecx, dword ptr [edi+eax*4] mov ebp, dword ptr [edi+edx*4] add bl, cl mov edx, dword ptr [edi+ebx*4] mov dword ptr [edi+ebx*4], ecx mov dword ptr [edi+eax*4], edx add edx, ecx inc al and edx, 0x0FF ror ebp, 8 mov ecx, dword ptr [edi+eax*4] or ebp, dword ptr [edi+edx*4] add bl, cl mov edx, dword ptr [edi+ebx*4] mov dword ptr [edi+ebx*4], ecx mov dword ptr [edi+eax*4], edx add edx, ecx inc al and edx, 0x0FF ror ebp, 8 mov ecx, dword ptr [edi+eax*4] or ebp, dword ptr [edi+edx*4] add bl, cl mov edx, dword ptr [edi+ebx*4] mov dword ptr [edi+ebx*4], ecx mov dword ptr [edi+eax*4], edx add edx, ecx inc al and edx, 0x0FF ror ebp, 8 mov ecx, dword ptr [esp+0x20] or ebp, dword ptr [edi+edx*4] ror ebp, 8 xor ebp, dword ptr [esi] cmp esi, dword ptr [esp+0x1C] mov dword ptr [ecx+esi], ebp lea esi, dword ptr [esi+4] mov ecx, dword ptr [edi+eax*4] jb Label4 cmp esi, dword ptr [esp+0x18] je Label5 mov ebp, dword ptr [esp+0x20] Label3: add bl, cl mov edx, dword ptr [edi+ebx*4] mov dword ptr [edi+ebx*4], ecx mov dword ptr [edi+eax*4], edx add edx, ecx inc al and edx, 0x0FF mov edx, dword ptr [edi+edx*4] xor dl, byte ptr [esi] lea esi, dword ptr [esi+1] mov ecx, dword ptr [edi+eax*4] cmp esi, dword ptr [esp+0x18] mov byte ptr [ebp+esi-1], dl jb Label3 jmp Label5 Label2: movzx ecx, byte ptr [edi+eax] Label6: add bl, cl movzx edx, byte ptr [edi+ebx] mov byte ptr [edi+ebx], cl mov byte ptr [edi+eax], dl add dl, cl movzx edx, byte ptr [edi+edx] add al, 1 xor dl, byte ptr [esi] lea esi, dword ptr [esi+1] movzx ecx, byte ptr [edi+eax] cmp esi, dword ptr [esp+0x18] mov byte ptr [ebp+esi-1], dl jb Label6 Label5: dec al mov byte ptr [edi-4], bl mov byte ptr [edi-8], al Label1: pop edi pop esi pop ebx pop ebp retn } } 

十二.不走游戏代码自己发送封包

我们简单分析一个喊话封包,开始自己调用不走任何游戏代码

send头文件

#include “winsock.h”

有问题记得加上如下代码

#pragma comment(lib,”ws2_32.lib”)

 void HXSYDialog::OnBnClickedButton16() { byte a[100] = {0x11,0x00,0x7E,0x00,0x00,0x00,0x00,0x02,0x00,0x31,0x31,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x60,0xA8,0x6C}; DWORD 包长 = 0x13; DWORD 包地址 = (DWORD)a; DWORD 加密地址 = 包地址 + 2; DWORD 加密长度 = 包长 - 2; DWORD 秘钥 = 0; __asm { mov ecx,0x00f84ba4 mov ecx,[ecx] mov ecx,[ecx] mov ecx,[ecx+0x4] mov ecx,[ecx+0x14] mov ecx,[ecx] lea ecx,[ecx+0x54] mov 秘钥,ecx } 加密call(秘钥,加密长度,加密地址,加密地址); HWND 窗口句柄 =FindWindowA("Lapis Network Class",0); DWORD A = GetWindowLongW(窗口句柄,-21); DWORD S =*(DWORD*)(A+0x38); send(S,(const char*)包地址,包长,0); // TODO: 在此添加控件通知处理程序代码 } 

我们分析几个明文包 ,然后调用测试

十三.收包

收包函数recv,recvfrom, WSARecv

(收包的参数包地址和长度 是准备接受的包地址 和最大包长)

这是必然的,因为调用前是不可能知道收到的内容和具体长度的,只有执行完毕才会获得

封包协议,加密解密,线程发包,recv,明文收包

recv 的实际包长 在返回值eax

封包协议,加密解密,线程发包,recv,明文收包

WSARecv 在第四个参数

十四.粘包

我们发现断的时间越长 收包越大 原因很简单 因为可能沾包

当我们线程停住的时候,服务器依然在给我们发包,这个时候就会一起接收到

那么停住的时间越长,包就粘的越长.

每个独立的封包都有很明显的划分方法,所以拆包并不难

十五.明文收包和解密call

收包我们收到的肯定也是服务器发给我们的加密封包

加密封包经过解密处理,把里面的数据写入到对应内存位置,这样我们就在界面上显示相应的反馈了.

明文收包和明文发包方向是反的

要找去哪里了,所以是下访问断追其去向

封包协议,加密解密,线程发包,recv,明文收包

我们发现   lpbuffers  +4里的包地址  是固定的, 是否固定其实无所谓

那么我们想追解密函数 就要对  他进行访问断

当然 通过我们自己喊话等方式 让其断下  

封包协议,加密解密,线程发包,recv,明文收包

2个拷贝的位置都可以

再对拷贝的地址下访问断

封包协议,加密解密,线程发包,recv,明文收包

返回就是解密call

同时也是明文收包的位置了

封包协议,加密解密,线程发包,recv,明文收包

然后我们发现    加密和解密是同一个函数

加密和解密是一个可逆的过程

正常我们其实直接搜索call 就可以找到明文收包的位置了

十六.线程发包实现的原理和方法

上面的例子学习完毕以后,实际上大家可以在追线程发包的时候还会存在一些疑惑

为什么一定要追到不变的地址,还有什么其他情况等等

其实,

线程发包本质是两条线交互信息.

那么无论是全局变量还是全局类对象下面的属性

肯定都是不变的地址

通信必然要写到这里

当然还有线程其他的通信方式

我们以后学习更多线程的知识再进行讲解

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/155442.html

(0)
上一篇 2025-02-19 14:33
下一篇 2025-02-19 14:45

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注微信