【文章标题】: Left 4 dead 破解攻略
【文章作者】: sunwayking
【作者邮箱】: sunwayking@163.com
【作者主页】: http://hi.baidu.com/suwnay
【作者QQ号】: 410109674
【软件名称】: Left 4 dead(求生之路)
【软件大小】: null
【下载地址】: 自己搜索下载
【加壳方式】: Steam App
【保护方式】: Steam检测+压缩壳
【编写语言】: VC++
【使用工具】: OD,PE Tools
【操作平台】: Windows
【软件介绍】: Left 4 dead 是一款非常成功的FPS游戏.
【作者声明】: 只为研究加密解密技术,不为破解而破解!失误之处敬请诸位大侠赐教!
--------------------------------------------------------------------------------
【详细过程】
大家好,早就承诺要放出 Left 4 dead (以下简称 L4D) 的详尽的破解过程,因为最近很忙所以一直拖到现在.好了下面切入正题...
QUOTE:
对于一下过程中的术语等内容大家可以参考 ghgzhilian大 发表的破解入门
首先我们大体感知一下这个游戏的加密手段,运行 Left4dead.exe 文件,游戏并未启动,而是出现了steam的登陆窗口(前提是您安装了steam,不要关闭steam的登陆窗口,再次运行L4D,这次可以进入游戏.所以可以判定游戏在启动的时候会有一段代码检测steam是否运行了(注意,游戏对是否登陆并不要求.
所以我们继续保留哪个steam 的登陆窗口,并且用 OD 载入 Left4dead.exe 文件,来到:
QUOTE:
0041C2ED > 53 push ebx
0041C2EE 51 push ecx
0041C2EF 52 push edx
0041C2F0 56 push esi
0041C2F1 57 push edi
0041C2F2 55 push ebp
0041C2F3 8BEC mov ebp, esp
0041C2F5 81EC 00100000 sub esp, 1000
0041C2FB C785 78FFFFFF F>mov dword ptr [ebp-88], 0041E1F4
0041C305 8BB5 78FFFFFF mov esi, dword ptr [ebp-88]
0041C30B B9 D9000000 mov ecx, 0D9
0041C310 8DBD 10FCFFFF lea edi, dword ptr [ebp-3F0]
0041C316 F3:A5 rep movs dword ptr es:[edi], dword p>
0041C318 8D85 10FCFFFF lea eax, dword ptr [ebp-3F0]
0041C31E 8985 04FCFFFF mov dword ptr [ebp-3FC], eax
0041C324 C785 D4FBFFFF 7>mov dword ptr [ebp-42C], 54B777D
这里大家注意以下,有些OD在调试 L4D 的时候使用 F8 过 Call 或者使用 F4 时会出现跑飞的现象,最简单的解决办法就是使用 F2 + F9 的组合跳过即可.
我在第一次调试 L4D 的时候并没有单步跟踪,而是往下翻,因为前往 OEP 的代码一般是一个跨区段的大跳转,而且根据当前入口点有寄存器顺序入栈的特点,我想,飞向光明顶的大跳转之前一定是那些寄存器按照 "FILO 原理" 弹出堆栈,即:
QUOTE:
pop ebp
pop edi
pop esi
pop edx
pop ecx
pop ebx
jmp [OEP]
果然,在如下地方找到了符合要求的代码:
QUOTE:
0041D96B 8B85 D0FBFFFF mov eax, dword ptr [ebp-430]
0041D971 81C4 00100000 add esp, 1000
0041D977 5D pop ebp
0041D978 5F pop edi
0041D979 5E pop esi
0041D97A 5A pop edx
0041D97B 59 pop ecx
0041D97C 5B pop ebx
0041D97D FFE0 jmp eax ; //此处就将跳到OEP
0041D97F 0FBE85 44FCFFFF movsx eax, byte ptr [ebp-3BC]
0041D986 83F8 35 cmp eax, 35
在 "jmp eax"上下断点(F2 ,然后 F9 运行程序,程序停在 "jmp eax" 处.如果您的 OD 使用 F4(运行到所选不会跑飞也可以使用 F4.
这样,继续 F8 ,峰回路转,我们经过一个大跳转后来到了光明顶:
QUOTE:
004018B0 E8 55330000 call 00404C0A
004018B5 ^ E9 16FEFFFF jmp 004016D0
004018BA 56 push esi
004018BB 8B35 9CF04000 mov esi, dword ptr [40F09C]
004018C1 EB 26 jmp short 004018E9
004018C3 57 push edi
004018C4 50 push eax
004018C5 FF7424 10 push dword ptr [esp+10]
004018C9 E8 11350000 call 00404DDF
004018CE 83C4 0C add esp, 0C
004018D1 85C0 test eax, eax
004018D3 75 11 jnz short 004018E6
在此处(004018B0 用OD自带的插件转存,却发现会出现读取错误,而此时内存镜像事实上是读写权限.拿出 PE Tools 将此进程转存(dump 出来,删除最后两个区段,并且将入口点(OP 修正为刚才得到的 004018B0,最后重建一下 PE 文件即可.至此steam已经完全被脱去.最后的文件大小应该在 80kb~90KB.
现在让我们回头在看看保护程序的大体流程,这里我没有做详尽的分析,事实上破解程序并不需要对所有代码进行分析,甚至有些代码因为是编译器编译出来的,所以非常怪异甚至非常愚蠢.
程序有这么几处会导致游戏不运行(要么退出要么运行steam:
1.
QUOTE:
0041C7E4 0FB685 ACF2FFFF movzx eax, byte ptr [ebp-D54]
0041C7EB 85C0 test eax, eax
0041C7ED 75 11 jnz short 0041C800 ; //关键位置
0041C7EF C685 44FCFFFF 4>mov byte ptr [ebp-3BC], 45
0041C7F6 E9 84110000 jmp 0041D97F
0041C7FB E9 7F110000 jmp 0041D97F
0041C800 FF55 F0 call dword ptr [ebp-10]
2.
QUOTE:
0041C866 8885 44FCFFFF mov byte ptr [ebp-3BC], al
0041C86C 0FBE85 44FCFFFF movsx eax, byte ptr [ebp-3BC]
0041C873 83F8 30 cmp eax, 30
0041C876 74 0A je short 0041C882 ; //关键位置
0041C878 E9 02110000 jmp 0041D97F
0041C87D E9 FD100000 jmp 0041D97F
0041C882 64:A1 18000000 mov eax, dword ptr fs:[18]
0041C888 8985 78FBFFFF mov dword ptr [ebp-488], eax
3.
QUOTE:
0041C8D5 0FB685 77FBFFFF movzx eax, byte ptr [ebp-489]
0041C8DC 85C0 test eax, eax
0041C8DE 74 11 je short 0041C8F1 ; //关键位置
0041C8E0 C685 44FCFFFF 5>mov byte ptr [ebp-3BC], 54
0041C8E7 E9 93100000 jmp 0041D97F
0041C8EC E9 8E100000 jmp 0041D97F
0041C8F1 8B85 34FCFFFF mov eax, dword ptr [ebp-3CC]
0041C8F7 8B00 mov eax, dword ptr [eax]
4.
QUOTE:
0041CAC7 8885 44FCFFFF mov byte ptr [ebp-3BC], al
0041CACD 0FBE85 44FCFFFF movsx eax, byte ptr [ebp-3BC]
0041CAD4 83F8 30 cmp eax, 30
0041CAD7 74 0A je short 0041CAE3 ; //关键位置
0041CAD9 E9 A10E0000 jmp 0041D97F
0041CADE E9 9C0E0000 jmp 0041D97F
0041CAE3 8B85 34FCFFFF mov eax, dword ptr [ebp-3CC]
0041CAE9 8B00 mov eax, dword ptr [eax]
0041CAEB 3B85 30FCFFFF cmp eax, dword ptr [ebp-3D0]
0041CAF1 74 11 je short 0041CB04 ; //关键位置
0041CAF3 C685 44FCFFFF 4>mov byte ptr [ebp-3BC], 4D
0041CAFA E9 800E0000 jmp 0041D97F
0041CAFF E9 7B0E0000 jmp 0041D97F
0041CB04 FFB5 38FCFFFF push dword ptr [ebp-3C8]
0041CB0A 6A 00 push 0
5.
QUOTE:
0041D83F 50 push eax
0041D840 FF55 C8 call dword ptr [ebp-38]
0041D843 83BD 0CFCFFFF 0>cmp dword ptr [ebp-3F4], 0
0041D84A 75 11 jnz short 0041D85D ; //关键位置
0041D84C C685 44FCFFFF 4>mov byte ptr [ebp-3BC], 42
0041D853 E9 27010000 jmp 0041D97F
0041D858 E9 22010000 jmp 0041D97F
0041D85D FFB5 38FCFFFF push dword ptr [ebp-3C8]
0041D863 FFB5 34FCFFFF push dword ptr [ebp-3CC]
0041D869 FF95 0CFCFFFF call dword ptr [ebp-3F4] ; //校验steam是否运行,如果运行则释放L4D真正的代码,并将OEP定位信息存放在eax里
0041D86F 8985 D0FBFFFF mov dword ptr [ebp-430], eax ; OEP存入[ebp-430]
0041D875 8B85 38FCFFFF mov eax, dword ptr [ebp-3C8]
0041D87B 8985 48F9FFFF mov dword ptr [ebp-6B8], eax
6.
QUOTE:
0041D8CD 50 push eax
0041D8CE FF55 C8 call dword ptr [ebp-38]
0041D8D1 81BD D0FBFFFF F>cmp dword ptr [ebp-430], 0FF
0041D8DB 73 16 jnb short 0041D8F3 ; //又是关键位置,修改标志位C即可更改跳转状态
0041D8DD 8A85 D0FBFFFF mov al, byte ptr [ebp-430]
0041D8E3 8885 44FCFFFF mov byte ptr [ebp-3BC], al
0041D8E9 E9 91000000 jmp 0041D97F
0041D8EE E9 8C000000 jmp 0041D97F ; 跳飞,程序转而运行steam.
0041D8F3 8D85 10FCFFFF lea eax, dword ptr [ebp-3F0]
总结一下以上几段代码的特点,那就是只要 jmp 到 0041D97F,那么游戏就不会运行了.为什么呢,因为 "jmp eax" 那句的地址是 0041D97D.
第 5 段里的带注释的 call 的功能正是解压 OEP 入口处代码,如果 steam 没有在运行,那么这个 call 就不会解压入口点的代码.另外整个流程也说明了为什么只要 steam 开着,无论是否登陆都可以进入单机游戏,正如本文开头所述.