dismantle.py
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 """
00016 Dismantles a .py file by compiling it
00017 into a code object and recursively dismantling
00018 and disassembling the code object.
00019 """
00020
00021 __usage__ = """Usage:
00022 dismantle.py sourcefilename.py
00023 """
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034 STRINGTOOLONG = 32
00035
00036
00037 import dis, sys, types, py_compile, time
00038
00039
00040 def dismantle_file(fn):
00041 """Dismantles the .py file, fn. Returns the root code object.
00042 """
00043
00044
00045 f = open(fn)
00046 source = f.read()
00047 f.close()
00048 return dismantle(source, fn)
00049
00050
00051 def dismantle(source, fn=""):
00052
00053
00054 if fn == "":
00055 magic = 0
00056 ignore = 0
00057 fn = "fn"
00058 pyc = ""
00059
00060 else:
00061
00062 py_compile.compile(fn)
00063 f = open(fn + 'c','rb')
00064 pyc = f.read()
00065 f.close()
00066
00067
00068 magic = int((ord(pyc[0]) ) | (ord(pyc[1]) << 8) |
00069 (ord(pyc[2]) << 16) | (ord(pyc[3]) << 24))
00070
00071
00072 ignore = int((ord(pyc[4]) ) | (ord(pyc[5]) << 8) |
00073 (ord(pyc[6]) << 16) | (ord(pyc[7]) << 24))
00074
00075 code = compile(source, fn, "exec")
00076
00077
00078 print "BEGIN DISMANTLE"
00079 print "date: \t", time.ctime(time.time())
00080 print "src file: \t", fn
00081 print "src file size: \t", len(source), "bytes"
00082 print "pyc file size: \t", len(pyc), "bytes"
00083 print
00084 print "magic: \t0x%08x" % magic
00085 print "ignore: \t0x%08x" % ignore
00086 print
00087
00088
00089 rdismantle(code)
00090
00091 print "END DISMANTLE"
00092 return code
00093
00094
00095 def rdismantle(co, parent = None):
00096 """Dismantles the code object, co. Prints the co_* field values and
00097 the co_code disassembly for each code object in the file and recurses
00098 into any code objects in the constant pool.
00099 """
00100
00101
00102 if parent:
00103 fullname = parent + "." + co.co_name
00104 else:
00105 fullname = co.co_name
00106
00107
00108 print "fullname: \t", fullname
00109 print " co_name: \t", co.co_name
00110 print " co_filename: \t", co.co_filename
00111 print " co_firstlineno:\t", co.co_firstlineno
00112 print " co_flags: \t0x%04x" % co.co_flags
00113 print " co_stacksize: \t", co.co_stacksize
00114 print " co_lnotab[%3d]:\t%s" % \
00115 (len(co.co_lnotab), repr(co.co_lnotab[:8]))
00116 print " co_argcount: \t", co.co_argcount
00117 print " co_nlocals: \t", co.co_nlocals
00118 print " co_freevars: \t", co.co_freevars
00119 print " co_cellvars: \t", co.co_cellvars
00120
00121
00122 tabspacing = "\t\t"
00123
00124 print " co_varnames:"
00125 i = 0
00126 for item in co.co_varnames:
00127 print tabspacing, i, ":\t", item
00128 i += 1
00129
00130 print " co_names: "
00131 i = 0
00132 for item in co.co_names:
00133 print tabspacing, i, ":\t", item
00134 i += 1
00135
00136 print " co_consts: "
00137 i = 0
00138 for item in co.co_consts:
00139 if type(item) == types.StringType and \
00140 len(item) > STRINGTOOLONG:
00141 print tabspacing, i, ":\t", repr(item[:STRINGTOOLONG]), "..."
00142 else:
00143 print tabspacing, i, ":\t", repr(item)
00144 i += 1
00145
00146
00147 print " co_code:"
00148 dis.dis(co)
00149 print "\n"
00150
00151
00152 for obj in co.co_consts:
00153 if type(obj) == types.CodeType:
00154 rdismantle(obj, fullname)
00155 return
00156
00157
00158 def main():
00159 """Dismantles the source file given as an arg.
00160 """
00161
00162 if len(sys.argv) == 2:
00163 return dismantle_file(sys.argv[1])
00164 else:
00165 print __usage__
00166
00167
00168 if __name__ == "__main__":
00169 main()
00170