En la entrada anterior habíamos encontrado un .zip altamente jugoso, así que vamos a empezar a apalearlo para que cante todas las flags de este nivel…
1. ¿Qué lenguaje ha sido empleado para crear el ejecutable del proyecto secreto?
Esta la vamos a responder con la información de la última pregunta de la parte anterior. Dentro de ese estupendo .zip podemos encontrar un ejecutable cuyo icono es bastante delator:
* Respuesta: Python
!Extra Bonus! Cuando respondemos esta pregunta se abren 5 preguntas más. Esto parece que va para largo…
2. ¿Qué versión de Python usa el binario compilado (formato N.N)?
El duro trabajo de la respuesta 3 nos da una justa recompensa (Python 3 lo tiene claro para eliminar a Python 2.7, que parece tener cuerda para rato):
* Respuesta: 2.7
3. ¿Qué herramienta ha sido empleada para crear el ejecutable?
Nos dan una serie de opciones a elegir. Viendo otras preguntas que hay más adelante, parece que vamos a tener que decompilar el código, así que vamos a ello.
Py2exe es la opción más común para generar ejecutables Windows basados en código Python, y puede ser decompilado con una herramienta como unpy2exe. Sin embargo, no parece que nuestro ejecutable haya sido generado con py2exe:
La segunda opción es PyInstaller, que podemos decompilar con el script pyinstxtractor.py del toolset de Python-exe-unpacker :
… y como funciona, nos da nuestra merecida respuesta (y de paso, la del apartado anterior).
* Respuesta: PyInstaller
4. ¿Qué arquitectura de procesador tiene el binario compilado?
Un poco de pestudio nos da la respuesta en un periquete:
* Respuesta: amd64
5. ¿A qué número hace rellamada el AT-5000?
pyinstxtractor.py nos ha extraído los diversos componentes del ejecutable. Sin embargo, parece que no ha sabido interpretar correctamente el fichero at-500, que parece nuestro código principal.
Si revisamos la documentación de pyinstxtractor.py, parece que en algunos casos no interpreta correctamente el método principal, algo que podemos corregir con el script python_exe_unpack.py (también de Python-exe-unpacker):
# python python_exe_unpack.py.py -p at-5000
Que nos da un precioso fichero en Python:
# uncompyle6 version 2.11.5 # Python bytecode 2.7 (62211) # Decompiled from: Python 2.7.15rc1 (default, Apr 15 2018, 21:51:34) # [GCC 7.3.0] # Embedded file name: at-5000.py import time import random NED_FLANDERS = [ 5, 5, 5, 8, 9, 0, 4] class At5000Error(Exception): def __init__(self, message): super(At5000Error, self).__init__(message) class PhoneState(object): def __init__(self): self.phone_digits = [ 5, 5, 5, 0, 0, 0, 0] def increment(self): if self.phone_digits == NED_FLANDERS: return increment_number(self.phone_digits, 6) def __str__(self): return '{}{}{}-{}{}{}{}'.format(*self.phone_digits) def increment_number(phone_number, index): if index < 0: raise At5000Error('AT-5000 Auto-dialer errorerororororor') phone_number[index] += 1 if phone_number[index] == 10: phone_number[index] = 0 increment_number(phone_number, index - 1) def main(): phone_state = PhoneState() for i in range(10000000): phone_state.increment() if phone_state.phone_digits == NED_FLANDERS: print 'Redialing: {}'.format(phone_state) else: print 'Calling: {}'.format(phone_state) time.sleep(0.01) if __name__ == '__main__': main()
Si lo miramos un poco por encima, cuando el número de teléfono a marcar coincide con la variable NED_FLANDERS, se produce una rellamada (el theme simpsoniano está aplicándose a rajatabla al parecer).
* Respuesta: 5558904
6. ¿De quién es el número al que se hacen las rellamadas?
Pregunta de combo ya que la teníamos resuelta en la anterior con solo ver la variable que se llama … ;-)
* Respuesta: Ned Flanders
7. ¿Cuánto tiempo espera (en segundos) el AT-5000 para marcar números?
Si repasamos el código encontramos un sleep más que revelador:
time.sleep(0.01)
* Respuesta: 0.01
8. ¿Qué dos librerías importa el AT-5000?
Si miramos el comienzo del código veremos los imports:
import time
import random
* Respuesta: time random
9. ¿Cuál es el máximo número de llamadas que puede hacer el AT-5000?
Inspeccionando el código tenemos el bucle for con nuestra respuesta:
def main(): phone_state = PhoneState() for i in range(10000000):
* Respuesta: 10000000