# .pyc ## Getting the code For the .pyc binaries \("compiled" python\) you should start trying to **extract** the **original** **python** **code**: ```bash uncompyle6 binary.pyc > decompiled.py ``` **Be sure** that the binary has the **extension** "**.pyc**" \(if not, uncompyle6 is not going to work\) After extracting it, it will be more easy to analyze. ## Analyzing python assembly If you weren't able to extract the python "original" code following the previous steps, then you can try to **extract** the **assembly** \(but i**t isn't very descriptive**, so **try** to extract **again** the original code\). In [here](https://bits.theorem.co/protecting-a-python-codebase/) I found a very simple code to **dissasemble** the _.pyc_ binary \(good luck understanding the code flow\). If the _.pyc_ is from python2, use python2: ```bash >>> import dis >>> import marshal >>> import struct >>> import imp >>> >>> with open('hello.pyc', 'r') as f: # Read the binary file ... magic = f.read(4) ... timestamp = f.read(4) ... code = f.read() ... >>> >>> # Unpack the structure content and un-marshal the code >>> magic = struct.unpack('>> timestamp = struct.unpack('>> code = marshal.loads(code) >>> magic, timestamp, code ((62211,), (1425911959,), at 0x7fd54f90d5b0, file "hello.py", line 1>) >>> >>> # Verify if magic number corresponds with the current python version >>> struct.unpack('>> >>> # Disassemble the code object >>> dis.disassemble(code) 1 0 LOAD_CONST 0 () 3 MAKE_FUNCTION 0 6 STORE_NAME 0 (hello_world) 9 LOAD_CONST 1 (None) 12 RETURN_VALUE >>> >>> # Also disassemble that const being loaded (our function) >>> dis.disassemble(code.co_consts[0]) 2 0 LOAD_CONST 1 ('Hello {0}') 3 LOAD_ATTR 0 (format) 6 LOAD_FAST 0 (name) 9 CALL_FUNCTION 1 12 PRINT_ITEM 13 PRINT_NEWLINE 14 LOAD_CONST 0 (None) 17 RETURN_VALUE ```