HackIt! 2014 _ Level 6

¿Level 6? ¿Y qué ha pasado con el level 5? El nivel 5 está cocinándose en el server de @marcan42 (prepararlo sobre un server con arquitectura Big Endian requiere su tiempo ;-). Así que vamos a por el level 6. No pudimos superarlo en la competición. Tras la Euskal, con ayuda de Timosoft, supimos por dónde tirar. El título del reto es «A null is a null» y reza así: ‘Hemos recibido una imagen forense de una tarjeta SD, pero no encontramos nada interesante…’. La imagen es un fichero llamado image:

$ file image
image: Linux rev 1.0 ext4 filesystem data (extents) (huge files)

Intentamos montarlo en modo lectura:

$ sudo losetup -r -o 0 /dev/loop0 image
$ sudo mount -o ro,noexec,noload /dev/loop0 /tmp/s
$ ls -al /tmp/s
-rw-r--r--  1 root root 179201 jul 24 18:55 data.bin
drwx------  2 root root  12288 jul 24 18:55 lost+found

El directorio lost+found está vacío. El fichero data.bin está compuesto de 0’s.

$ file /tmp/s/data.bin
/tmp/s/data.bin: data
 
$ strings /tmp/s/data.bin
$

Pues qué bien… aquí nos quedamos clavados. @acuartango le dedicó unas cuantas horas a salir del atolladero, pero no conseguimos ver la solución.

La cuestión es que el fichero image es un fichero disperso (sparse). Algunos bloques están ocupados – con 0’s – y otros no. Podemos verlo con este comando:

 
$ debugfs -R "stat data.bin" image
 
Inode: 12   Type: regular    Mode:  0644   Flags: 0x80000
Generation: 2845516278    Version: 0x00000001
User:     0   Group:     0   Size: 179201
File ACL: 0    Directory ACL: 0
Links: 1   Blockcount: 166
Fragment:  Address: 0    Number: 0    Size: 0
ctime: 0x53d13a76 -- Thu Jul 24 12:55:18 2014
atime: 0x53d13a76 -- Thu Jul 24 12:55:18 2014
mtime: 0x53d13a76 -- Thu Jul 24 12:55:18 2014
EXTENTS:
(ETB0):1594, (1-3):1082-1084, (6):1085, (10-11):1086-1087, (14-15):1088-1089, (18-19):2019-2020, (21):2022, (25-26):2026-2027, (29):2030, (34-35):1987-1988, (39):1992, (41):1994, (44-46):1997-1999, (49):2002, (53-55):2006-2008, (57):2010, (62):2015, (66-67):1923-1924, (70-71):1927-1928, (73-75):1930-1932, (77):1934, (81-83):1938-1940, (85-87):1942-1944, (90-91):1947-1948, (94-95):1951-1952, (98-99):1955-1956, (102-103):1959-1960, (105):1962, (108-110):1965-1967, (113-115):1970-1972, (117):1974, (121-122):1978-1979, (124):1981, (130-131):1795-1796, (134-135):1799-1800, (137):1802, (142):1807, (145-148):1810-1813, (151):1816, (153):1818, (155):1820, (157):1822, (161):1826, (165):1830, (167):1832, (169-171):1834-1836, (174-175):1839-1840

A null is a null… Si no hay bloque ocupado, tendremos un 0. Si está ocupado, tendremos un 1. Así,

0 --> 0
1-3 --> 111
4 --> 0
5 --> 0
6 --> 1

Si agrupamos esa ristra de bits (0’s y 1’s) de 8 en 8, y los interpretamos como caracteres ASCII, tendremos la solución 😉

Un script quick&dirty en Python que lo hace por nosotros:

import re
import sys
 
# recuerda ejecutar antes debugfs -R "stat data.bin" image > stats.txt
 
fname = './stats.txt'
 
with open(fname) as f:
    content = f.readlines()  
 
res = []
for line in content:
    if re.search('(', line):
       res.append(line)
 
cadena = ''
last = 0
for i in res[0].split(',')[1:] :
   m = re.search('(?P<num>(.*))', i)
   par = m.group('num')
   n = re.search('(d+)(-(d+))?', par)
   inicio = int(n.group(1))
   if len(n.groups()) < 2 or n.group(3) is None:
      fin = inicio
   else:
      fin = int(n.group(3))
   for j in range( inicio, fin+1):
      if last < fin:
        for k in range (last, inicio):
            cadena +='0'
      cadena +='1'
      last = fin+1
 
string_blocks = (cadena[i:i+8] for i in range(0, len(cadena), 8)) 
string = ''.join(chr(int(char, 2)) for char in string_blocks)
 
print string

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.