巧妙地使同一个程序集执行的方式不同?

时间:2009-07-31 14:12:45

标签: obfuscation

在不改变构建过程或包含源文件的情况下,是否有人能够想出一种方法来制作两段代码,这些代码在编译时会生成相同的程序集但仍然执行不同的操作?我已经知道为什么这个应该是不可能的,所以请不要费心去解释。肯定有办法做到这一点,主要是通过找到隐藏源代码中信息的方法,这些信息最终会出现在可执行文件之外的其他地方。

一个相当无聊且无法实现的例子可以做到这一点:创建一大块代码需要很长时间才能解析,但在编译过程中会被优化掉(或者只是添加太多空白区域,磁盘I / O会降低编译速度)。使程序在构建过程中生成exe和dll。程序的行为会有所不同,具体取决于dll和exe上创建的时间戳之间的差异。不过,这是一个相当蹩脚的例子。我想知道是否有人能想出更聪明的东西。

也可以以某种方式生成不同的调试输出,并改变代码的运行方式,但这也是一种蹩脚的。

如果您的代码似乎没有检查自身或输出,那么当然会更令人印象深刻。如果看到你的代码的人会感到震惊,因为这两个版本的表现不同,这是一个很好的答案。

6 个答案:

答案 0 :(得分:4)

还有Self-Modifying Code

  

[S]精灵修改代码是在执行时改变自己的指令的代码

因此从理论上讲,您可以使用一些代码来查看时间戳,并让代码根据它自行修改。 SO有一篇文章:What are the uses of self modifying code?

答案 1 :(得分:3)

以下是使用Python作为伪代码的一般示例:

input = raw_input("type something!\n")
if "a" in input:
    print "Great job!"
else:
    print "Ohh, too bad."

如果用编译语言编写并编译它,程序集将完全相同,但每次执行它时都会产生不同的行为!顺便说一句,这正是您的示例所描述的内容。基于外部输入改变执行路径是编程的一个非常基本的部分。

要解释:当两个可执行文件的程序集完全相同时,执行将完全相同。行为可能不同,但这完全取决于每次运行时接收的输入。将输入作为创建可执行文件的时间是有效的,但基本上没用。

答案 2 :(得分:1)

让我们看看我是否理解。假设您声称可以执行此操作。您编写两个不同的程序,导致相同的程序集。你把每个放在一张CD-ROM上。 CD-ROM是逐位相同的。用笔标记A和B.我将一个或另一个放入我的电脑并安装它。如果我安装了标有“A”的磁盘,程序将显示“我是程序A”。如果我安装了标有“B”的磁盘,程序将显示“我是程序B”。

我看不出这是怎么可能的。

你肯定可以做一些技巧。如果您可以看到我放入的磁盘,您可以在手机上秘密按A或B,向您的Web服务器发送一条消息,该消息由程序检索。

答案 3 :(得分:1)

如果你努力工作,你应该能够拥有完全相同的机器指令块,通过跳转到原始指令之一的“中间”来做两件不同的事情,在这种情况下CPU会看到完全不同的指令序列。 IIRC,80年代早期针对8位计算机的ROM空间代码进行了高度优化,为节省空间做了相当多的工作。

答案 4 :(得分:1)

如果它在内存中是相同的位模式,并且程序在相同的起始状态下执行,则各个指令的确定性将强制确定性的答案。 (否则你将无法调试任何东西)。

现在,您可能有基于外部状态产生不同结果的指令(“最近宇宙射击CPU芯片?”)。这些会产生不同的结果。 在x86上产生这种效果的一个特定指令是RDTSC,“读取时间戳计数器”,它读取自执行开始以来当前CPU的时钟数。如果操作系统中断了您的应用程序,并且没有保存/恢复RDTSC内容,那么不同的执行将在代码中的相同位置看到不同的RDTSC值(“宇宙中断最近点击CPU芯片”)。

这个问题的真正问题在于结果不受程序控制,因此很难确保程序以可控的方式表现不同。

你想用这个来完成什么?

答案 5 :(得分:1)

嗯,它不可能真的被'执行'不同。它只能以你描述的方式执行(不管它是否模糊,它仍然遵循给定环境的执行规则)。

在我看来,你希望你的代码在完全避免使用条件语句的同时表现得不同。

这是不可能的,并且有充分的理由:计算机是合乎逻辑的,即使您对其进行编程以使其在不同的环境中表现不同,它仍然遵循您所规定的规则。谢天谢地,因为如果计算机有可能根据它自己的敏感性来决定,那么我们程序员会遇到一些麻烦...

int k = 2;

// computer internally has decided k should = 5, because it is upset about a prior 
// argument, so you must actually write:

computer.pleaseWork();
int k = 2;