3

你能解释一下下面的代码是如何工作的吗?

main(O){10<putchar(4^--O?77-(15&5128>>4*O):10)&&main(2+O);}

输出:

EMIL

您可以在Ideone上对其进行测试。我在unwind的个人资料上找到了这条线。

4

2 回答 2

7

反混淆可以很容易地逐步完成。

空白总是有帮助的:

main(O)
{
  10 < putchar(4 ^ --O ? 77 - (15 & 5128 >> 4 * O)
                       : 10)
  && main(2+O);
}

添加一个变量:

main(O)
{
  int i = 4 ^ --O ? 77 - (15 & 5128 >> 4 * O)
                  : 10;
  i = putchar(i);
  10 < i && main(2+O);
}

替换?:为 if-else:

main(O)
{
  int i;
  if (4 ^ --O)
    i = 77 - (15 & 5128 >> 4 * O)
  else
    i = 10;
  i = putchar(i);
  10 < i && main(2 + O);
}

替换&&为如果:

main(O)
{
  int i;
  if (4 ^ --O)
    i = 77 - (15 & 5128 >> 4 * O)
  else
    i = 10;
  i = putchar(i);
  if (10 < i)
    main(2 + O);
}

为了清楚起见,括号:

main(O)
{
  int i;
  if (4 ^ --O)
    i = 77 - (15 & (5128 >> (4 * O)))
  else
    i = 10;
  i = putchar(i);
  if (10 < i)
    main(2 + O);
}

从这里开始,这是一个应用运算符的基本 C 知识的简单案例。

运行代码:(初始参数main为1,我们可以查看这个

main(1)
  4 ^ 0 = 4 = true
    5128 >> 4 * 0 = 5128
    15 & 5128 = 8
    i = 77 - 8 = 69
  putchar(69) -> 'E'
  10 < 69
    call main(2+0)
main(2)
  ...

写它的人是怎么想出来的?好吧,据我所知,当涉及到混淆代码时,这主要是一个谜。

于 2013-08-08T11:35:23.823 回答
5

如果你把代码翻译成更好的 C,那么它可能看起来像这样:

int main(int i)
{
    int ch;

    i--;
    if (i ^ 4)
        ch = 77 - (15 & (5128 >> (4 * i))); 
    else
        ch = 10;

    ch = putchar(ch);
    if (ch > 10)
        main(i + 2);

    return 0;
}

笔记:

  • main()为每个字符递归调用。
  • putchar()成功返回时,字符只是写入控制台。
  • 打印换行符(ASCII 代码 10)是停止递归的条件。
  • 原始代码依赖于未声明的变量是 type 的旧 C 规则int
  • 该变量i在第一次调用时的值为 1(它实际上是argc参数)。
  • 对于第一个if,变量i在五次迭代中具有值 0、1、2、3、4。对于值 4,if 条件变为 false,并使用换行符 (ASCII 10)。
  • 该表达式77 - (15 & (5128 >> (4 * i)))i值 0、1、2、3 的字母 E、M、I、L 生成 ASCII 代码。
于 2013-08-08T11:36:25.360 回答