5

假设我们这里有这个程序

class Message{

public static SUPER_SECRET_STRING = "bar";

    public static void Main(){
        string SECRET = "foo";
        Console.Write(sha(SUPER_SECRET_STRING) + "" + sha(SECRET));
    }

}

现在,在构建这个程序之后,有没有办法使用十六进制编辑器或其他一些实用程序从编译的二进制文件中提取值“foo”和“bar”?

还让我们假设不允许使用内存编辑器。

这适用于 C++ 等所有编译语言吗?在 Java 或 C# 等其他环境中运行的那些呢?

4

2 回答 2

7

Mene 的回答是正确的,但我想花两分钱让您知道从编译的二进制文件中提取字符串是多么容易(不管是哪种语言)。如果您有 Linux,您所要做的就是运行命令strings <compiled binary>并获得提取的字符串。您不必成为任何类型的逆向工程师即可完成此任务。我只是在我的 Ubuntu 机器上针对 eclipse 二进制文件运行它并查看(截断的)输出:

> strings eclipse
ATSH
0[A\
8.uCH
The %s executable launcher was unable to locate its 
companion shared library.
There was a problem loading the shared library and 
finding the entry point.
setInitialArgs
-vmargs
-name
--launcher.library
--launcher.suppressErrors
--launcher.ini
eclipse

请注意字符串“%s 可执行启动器无法找到其伴随的共享库。加载共享库和查找入口点时出现问题。” 出现在输出中。这个字符串无疑是硬编码到程序中的。

当字符串(和其他数据)被硬编码到程序中时,大多数编译器将它们放在二进制文件的特殊部分中,在那里它们可以直接映射到内存中,以便程序在需要时访问它们。如果你用十六进制编辑器打开二进制文件,你可以很容易地找到这个字符串。

于 2013-06-13T00:01:54.730 回答
6

是的,您可以轻松地使用反编译器来提取这些常量,尤其是字符串(因为它们需要更大的内存块)。这甚至可以在机器代码二进制文件中工作,并且对于 Java 和 C# 等 VM 语言更容易。

如果您需要在那里保密,您将需要竭尽全力。例如,简单地加密字符串会增加一层安全性,但对于知道自己在做什么的人来说,这不会是一个很大的障碍。例如,扫描文件以查找具有不常见熵的地方可能会揭示用于加密的密钥。甚至有一些系统通过更改二进制文件中使用的低级命令来对秘密进行编码。这些工具将某些命令组合替换为其他等效命令。但即使是 thou 系统也不是很难规避,因为不常见的命令组合将揭示这些工具的使用。

即使您设法通过二进制文件中的某种加密来保护字符串,您有时也会需要一个解密版本来执行。因此,在使用字符串的时间点创建内存转储也将包含秘密值的副本。这在 Java 中尤其成问题,因为您无法释放一块内存并且字符串是不可变的(这意味着对字符串的“更改”将导致新的内存块)。

如您所见,问题远非微不足道。当然,没有办法给你 100% 的安全性(想想所有破解的游戏等等)。

可以以安全方式实现的东西是使用公钥密码术。在这种情况下,您需要隐藏私钥。例如,如果您可以将内容发送到您的服务器以对其进行加密,或者您拥有提供Trusted Platform Module的硬件,那么这可能是可能的。但是对于您的情况,这些事情可能不可行。

于 2013-06-12T21:02:44.333 回答