当前位置:编程学习 > 网站相关 >>

破解网络游戏幸福花园Online

【破解作者】 shoooo[iPB][pycg]
【作者邮箱】 shoooo314@163.com
【使用工具】 softice 套装2.7 iceext插件,Iris
【破解平台】 win2000 sp4
【破解目标】 账号,密码
【软件名称】 幸福花园Online 内测中
【破解时间】 2005-01-28 午
【加壳方式】 无壳
【破解声明】 应一好友要求,帮忙看看幸福花园Online,隧有此文,不对的地方大家批评

一,登录包

截包工具有很多,看个人喜好了~~我Iris用惯了

以账号shoooo密码12345登录,截到的登录包是 "LVJMV2V0dTIrQ0dWZEoeWVYdKTpmel4DDERF" (注:最后的""是0x0A)
再登录几次,截到的登录包是相同的

总结:加密算法是上下文无关单包操作的,偶非常稀饭

二,从send包反推

绝大多数网游的客户端与服务器用的是一套加密,即客户端加密,服务器解密;服务器加密,客户端解密(好像是废话)
我想说的是,客户是端含有解密代码的,只要断recv后,观察客户端是怎么处理接收的包就能找到解密过程。

但是偶喜欢从send包反推,研究它的加密过程,自己搞解密。

呼出sice, bpx send
以shoooo,12345登录,断下,F11返回

00416759 |. 6A 00 push 0 ; /Flags = 0
0041675B |. 53 push ebx ; |DataSize
0041675C |. 50 push eax ; |Data 我们关心的是这里的值,很可惜断在正面时eax的值被改了
0041675D |. 51 push ecx ; |Socket
0041675E |. E8 2F9C1200 call <jmp.&WSOCK32.#19> ; send
00416763 |. 8BF0 mov esi,eax ; 停在这里

bc * 取消send断点
bpx 41675e,再次登录断下,这次可以看清Data的值了是,也就是发送数据的地址是617B2C

bpmd 617B2C w 再次登录,断在这儿
004168CE |. BE D0F19100 mov esi,ST_cb_01.0091F1D0 ESI= 91F1D0
004168D3 |. BF 2C7B6100 mov edi,ST_cb_01.00617B2C EDI= 617B2C
004168D8 |. C705 D0F192>mov dword ptr ds:[92F1D0],0
004168E2 |. C1E9 02 shr ecx, 2 这句做完ECX= 1A
004168E5 |. F3:A5 rep movs dword ptr es:[edi],dword ptr ds:[esi] memcpy(EDI, ESI, ECX)
004168E7 |. 8BCA mov ecx,edx
004168E9 |. 50 push eax
004168EA |. 83E1 03 and ecx,3
004168ED |. 68 2C7B6100 push ST_cb_01.00617B2C
004168F2 |. F3:A4 rep movs byte ptr es:[edi],byte ptr ds:[esi]
可见617B2C中发送的数据是从91F1D0 中memcpy得来

bpmd 91F1D0 w 再次登录,断在这儿
0041683B |. 03F2 add esi,edx ESI= 5C7B2C
0041683D |> 8BC1 mov eax,ecx
0041683F |. 8DBD D0F191>lea edi,dword ptr ss:[ebp+91F1D0] ESI= 91F1D0
00416845 |. C1E9 02 shr ecx,2
00416848 |. F3:A5 rep movs dword ptr es:[edi],dword ptr ds:[esi] memcpy
0041684A |. 8BC8 mov ecx,eax
0041684C |. 83E1 03 and ecx,3
0041684F |. F3:A4 rep movs byte ptr es:[edi],byte ptr ds:[esi]
又memcpy! 91F1D0的数据从5C7B2C处来,没完没了

继续 bpmd 5C7B2C w,登录,断在这儿
00415C53 |. 85C9 test ecx,ecx
00415C55 |. 0F8E 100100>jle ST_cb_01.00415D6B

