不重新构建C++,如何更改常量变量?

6
我用Visual Studio 2015开发了一个C++项目。我的项目输出是一个单独的可执行文件,每个客户端都需要有一个唯一的ID,并且这个ID必须在代码内可访问。一个简单的方法是在代码内定义一个常量变量,并为每个客户端更改其值并多次构建它,但我有一个Linux服务器,我不确定能否简单地构建它,因为我使用了许多Winapi库。我在想,也许有另一种方式可以改变或添加一些常量值到输出,例如操纵可执行文件。
#include <string>
#include <iostream>
#include <Windows.h>


const std::string ID = "some unique ID";

int main() {
    std::cout << "Your ID: " << ID << std::endl;
    getchar();
    return(0);
}

1
将ID放入配置文件中?还是将其作为程序的参数传递? - Some programmer dude
1
我认为他会提供一个下载链接到一个定制的可执行文件,该文件具有分配给特定下载器的ID,因此热修补标准可执行文件可能是重新编译整个文件的替代方法(顺便说一句,在修补时ID也可以被加密并在运行时解密)。 - alo Malbarez
2
@MasoudR. -- 首先,这是一个Windows程序吗?如果是的话,您可以创建一个字符串资源,并直接在可执行文件中更改它。我知道这违反了您不使用其他程序的规则,但只是为了说明它是可以做到的。您只需要找出实现它的机制即可。 - PaulMcKenzie
1
也许这个链接可以帮助:http://everydaywithlinux.blogspot.com.ar/2012/11/patch-strings-in-binary-files-with-sed.html - alo Malbarez
1
请尝试这个:https://unix.stackexchange.com/a/214824/258399 - alo Malbarez
显示剩余13条评论
3个回答

2

看起来只有两种方法。一种是在Linux环境下构建项目,这是更好的方法,但必须使用一些工具,如Mono XBuild 链接在这里。 另一个可能更简单的选项是打开二进制文件并操作特定的字符串。根据@aloMalbarez的评论,这里是一个基于这个的简单脚本。 假设这个例子:(我使用50 ms作为我的ID的固定长度)

#include <string>
#include <iostream>
#include <Windows.h>

#define ID "mmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm"


using namespace std;

int main() {
    cout << "Your ID: " << ID << "\nlen:" << strlen(ID) <<  endl;
    getchar();
    return(0);
}

在生成可执行文件后,使用以下脚本创建输出。由于我不是Linux专家,所以您可以帮助我改进这个过程。

./build.sh input.exe output.exe "myfixedID"
#!/bin/bash
# build.sh input_file output_file <ID>


input_file=$1
output_file=$2
ID=$3


if [ -z "$1" ] || [ -z "$2" ] || [ -z "$3" ]; then
  echo "wrong parameters"
  echo "build.sh input_file output_file <ID>"
  exit 1
fi

# use fixed string (ID) in the source file
# this creates 50 of "m"s
search_value=$(printf 'm%.0s' {1..50})

extension=".back"
temp_file="$input_file$extension"
tmpstring_file="./tmp"
null_termin='\0'


echo "copying the original file..."
yes | cp -rf $input_file $temp_file

address=$(strings -t d $temp_file | grep $search_value | grep -o '[0-9]*')

echo "Address:"
echo $address
if ! [[ $address =~ ^[0-9]+$ ]]; then
  echo "cannot find valid ID in executable"
  echo "removing temps"
  rm $temp_file
  exit 1
fi


# make the tempstring file
printf "$ID$null_termin" > $tmpstring_file

dd if=$tmpstring_file of=$temp_file obs=1 seek=$address conv=notrunc

echo "make new file"
yes | cp -rf $temp_file $output_file

echo "removing temps"

rm $temp_file $tmpstring_file

echo "Done!"

1
在程序的init函数中,生成一个基于当前时间、IP地址、用户名(等等)的SHA-1哈希唯一标识符。之后,您可以在该程序中进行任何您想要做的操作(例如保存到数据库)。这样会起作用吗?

谢谢,但是ID是固定的,必须为服务器所知。对于每个可能的客户端都构建1000次并不是一个好主意。 - Masoud Rahimi
客户端和服务器是否可以基于相同的信息生成ID?例如,基于用户名、电子邮件地址、用户ID(使用哈希函数如SHA-1)?这样,服务器就可以在不明确传递信息的情况下知道客户端了吗? - code707
你是正确的,那样做是可能的,但服务器不知道什么是客户端,只需要用唯一的标识符制作可执行文件。 - Masoud Rahimi

-4
常量和变量是相反的类型。 常量是分配了特定值且不会更改的元素,因此称为常量,即不变的。 另一方面,变量是存储在内存中的可变值,随着程序运行,变量可以更改其当前值。
在Visual Studio中,您可以创建一个配置文件,将设置值传递给程序,这些值是可变的,并且可以通过编程和手动更改。 但是,正如您所说,您不想从单独的文件中查找信息。
如果您想通过唯一ID跟踪用户,则必须在某个地方拥有可以记录新用户并发出唯一ID的数据库,或者可以根据帐户创建的日期和时间创建唯一ID。 如果您为每个用户创建唯一的可执行文件,则日期/时间信息包含在文件创建信息中,因此您只需使用该信息,因为每个文件都是在唯一的日期/时间创建的,这将始终指示ID。 您可以为每个文件保留相同的名称,也可以将日期/时间合并到文件名中,例如myPro20180522183231.exe,其中年份为2018年,月份为05月,日期为22日,小时为18,分钟为32,秒为31,这可以通过文件创建数据的日期/时间信息进行确认。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接