需要帮助解释一个混淆的 C++代码?
这段代码让我抓狂,有人能帮我解释一下吗?
#include <stdio.h>
char*_="XxTIHRCXCxTIHRXRCxTIHXHRCxTIXIHRCxTXTIHRCxXxTIHRCX";
int main(int l){for(l+=7;l!=putchar(010);++l);if(*(++_))main
(*_!=88?(putchar(*_^073)|putchar(33))&1:0xffff2a8b);}
谢谢,
陈阮
This code snippet drove me crazy, anyone could help me explain this?
#include <stdio.h>
char*_="XxTIHRCXCxTIHRXRCxTIHXHRCxTIXIHRCxTXTIHRCxXxTIHRCX";
int main(int l){for(l+=7;l!=putchar(010);++l);if(*(++_))main
(*_!=88?(putchar(*_^073)|putchar(33))&1:0xffff2a8b);}
Thanks,
Chan Nguyen
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
为了理解这段代码是如何工作的,开始以一种可读的方式重写它:
现在让我们来理解它:
它的参数
l
(如果你运行这个没有参数的程序,它将是1)得到增加 7(变为 8)循环将打印
010
(8 的八进制:ascii backspace)直到l==8
(因此当您运行程序时它不会执行任何操作010
(8 的八进制:ascii backspace)直到l==8
(因此,当您运行程序时如果下一个字符指向, by
_
(现在是x
)与 0 不同(这可能意味着“直到我们到达_
的末尾”),main
被调用,但让我们看看在评估其参数时会发生什么:当前
_
指向的字符与88不同(88在ascii中是x
),因此main的参数将是表达式<的结果代码>( putchar(*_^073) | putchar(33) )&1:在评估
main
的参数时,将打印两个字符第一个是:
*_^073
,就是这样,120^59
(因为x
在 ascii 中是 120 ,八进制的 073 十进制的 59),即67
: 120(0b1000011
) XOR 59(0b111011
) = 670b1000011
第二个是 33 (
!
)main
参数将是(67|33)&1
的结果,即 1如果您确实想了解细节中发生的情况,则必须继续这项工作,但您将能够通过运行程序来查看发生的情况(也许可以输入
usleep(10000) 某处,以便您可以实际看到输出)。它将写入一个旋转字符串“
Corsix!
”。编写这样的程序非常简单:一旦您决定了算法的工作原理,就很容易生成一个字符串,例如
_
,这使得算法生成您想要的内容,但要进行逆向工程,它是一个困难得多。In order to understand how this code works, start rewriting it in a readable way:
Now let's understand it:
its parameter
l
(which will be 1, if you run this program without parameters) gets incremented by 7 (it becomes 8)the loop will print
010
(octal for 8: ascii backspace) untill==8
(thus it won't do anything when you run the programif the next character pointed by
_
(it'sx
now) is different than 0 (this will probably mean "until we reached the end of_
"),main
is called, but lets see what happens while we're evaluating its parameters:the character currently pointed by
_
is different from 88 (88 isx
in ascii), thus the parameter for main will be the result of expression( putchar(*_^073) | putchar(33) )&1
:while evaluating
main
's parameter two characters will be printedfirst one is:
*_^073
, that's it,120^59
(sincex
is 120, in ascii, and 073 in octal is 59 in decimal), which is67
: 120(0b1000011
) XOR 59(0b111011
) = 670b1000011
second one is 33 (
!
)main
parameter will then be the result of(67|33)&1
, which is 1If you really want to understand what happens in the details you'll have to go on with this work, but you'll be able to see what happens by running the program (maybe put an
usleep(10000)
somewhere, so that you can actually see the output). It will write a roteating string "Corsix!
".Writing a program like this is pretty easy: once you decide how your algorithm works, it's easy to generate a string, like
_
, that makes the algorithm generate what you want, but to reverse engineer it is a lot more difficult.虽然这段代码不符合标准,但 gcc 会对其进行编译,并且输出与我对代码的分析一致。遗憾的是,如果没有更多上下文,我无法真正解释输出。如果我忽略退格键,输出看起来像这样:
要分析代码,我们首先对其进行一些格式化:
在我们继续之前,有一些值得注意的事情:
现在请注意,每当输出 _ 指针时,它都会与八进制值 073 进行异或。如果我们将其应用于整个字符串,我们会得到:
这开始类似于我们之前看到的输出。让我们继续分析一些更有趣的行:
这行的要点是输出一系列退格键。如果 l 等于 1,则仅输出一个退格键。但如果它与其他东西相同,它就会疯狂地倾倒一卡车的炭。该行为取决于 main 的调用方式。启动时,它似乎总是以值 1 调用(不知道为什么)。
现在让我们看看递归主调用的组成部分。
这是第一个可能的分支。首先它输出一个异或字符,然后输出一个“!”字符。如果您查看 33 的位模式,您会注意到 (x | 33) & 1 的计算结果始终为 1。因此,在本例中,我们仅在 for 循环中输出单个退格字符。
另一方面,第二个分支有点棘手,因为传递给 main 的值不是 1。如果仔细查看程序的输出,您会发现它确实在字符串中的某个位置输出了一大堆退格键。 。如果没有上下文,我无法真正说出目标是什么。
现在我们已经有了所有的部分,让我们重写代码:
我的 C 有点生疏,所以这可能无法编译/运行。它仍然可以让您很好地了解正在发生的事情。
编辑:好吧,我发布答案有点晚了,我刚刚意识到我的控制台正在打印退格符,而不是仅仅删除字符。这就是为什么我有点误解了输出。因此,就像已接受的答案所说,如果您实际上正确处理了退格键,它会打印 Corsix!。
While this piece of code is not standard compliant, gcc will compile it and the output is consistent with my analysis of the code. Sadly, I can't really interpret the output without a bit more context. If I ignore the backspaces, the output looks something like this:
To analyze the code, we'll start by formatting it a bit :
Here's a few things worth noting before we go any further:
Now notice that whenever the _ pointer is outputed, it's XORed with the octal value 073. If we apply this on the entire string we get:
This is starting to resemble the output that we saw earlier. Let's continue by analysing a few of the more interesting lines:
The point of this line is to output a series of backspaces. If l is equal to 1 it will output only one backspace. But if it's equal to something else, it goes berserk on dumps a truck load of chars. The behaviour depends on how main is called. On startup, it appears to always be called with the value 1 (don't know why).
Now let's look at the components of the recursive main call.
This is the first possible branch. First it outputs, one of the XORed characters and then it outputs a '!' char. If you look at the bit pattern of 33, you'll notice that (x | 33) & 1 will always evaluate to 1. So in this case we're only outputting a single backspace character in the for loop.
The second branch on the other hand is a little trickier because the value passed to main is not 1. If you look carefully at the output of the program you will notice that it does output a truck load of backspaces at a certain place in the string. Without context, I can't really say what the goal is.
Now that we have all the pieces, let's rewrite the code:
My C is a little rusty so this might not compile/run. It should still give you a good idea of what's going on.
EDIT: Well I was a little late in posting my answer and I just realised that my console was printing the backspaces a little to literaly instead of just removing chars. So that's why I somewhat misinterpreted the output. So like the accepted answer says, if you actually process the backspaces correctly, it prints Corsix!.