.....
.....
00415D75 |. 5F pop edi
00415D76 |. 5B pop ebx
00415D77 |. 83C4 14 add esp,14
00415D7A . C3 retn 返回到 416627
这里已经在执行加密的过程了,bc *, g 415d7a,跑出这个加密的call,来到这里
004165E7 |. 68 00000100 push 10000
004165EC |. 68 2C7B5F00 push ST_cb_01.005F7B2C
004165F1 |. 51 push ecx
004165F2 |. 52 push edx
004165F3 |. E8 58F9FFFF call ST_cb_01.00415F50
004165F8 |. 6A 40 push 40
004165FA |. 68 E87A5C00 push ST_cb_01.005C7AE8
004165FF |. 50 push eax
00416600 |. 68 2C7B5F00 push ST_cb_01.005F7B2C
00416605 |. E8 36000000 call ST_cb_01.00416640
0041660A |. 83C4 20 add esp,20
0041660D |. 68 2C7B5C00 push ST_cb_01.005C7B2C
00416612 |. 50 push eax
00416613 |. 68 2C7B5F00 push ST_cb_01.005F7B2C
00416618 |. 56 push esi
00416619 |. E8 12F9FFFF call ST_cb_01.00415F30
0041661E |. 83C4 04 add esp,4
00416621 |. 50 push eax
00416622 |. E8 E9F5FFFF call ST_cb_01.00415C10
00416627 |. 50 push eax 前面的ret跳到了这里,因此前面的call都值得注意
00416628 |. 68 2C7B5C00 push ST_cb_01.005C7B2C
0041662D |. 56 push esi
0041662E |. E8 2D000000 call ST_cb_01.00416660

总结一下,客户端把数据明文加密后第一时间写在5C7B2C,然后memcpy到91F1D0,再memcpy到617B2C,然后send出去


三,加密

从EIP:4165EC 开始看,因为再前面没什么特别的
因此,bc *,bpx 4165ec,先F10(相当于OD中的F8)走一遍,看看加密的大致流程
004165E7 |. 68 00000100 push 10000
004165EC |. 68 2C7B5F00 push ST_cb_01.005F7B2C
004165F1 |. 51 push ecx ECX= 1A 明文长度
004165F2 |. 52 push edx 明文的地址
004165F3 |. E8 58F9FFFF call ST_cb_01.00415F50

这里我们看到了明文中的地址,可以d edx 看看明文是什么
61 03 00 00 00 00 00 00 0E 00 00 00 06 73 68 6F
命令码 长度s h o
6F 6F 6F 05 31 32 33 34 35 00
o o o 长度1 2 3 4 5

这个call过后,显然看出,它把EAX指向的明文memcpy到了 5F7B2C内存处

004165F8 |. 6A 40 push 40 十进制64
004165FA |. 68 E87A5C00 push ST_cb_01.005C7AE8 指向一张64字节大小的第一次加密的密钥表
004165FF |. 50 push eax 明文长度
00416600 |. 68 2C7B5F00 push ST_cb_01.005F7B2C 指向明文,同时密文这里输出
00416605 |. E8 36000000 call ST_cb_01.00416640 第一次加密,详见A部分

这个CALL后,5F7B2C处的明文加密成了
2D 52 4C 57 65 74 75 32 2B 43 47 56 64 4A 1E 59
56 1D 29 3A 66 7A 5E 03 0C 44 45

0041660A |. 83C4 20 add esp,20
0041660D |. 68 2C7B5C00 push ST_cb_01.005C7B2C 指向我们期待的最终密文的内存地址
00416612 |. 50 push eax 长度
00416613 |. 68 2C7B5F00 push ST_cb_01.005F7B2C 经过第一次加密后的密文
00416618 |. 56 push esi
00416619 |. E8 12F9FFFF call ST_cb_01.00415F30 这个call过后,上面的数据都无发生变化,不采

