我有一个字符串文字,用于我的可执行文件周围的许多不同的地方。
让我们说:
const char *formatString = "Something I don't want to make obvious: %d";
int format1(char *buf) { sprintf(buf, formatString, 1); }
int format2(char *buf) { sprintf(buf, formatString, 2); }
//...
现在,这个字符串文字在可执行代码中变得非常非常,因为它是字面上嵌入的。
有没有办法通过强制编译器来避免这种情况,例如,生成汇编指令(例如mov [ptr + 4], 0x65
)指令来创建字符串,而不是字面上嵌入字符串?
我不想做任何类型的混淆 - 我只是想避免在可执行文件中使字符串明显。 (我也不想在每个使用字符串的地方修改我的代码。)
这可能吗?
答案 0 :(得分:4)
为避免手动将加密字符串粘贴到代码中,您可以创建一个宏来标记需要混淆的字符串和一个解密它们的函数:
#define OB(s) dec("START_MARK_GUID" s "\0" "END_MARK_GUID")
const char* dec(const char* s) { ... }
...
const char* s = OB("not easily readable"); // on all strings needed
const char* s = OB("either");
该功能必须做两件事:
如果参数以START_MARK_GUID开头,只需返回原始字符串(不带guids)。这样您就可以使用未经模糊处理的可执行文件,例如在调试时。
如果它以ENCRYPTED_MARK_GUID开头,则首先进行反混淆,然后返回一个新字符串。在C中你将不得不关心内存的生命周期;在C ++中,您只需返回std :: string()。
最后,创建一个混淆程序,该程序在已编译的二进制文件中查找GUID并在它们之间加密数据。它只是Python或类似语言中的几行。我还建议在之后修复EXE的CRC,尽管我的程序在没有它的情况下工作。
您可以使用较少的唯一标识符更改guid以节省一些空间。此外,您可以对此进行改进,使解密只发生一次(例如,使用ENCRYPTED_MARK_GUID写入字符串ID,并通过该ID将解密的字符串保存在字典中)。
答案 1 :(得分:2)
混淆可能是你最好的选择。使用简单的混淆(例如XOR),并在运行任何需要该字符串的代码之前,将其在程序开头的另一个变量中进行解混淆。
答案 2 :(得分:0)
我经常使用非编程方式。编译您的程序,然后使用upx
压缩和混淆字符串。您可以找到upx
,here。
答案 3 :(得分:0)
很快,使用C ++ 11,您将能够使用用户定义的文字。
constexpr const char*
operator"" _decrypto(const char*, size_t len)
{
// decrypt input string.
}
const char* formatString = "encrypted gibberish"_decrypto;
int format1(char* buf) { sprintf(buf, formatString, 1); }
int format2(char* buf) { sprintf(buf, formatString, 2); }
int
main()
{
}
gcc is working on this furiously我认为IBM已经有了这个。不确定Visual Studio的状态。这是在修补过的gcc上编译的。