Hello World的魔幻打印

今天遇到了个很好玩的话题,怎么模(魔)糊(幻)打印Hello World。和平常第一次接触编程语言的Hello World不一样,平常一行就能完成的功能这里实现的能够异常复杂,并且生成了一堆看似乱码的字符,结果用python解析运行却能得到和Hello World一样的结果,原理我到现在还没完全搞明白,先做个记录后面慢慢理解吧。

先看要求:
Task:

Create an obfuscated program that prints Hello World! (exactly like that). Your program may not have any strings in it.

Rules:

You can use any programming language you like.
Make it as obfuscated as possible
This is a popularity-contest, so the answer with the most upvotes wins.

如下答案高票得选:

1
(lambda _, __, ___, ____, _____, ______, _______, ________: getattr(__import__(True.__class__.__name__[_] + [].__class__.__name__[__]), ().__class__.__eq__.__class__.__name__[:__] + ().__iter__().__class__.__name__[_____:________])(_, (lambda _, __, ___: _(_, __, ___))(lambda _, __, ___: chr(___ % __) + _(_, __, ___ // __) if ___ else (lambda: _).func_code.co_lnotab, _ << ________, (((_____ << ____) + _) << ((___ << _____) - ___)) + (((((___ << __) - _) << ___) + _) << ((_____ << ____) + (_ << _))) + (((_______ << __) - _) << (((((_ << ___) + _)) << ___) + (_ << _))) + (((_______ << ___) + _) << ((_ << ______) + _)) + (((_______ << ____) - _) << ((_______ << ___))) + (((_ << ____) - _) << ((((___ << __) + _) << __) - _)) - (_______ << ((((___ << __) - _) << __) + _)) + (_______ << (((((_ << ___) + _)) << __))) - ((((((_ << ___) + _)) << __) + _) << ((((___ << __) + _) << _))) + (((_______ << __) - _) << (((((_ << ___) + _)) << _))) + (((___ << ___) + _) << ((_____ << _))) + (_____ << ______) + (_ << ___))))(*(lambda _, __, ___: _(_, __, ___))((lambda _, __, ___: [__(___[(lambda: _).func_code.co_nlocals])] + _(_, __, ___[(lambda _: _).func_code.co_nlocals:]) if ___ else []), lambda _: _.func_code.co_argcount, (lambda _: _, lambda _, __: _, lambda _, __, ___: _, lambda _, __, ___, ____: _, lambda _, __, ___, ____, _____: _, lambda _, __, ___, ____, _____, ______: _, lambda _, __, ___, ____, _____, ______, _______: _, lambda _, __, ___, ____, _____, ______, _______, ________: _)))

第一印象,什么鬼??第二眼还是看不懂。
来看看作者怎么解释的。

1
2
3
4
5
6
7
8
Here is a more readable version: http://codepad.org/UzSmoxF2

Notes:
One line, single expression (i.e. no print statement).
No strings, no ints; only functions, attribute access, lists, tuples, basic math, one True, and one star-args.
Minimal builtin usage (__import__, getattr, and chr once each).
The payload can be changed easily. Here is the program I wrote to generate it.
Edit: I wrote a fairly substantial explanation of how this works on my blog.

编写generate.py脚本通过对输入字符串加密:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
# How to use?
# python generate.py "the str needed to be encry"
#

from math import ceil, log
import sys

def encode_string(s):
bytes = [ord(c) for c in s]
num = sum(bytes[i] * 256 ** i for i in range(len(bytes)))
return reduce(num, 0)

def reduce(num, depth):
def _encode(num, depth):
if num == 0:
return "_ - _"
if num in range(9):
return "_" * num
return "(" + reduce(num, depth + 1) + ")"
result = ""
while num:
best_base = best_shift = 0
best = num
span = int(ceil(log(abs(num), 1.5))) + (16 >> depth)
for base in range(span):
for shift in range(span):
diff = abs(num) - (base << shift)
if abs(diff) < abs(best):
best = diff
best_base = base
best_shift = shift
if result:
result += " + " if num > 0 else " - "
elif num < 0:
best_base = -best_base
if best_shift == 0:
result += _encode(best_base, depth)
else:
result += "(%s << %s)" % (_encode(best_base, depth),
_encode(best_shift, depth))
num = best if num > 0 else -best
return result

# print(len(sys.argv))
# print(' '.join(sys.argv[1:]))
result = encode_string(str(' '.join(sys.argv[1:]))+"\n")
print("Encrypted Text: ")
print(result)

Run tese case:

1
2
3
(base) huang@mlp:~/taichi/intel$ python generate.py huang zhiyuan
Encrypted Text:
(((_______ << ___) - _) << ((___ << _____) + _)) + (((___ << _____) + _) << ((((___ << __) - _) << ___))) + (((((_ << ____) - _) << ___) - ___) << ((_____ << ____))) + (((((_ << ____) - _) << ___) + _) << (((((_ << ___) + _)) << ___))) + (((((___ << __) + _) << ___) + _) << ((_ << ______))) + ((((___ << __) + _)) << ((((_ << ____) - _) << __) - _)) + (((((_ << ____) - _) << __) + _) << ((___ << ____) + _)) + (((_ << ______) + _) << ((_____ << ___) - _)) - (((___ << ____) + _) << ((_ << _____) - _)) - ((((((_ << ___) + _)) << __) - _) << ((___ << ___) - _)) - (((_ << _____) - _) << ((_ << ____))) + (((_______ << __) + _) << ((_____ << _))) + ((((___ << __) - _)) << _____) + (_ << ___)

利用上面生成的加密字符填充运行脚本run.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
huang@mlp:~/taichi/intel$ cat run.py

(lambda _, __, ___, ____, _____, ______, _______, ________:
getattr(
__import__(True.__class__.__name__[_] + [].__class__.__name__[__]),
().__class__.__eq__.__class__.__name__[:__] +
().__iter__().__class__.__name__[_____:________]
)(
_, (lambda _, __, ___: _(_, __, ___))(
lambda _, __, ___:
chr(___ % __) + _(_, __, ___ // __) if ___ else
(lambda: _).func_code.co_lnotab,
_ << ________,

## fill the encrypted text here
(((_____ << _____) + _______) << ((___ << _____) + (_ << __))) - ((((___ << __) + _)) << ((___ << _____) - ___)) + (((___ << _____) - ___) << ((_____ << ____) + (_ << _))) + (((___ << ____) - _) << (((((_ << ___) + _)) << ___) + ___)) + (((((___ << __) - _) << __) + _) << ((((_ << ____) + _) << __) - _)) + (((((___ << __) - _) << __) + _) << ((((_ << ____) - _) << __) - _)) + (((((_ << ____) - _) << __) + _) << ((___ << ____) + _)) + (((_ << ______) + _) << ((_____ << ___) - _)) - (((___ << ____) + _) << ((_ << _____) - _)) - ((((((_ << ___) + _)) << __) - _) << ((___ << ___) - _)) - (((_ << _____) - _) << ((_ << ____))) + (((_______ << __) + _) << ((_____ << _))) + ((((___ << __) - _)) << _____) + (_ << ___)

)
)
)(
*(lambda _, __, ___: _(_, __, ___))(
(lambda _, __, ___:
[__(___[(lambda: _).func_code.co_nlocals])] +
_(_, __, ___[(lambda _: _).func_code.co_nlocals:]) if ___ else []
),
lambda _: _.func_code.co_argcount,
(
lambda _: _,
lambda _, __: _,
lambda _, __, ___: _,
lambda _, __, ___, ____: _,
lambda _, __, ___, ____, _____: _,
lambda _, __, ___, ____, _____, ______: _,
lambda _, __, ___, ____, _____, ______, _______: _,
lambda _, __, ___, ____, _____, ______, _______, ________: _
)
)
)

验(zhuang)证(bi)结(shi)果(ke):

1
2
(base) huang@mlp:~/taichi/intel$ python2 run.py
huang zhiyuan

版本目前来看只支持python2,否则会报error,从python2到python3有些built-in函数attribute命名规则发生了改变

1
The function attributes named func_X have been renamed to use the __X__ form, freeing up these names in the function attribute namespace for user-defined attributes. To wit, func_closure, func_code, func_defaults, func_dict, func_doc, func_globals, func_name were renamed to __closure__, __code__, __defaults__, __dict__, __doc__, __globals__, __name__, respectively.
1
2
3
4
5
6
7
8
9
(base) huang@mlp:~/taichi/intel$ python run.py
Traceback (most recent call last):
File "run.py", line 32, in <module>
lambda _, __, ___, ____, _____, ______, _______, ________: _
File "run.py", line 18, in <lambda>
*(lambda _, __, ___: _(_, __, ___))(
File "run.py", line 21, in <lambda>
_(_, __, ___[(lambda _: _).func_code.co_nlocals:]) if ___ else []
AttributeError: 'function' object has no attribute 'func_code'

参考链接:
https://codegolf.stackexchange.com/questions/22533/weirdest-obfuscated-hello-world
https://benkurtovic.com/2014/06/01/obfuscating-hello-world.html
http://codepad.org/UzSmoxF2
http://codepad.org/oVuFVcB5