为什么1987 Korn oneliner打印unix?

时间:2013-10-10 14:36:33

标签: c deobfuscation

好的,我会咬人的。广受欢迎的answer问题Why does the C preprocessor interpret the word "linux" as the constant "1"?提及

main() { printf(&unix["\021%six\012\0"],(unix)["have"]+"fun"-0x60);}`
  

打印"unix",但原因与宏名称的拼写完全无关。

我读过http://www.ioccc.org/1987/korn.hint,但我认为更多细节会有助于不加协商:)

2 个答案:

答案 0 :(得分:12)

由于编译器或运行时环境中存在隐式unix

#define为1。

因此,因为a[b] == b[a] == *(a + b)因此1["xy"] == "xy"[1],你得到:

  • &unix["\021%six\012\0"]指向"%six\012\0"
  • (unix)["have"] = "have"[1] = 'a'
  • "'a'+"fun"-0x60" = "fun" + 1 = "un"

这会引导您printf("%six\012\0", "un");显然打印"unix\012"\012是换行符(与\n相同)。

如果unix未定义,e。 G。在Windows系统上,您会收到错误。

如果unix0(这可能是干净系统的方式吗?),那么

printf("\012%six\n", 'h'+"fun"-0x60)

其中第二个参数是"fun"+8,指向Nirvana并导致未定义的行为。

答案 1 :(得分:4)

通常情况下,我认为只有在类似unix的系统下编译才能打印“unix”。

这是因为在此类系统上,unix预定义宏,其值为1

因此,它翻译为:

main() { printf(&1["\021%six\012\0"], (1)["have"]+"fun"-0x60); }

重新命令处置int[array]废话,我们得到:

main() { printf(&"\021%six\012\0"[1], "have"[1] + "fun"-0x60); }

我们可以忽略\021,因为它已被跳过(我只需将其替换为?),并将\012翻译为\n

main() { printf(&"?%six\n\0"[1], 'a' + "fun" - 0x60); }
main() { printf(  "%six\n",     0x61 + "fun" - 0x60); }

给出了:

main() { printf("%six\n", "un"); }

注意:我正在重新解决它(特别是第二部分),但是第一次看到它时我需要两个提示来理解解释:

  • unix表示1
  • int[array]是编译器接受的实际表示法。