需要帮助解释一个混淆的 C++代码?

发布于 2024-10-12 23:49:50 字数 286 浏览 6 评论 0原文


这段代码让我抓狂,有人能帮我解释一下吗?

#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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

江湖正好 2024-10-19 23:49:50

为了理解这段代码是如何工作的,开始以一种可读的方式重写它:

#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 );
    }

    return 0;
}

现在让我们来理解它:

  • 它的参数l(如果你运行这个没有参数的程序,它将是1)得到增加 7(变为 8)

  • 循环将打印 010 (8 的八进制:ascii backspace)直到 l==8 (因此当您运行程序时它不会执行任何操作

  • print 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) = 67 0b1000011

      • 第二个是 33 (!)

      main 参数将是 (67|33)&1 的结果,即 1

如果您确实想了解细节中发生的情况,则必须继续这项工作,但您将能够通过运行程序来查看发生的情况(也许可以输入 usleep(10000) 某处,以便您可以实际看到输出)。它将写入一个旋转字符串“Corsix!”。

编写这样的程序非常简单:一旦您决定了算法的工作原理,就很容易生成一个字符串,例如 _,这使得算法生成您想要的内容,但要进行逆向工程,它是一个困难得多。

In order to understand how this code works, start rewriting it in a readable way:

#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 );
    }

    return 0;
}

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) until l==8 (thus it won't do anything when you run the program

  • if the next character pointed by _ (it's x 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 is x 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 printed

      • first one is: *_^073, that's it, 120^59 (since x is 120, in ascii, and 073 in octal is 59 in decimal), which is 67: 120(0b1000011) XOR 59(0b111011) = 67 0b1000011

      • second one is 33 (!)

      main parameter will then be the result of (67|33)&1, which is 1

If 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.

寄居人 2024-10-19 23:49:50

虽然这段代码不符合标准,但 gcc 会对其进行编译,并且输出与我对代码的分析一致。遗憾的是,如果没有更多上下文,我无法真正解释输出。如果我忽略退格键,输出看起来像这样:

C!o!r!s!i!...

要分析代码,我们首先对其进行一些格式化:

#include <stdio.h>

char* _ ="XxTIHRCXCxTIHRXRCxTIHXHRCxTIXIHRCxTXTIHRCxXxTIHRCX";

int main(int l){
    for(l+=7; l != putchar(010); ++l); // 010 = 8 -> backspace char
    if(*(++_))
        main(
            *_ != 88 ? // *_ != 'X'
                ( putchar(*_ ^ 073) | putchar(33) ) & 1 : // 33 = '!'
                0xffff2a8b);
}

在我们继续之前,有一些值得注意的事情:

  1. 如果 putchar 成功,它返回传递的字符。
  2. 在C中,以0开头的数字实际上是八进制而不是十进制。所以 010 实际上是十进制数字 8。

现在请注意,每当输出 _ 指针时,它都会与八进制值 073 进行异或。如果我们将其应用于整个字符串,我们会得到:

cCorsixcxCorsicixCorscsixCorcrsixCocorsixCcCorsixc

这开始类似于我们之前看到的输出。让我们继续分析一些更有趣的行:

for(l+=7; l != putchar(010); ++l); // 010 = 8 -> backspace char

这行的要点是输出一系列退格键。如果 l 等于 1,则仅输出一个退格键。但如果它与其他东西相同,它就会疯狂地倾倒一卡车的炭。该行为取决于 main 的调用方式。启动时,它似乎总是以值 1 调用(不知道为什么)。

现在让我们看看递归主调用的组成部分。

( putchar(*_ ^ 073) | putchar(33) ) & 1 : // 33 = '!'

这是第一个可能的分支。首先它输出一个异或字符,然后输出一个“!”字符。如果您查看 33 的位模式,您会注意到 (x | 33) & 1 的计算结果始终为 1。因此,在本例中,我们仅在 for 循环中输出单个退格字符。

另一方面,第二个分支有点棘手,因为传递给 main 的值不是 1。如果仔细查看程序的输出,您会发现它确实在字符串中的某个位置输出了一大堆退格键。 。如果没有上下文,我无法真正说出目标是什么。

现在我们已经有了所有的部分,让我们重写代码:

#include <stdio.h>

#define BIG_CONSTANT 42 // Not the actual value.

int main () {
    char* str = "cCorsixcxCorsicixCorscsixCorcrsixCocorsixCcCorsixc";

    putchar(8);

    char* c = str;
    while (*c != '\0') {

        if (*c != 'c') { // 'X' ^ 073 = 'c'
            putchar(*c);
            putchar('!');
            putchar(8);
        }
        else {
            for (int i = 0; i < BIG_CONSTANT; ++i)
                putchar(8);
        }
        c++;
    }
}

我的 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:

C!o!r!s!i!...

To analyze the code, we'll start by formatting it a bit :

#include <stdio.h>

char* _ ="XxTIHRCXCxTIHRXRCxTIHXHRCxTIXIHRCxTXTIHRCxXxTIHRCX";

int main(int l){
    for(l+=7; l != putchar(010); ++l); // 010 = 8 -> backspace char
    if(*(++_))
        main(
            *_ != 88 ? // *_ != 'X'
                ( putchar(*_ ^ 073) | putchar(33) ) & 1 : // 33 = '!'
                0xffff2a8b);
}

Here's a few things worth noting before we go any further:

  1. If putchar succeeds, it returns the char it was passed.
  2. In C, numbers starting with 0 are actually octals and not decimals. So 010 is really the decimal number 8.

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:

cCorsixcxCorsicixCorscsixCorcrsixCocorsixCcCorsixc

This is starting to resemble the output that we saw earlier. Let's continue by analysing a few of the more interesting lines:

for(l+=7; l != putchar(010); ++l); // 010 = 8 -> backspace char

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.

( putchar(*_ ^ 073) | putchar(33) ) & 1 : // 33 = '!'

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:

#include <stdio.h>

#define BIG_CONSTANT 42 // Not the actual value.

int main () {
    char* str = "cCorsixcxCorsicixCorscsixCorcrsixCocorsixCcCorsixc";

    putchar(8);

    char* c = str;
    while (*c != '\0') {

        if (*c != 'c') { // 'X' ^ 073 = 'c'
            putchar(*c);
            putchar('!');
            putchar(8);
        }
        else {
            for (int i = 0; i < BIG_CONSTANT; ++i)
                putchar(8);
        }
        c++;
    }
}

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!.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文