PC版《侠盗猎车手》反向工程为原始源代码

2021-02-17 19:19:02

一组专门的编码人员在长达数年的过程中为侠盗猎车手III和Vice City的PC版本生成了完整的逆向工程原始代码,其中包括成千上万行C ++代码。

过去,我们已经讨论了视频游戏迷编码器如何使用逆向工程技术来解构由游戏原始开发人员分发的打包可执行文件。这个艰苦的,逐个函数的过程创建了原始的编程代码,在编译时可以生成完全相同的二进制文件。

有了这些代码,编码人员可以检查是什么使游戏停滞不前,并在比传统改装更细粒度的层次上进行改进和更改。仅举几个例子,就侠盗猎车手而言,这些改进包括错误修复,减少了加载时间,改进了渲染,宽屏监视器支持以及自由浮动的摄像头系统。源代码还可用于生成游戏移植到Linux,Switch和PlayStation Vita等新平台的端口(尽管这些重新编译的版本都需要从原始游戏中提取受版权保护的艺术品和音乐文件)。

Github贡献者" aap"写道,该项目始于2018年初,最初是为了测试游戏内反向碰撞和物理代码的一种方式。通过对特定的DLL进行反向工程。到2019年,该项目的合并人员也有所增加,他们能够在2020年4月之前生成可运行的可执行文件。aap写道,该团队利用该代码生成了Vice版本的源代码,该版本将于2020年12月准备就绪。

除了为《侠盗猎车手:自由城故事》进行类似的反编译外,源代码团队还表示有兴趣生成PC版游戏的PS2和Xbox端口,以及其他错误修复程序。

我曾经参加过很多复古的DOS / Windows 9x时代的游戏挖掘/分解工作,主要是出于娱乐目的,我必须说,游戏越老,它们对反向工程的难度就越大。它主要来自开发人员必须采用的所有怪癖和优化措施,以使当时的机器获得最佳性能。自定义压缩算法,预编译资产,位打包...有很多技术在当时非常普遍,现在已经不复存在。以及资产的使用方式。当时,大多数东西是带有调色板的位图,特效经过硬编码或在运行时应用一系列精灵。现在,一切都是着色器和3D模型。

曾经有一个很酷的程序,叫做" Sourcerer"。可以将任何dos程序反编译为asm。这使您对游戏/程序中发生的事情有很多了解。几年后,出现了Windows版本&一本非常不错的书,向您展示了如何使用asm优化Windows代码。到那时,您所拥有的只是带有WinWindow入口点的带有CreateWindow / CreateWindowEx api调用的c sdk,因为您确实了解使代码片段起作用的原因,因此上述某些内容确实需要进行教学。另一个出色的资料来源是乔恩·斯托克斯(Jon Stokes)的书《机器里面》(Inside The Machine)。 https://www.amazon.com/Inside-Machine-I ... 183& sr = 8-1一旦深入兔子的洞,便有" Linkers&约翰·莱文(John Levine)的装载机

我一直想知道何时听到反编译的一件事是,因为我假设您最终生成的变量名在很大程度上是毫无意义的文本字符串,有人曾经尝试编写反编译程序来尝试分配有用的变量名吗?我不期望使用具有高度描述性的驼峰名称,但是反编译器至少会尝试指出类型吗?

是的,他们绝对有能力确定类型。 CPU具有指定操作数类型的指令。例如,ADD指令指定整数操作数的相加,而ADDSS和ADDSD指令指定单精度和双精度操作数的相加。处理类型转换和价值提升时需要进行其他工作,但这实际上非常容易。编写反向编译器的真正困难来自两个方面:编译器优化和手写汇编。编译器优化会动态更改源代码,因此编译的内容可能不是源代码中编写的内容。但是,最终结果是相同的。例如,将乘法和除法更改为左右两次,然后将9乘以更改为LEA操作码(尽管LEA也可以用作执行某些乘法的较快方法,但您可以认为输入是一个内存地址。 )。编译器优化并不总是很复杂,因此可以通过一些工作对其进行逆向工程。手写大会是所有下注的地方。显然,在较旧的程序中找到手写汇编更为普遍。 C和C ++编译器的效率不如现在,并且程序更小。但是,高级语言的好处是可以基于一组固定的模式生成代码,因此被称为“结构化语言”。一旦知道了模式,就可以将其反转。但是,手写汇编很少基于模式,因此反向编译器可能必须采用各种技巧来确定代码中正在发生的事情。更糟糕的是,诸如C和C ++的高级语言允许使用GOTO语句。关于为什么不应该使用此声明的所有论文,包括埃德加·吉克斯特拉(Edgar Djikstra)著名的“ GOTO被认为有害”,已被撰写。使用此语句会导致程序中出现大量错误,并且由于缺乏结构,实际上使反向编译成为不可能。 GOTO被实现为无条件跳转,它可以在函数内部的任何位置跳转。考虑循环控制结构:1)逻辑比较2)有条件跳转3)代码4)无条件跳转回1)反向编译器可以轻松确定1-4是循环。并且如果循环内无条件跳转,则该方向告诉反向编译器这意味着什么:跳过4)是BREAK语句,跳转到4)是CONTINUE语句。那就是结构的好处。现在,想象一下当GOTO语句从循环外跳入3时出现的问题。...完全公开:我正在为类似C的语言编写一个反向编译器,该编译器可以编译为简单的x86类似语言字节码。感谢我的幸运星,开发人员不包括对GOTO的支持。