0041661E |. 83C4 04 add esp,4
00416621 |. 50 push eax eax+100处是第二次加密的密钥表
00416622 |. E8 E9F5FFFF call ST_cb_01.00415C10 最终第二次加密,详见B部分

这个call过后,我们期待的5C7B2C处出现了最终的密文。

总结:客户端把明文先第一次加密放在5F7B2C处,再第二次加密放到5C7B2C,加密完成。

四,算法

A部分:跟进第一次加密的CALL看看做了些什么,很容易找到这一段:
0041623C |> /3BC8 /cmp ecx,eax 加密完了吗?
0041623E |. |7C 04 |jl short ST_cb_01.00416244 没有就跳下去继续加密
00416240 |. |33C9 |xor ecx,ecx
00416242 |. |EB 07 |jmp short ST_cb_01.0041624B 加密完了就跳走88
00416244 |> |8A1C39 |mov bl,byte ptr ds:[ecx+edi] 取出一个密钥
00416247 |. |301C32 |xor byte ptr ds:[edx+esi],bl 明文异或密钥
0041624A |. |41 |inc ecx 密钥指针加1
0041624B |> |42 |inc edx 明文指针加1
0041624C |. |3BD5 |cmp edx,ebp 明文还有要加密的吗?
0041624E |.^7C EC jl short ST_cb_01.0041623C 有的话跳上去继续加密吧

总结:依次取出明文与密钥异或后产生密文
这里密钥表是固定的
-3OWetu2+MGVdLm1
9rFUcKl08qETbJkz
7pDSaIjy6oCRZHix
5nAQYghw4BsPXfNv

因此这段加密也即是解密
void sg_de0(unsigned char* data, int length)
{
int i;
unsigned char key[64] = "-3OWetu2+MGVdLm19rFUcKl08qETbJkz7pDSaIjy6oCRZHix5nAQYghw4BsPXfNv";

for (i=0; i<length; i++)
{
data[i] ^= key[i%0x40];
}
}

B部分:这里我们暂且把第一次加密后的密文称为明文吧,跟进第二次加密的call,很容易发现它是每3个字节加密成4个字节

00415C83 |> 8A541E 01 |mov dl,byte ptr ds:[esi+ebx+1] 取出明文的第2字节
00415C87 |. 83C1 FE |add ecx,-2
00415C8A |. 3BF1 |cmp esi,ecx
00415C8C |. 8A0C1E |mov cl,byte ptr ds:[esi+ebx] 取出明文的第1字节
00415C8F |. 884C24 10 |mov byte ptr ss:[esp+10],cl
00415C93 |. 885424 14 |mov byte ptr ss:[esp+14],dl
00415C97 |. 7C 09 |jl short ST_cb_01.00415CA2
00415C99 |. 32C0 |xor al,al
00415C9B |. BD 03000000 |mov ebp,3
00415CA0 |. EB 09 |jmp short ST_cb_01.00415CAB
00415CA2 |> 8A441E 02 |mov al,byte ptr ds:[esi+ebx+2] 取出明文的第3字节
00415CA6 |. BD 04000000 |mov ebp,4
00415CAB |> 80E2 0F |and dl,0F 第2个字节留下后4位
00415CAE |. 8AD8 |mov bl,al
00415CB0 |. C0E2 02 |shl dl,2 第2个字节留下后4位后左移2位
00415CB3 |. C0EB 06 |shr bl,6 第3个字节右移6位,最高2位移到低2位
00415CB6 |. 0AD3 |or dl,bl 把上面2个或操作,即合并起来,不存在冲突部分,放dl
00415CB8 |. 24 3F |and al,3F 第3个字节只留下最后6位,放al
00415CBA |. 83FD 02 |cmp ebp,2
00415CBD |. 885424 1C |mov byte ptr ss:[esp+1C],dl dl内存中存一下 一会儿要取出
00415CC1 |. 884424 20 |mov byte ptr ss:[esp+20],al al内存中存一下 一

补充:综合编程 , 安全编程 ,
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,