蜀门Online加密分析
Online
分析仅仅是为了娱乐而已,游戏也不难。有错误就不好意思了。
这个游戏加了个TMD的壳,会关闭调试端口,在内核里面打个补丁就好了。
首先找到收报和发包明文的地址。如果游戏更新地址不对,请用特征码重新找:
收报HOOK地址:
通过 hook 这个两个函数,通过分析
协议
离婚协议模板下载合伙人协议 下载渠道分销协议免费下载敬业协议下载授课协议下载
,已经能够做一个基于封包的内挂了。需要多说
一嘴的是,如果你直接分析包,可能会发现找包的类型标示不容易,包标示是通过包的第二
个WORD字节标示的,具体算法大概是:
PBYTE pret = buf; ?
1
WORD wd = *(WORD*)(buf+1);
wd+=7;
WORD plen = *(WORD*)(buf+3);
plen -= (wd/8);
pret = buf+7+(wd/8);
游戏收包加密分析:
数据包格式如下:
0x40,0x00,0x00,0x0D,0x00,0x03,0x00,0x0C,0x04,0xC2,0x01,0x04,0x3C,0xF4,0x45,0x
8C,0xD7,0xCA,0x46,0x03
按照协议解析规则拆分如下:
1 0x41, -- 加密标志,这个标志标志了加密的方式和次数
0x0D,0x00, --- 数据包长度 0x00,0x00, -- 通过这个WORD可以定位到真正的数据地方。见前面?
0x03,0x00, --- 包序列号 0x0C,0x04,0xC2,0x01,0x04,0x3C,0xF4,0x45,0x8C,0xD7,0xCA,0x46,0x03
加密标志标志了需要解密的方式和次数,举例如下:
具体如下:
BYTE bsig = buf[0];
if ( bsig & 1){
decrpt(buf,len); -?-解密1
buf[0] = bsig & 0xFE;
}
bsig = buf[0];
__asm{
xor eax , eax
mov al , bsig
shr al, 1
and al, 1
mov bsig , al
}
if (bsig){
len = sub_C67670(buf+7,len-7, decbuf2+7); --二次解密,返回解密后的数据长度
memcpy(decbuf2,buf,7);
*(WORD*)(decbuf2+3) = (WORD)len;
len+=7;
decbuf2[0] = decbuf2[0] & 0xFD;
bp = decbuf2;
}
其中decrpt函数和sub_C67670如下: void CProtocol::decrpt(PBYTE buf, int len) ///很明显,这个函数就是简单的xor解密
{
int istart = 5;
while (istart
0x11u )
{
v7 = *(_BYTE *)a1 - 17;
v3 = a1 + 1;
if ( (unsigned int)v7 < 4 )
goto LABEL_21;
do
{
*(_BYTE *)v6++ = *(_BYTE *)v3++;
--v7;
}
while ( v7 );
goto LABEL_17;
}
LABEL_5:
v9 = *(_BYTE *)v3;
v8 = v3 + 1;
if ( v9 < 0x10 )
{
if ( !v9 )
{
if ( *(_BYTE *)v8 == (_BYTE)v9 )
{
do
{
++v8;
v9 += 255;
}
while ( !*(_BYTE *)v8 );
}
v9 += *(_BYTE *)v8++ + 15;
}
*(_DWORD *)v6 = *(_DWORD *)v8;
v6 += 4;
v3 = v8 + 4;
v10 = v9 - 1;
if ( v10 )
{
if ( (unsigned int)v10 < 4 )
{
do
{
*(_BYTE *)v6++ = *(_BYTE *)v3++;
--v10;
}
while ( v10 );
}
else
{
do
{
*(_DWORD *)v6 = *(_DWORD *)v3;
v10 -= 4;
v6 += 4;
v3 += 4;
}
while ( (unsigned int)v10 >= 4 );
for ( ; v10; --v10 )
*(_BYTE *)v6++ = *(_BYTE *)v3++;
}
}
LABEL_17:
v9 = *(_BYTE *)v3;
v8 = v3 + 1;
if ( v9 < 0x10 )
{
v21 = v6 - 4 * *(_BYTE *)v8 - (v9 >> 2);
v22 = *(_BYTE *)(v21 - 2049);
v21 -= 2049;
*(_BYTE *)v6 = v22;
v12 = *(_BYTE *)(v21 + 1);
++v6;
v11 = v21 + 1;
LABEL_19:
*(_BYTE *)v6 = v12;
v23 = v6 + 1;
v3 = v8 + 1;
*(_BYTE *)v23 = *(_BYTE *)(v11 + 1);
v6 = v23 + 1;
goto LABEL_20;
}
}
while ( 1 )
{
if ( v9 >= 0x40 )
{
v14 = v6 - ((v9 >> 2) & 7) - 8 * *(_BYTE *)v8 - 1;
v3 = v8 + 1;
v13 = (v9 >> 5) - 1; LABEL_25:
*(_BYTE *)v6 = *(_BYTE *)v14;
v24 = v6 + 1;
*(_BYTE *)v24 = *(_BYTE *)(v14 + 1);
v6 = v24 + 1;
v15 = v14 + 2;
do
{
*(_BYTE *)v6++ = *(_BYTE *)v15++;
--v13;
}
while ( v13 );
goto LABEL_20;
}
if ( v9 < 0x20 )
break;
v13 = v9 & 0x1F;
if ( !v13 )
{
for ( ; !*(_BYTE *)v8; v13 += 255 )
++v8;
v13 += *(_BYTE *)v8++ + 31;
}
v14 = v6 - ((unsigned int)*(_WORD *)v8 >> 2) - 1;
v3 = v8 + 2;
LABEL_41:
if ( (unsigned int)v13 < 6 || v6 - v14 < 4 )
goto LABEL_25;
*(_DWORD *)v6 = *(_DWORD *)v14;
v6 += 4;
v19 = v14 + 4;
v18 = v13 - 2;
do
{
*(_DWORD *)v6 = *(_DWORD *)v19;
v18 -= 4;
v6 += 4;
v19 += 4;
}
while ( (unsigned int)v18 >= 4 );
for ( ; v18; --v18 )
*(_BYTE *)v6++ = *(_BYTE *)v19++; LABEL_20:
v7 = *(_BYTE *)(v3 - 2) & 3;
if ( !(*(_BYTE *)(v3 - 2) & 3) )
goto LABEL_5;
do
{
LABEL_21:
*(_BYTE *)v6++ = *(_BYTE *)v3++;
--v7;
}
while ( v7 );
v9 = *(_BYTE *)v3;
v8 = v3 + 1;
}
if ( v9 < 0x10 )
{
v25 = v6 - 4 * *(_BYTE *)v8 - (v9 >> 2);
v12 = *(_BYTE *)(v25 - 1);
v11 = v25 - 1;
goto LABEL_19;
}
v16 = v6 - ((v9 & 8) << 11);
v13 = v9 & 7;
if ( !v13 )
{
for ( ; !*(_BYTE *)v8; v13 += 255 )
++v8;
v13 += *(_BYTE *)v8++ + 7;
}
v17 = v16 - ((unsigned int)*(_WORD *)v8 >> 2);
v3 = v8 + 2;
if ( v17 != v6 )
{
v14 = v17 - 16384;
goto LABEL_41;
}
if ( v3 == v5 )
result = v6 - v4;
else
result = -1;
return result;
}
原始汇编如下:
00A6EA40 53 push ebx
00A6EA41 56 push esi
00A6EA42 8BF1 mov esi, ecx
00A6EA44 8B8E 08010000 mov ecx, dword ptr [esi+108] 00A6EA4A 8B86 14010000 mov eax, dword ptr [esi+114] 00A6EA50 038E 10010000 add ecx, dword ptr [esi+110] 00A6EA56 57 push edi
00A6EA57 8B7C24 10 mov edi, dword ptr [esp+10] 00A6EA5B 50 push eax
00A6EA5C 51 push ecx
00A6EA5D 8BCF mov ecx, edi
00A6EA5F E8 0CEDFFFF call 00A6D770 ; 拆
包
00A6EA64 > 8BD8 mov ebx, eax
00A6EA66 85DB test ebx, ebx
00A6EA68 0F8E 6D010000 jle 00A6EBDB
00A6EA6E 299E 14010000 sub dword ptr [esi+114], ebx 00A6EA74 019E 10010000 add dword ptr [esi+110], ebx 00A6EA7A 8BCF mov ecx, edi
00A6EA7C E8 AFEBFFFF call 00A6D630 ; 检
查第一加密位
00A6EA81 84C0 test al, al
00A6EA83 74 15 je short 00A6EA9A 00A6EA85 8B96 4C010000 mov edx, dword ptr [esi+14C] 00A6EA8B 52 push edx
00A6EA8C 8D86 2C010000 lea eax, dword ptr [esi+12C] 00A6EA92 50 push eax
00A6EA93 8BCF mov ecx, edi
00A6EA95 E8 46EBFFFF call 00A6D5E0 ; 第
一次解密
00A6EA9A 8B97 14FB0000 mov edx, dword ptr [edi+FB14] ; 收到
数据包头不是41
00A6EAA0 0FB78E 58010000 movzx ecx, word ptr [esi+158] 00A6EAA7 0FB702 movzx eax, word ptr [edx] 00A6EAAA 66:3BC8 cmp cx, ax
00A6EAAD 74 5D je short 00A6EB0C 00A6EAAF 0FB7F8 movzx edi, ax
00A6EAB2 E8 E9DE1C00 call 00C3C9A0
00A6EAB7 8B10 mov edx, dword ptr [eax] 00A6EAB9 8BC8 mov ecx, eax
00A6EABB 8B42 40 mov eax, dword ptr [edx+40] 00A6EABE FFD0 call eax
00A6EAC0 8378 04 00 cmp dword ptr [eax+4], 0 00A6EAC4 75 04 jnz short 00A6EACA 00A6EAC6 33C0 xor eax, eax
00A6EAC8 EB 0C jmp short 00A6EAD6 00A6EACA 8B40 04 mov eax, dword ptr [eax+4] 00A6EACD 8B10 mov edx, dword ptr [eax] 00A6EACF 8BC8 mov ecx, eax
00A6EAD1 8B42 08 mov eax, dword ptr [edx+8] 00A6EAD4 FFD0 call eax
00A6EAD6 0FB78E 58010000 movzx ecx, word ptr [esi+158] 00A6EADD 51 push ecx
00A6EADE 57 push edi
00A6EADF 8D96 8C010000 lea edx, dword ptr [esi+18C] 00A6EAE5 52 push edx
00A6EAE6 68 88C4F600 push 00F6C488 ;
ASCII "%s: seq error packet seq = %d, expect seq = %d, close session",LF
00A6EAEB 50 push eax
00A6EAEC E8 BF101D00 call 00C3FBB0
00A6EAF1 8B4E 60 mov ecx, dword ptr [esi+60] 00A6EAF4 83C4 14 add esp, 14
00A6EAF7 85C9 test ecx, ecx
00A6EAF9 0F84 25010000 je 00A6EC24
00A6EAFF 8B01 mov eax, dword ptr [ecx] 00A6EB01 8B50 10 mov edx, dword ptr [eax+10] 00A6EB04 56 push esi
00A6EB05 FFD2 call edx
00A6EB07 E9 18010000 jmp 00A6EC24
00A6EB0C 8D41 01 lea eax, dword ptr [ecx+1] 00A6EB0F BB 01000000 mov ebx, 1
00A6EB14 019E 64010000 add dword ptr [esi+164], ebx 00A6EB1A 66:3D E8FD cmp ax, 0FDE8
00A6EB1E 66:8986 5801000>mov word ptr [esi+158], ax 00A6EB25 76 07 jbe short 00A6EB2E 00A6EB27 66:899E 5801000>mov word ptr [esi+158], bx 00A6EB2E 8BCF mov ecx, edi
00A6EB30 E8 EBEBFFFF call 00A6D720 ; 判
断第二加密位
00A6EB35 84C0 test al, al
00A6EB37 74 29 je short 00A6EB62 00A6EB39 807E 0E 00 cmp byte ptr [esi+E], 0 ; [head]44
00A6EB3D 75 14 jnz short 00A6EB53 00A6EB3F 8B87 0CFB0000 mov eax, dword ptr [edi+FB0C] 00A6EB45 0186 6C010000 add dword ptr [esi+16C], eax 00A6EB4B 5F pop edi
00A6EB4C 5E pop esi
00A6EB4D 32C0 xor al, al
00A6EB4F 5B pop ebx
00A6EB50 C2 0400 retn 4
00A6EB53 8BCF mov ecx, edi
00A6EB55 E8 56EBFFFF call 00A6D6B0 ; 第
二次解密
00A6EB5A 84C0 test al, al
00A6EB5C 0F84 D6000000 je 00A6EC38
00A6EB62 8B8F 1CFB0000 mov ecx, dword ptr [edi+FB1C] 00A6EB68 0FB701 movzx eax, word ptr [ecx] 00A6EB6B 83C0 07 add eax, 7
00A6EB6E 99 cdq
00A6EB6F 83E2 07 and edx, 7
00A6EB72 03C2 add eax, edx
00A6EB74 8B97 18FB0000 mov edx, dword ptr [edi+FB18] 00A6EB7A 0FB70A movzx ecx, word ptr [edx] 00A6EB7D C1F8 03 sar eax, 3
00A6EB80 3BC8 cmp ecx, eax
00A6EB82 7D 43 jge short 00A6EBC7 00A6EB84 50 push eax
00A6EB85 51 push ecx 00A6EB86 8D86 8C010000 lea eax, dword ptr [esi+18C]
最后,这个游戏坐标和数据包坐标是经过变换的,变换公式如下:
POINT CBot::gamexy2mapxy(float x, float y) //数据包游戏坐标转化到屏幕坐标
{
POINT pt;
float f1(5120.0f);
int ix = (int)((x+f1*7.0f)/20.0f);
int iy = (int)((y+f1*9.0f)/20.0f);
__asm{
mov eax , 7
neg eax
shl eax , 8
add ix , eax
mov eax , 9
neg eax
shl eax , 8
add iy , eax
}
pt.x = ix;
pt.y = iy;
return pt;
}
GAMEPOS CBot::mapxy2gamexy(int x, int y) //屏幕坐标转化到游戏坐标
{
GAMEPOS gpso;
// POINT pt;
float f1(5120.0f);
__asm{
mov eax , 7
neg eax
shl eax , 8
sub x , eax
mov eax , 9
neg eax
shl eax , 8
sub y , eax
}
gpso.x = x*20-7.0f*f1; //(int)((x+f1*7.0f)/20.0f);
gpso.y = y*20-9*f1 ;//(int)((y+f1*9.0f)/20.0f);
return gpso;
}
写字太累,就到这里吧
作者: linger 14465340