我应该如何解码这个 data/these 字符串
How should i decode this data/these strings
我目前正在尝试解决旧的 python CTF 挑战,提供了服务器的脚本,想法是将正确的数据发送到此服务器,
#!/usr/bin/env python3
# from dis import dis
import socketserver
import types
class RequestHandler(socketserver.BaseRequestHandler):
def handle(self):
self.request.sendall(b'PyDRM Proof of Concept version 0.7\n')
self.request.sendall(
b'Submit the secret password to retrieve the flag:\n')
user_input_bytes = self.request.recv(4096).strip()
user_input = user_input_bytes.decode('utf-8', 'ignore')
if validate_password(user_input):
self.request.sendall(read_flag())
else:
self.request.sendall(b'Invalid password\n')
class RequestServer(socketserver.ThreadingMixIn, socketserver.TCPServer):
pass
def read_flag():
with open('flag.txt', 'rb') as fh:
return fh.read()
def generate_validation_function():
code_obj = types.CodeType(
1,
0,
5,
32,
67,
b'd\x01\x00d\x02\x00d\x03\x00d\x04\x00d\x05\x00d\x06\x00d\x05\x00d\x07'
b'\x00d\x08\x00d\x05\x00d\t\x00d\x08\x00d\n\x00d\x01\x00d\x07\x00d\x07'
b'\x00d\x01\x00d\x0b\x00d\x08\x00d\x07\x00d\x0c\x00d\r\x00d\x0e\x00d'
b'\x08\x00d\x05\x00d\x0f\x00d\x03\x00d\x04\x00d\x05\x00d\x06\x00d\x05'
b'\x00d\x07\x00g \x00}\x01\x00g\x00\x00}\x02\x00x+\x00|\x01\x00D]#\x00'
b'}\x03\x00|\x02\x00j\x00\x00t\x01\x00t\x02\x00|\x03\x00\x83\x01\x00d'
b'\x10\x00\x18\x83\x01\x00\x83\x01\x00\x01qs\x00Wd\x11\x00j\x03\x00|'
b'\x02\x00\x83\x01\x00}\x04\x00|\x00\x00|\x04\x00k\x02\x00r\xb9\x00d'
b'\x12\x00Sd\x13\x00S',
(None, '\x87', '\x9a', '\x92', '\x8e', '\x8b', '\x85', '\x96', '\x81',
'\x95', '\x84', '\x94', '\x8a', '\x83', '\x90', '\x8f', 34, '', True,
False),
('append', 'chr', 'ord', 'join'),
('a', 'b', 'c', 'd', 'e'),
'drm.py',
'validate_password',
5,
b'\x00\x01$\x01$\x01\x1e\x01\x06\x01\r\x01!\x01\x0f\x01\x0c\x01\x04'
b'\x01',
(),
()
)
func_obj = types.FunctionType(code_obj, globals())
return func_obj
def main():
setattr(__import__(__name__), 'validate_password',
generate_validation_function())
server = RequestServer(('0.0.0.0', 8765), RequestHandler)
try:
server.serve_forever()
except (SystemExit, KeyboardInterrupt):
server.shutdown()
server.server_close()
if __name__ == '__main__':
main()
编辑
我明白了,validate_password 函数是使用 CodeType 和 FunctionType 对象创建的。我还了解到,如果 validate_password(user_input) 评估为真,则将发送标志。这意味着 return 类型必须是布尔值。 CodeType 的文档以及服务器脚本还显示 validate_password 只有一个参数。
我的实际问题
源代码包含已编译的 python 字节码。 b'd\x01\x00d\x02\x00d\x03\x00d\x04\x00d\x05\x00d\x06\x00d\x05\x00d\x07'
例如。我尝试了多种方法 decode/encode 这些字符串来获取一些有意义的数据,我设法提取的唯一数据是十六进制的。
如何将此数据转换为实际代码,从而能够重建 validate_password
函数。
我试过的
SO - Python: convert string to packed hex ( '01020304' -> '\x01\x02\x03\x04' ) - 我试图基本上按照这个答案的建议去做,但反过来,我要么没有正确理解它,要么这不起作用
binascii.b2a_hex() - 这就是我设法将字符串转换为十六进制的方法,就像我之前所说的那样,但是我无法从这个十六进制中生成 utf-8 数据。
struct.unpack() - 用这种方法取得了一些成功,但我不知道数据在 validate_password 函数的上下文中意味着什么,我只能用这个得到整数方法。 (除非我误解了)
开始交互式 Python 3 会话。如果你使用普通的 python 解释器,输入
import types
help(types.CodeType)
如果您使用的是 IPython,您可以改写
import types
types.CodeType?
您会了解到 types.CodeType
可以
Create a code object. Not for the faint of heart.
嗯嗯。什么是代码对象?让我们来看看 Python documentation.
The type for code objects such as returned by compile()
.
所以 bytestring 参数可能至少部分是二进制数据(或二进制指令),而不是以某种方式编码的(文本)字符串。
help
或 ?
调用还告诉我们该类型初始化器的签名:
code(argcount, kwonlyargcount, nlocals, stacksize, flags, codestring,
constants, names, varnames, filename, name, firstlineno,
lnotab[, freevars[, cellvars]])
有了它,我们可以更自述地编写构造:
code_obj = types.CodeType(
argcount=1,
kwonlyargcount=0,
nlocals=5,
stacksize=32,
flags=67,
codestring=b'd\x01\x00d\x02\x00d\x03\x00d\x04\x00d\x05\x00d\x06\x00d\x05\x00d\x07'
b'\x00d\x08\x00d\x05\x00d\t\x00d\x08\x00d\n\x00d\x01\x00d\x07\x00d\x07'
b'\x00d\x01\x00d\x0b\x00d\x08\x00d\x07\x00d\x0c\x00d\r\x00d\x0e\x00d'
b'\x08\x00d\x05\x00d\x0f\x00d\x03\x00d\x04\x00d\x05\x00d\x06\x00d\x05'
b'\x00d\x07\x00g \x00}\x01\x00g\x00\x00}\x02\x00x+\x00|\x01\x00D]#\x00'
b'}\x03\x00|\x02\x00j\x00\x00t\x01\x00t\x02\x00|\x03\x00\x83\x01\x00d'
b'\x10\x00\x18\x83\x01\x00\x83\x01\x00\x01qs\x00Wd\x11\x00j\x03\x00|'
b'\x02\x00\x83\x01\x00}\x04\x00|\x00\x00|\x04\x00k\x02\x00r\xb9\x00d'
b'\x12\x00Sd\x13\x00S',
constants=(None, '\x87', '\x9a', '\x92', '\x8e', '\x8b', '\x85', '\x96', '\x81',
'\x95', '\x84', '\x94', '\x8a', '\x83', '\x90', '\x8f', 34, '', True,
False),
names=('append', 'chr', 'ord', 'join'),
varnames=('a', 'b', 'c', 'd', 'e'),
filename='drm.py',
name='validate_password',
firstlineno=5,
lnotab=b'\x00\x01$\x01$\x01\x1e\x01\x06\x01\r\x01!\x01\x0f\x01\x0c\x01\x04'
b'\x01',
freevars=(),
cellvars=()
)
(这只是为了说明。它实际上不是这样可执行的,因为 types.CodeType()
期望所有参数都按位置传递而不是作为关键字参数。)
那么这一切意味着什么?
您可以反汇编代码对象以更接近该问题:
import dis
dis.dis(code_obj)
(输出:)
6 0 LOAD_CONST 1 ('\x87')
3 LOAD_CONST 2 ('\x9a')
6 LOAD_CONST 3 ('\x92')
9 LOAD_CONST 4 ('\x8e')
12 LOAD_CONST 5 ('\x8b')
15 LOAD_CONST 6 ('\x85')
18 LOAD_CONST 5 ('\x8b')
21 LOAD_CONST 7 ('\x96')
24 LOAD_CONST 8 ('\x81')
27 LOAD_CONST 5 ('\x8b')
30 LOAD_CONST 9 ('\x95')
33 LOAD_CONST 8 ('\x81')
7 36 LOAD_CONST 10 ('\x84')
39 LOAD_CONST 1 ('\x87')
42 LOAD_CONST 7 ('\x96')
45 LOAD_CONST 7 ('\x96')
48 LOAD_CONST 1 ('\x87')
51 LOAD_CONST 11 ('\x94')
54 LOAD_CONST 8 ('\x81')
57 LOAD_CONST 7 ('\x96')
60 LOAD_CONST 12 ('\x8a')
63 LOAD_CONST 13 ('\x83')
66 LOAD_CONST 14 ('\x90')
69 LOAD_CONST 8 ('\x81')
8 72 LOAD_CONST 5 ('\x8b')
75 LOAD_CONST 15 ('\x8f')
78 LOAD_CONST 3 ('\x92')
81 LOAD_CONST 4 ('\x8e')
84 LOAD_CONST 5 ('\x8b')
87 LOAD_CONST 6 ('\x85')
90 LOAD_CONST 5 ('\x8b')
93 LOAD_CONST 7 ('\x96')
96 BUILD_LIST 32
99 STORE_FAST 1 (b)
9 102 BUILD_LIST 0
105 STORE_FAST 2 (c)
10 108 SETUP_LOOP 43 (to 154)
111 LOAD_FAST 1 (b)
114 GET_ITER
>> 115 FOR_ITER 35 (to 153)
118 STORE_FAST 3 (d)
11 121 LOAD_FAST 2 (c)
124 LOAD_ATTR 0 (append)
127 LOAD_GLOBAL 1 (chr)
130 LOAD_GLOBAL 2 (ord)
133 LOAD_FAST 3 (d)
136 CALL_FUNCTION 1
139 LOAD_CONST 16 (34)
142 BINARY_SUBTRACT
143 CALL_FUNCTION 1
146 CALL_FUNCTION 1
149 POP_TOP
150 JUMP_ABSOLUTE 115
>> 153 POP_BLOCK
12 >> 154 LOAD_CONST 17 ('')
157 LOAD_ATTR 3 (join)
160 LOAD_FAST 2 (c)
163 CALL_FUNCTION 1
166 STORE_FAST 4 (e)
13 169 LOAD_FAST 0 (a)
172 LOAD_FAST 4 (e)
175 COMPARE_OP 2 (==)
178 POP_JUMP_IF_FALSE 185
14 181 LOAD_CONST 18 (True)
184 RETURN_VALUE
15 >> 185 LOAD_CONST 19 (False)
188 RETURN_VALUE
请参阅 the meaning of the bytecode operations(LOAD_CONST
、BUILD_LIST
等)的 dis
文档。
为了更好地了解函数的作用,可以尝试将其反编译回 Python 代码。不过,我没能做到。 (尝试 uncompyle6。)
模仿 das-g 的回答,这段代码有效。排序。
import uncompyle6
import types
code_obj = types.CodeType(
1, 0, 5, 32, 67, b'd\x01\x00d\x02\x00d\x03\x00d\x04\x00d\x05\x00d\x06\x00d\x05\x00d\x07'
b'\x00d\x08\x00d\x05\x00d\t\x00d\x08\x00d\n\x00d\x01\x00d\x07\x00d\x07'
b'\x00d\x01\x00d\x0b\x00d\x08\x00d\x07\x00d\x0c\x00d\r\x00d\x0e\x00d'
b'\x08\x00d\x05\x00d\x0f\x00d\x03\x00d\x04\x00d\x05\x00d\x06\x00d\x05'
b'\x00d\x07\x00g \x00}\x01\x00g\x00\x00}\x02\x00x+\x00|\x01\x00D]#\x00'
b'}\x03\x00|\x02\x00j\x00\x00t\x01\x00t\x02\x00|\x03\x00\x83\x01\x00d'
b'\x10\x00\x18\x83\x01\x00\x83\x01\x00\x01qs\x00Wd\x11\x00j\x03\x00|'
b'\x02\x00\x83\x01\x00}\x04\x00|\x00\x00|\x04\x00k\x02\x00r\xb9\x00d'
b'\x12\x00Sd\x13\x00S',
(None, '\x87', '\x9a', '\x92', '\x8e', '\x8b', '\x85', '\x96', '\x81',
'\x95', '\x84', '\x94', '\x8a', '\x83', '\x90', '\x8f', 34, '', True,
False),
('append', 'chr', 'ord', 'join'),
('a', 'b', 'c', 'd', 'e'),
'drm.py',
'validate_password',
5,
b'\x00\x01$\x01$\x01\x1e\x01\x06\x01\r\x01!\x01\x0f\x01\x0c\x01\x04'
b'\x01',
freevars=(),
cellvars=()
)
import sys
uncompyle6.main.uncompyle(3.5, code_obj, sys.stdout)
这里缺少的是,这段代码确实包含在一个带有 "a" 参数的函数中。
我不会破坏给出答案的乐趣。相反:
- 运行上面的程序。
- 将输出包装成如下形式:
def drm(a):
# Output from run above.
我目前正在尝试解决旧的 python CTF 挑战,提供了服务器的脚本,想法是将正确的数据发送到此服务器,
#!/usr/bin/env python3
# from dis import dis
import socketserver
import types
class RequestHandler(socketserver.BaseRequestHandler):
def handle(self):
self.request.sendall(b'PyDRM Proof of Concept version 0.7\n')
self.request.sendall(
b'Submit the secret password to retrieve the flag:\n')
user_input_bytes = self.request.recv(4096).strip()
user_input = user_input_bytes.decode('utf-8', 'ignore')
if validate_password(user_input):
self.request.sendall(read_flag())
else:
self.request.sendall(b'Invalid password\n')
class RequestServer(socketserver.ThreadingMixIn, socketserver.TCPServer):
pass
def read_flag():
with open('flag.txt', 'rb') as fh:
return fh.read()
def generate_validation_function():
code_obj = types.CodeType(
1,
0,
5,
32,
67,
b'd\x01\x00d\x02\x00d\x03\x00d\x04\x00d\x05\x00d\x06\x00d\x05\x00d\x07'
b'\x00d\x08\x00d\x05\x00d\t\x00d\x08\x00d\n\x00d\x01\x00d\x07\x00d\x07'
b'\x00d\x01\x00d\x0b\x00d\x08\x00d\x07\x00d\x0c\x00d\r\x00d\x0e\x00d'
b'\x08\x00d\x05\x00d\x0f\x00d\x03\x00d\x04\x00d\x05\x00d\x06\x00d\x05'
b'\x00d\x07\x00g \x00}\x01\x00g\x00\x00}\x02\x00x+\x00|\x01\x00D]#\x00'
b'}\x03\x00|\x02\x00j\x00\x00t\x01\x00t\x02\x00|\x03\x00\x83\x01\x00d'
b'\x10\x00\x18\x83\x01\x00\x83\x01\x00\x01qs\x00Wd\x11\x00j\x03\x00|'
b'\x02\x00\x83\x01\x00}\x04\x00|\x00\x00|\x04\x00k\x02\x00r\xb9\x00d'
b'\x12\x00Sd\x13\x00S',
(None, '\x87', '\x9a', '\x92', '\x8e', '\x8b', '\x85', '\x96', '\x81',
'\x95', '\x84', '\x94', '\x8a', '\x83', '\x90', '\x8f', 34, '', True,
False),
('append', 'chr', 'ord', 'join'),
('a', 'b', 'c', 'd', 'e'),
'drm.py',
'validate_password',
5,
b'\x00\x01$\x01$\x01\x1e\x01\x06\x01\r\x01!\x01\x0f\x01\x0c\x01\x04'
b'\x01',
(),
()
)
func_obj = types.FunctionType(code_obj, globals())
return func_obj
def main():
setattr(__import__(__name__), 'validate_password',
generate_validation_function())
server = RequestServer(('0.0.0.0', 8765), RequestHandler)
try:
server.serve_forever()
except (SystemExit, KeyboardInterrupt):
server.shutdown()
server.server_close()
if __name__ == '__main__':
main()
编辑
我明白了,validate_password 函数是使用 CodeType 和 FunctionType 对象创建的。我还了解到,如果 validate_password(user_input) 评估为真,则将发送标志。这意味着 return 类型必须是布尔值。 CodeType 的文档以及服务器脚本还显示 validate_password 只有一个参数。
我的实际问题
源代码包含已编译的 python 字节码。 b'd\x01\x00d\x02\x00d\x03\x00d\x04\x00d\x05\x00d\x06\x00d\x05\x00d\x07'
例如。我尝试了多种方法 decode/encode 这些字符串来获取一些有意义的数据,我设法提取的唯一数据是十六进制的。
如何将此数据转换为实际代码,从而能够重建 validate_password
函数。
我试过的
SO - Python: convert string to packed hex ( '01020304' -> '\x01\x02\x03\x04' ) - 我试图基本上按照这个答案的建议去做,但反过来,我要么没有正确理解它,要么这不起作用
binascii.b2a_hex() - 这就是我设法将字符串转换为十六进制的方法,就像我之前所说的那样,但是我无法从这个十六进制中生成 utf-8 数据。
struct.unpack() - 用这种方法取得了一些成功,但我不知道数据在 validate_password 函数的上下文中意味着什么,我只能用这个得到整数方法。 (除非我误解了)
开始交互式 Python 3 会话。如果你使用普通的 python 解释器,输入
import types
help(types.CodeType)
如果您使用的是 IPython,您可以改写
import types
types.CodeType?
您会了解到 types.CodeType
可以
Create a code object. Not for the faint of heart.
嗯嗯。什么是代码对象?让我们来看看 Python documentation.
The type for code objects such as returned by
compile()
.
所以 bytestring 参数可能至少部分是二进制数据(或二进制指令),而不是以某种方式编码的(文本)字符串。
help
或 ?
调用还告诉我们该类型初始化器的签名:
code(argcount, kwonlyargcount, nlocals, stacksize, flags, codestring, constants, names, varnames, filename, name, firstlineno, lnotab[, freevars[, cellvars]])
有了它,我们可以更自述地编写构造:
code_obj = types.CodeType(
argcount=1,
kwonlyargcount=0,
nlocals=5,
stacksize=32,
flags=67,
codestring=b'd\x01\x00d\x02\x00d\x03\x00d\x04\x00d\x05\x00d\x06\x00d\x05\x00d\x07'
b'\x00d\x08\x00d\x05\x00d\t\x00d\x08\x00d\n\x00d\x01\x00d\x07\x00d\x07'
b'\x00d\x01\x00d\x0b\x00d\x08\x00d\x07\x00d\x0c\x00d\r\x00d\x0e\x00d'
b'\x08\x00d\x05\x00d\x0f\x00d\x03\x00d\x04\x00d\x05\x00d\x06\x00d\x05'
b'\x00d\x07\x00g \x00}\x01\x00g\x00\x00}\x02\x00x+\x00|\x01\x00D]#\x00'
b'}\x03\x00|\x02\x00j\x00\x00t\x01\x00t\x02\x00|\x03\x00\x83\x01\x00d'
b'\x10\x00\x18\x83\x01\x00\x83\x01\x00\x01qs\x00Wd\x11\x00j\x03\x00|'
b'\x02\x00\x83\x01\x00}\x04\x00|\x00\x00|\x04\x00k\x02\x00r\xb9\x00d'
b'\x12\x00Sd\x13\x00S',
constants=(None, '\x87', '\x9a', '\x92', '\x8e', '\x8b', '\x85', '\x96', '\x81',
'\x95', '\x84', '\x94', '\x8a', '\x83', '\x90', '\x8f', 34, '', True,
False),
names=('append', 'chr', 'ord', 'join'),
varnames=('a', 'b', 'c', 'd', 'e'),
filename='drm.py',
name='validate_password',
firstlineno=5,
lnotab=b'\x00\x01$\x01$\x01\x1e\x01\x06\x01\r\x01!\x01\x0f\x01\x0c\x01\x04'
b'\x01',
freevars=(),
cellvars=()
)
(这只是为了说明。它实际上不是这样可执行的,因为 types.CodeType()
期望所有参数都按位置传递而不是作为关键字参数。)
那么这一切意味着什么?
您可以反汇编代码对象以更接近该问题:
import dis
dis.dis(code_obj)
(输出:)
6 0 LOAD_CONST 1 ('\x87')
3 LOAD_CONST 2 ('\x9a')
6 LOAD_CONST 3 ('\x92')
9 LOAD_CONST 4 ('\x8e')
12 LOAD_CONST 5 ('\x8b')
15 LOAD_CONST 6 ('\x85')
18 LOAD_CONST 5 ('\x8b')
21 LOAD_CONST 7 ('\x96')
24 LOAD_CONST 8 ('\x81')
27 LOAD_CONST 5 ('\x8b')
30 LOAD_CONST 9 ('\x95')
33 LOAD_CONST 8 ('\x81')
7 36 LOAD_CONST 10 ('\x84')
39 LOAD_CONST 1 ('\x87')
42 LOAD_CONST 7 ('\x96')
45 LOAD_CONST 7 ('\x96')
48 LOAD_CONST 1 ('\x87')
51 LOAD_CONST 11 ('\x94')
54 LOAD_CONST 8 ('\x81')
57 LOAD_CONST 7 ('\x96')
60 LOAD_CONST 12 ('\x8a')
63 LOAD_CONST 13 ('\x83')
66 LOAD_CONST 14 ('\x90')
69 LOAD_CONST 8 ('\x81')
8 72 LOAD_CONST 5 ('\x8b')
75 LOAD_CONST 15 ('\x8f')
78 LOAD_CONST 3 ('\x92')
81 LOAD_CONST 4 ('\x8e')
84 LOAD_CONST 5 ('\x8b')
87 LOAD_CONST 6 ('\x85')
90 LOAD_CONST 5 ('\x8b')
93 LOAD_CONST 7 ('\x96')
96 BUILD_LIST 32
99 STORE_FAST 1 (b)
9 102 BUILD_LIST 0
105 STORE_FAST 2 (c)
10 108 SETUP_LOOP 43 (to 154)
111 LOAD_FAST 1 (b)
114 GET_ITER
>> 115 FOR_ITER 35 (to 153)
118 STORE_FAST 3 (d)
11 121 LOAD_FAST 2 (c)
124 LOAD_ATTR 0 (append)
127 LOAD_GLOBAL 1 (chr)
130 LOAD_GLOBAL 2 (ord)
133 LOAD_FAST 3 (d)
136 CALL_FUNCTION 1
139 LOAD_CONST 16 (34)
142 BINARY_SUBTRACT
143 CALL_FUNCTION 1
146 CALL_FUNCTION 1
149 POP_TOP
150 JUMP_ABSOLUTE 115
>> 153 POP_BLOCK
12 >> 154 LOAD_CONST 17 ('')
157 LOAD_ATTR 3 (join)
160 LOAD_FAST 2 (c)
163 CALL_FUNCTION 1
166 STORE_FAST 4 (e)
13 169 LOAD_FAST 0 (a)
172 LOAD_FAST 4 (e)
175 COMPARE_OP 2 (==)
178 POP_JUMP_IF_FALSE 185
14 181 LOAD_CONST 18 (True)
184 RETURN_VALUE
15 >> 185 LOAD_CONST 19 (False)
188 RETURN_VALUE
请参阅 the meaning of the bytecode operations(LOAD_CONST
、BUILD_LIST
等)的 dis
文档。
为了更好地了解函数的作用,可以尝试将其反编译回 Python 代码。不过,我没能做到。 (尝试 uncompyle6。)
模仿 das-g 的回答,这段代码有效。排序。
import uncompyle6
import types
code_obj = types.CodeType(
1, 0, 5, 32, 67, b'd\x01\x00d\x02\x00d\x03\x00d\x04\x00d\x05\x00d\x06\x00d\x05\x00d\x07'
b'\x00d\x08\x00d\x05\x00d\t\x00d\x08\x00d\n\x00d\x01\x00d\x07\x00d\x07'
b'\x00d\x01\x00d\x0b\x00d\x08\x00d\x07\x00d\x0c\x00d\r\x00d\x0e\x00d'
b'\x08\x00d\x05\x00d\x0f\x00d\x03\x00d\x04\x00d\x05\x00d\x06\x00d\x05'
b'\x00d\x07\x00g \x00}\x01\x00g\x00\x00}\x02\x00x+\x00|\x01\x00D]#\x00'
b'}\x03\x00|\x02\x00j\x00\x00t\x01\x00t\x02\x00|\x03\x00\x83\x01\x00d'
b'\x10\x00\x18\x83\x01\x00\x83\x01\x00\x01qs\x00Wd\x11\x00j\x03\x00|'
b'\x02\x00\x83\x01\x00}\x04\x00|\x00\x00|\x04\x00k\x02\x00r\xb9\x00d'
b'\x12\x00Sd\x13\x00S',
(None, '\x87', '\x9a', '\x92', '\x8e', '\x8b', '\x85', '\x96', '\x81',
'\x95', '\x84', '\x94', '\x8a', '\x83', '\x90', '\x8f', 34, '', True,
False),
('append', 'chr', 'ord', 'join'),
('a', 'b', 'c', 'd', 'e'),
'drm.py',
'validate_password',
5,
b'\x00\x01$\x01$\x01\x1e\x01\x06\x01\r\x01!\x01\x0f\x01\x0c\x01\x04'
b'\x01',
freevars=(),
cellvars=()
)
import sys
uncompyle6.main.uncompyle(3.5, code_obj, sys.stdout)
这里缺少的是,这段代码确实包含在一个带有 "a" 参数的函数中。
我不会破坏给出答案的乐趣。相反:
- 运行上面的程序。
- 将输出包装成如下形式:
def drm(a): # Output from run above.