- 注册时间
- 2011-3-6
- 最后登录
- 1970-1-1
该用户从未签到
|
以封神榜为例,(适合金山绝大部分游戏,原理相同)
先脱壳(由于脱很简单,不介绍了)
用IDA看下这游戏从 ws2_32导入了哪些函数..网络游戏通迅一般用到的是send,recv,WSASend,WSARecv这四个API函数.发现用到了 recv,WSASend,WSARecv,游戏中时发现并未用recv,所以有可能登陆用到了,初步分析是游戏过程中用WSASend和WSARecv 通讯,recv用来登陆收包.
进游戏后下断bp WSASend,游戏中按V(坐下),游戏被断下,看堆栈区:
0012F1B8 0056616A /CALL 到 WSASend 来自 GAME1_.00566164
0012F1BC 00000318 |Socket = 318
0012F1C0 03E9B07C |pBuffers = 03E9B07C
0012F1C4 00000001 |nBuffers = 1
0012F1C8 0012F1E8 |pBytesSent = 0012F1E8
0012F1CC 00000000 |Flags = 0
0012F1D0 00000000 |pOverlapped = NULL
0012F1D4 00000000 \Callback = NULL
WSASend的第二个参数buffer指向加密后的包结构,
03E9B07C 04 00 00 00 E8 0B 2E 01 DC C3 E9 03 01 00 00 00 ...?.苊?...
03E9B08C 00 04 00 00 00 00 00 00 E8 0B 2E 01 51 00 00 00 .......?.Q...
观察发现 03E9B080的地址不变,dd 012E0BE8查看发现此地址存放着好像包的内容..
012E0BE8 E7FF0004
一般游戏函数调用流程是这样的:
功能函数(打坐)->明文发包函数(明文包)->加密函数(密文包)->通讯函数(send等通讯函数发送密文包..)
通讯函数(recv等通讯函数收到密文包..)->解密函数(密文包)->解密明文包(解密后的明文包)..
所以012E0BE8地址存放的是密文包.再次下断bp WSASend,按V断下,连续两次CRTL+F9,加密过程要往回找(解密过程往下找);
005605B0 A1 A4F25C00 mov eax, dword ptr [5CF2A4]//F2下断单步调试,看012E0BE8何时生成
005605B5 53 push ebx
005605B6 83F8 02 cmp eax, 2
005605B9 55 push ebp
005605BA 0F84 CE000000 je 0056068E
005605C0 83F8 03 cmp eax, 3
005605C3 0F84 C5000000 je 0056068E
005605C9 83F8 04 cmp eax, 4
005605CC 0F84 BC000000 je 0056068E
005605D2 83F8 05 cmp eax, 5
005605D5 0F84 B3000000 je 0056068E
005605DB 83F8 06 cmp eax, 6
005605DE 0F84 AA000000 je 0056068E
005605E4 83F8 07 cmp eax, 7
005605E7 0F84 A1000000 je 0056068E
005605ED 83F8 08 cmp eax, 8
005605F0 0F84 98000000 je 0056068E
005605F6 8B6C24 10 mov ebp, dword ptr [esp+10]
005605FA 85ED test ebp, ebp
005605FC 0F84 93000000 je 00560695
00560602 8B5C24 14 mov ebx, dword ptr [esp+14]
00560606 833B 00 cmp dword ptr [ebx], 0
00560609 0F84 86000000 je 00560695
0056060F 56 push esi
00560610 57 push edi
00560611 8B7C24 14 mov edi, dword ptr [esp+14]
00560615 8D4F 0C lea ecx, dword ptr [edi+C]
00560618 E8 83640000 call 00566AA0
0056061D 8BF0 mov esi, eax
0056061F 8B03 mov eax, dword ptr [ebx]
00560621 8D4C24 18 lea ecx, dword ptr [esp+18]
00560625 6A 02 push 2
00560627 83C0 02 add eax, 2
0056062A 51 push ecx
0056062B 8BCE mov ecx, esi
0056062D 894424 20 mov dword ptr [esp+20], eax
00560631 E8 3A610000 call 00566770
00560636 8B13 mov edx, dword ptr [ebx]
00560638 8BCE mov ecx, esi
0056063A 52 push edx
0056063B 55 push ebp
0056063C E8 2F610000 call 00566770
00560641 8B8F D4020000 mov ecx, dword ptr [edi+2D4]
00560647 85C9 test ecx, ecx
00560649 75 1B jnz short 00560666
0056064B 8B4E 44 mov ecx, dword ptr [esi+44]
0056064E 8B13 mov edx, dword ptr [ebx]
00560650 8D87 D8010000 lea eax, dword ptr [edi+1D8]
00560656 83C1 02 add ecx, 2
00560659 50 push eax
0056065A 51 push ecx
0056065B 52 push edx
0056065C E8 AF700000 call 00567710 //发现经过这个CALL后,12E0BE8中的包生成,所以这有可能是加密函数..重新在此处下断,去掉原先断点,F7跟进.
00560661 83C4 0C add esp, 0C
00560664 EB 16 jmp short 0056067C
00560666 8D97 D8010000 lea edx, dword ptr [edi+1D8]
0056066C 8B01 mov eax, dword ptr [ecx]
0056066E 52 push edx
0056066F 8B56 44 mov edx, dword ptr [esi+44]
00560672 83C2 02 add edx, 2
00560675 52 push edx
00560676 8B13 mov edx, dword ptr [ebx]
00560678 52 push edx
00560679 FF50 08 call dword ptr [eax+8]
0056067C 56 push esi
0056067D 8D4F 04 lea ecx, dword ptr [edi+4]
00560680 E8 4B5A0000 call 005660D0
00560685 8BCE mov ecx, esi
00560687 E8 24620000 call 005668B0
0056068C 5F pop edi
0056068D 5E pop esi
0056068E 5D pop ebp
0056068F 33C0 xor eax, eax
00560691 5B pop ebx
00560692 C2 0C00 retn 0C
00567710 8B4424 0C mov eax, dword ptr [esp+C]
00567714 8D5424 0C lea edx, dword ptr [esp+C]
00567718 52 push edx
00567719 8B08 mov ecx, dword ptr [eax]
0056771B 8B4424 0C mov eax, dword ptr [esp+C]
0056771F 894C24 10 mov dword ptr [esp+10], ecx
00567723 8B4C24 08 mov ecx, dword ptr [esp+8]
00567727 50 push eax
00567728 51 push ecx //包长
00567729 E8 82FFFFFF call 005676B0 //继续F7跟进
005676B0 53 push ebx
005676B1 8B4424 0C mov eax, dword ptr [esp+C]//明文包地址
005676B5 56 push esi
005676B6 8B7424 0C mov esi, dword ptr [esp+C]//包长度
005676BA 57 push edi
005676BB 8B7C24 18 mov edi, dword ptr [esp+18]//加密密钥
005676BF 8BD6 mov edx, esi
005676C1 8B0F mov ecx, dword ptr [edi]
005676C3 83E2 03 and edx, 3
005676C6 C1EE 02 shr esi, 2
005676C9 74 0D je short 005676D8
005676CB 8B18 mov ebx, dword ptr [eax]
005676CD 83C0 04 add eax, 4
005676D0 33D9 xor ebx, ecx
005676D2 4E dec esi
005676D3 8958 FC mov dword ptr [eax-4], ebx
005676D6 ^ 75 F3 jnz short 005676CB
005676D8 85D2 test edx, edx
005676DA 76 0D jbe short 005676E9
005676DC 8A18 mov bl, byte ptr [eax]
005676DE 32D9 xor bl, cl
005676E0 8818 mov byte ptr [eax], bl
005676E2 40 inc eax
005676E3 C1E9 08 shr ecx, 8
005676E6 4A dec edx
005676E7 ^ 75 F3 jnz short 005676DC
005676E9 8B07 mov eax, dword ptr [edi]
005676EB 8BC8 mov ecx, eax
005676ED C1E1 05 shl ecx, 5
005676F0 2BC8 sub ecx, eax
005676F2 B8 01000000 mov eax, 1
005676F7 81C1 05840808 add ecx, 8088405
005676FD 890F mov dword ptr [edi], ecx
005676FF 5F pop edi
00567700 5E pop esi
00567701 5B pop ebx
00567702 C3 retn
在单步调试的时候发现数据段中的数据是4字节4字节在变的..走完这段,密文包也就出来了..又因为这段没调用别的什么模块..所以断定这是加密函数.. (希望大家学的是方法,加密往前跟,解密往后跟,,你会发现这游戏调用的加解密是同一个函数,只是密钥不同,所以解密过程就不分析了.)
CString EncAndDec(CString datestr,CString key,int len) //加解密函数
{
int j,nprev,nkey,nxor;
CString strxor,nxor1;
j=0;
strxor=NULL;
for(int i=0;i<len,i++)
{
if (i<2)
{
strxor=strxor+copy(datastr,i*2+1,2);
continue;
}
nprev=(long int)((int)("0x"+copy(datastr,i*2+1,2)));
nkey=(long int)((int)("0x"+copy(key,i*2+1,2)));
j++;
if (j>3)
{
j=0;
}
nxor=nprev ^ nkey;
strxor=strxor+nxor1.Format("%x",nxor);
}
return strxor;
}
密钥的查找:
退出游戏,在选择服务器前下断:bp recv;选择服务器后断下:
0012F928 00566447 /CALL 到 recv 来自 GAME1_.00566445
0012F92C 00000360 |Socket = 360
0012F930 04C5983C |Buffer = 04C5983C
0012F934 00000022 |BufSize = 22 (34.)
0012F938 00000000 \Flags = 0
dd 04C5983C,ALT+F9看收到的数据:
04C5983C 22 00 20 00 D4 47 EE F9 D8 3B 99 89 F0 01 6E AC ". .訥铢?檳?n
04C5984C 62 7B 1A 75 64 97 FE C9 68 8B 22 5D AC BF 86 31 b{ud楟蒱?] |
|