exetractor / exetractor /

# -*- coding: utf-8 -*-


   Extractor for executable files created with PyInstaller.

from __future__ import with_statement

import marshal
import struct
import sys
from dis import disassemble
from zlib import decompress

from .common import wrap_stdio

class Cookie(object):
    # COOKIE magic (see source/common/launch.h)
    MAGIC = 'MEI\014\013\012\013\016'
    def __init__(self, data):
        assert data.startswith(Cookie.MAGIC)
        data = data[len(Cookie.MAGIC):]
         self.pyver) = struct.unpack('!4i', data)

    size = struct.calcsize('!4i') + len(MAGIC)

class TOCEntry(object):
    def __init__(self, data):
         self.typcd, = struct.unpack('!4i3c', data[:TOCEntry.size])
        # Get complete name += data[TOCEntry.size:data.index('\x00', TOCEntry.size)]
        # Convert cflag to Boolean
        self.cflag = self.cflag == '\x01'

    size = struct.calcsize('!4i3c')

class TOC(object):
    def __init__(self, data): = data

    def __iter__(self):
        i = 0
        while i < len(
            entry = TOCEntry([i:])
            yield entry
            i += entry.structlen

def is_valid_data(exe_data):
        cookie = Cookie(exe_data[-Cookie.size:])
        assert cookie.len > 0 and cookie.toc > 0 and cookie.toclen > 0
    except AssertionError:
        return False
    return True

def unpack(exe_data):
    cookie = Cookie(exe_data[-Cookie.size:])
    same_pyver = cookie.pyver == sys.version_info[0] * 10 + sys.version_info[1]
    if not same_pyver:
        print ('Warning: Python version does not match, '
               'will not unmarshal data')
    pkgstart = -cookie.len
    tocdata = exe_data[pkgstart + cookie.toc:
                       pkgstart + cookie.toc + cookie.toclen]
    # Extract strings
    for entry in TOC(tocdata):
        data = exe_data[pkgstart + entry.pos:
                        pkgstart + entry.pos + entry.len]
        if entry.cflag:
            data = decompress(data)
        if entry.typcd.lower() == 'm':
            # Module
            print 'Extracting module',
            with open( + '.pyc', 'wb') as outfile:
            if same_pyver:
                print 'Disassembling module',
                # skip header of pyc/pyo files and unmarshal the code
                # object
                code_object = marshal.loads(data[8:])
                # Write dis output to file
                # Note: this is a hack, but dis seems to be a hack, too
                with wrap_stdio(open( + '.dis', 'w')):
        elif entry.typcd == 's':
            print 'Extracting script',
            # Python script
            with open( + '.py', 'w') as outfile:
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.