[Reverse] PYPY - Cew xp0int Posted on Apr 29 2021 对call PyEval_EvalCode下断点(break *0x402B5B),当R14 寄存器保存的是'main'字串地址时dump main marshal(https://gist.github.com/stecman/3751ac494795164efa82a683130cabe5) ``` define dump_pyc eval "set $handle = fopen(\"main.marshal\", \"w\")" call (void) PyMarshal_WriteObjectToFile($rdi, $handle, 4) call fclose($handle) end command dump_pyc "./" continue end ``` 然后用下面的脚本将main.marshal还原成py ``` from __future__ import print_function import marshal import struct import sys import time import uncompyle6 def _pack_uint32(val): """ Convert integer to 32-bit little-endian bytes """ return struct.pack("<I", val) def code_to_bytecode(code, mtime=0, source_size=0): """ Serialise the passed code object (PyCodeObject*) to bytecode as a .pyc file The args mtime and source_size are inconsequential metadata in the .pyc file. """ # Get the magic number for the running Python version if sys.version_info >= (3,4): from importlib.util import MAGIC_NUMBER else: import imp MAGIC_NUMBER = imp.get_magic() # Add the magic number that indicates the version of Python the bytecode is for # # The .pyc may not decompile if this four-byte value is wrong. Either hardcode the # value for the target version (eg. b'\x33\x0D\x0D\x0A' instead of MAGIC_NUMBER) # or see trymagicnum.py to step through different values to find a valid one. data = bytearray(MAGIC_NUMBER) # Handle extra 32-bit field in header from Python 3.7 onwards # See: https://www.python.org/dev/peps/pep-0552 if sys.version_info >= (3,7): # Blank bit field value to indicate traditional pyc header data.extend(_pack_uint32(0)) data.extend(_pack_uint32(int(mtime))) # Handle extra 32-bit field for source size from Python 3.2 onwards # See: https://www.python.org/dev/peps/pep-3147/ if sys.version_info >= (3,2): data.extend(_pack_uint32(source_size)) data.extend(marshal.dumps(code)) return data if len(sys.argv) < 2: print("Usage %s <marshal-dump-file>" % sys.argv[0]) sys.exit(1) path = sys.argv[1] pycFile = path + ".pyc" pythonFile = path + ".py" # Open raw code that was saved using marshal.dump() # # It isn't strictly necessary to unmarshal this to write back as a .pyc file, # but this validates that the marshalled code content is valid (an exception # is thrown otherwise) with open(path, 'rb') as handle: code = marshal.load(handle) pyc = code_to_bytecode(code, time.time()) with open(pycFile, 'wb') as out: out.write(pyc) # Use uncompyle6 to decompile the bytecode and write it to disk alongside the .pyc with open(pythonFile, 'w') as decompiled: uncompyle6.main.decompile_file(pycFile, decompiled) ``` main.py中关于flag的操作为rc4加密,还原即可 ``` # exp DEFAULT_KEY = 'Yó\x02Ã%\x9a\x820\x0b»%\x7f~;ÒÜ' def rc4(O0O0O0000O0OOOO0O, key=DEFAULT_KEY, skip=1024): O00OOOOOOO00OO00O = 0 OO0OOOO0000OO00OO = bytearray([OO00OOOO0OOOOO00O for OO00OOOO0OOOOO00O in range(256)]) O00OOOOOOO00OO00O = 0 for OOOO000OOO00O000O in range(256): O00OOOOOOO00OO00O = (O00OOOOOOO00OO00O + OO0OOOO0000OO00OO[OOOO000OOO00O000O] + ord(key[(OOOO000OOO00O000O % len(key))])) % 256 OO000O0O0OOOOO0OO = OO0OOOO0000OO00OO[OOOO000OOO00O000O] O000O0OO00O00000O = OO0OOOO0000OO00OO[O00OOOOOOO00OO00O] OO0OOOO0000OO00OO[OOOO000OOO00O000O] = OO0OOOO0000OO00OO[O00OOOOOOO00OO00O] OO0OOOO0000OO00OO[O00OOOOOOO00OO00O] = OO000O0O0OOOOO0OO else: O00OOOOOOO00OO00O = 0 O0O0OO0OO00OOOOO0 = 0 OO0OOO000000OO0O0 = [] if skip > 0: for OOOO000OOO00O000O in range(skip): O00OOOOOOO00OO00O = (O00OOOOOOO00OO00O + 1) % 256 O0O0OO0OO00OOOOO0 = (O0O0OO0OO00OOOOO0 + OO0OOOO0000OO00OO[O00OOOOOOO00OO00O]) % 256 OO0OOOO0000OO00OO[O00OOOOOOO00OO00O], OO0OOOO0000OO00OO[O0O0OO0OO00OOOOO0] = OO0OOOO0000OO00OO[O0O0OO0OO00OOOOO0], OO0OOOO0000OO00OO[O00OOOOOOO00OO00O] for O0000O0OOO000OO0O in O0O0O0000O0OOOO0O: O00OOOOOOO00OO00O = (O00OOOOOOO00OO00O + 1) % 256 O0O0OO0OO00OOOOO0 = (O0O0OO0OO00OOOOO0 + OO0OOOO0000OO00OO[O00OOOOOOO00OO00O]) % 256 OO0OOOO0000OO00OO[O00OOOOOOO00OO00O], OO0OOOO0000OO00OO[O0O0OO0OO00OOOOO0] = OO0OOOO0000OO00OO[O0O0OO0OO00OOOOO0], OO0OOOO0000OO00OO[O00OOOOOOO00OO00O] O0O0OOOO0OOOOO0OO = OO0OOOO0000OO00OO[((OO0OOOO0000OO00OO[O00OOOOOOO00OO00O] + OO0OOOO0000OO00OO[O0O0OO0OO00OOOOO0]) % 256)] OO0OOO000000OO0O0.append(chr(ord(O0000O0OOO000OO0O) ^ O0O0OOOO0OOOOO0OO)) else: return ''.join(OO0OOO000000OO0O0) def func(O0O0O0OO00O00OOO0): O000OOOO0O00OO000 = rc4(O0O0O0OO00O00OOO0) if O000OOOO0O00OO000.encode('utf-8').hex() == '275b39c381c28b701ac3972338456022c2ba06c3b04f5501471c47c38ac380c29b72c3b5c38a7ec2a5c2a0': return 'YOU WIN' return 'YOU LOSE' import codecs s = b'275b39c381c28b701ac3972338456022c2ba06c3b04f5501471c47c38ac380c29b72c3b5c38a7ec2a5c2a0' enc = codecs.decode(s, 'hex').decode() print(rc4(enc)) ``` flag{snake_bao_is_really_lucky} 打赏还是打残,这是个问题 赏 Wechat Pay Alipay [Pwn] pwn1 - cpt.shao [Reverse] PE - Cew
没有帐号? 立即注册