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

时间:2011-01-18 05:39:41

标签: c obfuscation


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

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

谢谢,
Chan Nguyen

2 个答案:

答案 0 :(得分:7)

为了理解此代码的工作原理,请以可读的方式重新编写代码:

#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退格)直到l==8(因此在运行程序时它不会执行任何操作

  • 如果_指向的下一个字符(现在是x)不同于0(这可能意味着“直到我们到达_”的结尾), main被调用,但让我们看看在评估其参数时会发生什么:

    • _当前指向的字符与88中的字符不同(ascii中88为x),因此main的参数将是表达式( putchar(*_^073) | putchar(33) )&1的结果:< / p>

      在评估main的参数时,将打印两个字符

      • 第一个是:*_^073,就是它,120^59(因为x是120,在ascii中,而八进制中的073是十进制的59),这是{ {1}}:120(67)XOR 59(0b1000011)= 67 0b111011

      • 第二个是33(0b1000011

      !参数将是main的结果,即1

如果您真的想了解细节中发生的事情,您将不得不继续这项工作,但是您将能够看到运行程序会发生什么(可能会在某处放置(67|33)&1,这样你就可以看到输出了)。它会写一个反复的字符串“usleep(10000)”。

编写这样的程序非常简单:一旦你决定你的算法是如何工作的,很容易生成一个字符串,比如Corsix!,这会使算法生成你想要的,但是对它进行反向工程是一个更难。

答案 1 :(得分:4)

虽然这段代码不符合标准,但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。
  3. 现在注意,只要_指针被输出,它就会与八进制值073进行异或。如果我们将这个应用于整个字符串,我们得到:

    cCorsixcxCorsicixCorscsixCorcrsixCocorsixCcCorsixc
    

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

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

    这一行的目的是输出一系列退格。如果l等于1,则只输出一个退格。但是,如果它等于别的东西,它会在倾倒一辆卡车上变得狂暴起来。行为取决于主要的调用方式。在启动时,它似乎总是被调用值1(不知道为什么)。

    现在让我们看一下递归主调用的组件。

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

    这是第一个可能的分支。首先它输出一个XORed字符,然后输出'!'焦炭。如果你看一下33的位模式,你会注意到(x | 33)&amp; 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!。