Skip to content

Latest commit

 

History

History
165 lines (119 loc) · 5.91 KB

Ropfan.md

File metadata and controls

165 lines (119 loc) · 5.91 KB

Ropfan

Challenge

If you can run this binary, you will have the flag.

Attachment: Ropfan

Category: Reversing

Como siempre...

$ file Ropfan
Ropfan: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked,
interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 2.6.24,
BuildID[sha1]=9b343d01e7dfb6abc4070b0ed39270996502ff59, stripped

Decompilar Ropfan; leyendo el código, parece utilizar dlsym() y pinta que falla pues utiliza llamadas a funcion mediante hardcoded offsets desde el inicio de la libc.

La primera llamada a funcion deberia ser puts o fputs.

La segunda llamada a funcion deberia ser putc, fputc o putchar.

Lo interesante es que hay que encontrar qué versión de libc se utilizó para compilar (en realidad, hay que encontrar específicamente el archivo de esa misma librería) y hacer que el ejecutable utilice esa biblioteca.

Veamos que podemos obtener

$ strings -a Ropfan
/lib64/ld-linux-x86-64.so.2
libdl.so.2
__gmon_start__
_Jv_RegisterClasses
dlsym
libc.so.6
__stack_chk_fail
__libc_start_main
GLIBC_2.2.5
GLIBC_2.4
fff.
l$ L
t$(L
|$0H
__libc_start_main
Take your flag
;*3$"
GCC: (suxsuxsuxsuxsuxsuxsuxsuxsuxs) 0.0.0
.shstrtab
.interp
 ...

Por los strings, parece que fue compilado con alguna versión vieja de GCC. No es posible saber cual pues la versión que se indica en el binario está pisada por suxsuxsux...

GCC: (suxsuxsuxsuxsuxsuxsuxsuxsuxs) 0.0.0

Malditos!

Del binario se pueden obtener estos datos:

offset      funcion
0x00000     __libc_start_main
0x4e470     puts o fputs o printf o fprintf
0x4f080     putchar, putc o fputc

Para obtener el offset de alguna funcion en libc se puede utilizar

readelf -s libc.so.6 | grep funcion

Por ejemplo, los offsets en la versión de Debian Buster (libc6 2.28-10) son

$ strings -a  /usr/lib/x86_64-linux-gnu/libc.so.6 | grep 2.28
GNU C Library (Debian GLIBC 2.28-10) stable release version 2.28.

$ readelf -s /usr/lib/x86_64-linux-gnu/libc.so.6 | grep putc
   51: 0000000000073360    50 FUNC    GLOBAL DEFAULT   13 putchar_unlocked@@GLIBC_2.2.5
   96: 000000000007a170    42 FUNC    WEAK   DEFAULT   13 putc_unlocked@@GLIBC_2.2.5
  161: 0000000000078160   299 FUNC    GLOBAL DEFAULT   13 _IO_putc@@GLIBC_2.2.5
  363: 000000000007a080    42 FUNC    GLOBAL DEFAULT   13 fputc_unlocked@@GLIBC_2.2.5
  386: 0000000000078160   299 FUNC    WEAK   DEFAULT   13 putc@@GLIBC_2.2.5  <--
  496: 0000000000073260   241 FUNC    GLOBAL DEFAULT   13 putchar@@GLIBC_2.2.5
 1114: 00000000000778b0   299 FUNC    GLOBAL DEFAULT   13 fputc@@GLIBC_2.2.5

$ readelf -s /usr/lib/x86_64-linux-gnu/libc.so.6 | grep puts
   194: 0000000000071910   413 FUNC    GLOBAL DEFAULT   13 _IO_puts@@GLIBC_2.2.5
   426: 0000000000071910   413 FUNC    WEAK   DEFAULT   13 puts@@GLIBC_2.2.5  <--
   501: 00000000000fdfb0  1240 FUNC    GLOBAL DEFAULT   13 putspent@@GLIBC_2.2.5
   685: 00000000000ffa90   680 FUNC    GLOBAL DEFAULT   13 putsgent@@GLIBC_2.10
  1153: 0000000000070490   338 FUNC    WEAK   DEFAULT   13 fputs@@GLIBC_2.2.5
  1694: 0000000000070490   338 FUNC    GLOBAL DEFAULT   13 _IO_fputs@@GLIBC_2.2.5
  2332: 000000000007a460   151 FUNC    WEAK   DEFAULT   13 fputs_unlocked@@GLIBC_2.2.5

Para buscar la libc correspondiente, se puede utilizar el buscador https://libc.blukat.me/, pero en esta oportunidad se optó por otra estrategia.

Se descargó libc-database para obtener una base de varias glibc de ubuntu.

git clone https://github.com/niklasb/libc-database

Ejecutando ./get se obtienen las bibliotecas de los ubuntus (exceptuando los mas modernos) y es posible su tabla de símbolos y offsets. Esto popula el directorio libc-database/db/ con archivos .so, .symbols y .url

Sabiendo que los offsets relativos a __libc_start_main del binario Ropfan son

0x00000     __libc_start_main
0x4e470     puts o fputs o printf o fprintf
0x4f080     putchar, putc o fputc

codifiqué un script en python relative.py que para cada archivo en db/*.symbols obtiene los offsets de cada función y luego calcula el offset relativo a __libc_start_main en la que se encuentra cada función de la tabla de símbolos.

A medida que los va calculando, si encuentra alguno que coincide con 0x4e470 o 0x4f080 imprime el nombre de la función allí ubicada.

Al ejecutar ./relative.py, se encontró que en el archivo libc6_2.15-0ubuntu10.18_amd64.symbols, en los offsets 0x4e470 y 0x4f080 se encuentran las siguientes funciones, que son bastante apropiadas para lo que realizan en el binario.

Se obtuvo el .deb que contiene la libreria libc6 para esa versión desde

https://launchpad.net/ubuntu/precise/amd64/libc6/2.15-0ubuntu10.18

o bien

http://us.archive.ubuntu.com/ubuntu/pool/main/e/eglibc/

En particular nos interesa éste:

http://us.archive.ubuntu.com/ubuntu/pool/main/e/eglibc/libc-bin_2.15-0ubuntu10.18_amd64.deb

Se creó un chroot específico con la biblioteca vieja, el binario y un busybox estático para actuar como shell (también se puso un gdb estático por las dudas). Esto está documentado en test-libc6.sh

Ahora ingresamos al chroot y ejecutamos el binario

# /usr/sbin/chroot ./mnt /bin/busybox ash
$ ./bin/Ropfan
EKO{LIBC/0lder\th4n^you}

Hubiera sido más fácil instalar Ubuntu Precise Pangolin de 64 bits, que es la versión de Ubuntu que utiliza esta versión de la librería libc6, pero bueh.

Nota: el gdb estático lo conseguí en https://github.com/hugsy/gdb-static y el busybox estático se instala en el sistema operativo real mediante apt install busybox-static

Flag

EKO{LIBC/0lder\th4n^you}

-- maurom