Descompilar un *.exe creado con py2exe?
Gabriel Genellina
gagsl-py2 en yahoo.com.ar
Lun Jul 23 13:10:47 CEST 2007
Hola
(Uf, primero no veia el texto de tu mensaje, y despues me costó responder
citandolo - es que escribiste todo tu mensaje DEBAJO de una firma, con lo
que quedo como si lo tuyo fuera parte de la firma original...)
[Juan Pavon Ruiz]
> Como decía el exe ha sido creado con py2exe y la carpeta que creó se
> compone de los siguientes elementos:
> tcl - (dosier)
> Miaplicación.exe
> _bsddb.pyd [mas otros .pyd y .dll]
>Yo había pensado que descomprimiendo Miaplicación.exe me encontraría con
> un pyc, y luego podría intentar algo con Decompyle(visto que no llega a
> la 2.5).
>Pero ¿Cómo descomprimir ese exe? ¿Qué herramienta?
> (Miaplicación.exe tiene el mismo peso que tenía Miaplicación.py) .
> Luego en Library.zip encuentro algunos .pyc , pero ni rastro de
> Miaplicación.py (pyc) . Así, pienso, que lo que busco está detrás de
> Miaplicación.exe.
Ah, ok, ya entiendo. Hay opciones para que py2exe genere un .exe con todos
esos .pyd/.pyc/.dll ya incorporados dentro, usando el formato de un .zip,
pero no es tu caso.
Por otro lado, igual que cuando uno ejecuta un script directamente no se
genera su .pyc (sí se generan para modulos importados), el .pyc del script
principal no lo vas a encontrar junto con los demas.
Pero está, aunque es un poco trabajoso recuperarlo. Esta guardado como un
recurso dentro del .exe; para recuperarlo necesitas un programa que te
deje inspeccionar el contenido de un .exe (por ejemplo, PE Explorer; es
pago pero con la version demo de 30 dias alcanza y sobra).
Abriendo Miaplicacion.exe con el PE Explorer, yendo a View -> Resources,
vas a encontrar uno de tipo "PYTHONSCRIPT", id=1. Lo guardamos usando la
opcion "Save resource as" con el nombre por defecto, "pythonscript_1.res".
Ahora bien, ahi dentro hay varias cosas: 16 bytes de encabezado (empezando
con 12345678 en hexa, leido en big endian), seguido del nombre del
archivo, seguido de un byte en cero, seguido de un bloque de datos,
terminando con dos bytes en 0. El bloque de datos es una lista de bloques
de codigo, "marshaleada" usando marshal.dumps. De esa lista, lo que nos
interesa es el ultimo elemento (el codigo de la aplicacion).
Como supongo que ya te perdiste con todo esto :) ahi va un script que te
genera el .pyc en base al resource ya extraido desde dentro del .exe:
--- comienza res2pyc.py ---
""" res2pyc - extrae el .pyc del programa principal almacenado por py2exe
Primero hay que extraer el resource "PYTHONSCRIPT" desde dentro del .exe
y dejarlo en "pythonscript_1.res".
Es la inversa de lo que hace build_exe.py, dentro de py2exe
"""
import struct, marshal
data = open("pythonscript_1.res","rb").read()
magic, _, _, lenbytes = struct.unpack("iiii", data[:16])
assert magic==0x78563412
i = 16
while data[i]!='\000': i += 1 # saltear nombre del archivo
nombre = data[16:i]
code_bytes = data[i+1:i+lenbytes+1]
assert data[i+lenbytes+1:]=='\000\000'
# code_bytes es el resultado de "marshalear" una lista
code_objects = marshal.loads(code_bytes)
assert isinstance(code_objects, list)
assert len(code_objects)>1
# el ultimo item de la lista, es el codigo de la aplicacion
codeobject = code_objects[-1]
# genero el .pyc - basado en py_compile.py
import py_compile
cfile = nombre+'.pyc'
fc = open(cfile, 'wb')
fc.write(py_compile.MAGIC)
py_compile.wr_long(fc, 0)
marshal.dump(codeobject, fc)
fc.flush()
fc.close()
py_compile.set_creator_type(cfile)
--- fin res2pyc.py ---
Ahora te queda descompilar el .pyc -> .py, pero esa es otra historia.
Suerte!
--
Gabriel Genellina
------------ próxima parte ------------
_______________________________________________
Python-es mailing list
Python-es en aditel.org
http://listas.aditel.org/listinfo/python-es
Más información sobre la lista de distribución Python-es