让相同的程序集以不同的方式执行的巧妙方法?
在不更改构建过程或包含源文件的情况下,任何人都可以想出一种方法来制作两段代码,在编译时生成相同的程序集,但执行方式仍然不同? 我已经知道为什么这应该是不可能的,所以请不要费心解释。 肯定有办法做到这一点,主要是通过寻找方法来隐藏源代码中的信息,这些信息最终会出现在可执行文件之外的其他地方。
一个相当无聊且无趣的示例可以做到这一点:创建一段代码,需要很长时间来解析,但在编译过程中得到优化(或者只是添加太多空白,导致磁盘 I/O 减慢编译速度)。 让您的程序在构建过程中同时生成 exe 和 dll。 根据 dll 和 exe 上创建的时间戳之间的差异,让程序表现不同。 不过,这是一个相当蹩脚的例子。 我想知道是否有人能想出更聪明的办法。
人们还可以以某种方式生成不同的调试输出并改变代码的运行方式,但这也有点蹩脚。
当然,如果您的代码似乎没有检查自身或输出,那就更令人印象深刻了。 如果有人查看您的代码会对这两个版本的行为不同感到震惊,那么这是一个很好的答案。
Without changing the build process or including the source files, can anyone think of a way to make two pieces of code that, when compiled, generates the same assembly but still executes differently? I already know why this should be impossible, so please don't bother to explain. There are definitely ways to do it, primarily by finding ways to hide information in the source code that ends up somewhere other than in the executeable.
A rather boring and unfun example that can do this: Create a chunk of code that takes a long time to parse but gets optimized out during the compilation process (or just add so much white space that disk I/O slows down compilation). Make your program generate both an exe and a dll during the build process. Have the program behave differently depending on the difference between the created timestamps on the dll and the exe. This is a pretty lame example, though. I wonder if someone can come up with anything more clever.
One could also somehow generate a different debugging output and have that change how the code runs, but that's kind of lame, too.
It is, of course, more impressive if your code doesn't seem to be inspecting itself or the output. If someone looking at your code would be shocked that the two versions behaved differently, it's a great answer.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
还有自修改代码
因此理论上,您可以使用一些代码来查看时间戳并让代码基于此修改自身。 SO有一篇文章:自修改代码有什么用途?
There's also Self-Modifying Code
So in theory, you could use some code to look at a timestamp and have the code modify itself based on that. SO has an article: What are the uses of self modifying code?
下面是一个使用 Python 作为伪代码的一般示例:
如果您用编译语言编写并编译它,则程序集将完全相同,但每次执行它时可能会产生不同的行为! 顺便说一句,这正是您的示例所描述的内容。 根据外部输入更改执行路径是编程的一个非常基本的部分。
说明一下:当两个可执行文件的程序集完全相同时,执行结果将完全相同。 行为可能有所不同,但这完全取决于每个运行时收到的输入。 将输入设置为可执行文件的创建时间是有效的,但本质上是无用的。
Here's a general example using Python as pseudocode:
If you wrote that in a compiled language and compiled it, the assembly would be exactly the same, but it could produce different behaviour each time you execute it! This is exactly what your examples are describing, by the way. Changing execution path based on external input is a pretty fundamental part of programming.
To expound: when the assembly of two executables is exactly the same, then the execution is going to be exactly the same. The behaviour might be different, but this is completely dependent on the input each receives when run. Making the input be the time of creation of the executable is valid, but essentially useless.
让我们看看我是否理解。 假设您声称您可以做到这一点。 您编写两个不同的程序,产生相同的程序集。 您将每一个都放在 CD-ROM 上。 CD-ROM 的每一位都是相同的。 你用笔将它们标记为 A 和 B。 我将其中之一放入我的计算机中并安装它。 如果我安装了标有“A”的磁盘,则程序会显示“我是程序 A”。 如果我安装了标有“B”的磁盘,则程序会显示“我是程序B”。
我不明白这怎么可能。
您当然可以使用一些技巧。 如果你能看到我放入的磁盘,你可以在你的手机上偷偷按A或B,向你的网络服务器发送一条消息,该消息由程序检索。
Let's see if I understand. Suppose you claim that you can do this. You write two different programs that result in identical assemblies. You put each on a CD-ROM. The CD-ROMs are bit-for-bit identical. You label them A and B with a pen. I put one or the other into my computer and install it. If I installed the disk labeled "A", the program displays "I am program A." If I installed the disk labeled "B", the program displays "I am program B."
I can't see how this is possible.
There are certainly tricks you can do. If you can see which disk I put in, you can secretly press A or B on your cell phone, sending a message to your web server which is retrieved by the program.
如果你足够努力,你应该能够通过跳到原始指令之一的“中间”来拥有完全相同的机器指令块来完成两项不同的事情,在这种情况下,CPU 会看到完全不同的指令指令的顺序。 IIRC,80 年代初针对 8 位计算机的 ROM 中的空间代码进行了高度优化,在很大程度上节省了空间。
If you worked at it hard enough, you should be able to have the exact same chunk of machine instructions to do two different things by jumping to the "middle" of one of the original instructions, in which case the CPU would see a completely different sequence of instructions. IIRC, the highly optimized for space code in ROM for the 8 bit computers in the early '80's did this quite a bit to save space.
嗯,它不可能真正以不同的方式“执行”。 它只以您描述的方式执行(无论它多么模糊,它仍然遵循给定环境的执行规则)。
在我看来,您希望代码的行为有所不同,同时完全避免使用条件语句。
这是不可能的,并且有充分的理由:计算机是逻辑性的,即使你对其进行编程,使其在不同的环境中表现不同,它仍然遵循你制定的规则。 谢天谢地,因为如果计算机可以根据自己的感受做出决定,那么我们程序员就会遇到麻烦了……
Well, it can't ever really be 'executed' differently. It only ever execute in the fashion that you describe (however obscure it is, it's still following the rules of execution for the given environment).
It sounds to me like you want your code to behave differently while completely avoiding the use of conditional statements.
This isn't possible, and for good reason: computers are logical, and even if you program it so that it'll behave differently in a different environment, it's still following the rules you layed out. And thank goodness, because if it were possible for the computer to decide, based on it's own sensibilities, then we programmers are going to be in a bit of trouble ...
如果内存中具有相同的位模式,并且程序在相同的起始状态下执行,则各个指令的确定性将强制得出确定性答案。 (否则你将无法调试任何东西)。
现在,您的指令可能会根据外部状态产生不同的结果(“宇宙射线最近击中了 CPU 芯片?”)。 这些都会产生不同的结果。
在 x86 上产生这种效果的一条特定指令是 RDTSC(“读取时间戳计数器”),它读取自执行开始以来当前 CPU 的时钟数。 如果操作系统中断您的应用程序,并且不保存/恢复 RDTSC 内容,则不同的执行将在代码中的同一点看到不同的 RDTSC 值(“宇宙中断最近命中了 CPU 芯片”)。
真正的问题是结果不受程序控制,因此很难确保程序以可控的方式表现出不同的行为。
你想用这个来实现什么目的?
If it is the same bit pattern in memory, and the program executes in the same starting state, the determinism of the individual instructions will force a deterministic answer. (Otherwise you wouldn't be able to debug anything).
Now, you may have instructions that produce different results based on external state ("cosmic ray hit CPU chip recently?"). These would produce different results.
One specific instruction that produces this effect on the x86 is RDTSC, "read time stamp counter", which reads number of clocks for current CPU since execution started. If the OS interrupts your application, and doesn't save/restore RDTSC content, then different executions will see different RDTSC values at the same point in the code ("cosmic interrupt hit CPU chip recently").
The real problem with this is that the outcome isn't controlled by the program, so it is hard to ensure that the program behaves differently in a controllable way.
What are you trying to accomplish with this?