【问题标题】:How to basically encrypt text in an ELF binary?如何基本上加密 ELF 二进制文件中的文本?
【发布时间】:2017-06-24 15:16:48
【问题描述】:

我见过一些二进制文件,其中开发人员似乎有点偏执,并混淆了二进制文件中的所有文本。我以前从未见过类似的东西,也没有找到任何明显的选项来编译带有隐藏文本的 ELF。甚至标准的操作系统 API 字符串也被隐藏了,这很奇怪,因为它们通常是可见的。

这些程序在运行时不会有任何未公开的文本。未知文本除外。但隐藏全部内容只是危险信号,它看起来很可疑。

有没有简单的方法可以隐藏编译成 ELF 的文本?使用简单的编译器/链接选项即可。我想可以在 main() 中插入一个解码器,但是如何轻松编码文本部分?

我可以想象一种自定义的方法是在代码中使用一个带有密钥的隐式解码器。然后使用该键对 ELF 的文本进行编码。这样就很容易编码了。

【问题讨论】:

  • 你有什么问题?如果您所追求的只是混淆,只需使用固定密钥对其进行异或运算……但是,“标准操作系统 API 字符串”是什么意思?从共享库导入的符号?这确实很奇怪,我唯一能想到的确实是一个自定义加载器首先解密整个文件(就像upx 用于压缩一样)。
  • 我想知道是否有一种简单的方法可以做到这一点。无论混淆方法如何。假设为编译器选项添加一个开关,该开关将隐藏二进制文件中的文本。我检查了 ELF 格式,但在标志或将文本指定为隐藏的任何内容中都没有突出显示。然后由 ELF 加载程序解码。我所说的“标准 OS API 字符串”是指库或 solib 的名称。有一种有趣的说法。 :-)
  • 不,没有“简单”的方法,这样的功能通常没有多大意义。好吧,除了 -- 看到 chqrlie 的回答并重新阅读我自己的评论 -- upx(或类似工具)确实如此!它不加密任何东西,但当然,压缩文本也不能直接读取;)

标签: c encryption elf


【解决方案1】:

您一定一直在查看压缩的可执行文件。

有多种工具可用于压缩可执行文件并在加载时解压缩它们,例如用于 linux 的upx。二进制文件中的大多数文本将变得肉眼无法读取,但请注意,隐藏敏感数据是一种非常无效的方法,因为黑客可以轻松解压可执行文件以访问实际数据。

在可执行文件中使用加密字符串(其内容将在构建过程中由脚本生成)是一种更好的方法,但解密它们的代码必须在可执行文件的某个位置仍然可用,只是更难找到。如果数据足够有价值(数据库密码、比特币密钥……),黑客就会得到它。

【讨论】:

  • 我也想知道这一点。鉴于所有代码都在一个块中。我在它上面运行了 readelf,但没有出现 ELF 压缩标志。所以看起来像是使用了自定义方法。
【解决方案2】:

我猜你所说的“文本”是指人类可读的文本(而不是 code segment 又名文本段)。

您可以将其加密或混淆为只读

const char encrypted_text[] = {
  // a lot of encrypted bytes like 0x01, 0x43, etc
  // the C file containing that would be generated by some script
};

然后您将使用您的去混淆或解密例程来获取真正的(未加密的)文本。

我不确定这是否值得。生命太短暂了。

【讨论】:

  • 是的,我的意思是计算机调用人类可读的文本或字符串。 :-) 我一直认为二进制文件中的“文本”部分令人困惑,因为它只是源代码级别的文本。并且它应该被称为“代码”。好吧,对代码做了一些事情。即使在自定义 _start 函数甚至 main() 中插入了一个 decrypt() 例程,它也需要知道字符串在内存中的位置。我不知道是否可以找到字符串部分在内存中的存储位置。除了知道第一个字符串并将其用作起始地址。然后是长度。
  • 可以通过读取 ELF 二进制文件本身来解码。因此,假设所有字符串都连接在 ELF 的一个块或部分中,这是可能的。这虽然变得复杂,但对我来说是最简单的方法。设置一个早期解密例程,以使用某个密钥对一个块中的所有字符串进行解码。使用带有自定义 ELF 编码器的键来隐藏字符串。就像你所说。人生如此短暂。但它是以某种方式完成的。
【解决方案3】:

我在分析恶意软件时通常会看到这种情况。作者这样做是为了防止像strings 这样的静态分析工具无法正常工作。此外,这些作者可能会通过使用dlopendlsym 来加载函数以获取他们需要的函数。

例如下面的代码sn-p;

printf("Hello World");

我会在strings 的输出中看到字符串“Hello World”,通过查看elf 文件的导入部分,我会看到程序正在使用printf。因此,无需运行程序就可以了解它在做什么。

现在假设作者写了一个函数char* decrypt(int)。此函数将索引放入一个字符串表(每个字符串都被加密)并返回解密后的字符串。上面的一行代码现在理论上看起来像

void* pfile = dlopen(decrypt(3));
void* pfunct = dlsym(pfile, decrypt(15));
pfunct(decrypt(5));

同样,请记住,上面的代码更接近于伪代码,而不是实际可编译的代码。现在在这种情况下使用静态分析工具,我们将看不到字符串或函数名称(在导入部分中)。

此外,如果我们试图对代码进行逆向工程,我们需要花时间来解密字符串并通过逻辑来确定正在调用的函数。并不是说这不能完成,但它会减慢分析人员的速度,这意味着创建恶意软件的缓解措施将需要更长的时间。

现在回答你的问题;

有没有简单的方法来隐藏编译成 ELF 的文本?成为那个 带有简单的编译器/链接选项。我想解码器可能是 在 main() 处插入,但文本部分如何轻松编码?

没有编译器/链接器选项可以做到这一点。作者需要选择这样做,在上面编写适当的函数(即解密)并编写一个实用程序来生成字符串的加密形式。此外,正如其他人所建议的那样,一旦完成,整个应用程序就可以被加密/压缩(想想自解压的 zip 文件),因此您最初使用静态分析工具看到的唯一东西就是解密解压缩文件的存根.

请参阅https://www.ioactive.com/pdfs/ZeusSpyEyeBankingTrojanAnalysis.pdf 以获取此示例。 (当然这是基于 Windows 的,但加密和动态加载函数的技术是相同的。查看 API 调用部分)

有兴趣的也可以看看; https://www.researchgate.net/publication/224180021_On_the_analysis_of_the_Zeus_botnet_crimeware_toolkithttps://arxiv.org/pdf/1406.5569.pdf

【讨论】:

  • 感谢您对此的广泛解释。我怀疑代码是否会遇到麻烦来隐藏它正在做的事情,因为它真正隐藏的唯一东西是它打开的某些库。但我也没有看到代码运行。那是通过调试器运行的。我可能只是通过 GDB 运行它。最好使用 GUI,因为我不期待在 ASM 中逐步调试。 :-)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-03-20
  • 1970-01-01
  • 2017-04-08
  • 1970-01-01
  • 1970-01-01
  • 2015-11-07
  • 2016-11-07
相关资源
最近更新 更多