【破解作者】 shoooo
【作者邮箱】 [email]shoooo314@163.com[/email]
【使用工具】 softice 套装2.7 iceext插件,Iris
【破解平台】 win2000 sp4
【破解目标】 账号,密码
【软件名称】 倚天II (公测中)
【破解时间】 2004-12-20
【加壳方式】 无壳
【破解声明】 我是一只小菜鸟,偶得一点心得,愿与大家分享:)
本文旨在讨论网络游戏的破解思路,错误或不妥之处,各位批评指正
文章中的代码粘贴自IDA,我softice不会dump汇编代码
由于更新频繁或其它原因,内存地址可能存在出入
一,寻找登录包
输入错误的用户名或密码,让TCP流尽早结束,这样交流的数据包较少,容易找
截包工具有很多,看个人喜好了~~我Iris用惯了
启动倚天II,出现登录界面,随便找个服务器,以用户名shoooo 密码1234登录,报错。看看截的包包,在登录过程中,含有数据的共有9
个包,包中的数据都是无规则的16进制,可以肯定是经过加密的。很容易发现前面7个包长度较短,内容近似。
第8个包是客户端发给服务器,长度有56字节如下
C8 9E 23 AC BA 93 FD 12 05 72 11 85 BF D0 E7 BB
D1 C0 A9 36 35 AA 5B 0B 05 72 11 85 BF D0 E7 BB
F3 9C 41 BD C1 62 6B 7A 22 E5 37 46 B7 13 1E 00
B2 BC FA 80 11 B6 2D 82
第9个包从服务器发来给客户端,长度为16字节如下
0E 6B 32 F1 40 39 80 69 05 72 11 85 BF D0 E7 BB
猜测第8个包是登录包,第9个登录包是登录响应包。
用相同的账号再登录一次
重点观察第8个包如下,并发现前32字节与前次登录中的数据相同
C8 9E 23 AC BA 93 FD 12 05 72 11 85 BF D0 E7 BB
D1 C0 A9 36 35 AA 5B 0B 05 72 11 85 BF D0 E7 BB
5C 7C 2A 03 B6 CF D3 39 FE 04 3D 80 C8 B0 E3 25
5A F8 EA 9E 62 2A 13 87
重点观察第9个包如下,与前次完全相同
0E 6B 32 F1 40 39 80 69 05 72 11 85 BF D0 E7 BB
省略n次的相同或不同账号密码组合的登录试验......
这时我们得到如下结论
a. 登录包长度固定为56字节,若以相同的账号,密码登录,登录包的前32字节相同。登录的错误响应包数据相同,固定16字节
b. 56,32,16都是8的倍数,加密算法极有可能是8字节的分组算法
二,寻找发送buffer
可以从输入的账号,密码开始跟,也可以从发送的数据包反向跟,我个人倾向于后者,这里采用后者的方法
请出softice,symbol loader 加载ws2_32.dll,倚天2有防softice,用上iceext插件顺利躲过
启动客户端至登录界面
ctrl-d 呼出
确认右下角显示为倚天II的领空metein2(以下不再提示),如果不是可多试几次或用addr命令
下断点bpx send
下断点bpx wsasend
随便选个服务器,输用户名shoooo,密码1234。点登录
softice在send处断下,按F11回到调用send的地方,看EAX的值,EAX是调用send后的返回值也就是实际发送的字节长度,我们想要看到的
是56字节,即十六进制的38。现在不是,ctrl-d让它继续跑,马上又在send处断下,F11,看EAX的值,不是就ctrl-d 再继续
约5到6次后,EAX的值显示为38,立即对准调用send的EIP:499722下断点,同时清除send,wsasend断点,按若干次ctrl-d,让登录过程结束
.text:00499716 push 0 ; flags
.text:00499718 push eax ; len
.text:00499719 push dword ptr [esi+24h] ; buf
.text:0049971C push dword ptr [esi+244h] ; s
.text:00499722 call send 此处下断点
.text:00499727 mov edi, eax
.text:00499729 test edi, edi
再次点击登录,这次在 EIP:499722处断下
下命令 d esi+24
B8 07 EE 01 08 08 00 00 .......
下命令 d 1ee07b8
C8 9E 23 AC BA 93 FD 12 05 72 11 85 BF D0 E7 BB
D1 C0 A9 36 35 AA 5B 0B 05 72 11 85 BF D0 E7 BB
0D 15 41 28 73 52 5A 05 CF 87 39 DF 74 35 24 1C
87 7B 41 D6 18 21 BA B3
这便是实际发送的登录包的数据
三,寻找加密过程
即寻找发送buffer的数据从何而来,不断的下内存断点,直到找到我们需要的账号,密码的明文
只保留499722的eip断点
下断点bpmd 1ee07b8
以shoooo,1234再次登录
第一次断在1ee07b8的内存写入,先别急着看,ctrl-d继续
第二次断在了EIP:499722处。
好了,到这里清楚了,第一次断下的地方便是对发送buffer的头8个字节的写入
再次登录,断在第一处
.text:0048F30D mov [edx], eax 这里edx值是1ee07b8
.text:0048F30F mov [edx+4], ecx 断在此处
.text:0048F312 pop ebx
.text:0048F313 pop ebp
.text:0048F314 retn 跳转到48F3D0
取消1ee07b8的内存断点,F10单步跟踪,48F314的retn语句后,跳转到了48F3D0
.text:0048F383 push ebp
.....省略若干行
.text:0048F3C0 / push [ebp+arg_0]
.text:0048F3C3 | push [ebp+arg_8]
.text:0048F3C6 | push dword ptr [edi]
.text:0048F3C8 | push dword ptr [edi+4] 指向明文,待输出密文的指针入栈
.text:0048F3CB | call sub_48F2AA 核心加密,8字节明文加密,8字节密文输出
.text:0048F3D0 | add [ebp+arg_0], 8 准备下次加密的8字节明文
.text:0048F3D4 | add esp, 10h
.text:0048F3D7 | add edi, 8 准备下次输出的8字节密文
.text:0048F3DA | dec [ebp+arg_C]
.text:0048F3DD \ jnz short loc_48F3C0 跳上去继续加密下一组
.text:0048F3DF pop edi
.text:0048F3E0 mov eax, esi
.text:0048F3E2 pop esi
.text:0048F3E3 pop ebp
.text:0048F3E4 retn 跳转到499706
48F3E4返回后,到了 499706
.text:004996EF push edi 需要加密的字节数
.text:004996F0 lea ecx, [esi+42h]
.text:004996F3 push ecx 指向密钥
.text:004996F4 mov ecx, [esi+30h]
.text:004996F7 add ecx, eax
.text:004996F9 mov eax, [esi+24h]
.text:004996FC add eax, [esi+2Ch]
.text:004996FF push ecx 指向登录包的明文(包含账号,密码)
.text:00499700 push eax 指向登录包的待输出的密文,这里是1ee07b8
.text:00499701 call sub_48F383 最外层的加密函数
.text:00499706 add [esi+2Ch], eax
此时可以清除先前的所有断点,在EIP: 499071处下断,跟踪整个加密过程,到这里不难发现登录包的明文必须是8字节的倍数,每8个字节
调用call 48F2AA进行加密,输出8字节的密文
四,加密算法求逆
既然服务器能对我们发送的加密登录包作出登录失败的反应,显然它是可逆的
重点观察48F2AA处的核心加密函数,分析出相应的解密算法
.text:0048F2AA push ebp
.text:0048F2AB mov ebp, esp
.text:0048F2AD mov eax, [ebp+arg_4]
.text:0048F2B0 mov ecx, [ebp+arg_0]
.text:0048F2B3 mov edx, [ebp+arg_8]
.text:0048F2B6 push ebx
.text:0048F2B7 push esi
.text:0048F2B8 push edi
.text:0048F2B9 xor esi, esi
.text:0048F2BB mov [ebp+arg_4], 20h 作32轮
.text:0048F2C2 mov edi, ecx
.text:0048F2C4 shr edi, 5
.text:0048F2C7 mov ebx, ecx
.text:0048F2C9 shl ebx, 4
.text:0048F2CC xor edi, ebx
.text:0048F2CE add edi, ecx
.text:0048F2D0 mov ebx, esi
.text:0048F2D2 and ebx, 3
.text:0048F2D5 mov ebx, [edx+ebx*4]
.text:0048F2D8 add ebx, esi
.text:0048F2DA xor edi, ebx
.text:0048F2DC add eax, edi
.text:0048F2DE mov edi, eax
.text:0048F2E0 shr edi, 5
.text:0048F2E3 mov ebx, eax
.text:0048F2E5 shl ebx, 4
.text:0048F2E8 xor edi, ebx
.text:0048F2EA sub esi, 61C88647h 加密函数中唯一出现的奇怪常数
.text:0048F2F0 mov ebx, esi
.text:0048F2F2 shr ebx, 0Bh
.text:0048F2F5 and ebx, 3
.text:0048F2F8 mov ebx, [edx+ebx*4]
.text:0048F2FB add edi, eax
.text:0048F2FD add ebx, esi
.text:0048F2FF xor edi, ebx
.text:0048F301 add ecx, edi
.text:0048F303 dec [ebp+arg_4]
.text:0048F306 jnz short loc_48F2C2
.text:0048F308 mov edx, [ebp+arg_C]
.text:0048F30B pop edi
.text:0048F30C pop esi
.text:0048F30D mov [edx], eax
.text:0048F30F mov [edx+4], ecx
.text:0048F312 pop ebx
.text:0048F313 pop ebp
.text:0048F314 retn
一般到这里就要开始体力劳动了,不过或许可以碰碰运气
google 关键字 0x61C88647 很快便能找到这个公开的加密解密算法 ^_^
本文以讨论思路为主,破解到此为止,在网吧玩游戏的朋友小心哦~
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)