我目前正在尝试通过一个老的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()

编辑
我知道,使用CodeType和FunctionType对象创建validate_password函数是怎么回事。我还知道,如果validate_password(user_input)的值为True,则将发送标志。这意味着返回类型必须是布尔型。CodeType文档和服务器脚本还显示validate_password只有一个参数。
我的实际问题
源代码包含已编译的python字节码。b'd\x01\x00d\x02\x00d\x03\x00d\x04\x00d\x05\x00d\x06\x00d\x05\x00d\x07'例如。我尝试了很多方法来解码/编码这些字符串,以获得一些有意义的数据,我唯一设法提取的数据是十六进制。
如何将这些数据转换为实际代码,从而能够重建validate_password函数。
我试过的
SO - Python: convert string to packed hex ( '01020304' -> '\x01\x02\x03\x04' )-我试图基本上按照这个答案来做,但反过来说,我要么没有正确理解它,要么这不起作用
binasci.b2a_hex()-这就是我如何将字符串转换为十六进制的方法,就像我前面所说的,但是我不能从这个十六进制中产生utf-8数据。
struct.unpack()-在这个方法上取得了一些成功,但是在validate_password函数的上下文中,我无法理解数据的含义,我只能用这个方法获得整数。(除非我误解了)

最佳答案

抄下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.

08-16 02:31