Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/60.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 对可执行文件进行版本控制并在运行时对其进行修改_C++_C_Binary_Io_Versioning - Fatal编程技术网

C++ 对可执行文件进行版本控制并在运行时对其进行修改

C++ 对可执行文件进行版本控制并在运行时对其进行修改,c++,c,binary,io,versioning,C++,C,Binary,Io,Versioning,我试图做的是用版本签名对编译后的可执行文件的前32个字节进行签名,比如“1.2.0”,我需要在运行时修改此签名,请记住: 这将由可执行文件本身完成 可执行文件驻留在客户端,这意味着不可能重新编译 使用外部文件来跟踪版本而不是在二进制文件中对其进行编码也是不可取的 解决方案必须独立于平台;我知道Windows/VC允许您使用.rc资源对可执行文件进行版本设置,但我不知道Mac(可能是Info.plist?)和Linux有一个等价的版本 我脑海中的解决方案是在二进制文件的前32个字节或后32个字

我试图做的是用版本签名对编译后的可执行文件的前32个字节进行签名,比如“1.2.0”,我需要在运行时修改此签名,请记住:

  • 这将由可执行文件本身完成
  • 可执行文件驻留在客户端,这意味着不可能重新编译
  • 使用外部文件来跟踪版本而不是在二进制文件中对其进行编码也是不可取的
  • 解决方案必须独立于平台;我知道Windows/VC允许您使用.rc资源对可执行文件进行版本设置,但我不知道Mac(可能是Info.plist?)和Linux有一个等价的版本
我脑海中的解决方案是在二进制文件的前32个字节或后32个字节中写入版本签名(我还不知道怎么做),然后在需要时修改这些字节。可悲的是,这并不是那么简单,因为我正试图修改我正在执行的同一个二进制文件

如果你知道我如何做到这一点,或者知道一个更干净/主流的解决方案,我将非常感激。FWIW,该应用程序是游戏的补丁程序/启动器;我选择在补丁程序本身而不是游戏可执行文件中对版本进行编码,因为我希望它是自包含的和独立于目标的

更新:从您有用的回答和评论中,我发现搞乱二进制文件的页眉/页脚不是一条好路。但是关于运行用户的写入权限,游戏必须以某种方式进行修补,并且需要修改游戏文件,这是无法避免的:要更新游戏,您需要管理员权限

我会选择使用外部文件保存签名,并在每次更新时对其进行修改,但我看不出如何防止用户使用该文件进行欺骗:如果他们弄乱了版本号,我如何检测我正在运行的版本


更新2:感谢您的回答和评论,实际上有两种方法可以做到这一点:使用外部资源跟踪版本或将其嵌入主应用程序的二进制文件本身。我只能选择一个答案,所以我选择了我想要的答案,尽管它不是唯一的答案。:-)

除非您以管理员权限运行,否则现代Windows版本将不允许您更新已安装的程序文件。我相信所有版本的Windows都会阻止对运行文件的修改;这就是更新后您被迫重新启动的原因。我认为你是在要求不可能的事情。

这将是一个挑战,原因有很多。首先,写入二进制文件的前N个字节可能会影响二进制文件的头信息,程序加载器使用头信息来确定代码和数据段等在文件中的位置。这在不同的平台上是不同的(参见和)——有很多不同的二进制格式标准


假设您能够克服这个问题,那么如果您在运行时开始修改程序的代码,您可能会与安全/防病毒系统发生冲突。我不相信大多数当前的操作系统会允许您覆盖当前正在运行的可执行文件。至少,它们可能允许您在提升权限的情况下执行此操作——不太可能在玩游戏时出现。

我将给出一些有关如何执行此操作的想法

我认为不可能在没有副作用的情况下更改可执行文件中的任意字节。为了克服这个问题,我将在源代码中创建一些字符串,如:

char *Version = "Version: AA.BB.CC";
我不知道这是否是一条规则,但您可以在二进制代码中查找该字符串(在文本编辑器中打开它,您将看到)。因此,您可以在二进制文件中搜索并更改此字节作为您的版本号。很可能,每次编译应用程序时,它们的位置都会有所不同,因此只有在该位置对您来说不是问题的情况下,才有可能这样做

因为文件正在使用(正在运行),所以必须启动一个外部程序来执行此操作。修改文件后,此外部程序可以重新启动原始应用程序


该版本将存储在二进制代码的某些部分。这有用吗?您将如何检索版本号?

如果您的应用程序要修补游戏,为什么不在运行时将版本嵌入其中?您可以使用@Juliano shows这样的字符串,并在游戏未运行时从修补程序中修改该字符串-如果您当前正在进行修补,则应该如此:P


编辑:如果您正在使用Visual Studio,根据以下说明,使用
#pragma注释
将此类字符串嵌入可执行文件非常容易:

由于第二个参数是一个简单的字符串文字,因此可以将其串联起来,并且我将使用一个简单的
#define

// somehwere
#define MY_EXE_VERSION "1.4.1"
// somewhere else
#pragma comment(user, "Version: " MY_EXE_VERSION)

您正在尝试更改内存中磁盘上的签名吗?您是否想到可执行文件本身可能正在使用这些字节?@Seth:在磁盘上,进程终止后,它将如何保持@尼尔:完全是这样,这就是为什么我要问,我可以“保留”这些字节,或者在编译时指定它们的写入位置吗?你想做的事情是不可能移植的。考虑我的情况,使用Linux:我在一个特殊的“游戏”用户帐户下安装所有游戏发射器。该帐户没有对可执行启动器的写入权限。我没有用我用来安装的帐户运行游戏。@希思:我明白了,作为“游戏”用户运行,你可以修改所有游戏文件,但不能修改实际的可执行文件?因此,我应该修补游戏的可执行文件,而不是启动器?因此,将版本保存在外部文件中是一种方法?我担心用户使用文件进行欺骗,我将无法检测到这一点,然后整个修补过程将被破坏。他们不能欺骗exe文件吗?如果用户真的需要,他们可以破解任何东西
// somehwere
#define MY_EXE_VERSION "1.4.1"
// somewhere else
#pragma comment(user, "Version: " MY_EXE_VERSION)