英文:
Hide static strings in compiled golang executable
问题
我在代码中有这样的内容:
var myString = "test string"
我编译并运行:
strings myexecutable | grep "test string"
然后我在输出中看到了它。有没有办法在Golang的可执行文件中隐藏明文字符串?单独的文件不是一个选项。
这不是为了防止有资质的黑客,而是为了防止简单的用户能够在记事本中打开可执行文件并找到加密密钥。
英文:
I have somethind like this in code
var myString = "test string"
I compile it and run
strings myexecutable | grep "test string"
And I see it in output. Is there some way to hide clear text strings in executable in golang? Separate file is not an option.
It's protection not from qualified hackers, but against simple users who can open executable in notepad and find encryption key.
答案1
得分: 1
将文本作为一系列十六进制字节写入并不能帮助你——字符串在二进制中仍然会按原样显示。
一种解决方案是对其进行混淆,例如使用 ROT13,或者将所有字节与某个值进行异或运算,甚至可以使用一个已知种子值初始化的随机数生成器对值进行异或运算。在运行时,你将需要从“混乱”的版本中重新生成所需的字符串。
第二个问题:该变量可能具有一个有趣的名称,出现在可执行文件的符号表中,所以也许为编码的字符串选择一个“无聊”的名称。甚至可以将编码的字符串嵌入到一个较长的字符串中。
正如其他人所指出的那样,无论你做什么,总会有人找到方法来撤销你的努力并找到该字符串,但也许这些想法能帮到你。
祝你好运!
英文:
Writing the text as a series of hex bytes won't help you -- the string will still appear as-is in the binary.
One solution is to scramble it, rot-13 maybe, or XOR all the bytes with some value, or even XOR the values with a random number generator that's initialized with a known seed value. At run-time, you will have to regenerate the string you want from the "messed-up" version.
A second issue: that variable probably has an interesting name which appears in the symbol table of the executable, so maybe pick a "dull" name for the encoded string. Maybe even bury the encoded string within a longer string.
As everyone else has noted - someone will find a way to undo your efforts and find the string no matter what you do, but maybe these ideas will help you.
Good luck!
答案2
得分: 0
C++解决方案,如果你从Golang移植过来
这是我目前使用的代码,它有一些hack来支持在编译后的二进制文件中插入纯文本的sprintf函数。现在你可以使用w_sprintf_s代替sprintf,像这样:
char test[256] = { 0 };
w_sprintf_s(test, 256, XorStr("test test :D %d %+d\n"), 1, 1337);
或者像这样在屏幕上打印内容:
w_printf(XorStr("test I print this and can't see me inside .dll or .exe"));
如果你有自定义的printf()函数,也可以使用它。
char szGuid[255] = { 0 };
//generate serial code removed.
char finalSerial[512] = { 0 };
XorCompileTime::w_sprintf(finalSerial, XorStr("serial information=%s"), szGuid);
myprintf(XorStr("Your Hardware ID: %s\n"), szGuid);
可能会添加对wchar_t宽字符串的支持,就像arkan做的那样...但是我现在没有用到它们,因为我不写任何符号/Unicode。
这是一个文件,只需将下面的代码重命名为XorString.h
文件并包含在你的项目中,就这么简单:
#pragma once
#include <string>
#include <array>
#include <cstdarg>
#define BEGIN_NAMESPACE( x ) namespace x {
#define END_NAMESPACE }
BEGIN_NAMESPACE(XorCompileTime)
constexpr auto time = __TIME__;
constexpr auto seed = static_cast<int>(time[7]) + static_cast<int>(time[6]) * 10 + static_cast<int>(time[4]) * 60 + static_cast<int>(time[3]) * 600 + static_cast<int>(time[1]) * 3600 + static_cast<int>(time[0]) * 36000;
// 1988, Stephen Park and Keith Miller
// "Random Number Generators: Good Ones Are Hard To Find", considered as "minimal standard"
// Park-Miller 31 bit pseudo-random number generator, implemented with G. Carta's optimisation:
// with 32-bit math and without division
template <int N>
struct RandomGenerator
{
private:
static constexpr unsigned a = 16807; // 7^5
static constexpr unsigned m = 2147483647; // 2^31 - 1
static constexpr unsigned s = RandomGenerator< N - 1 >::value;
static constexpr unsigned lo = a * (s & 0xFFFF); // Multiply lower 16 bits by 16807
static constexpr unsigned hi = a * (s >> 16); // Multiply higher 16 bits by 16807
static constexpr unsigned lo2 = lo + ((hi & 0x7FFF) << 16); // Combine lower 15 bits of hi with lo's upper bits
static constexpr unsigned hi2 = hi >> 15; // Discard lower 15 bits of hi
static constexpr unsigned lo3 = lo2 + hi;
public:
static constexpr unsigned max = m;
static constexpr unsigned value = lo3 > m ? lo3 - m : lo3;
};
template <>
struct RandomGenerator< 0 >
{
static constexpr unsigned value = seed;
};
template <int N, int M>
struct RandomInt
{
static constexpr auto value = RandomGenerator< N + 1 >::value % M;
};
template <int N>
struct RandomChar
{
static const char value = static_cast<char>(1 + RandomInt< N, 0x7F - 1 >::value);
};
template <size_t N, int K>
struct XorString
{
private:
const char _key;
std::array<char, N + 1> _encrypted;
constexpr char enc(char c) const
{
return c ^ _key;
}
char dec(char c) const
{
return c ^ _key;
}
public:
template <size_t... Is>
constexpr __forceinline XorString(const char* str, std::index_sequence< Is... >) : _key(RandomChar< K >::value), _encrypted{ enc(str[Is])... }
{
}
__forceinline decltype(auto) decrypt(void)
{
for (size_t i = 0; i < N; ++i) {
_encrypted[i] = dec(_encrypted[i]);
}
_encrypted[N] = '\0';
return _encrypted.data();
}
};
//--------------------------------------------------------------------------------
//-- 注意:XorStr将无法直接与printf等函数一起使用。
// 要与它们一起使用,你需要一个接受const char*参数并将其传递给printf等函数的包装函数。
//
// Microsoft编译器/链接器在处理可变参数模板时工作不正确!
//
// 使用下面的函数或使用std::cout(以及类似的函数)。
//--------------------------------------------------------------------------------
static auto w_printf = [](const char* fmt, ...) {
va_list args;
va_start(args, fmt);
vprintf_s(fmt, args);
va_end(args);
};
static auto w_printf_s = [](const char* fmt, ...) {
va_list args;
va_start(args, fmt);
vprintf_s(fmt, args);
va_end(args);
};
static auto w_sprintf = [](char* buf, const char* fmt, ...) {
va_list args;
va_start(args, fmt);
vsprintf(buf, fmt, args);
va_end(args);
};
static auto w_sprintf_s = [](char* buf, size_t buf_size, const char* fmt, ...) {
va_list args;
va_start(args, fmt);
vsprintf_s(buf, buf_size, fmt, args);
va_end(args);
};
#define XorStr( s ) ( XorCompileTime::XorString< sizeof( s ) - 1, __COUNTER__ >( s, std::make_index_sequence< sizeof( s ) - 1>() ).decrypt() )
END_NAMESPACE
英文:
C++ solution if you ported over from golang
Here is what I currently use it has hacks to support sprintf functions which spilled plain-text in compiled binary file. You could now use w_sprintf_s instead of sprintf, like so
char test[256] = { 0 };
w_sprintf_s(test, 256, XorStr("test test :D %d %+d\n"), 1, 1337);
or use it like this to print stuff on screen for example
w_printf(XorStr("test I print this and can't see me inside .dll or .exe"));
works on variables, if you have a custom printf() you could use that as well..
char szGuid[255] = { 0 };
//generate serial code removed.
char finalSerial[512] = { 0 };
XorCompileTime::w_sprintf(finalSerial, XorStr("serial information=%s"), szGuid);
myprintf(XorStr("Your Hardware ID: %s\n"), szGuid);
<br>
May add support for wchar_t wide strings like arkan did.. but I have no use for them right now as I don't write anything in symbols / unicode.
<br>
Here is a file just rename the code below to a XorString.h
file and include it in your project simple as that
#pragma once
#include <string>
#include <array>
#include <cstdarg>
#define BEGIN_NAMESPACE( x ) namespace x {
#define END_NAMESPACE }
BEGIN_NAMESPACE(XorCompileTime)
constexpr auto time = __TIME__;
constexpr auto seed = static_cast< int >(time[7]) + static_cast< int >(time[6]) * 10 + static_cast< int >(time[4]) * 60 + static_cast< int >(time[3]) * 600 + static_cast< int >(time[1]) * 3600 + static_cast< int >(time[0]) * 36000;
// 1988, Stephen Park and Keith Miller
// "Random Number Generators: Good Ones Are Hard To Find", considered as "minimal standard"
// Park-Miller 31 bit pseudo-random number generator, implemented with G. Carta's optimisation:
// with 32-bit math and without division
template < int N >
struct RandomGenerator
{
private:
static constexpr unsigned a = 16807; // 7^5
static constexpr unsigned m = 2147483647; // 2^31 - 1
static constexpr unsigned s = RandomGenerator< N - 1 >::value;
static constexpr unsigned lo = a * (s & 0xFFFF); // Multiply lower 16 bits by 16807
static constexpr unsigned hi = a * (s >> 16); // Multiply higher 16 bits by 16807
static constexpr unsigned lo2 = lo + ((hi & 0x7FFF) << 16); // Combine lower 15 bits of hi with lo's upper bits
static constexpr unsigned hi2 = hi >> 15; // Discard lower 15 bits of hi
static constexpr unsigned lo3 = lo2 + hi;
public:
static constexpr unsigned max = m;
static constexpr unsigned value = lo3 > m ? lo3 - m : lo3;
};
template <>
struct RandomGenerator< 0 >
{
static constexpr unsigned value = seed;
};
template < int N, int M >
struct RandomInt
{
static constexpr auto value = RandomGenerator< N + 1 >::value % M;
};
template < int N >
struct RandomChar
{
static const char value = static_cast< char >(1 + RandomInt< N, 0x7F - 1 >::value);
};
template < size_t N, int K >
struct XorString
{
private:
const char _key;
std::array< char, N + 1 > _encrypted;
constexpr char enc(char c) const
{
return c ^ _key;
}
char dec(char c) const
{
return c ^ _key;
}
public:
template < size_t... Is >
constexpr __forceinline XorString(const char* str, std::index_sequence< Is... >) : _key(RandomChar< K >::value), _encrypted{ enc(str[Is])... }
{
}
__forceinline decltype(auto) decrypt(void)
{
for (size_t i = 0; i < N; ++i) {
_encrypted[i] = dec(_encrypted[i]);
}
_encrypted[N] = '\0';
return _encrypted.data();
}
};
//--------------------------------------------------------------------------------
//-- Note: XorStr will __NOT__ work directly with functions like printf.
// To work with them you need a wrapper function that takes a const char*
// as parameter and passes it to printf and alike.
//
// The Microsoft Compiler/Linker is not working correctly with variadic
// templates!
//
// Use the functions below or use std::cout (and similar)!
//--------------------------------------------------------------------------------
static auto w_printf = [](const char* fmt, ...) {
va_list args;
va_start(args, fmt);
vprintf_s(fmt, args);
va_end(args);
};
static auto w_printf_s = [](const char* fmt, ...) {
va_list args;
va_start(args, fmt);
vprintf_s(fmt, args);
va_end(args);
};
static auto w_sprintf = [](char* buf, const char* fmt, ...) {
va_list args;
va_start(args, fmt);
vsprintf(buf, fmt, args);
va_end(args);
};
static auto w_sprintf_s = [](char* buf, size_t buf_size, const char* fmt, ...) {
va_list args;
va_start(args, fmt);
vsprintf_s(buf, buf_size, fmt, args);
va_end(args);
};
#define XorStr( s ) ( XorCompileTime::XorString< sizeof( s ) - 1, __COUNTER__ >( s, std::make_index_sequence< sizeof( s ) - 1>() ).decrypt() )
END_NAMESPACE
> Blockquote
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论