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