Home > Python > Mitos en Python sobre ofuscación y reversing

Es habitual que se entregue el código fuente de los programas en Python, aunque en algunos casos se aplican diversas técnicas como ofuscación y compilación para proteger el código de los ojos curiosos. Pero ¿realmente funcionan estas técnicas?

En este artículo veremos algunas herramientas que supuestamente nos ayudan a proteger nuestro código y lo fácil que es subvertirlas.

A continuación tenemos dos programas de ejemplo escritos en Python: el primero es una simple función que nos pide una contraseña y nos muestra un mensaje; el segundo ejemplo es igual, aunque en esta ocasión hemos utilizado una clase.

def main():

        a = "toomanysecrets"

        res = raw_input("Please enter your password: ")
        
        if res == a:
                print "ACCESS GRANTED"
        else:
                print "ACCESS DENIED"

if __name__ == "__main__":
	main()

secretapp1.py

class DoMain:

        def __init__(self):
                self.a = "toomanysecrets"

        def Ask(self):
                res = raw_input("Please enter your password: ")

                if res == self.a:
                        print "ACCESS GRANTED"
                else:
                        print "ACCESS DENIED"

if __name__ == "__main__":
	dm = DoMain()
	dm.Ask()

secretapp2.py

Supongamos que no quiero entregar el código de estos programas, por lo que tengo varias opciones. Nuestra primera opción será ofuscar el código, dificultando su lectura.

Pyobfuscate

Este programa nos permite ofuscar nuestro programa de forma totalmente válida para el intérprete Python. Veamos un ejemplo con SecretApp1 y SecretApp2.

simonroses_python_cap1
Fig. 1 – Secretapp1 ofuscado

simonroses_python_cap2
Fig. 2 – Secretapp2 ofuscado

A simple vista nuestro código no tiene sentido, pero si analizamos el resultado veremos cómo las cadenas de texto siguen en el código y podemos reconocer sintaxis de Python. No es demasiado difícil reconstruir el código ofuscado.

Htibctobf

Originalmente esta herramienta se escribió para resolver un reto en una competición de hacking en el congreso Hack in the Box.

A diferencia de la anterior herramienta, Htibctobf ofusca el código Python modificando los AST (Abstract Syntax Trees). Al ejecutar esta herramienta podemos ver nuestro código Python ofuscado en la Fig. 3 y Fig. 4.

simonroses_python_cap3
Fig. 3 – Secretapp1 ofuscado

simonroses_python_cap4
Fig. 4 – Secretapp2 ofuscado

Podemos observar el código ofuscado, incluso las cadenas de texto, sin embargo a pesar de todo no es demasiado difícil reconstruir el código original.

Sin duda un interesante concepto con amplias posibilidades pero que requiere de mejoras para ser útil.

En algunos casos quizás baste con ofuscar el código, pero busquemos otras opciones para proteger nuestro código de forma más efectiva: tendremos que recurrir a compilar el código Python creando un ejecutable.

Py2exe

Posiblemente una de las opciones más populares para convertir código Python en ejecutables Windows. Py2exe

En primer lugar tenemos que crear un fichero llamado setup.py que incluya una referencia a nuestro programa que queremos compilar. Ver código setup.

from distutils.core import setup
import py2exe

setup(console=['secretapp1.py'])

setup.py

Ya estamos listos para compilar nuestro código Python en un ejecutable Windows, para ello ejecutamos py2exe. Ver Fig. 5.

simonroses_python_cap5
Fig. 5 – Compilando secretapp1.exe

Una vez finalizado el proceso de compilación, py2exe nos creará un directorio llamado “dist” que incluye nuestro ejecutable y algunas librerías necesarias. En la Fig. 6 podemos ver que py2exe finaliza con éxito y ejecutamos nuestro programa en formato exe.

simonroses_python_cap6
Fig. 6 – Compilación completada

Ahora podríamos distribuir este binario sin miedo a entregar nuestro código o quizás no ¿?

Py2exe_extract

Esta herramienta nos permite extraer los objetos Python dentro de los ejecutables creados con py2exe, básicamente invertimos el proceso.Py2exe_extract

En la Fig. 7 podemos ver como utilizamos py2exe_extract para obtener el fichero objeto (el contenido de este fichero es independiente de la plataforma y se conoce como Bytecode) de nuestra aplicación secretapp1.exe (secretapp1.pyc)

simonroses_python_cap7
Fig. 7 – Extrayendo el fichero objeto

Ahora tenemos que ver cómo podemos obtener el código de este fichero objeto.

Unwind

Unwind es un desensamblador para Python Bytecode que podemos utilizar para analizar ficheros objetos “.pyc”. Para este ejemplo he escrito un simple script en Python, mytest.py, que importa el desensamblador y analiza el fichero pyc. Ver código a continuación.


import unwind

print(unwind.disassemble('secretapp1.pyc'))

mytest.py

Con este script podemos ejecutar el siguiente comando y obtener un desensamblado del fichero objeto. Ver Fig. 8.

simonroses_python_cap8
Fig. 8 – Python Bytecode

Uncompyle2

Otra opción es utilizar un decompilador como uncompyle2 para obtener el código directamente del fichero objeto “.pyc” sin tener que pasar por el desensamblador como vimos anteriormente.

Esta herramienta es potente y fácil de utilizar, como se puede observar en la Fig. 9 mediante un simple comando obtenemos el código fuente de secretapp1.pyc.

simonroses_python_cap9
Fig. 9 – Código de secretapp1 obtenido del fichero objeto

Wow, tenemos código fuente!

A lo largo del artículo hemos visto algunas técnicas de ofuscación y compilación de código Python para protegerlo, no obstante hemos podido subvertir todo el proceso de protección fácilmente 

La siguiente lista son otros compiladores Python que podemos utilizar para Windows, Linux o MacOS, pero tienen los mismos problemas.

También podríamos analizar y subvertir el binario utilizando herramientas como IDA PRO o Immunity Debugger, lo que dejaremos para un futuro post. Otra interesante herramienta que no he comentado es pyREtic, un potente framework para reversing de in-memory de Python Bytecode.

Que un atacante consiga el código Python es cuestión de tiempo, sin embargo para ponérselo realmente difícil desde un punto de vista defensivo se
tienen que combinar diferentes técnicas.

Fuente simonroses