使用二进制代码和密钥防止逆向工程

Preventing reverse engineering with binary code and secret key

我正在开发一个软件程序,该程序必须部署在具有根访问权限的客户端的私有云服务器上。 我可以通过安全端口与软件通信。

我想阻止客户对我的程序进行逆向工程,或者至少做到这一点 "hard enough"。以下是我的方法:

  1. 用Go编写代码并将软件编译成二进制代码(可能会混淆)
  2. 确保只能使用可通过安全端口发送的密钥启动程序。密钥可以根据时间更改。
  3. 每次我需要 start/stop 程序时,我都可以通过安全端口发送带有密钥的命令。

我认为这种方法可以防止 root 用户:

  1. 使用调试器对我的代码进行逆向工程

  2. 运行 程序重复检查输出

我的问题是:这种设计的弱点是什么? root 用户如何攻击它?

I want to prevent client from reverse engineering my program,

当软件 运行 在您不拥有的硬件上时,您无法完全避免这种情况。要运行软件,CPU必须看到程序的所有指令,并将它们存储在计算机内存中。

https://softwareengineering.stackexchange.com/questions/46434/how-can-software-be-protected-from-piracy

Code is data. When the code is runnable, a copy of that data is un-protected code. Unprotected code can be copied.

Peppering the code with anti-piracy checks makes it slightly harder, but hackers will just use a debugger and remove them. Inserting no-ops instead of calls to "check_license" is pretty easy.

https://softwareengineering.stackexchange.com/questions/46434 中的答案可能对您有用)

硬件所有者控制 OS 和内存,他可以转储所有内容。

or at least make it "hard enough".

只能再难一点。

Write code in Go and compile the software into binary code (may be with obfuscation)

IDA 将反编译任何机器代码。使用本机机器码比字节码强一点(java or .NET or dex)

Make sure that program can only be initiate with secret key that can be sent through the secure port. The secret key can be changing depending on time.

如果相同密钥(多个密钥)的副本在程序的代码或内存中,用户可能会转储它并模拟您的服务器。如果您的部分代码或 运行 代码所需的部分数据被加密存储,并使用此类外部密钥解密,则用户可以窃听密钥(在从 SSL 解码之后但在使用之前)解密代码的秘密部分),或从内存中转储解密的code/data(即使使用Linux中的strace等默认预装工具,也很容易看到在内存中创建的新可执行代码,只需搜索所有mmaps 带有 PROT_EXEC 个标志)

Every time I need to start/stop the program, I can send commands with the secret keys through the secured port.

这只是在线 license/antipiracy 检查 ("phone home")

的变体

I think this approach can prevent a root user to: use a debugger to reverse engineer my code, or

不,他可以随时启动调试器;但是如果程序经常(每 5 秒)与您的服务器通信,您可以使使用交互式调试器变得有点困难。但是,如果它经常通信,最好将部分计算移到您的服务器上;这部分将被保护。

而且他仍然可以使用非交互式调试器、跟踪工具和内存转储。他还可以 运行 在虚拟机中编程,等待在线检查完成(使用 tcpdump 和 netstat 监控网络流量),然后对虚拟机进行实时快照(有多种变体可以启用 "live migration" VM;如果有外部定时,你的程序可能只记录短暂的暂停),继续运行在线第一个副本,并拍摄快照以供离线调试(其中包含所有密钥和解密代码)。

run the program repeatedly to check outputs

直到他破解通讯...