Parte 2

Enumerar pew con nm

1
nm -D pew

Under the hood of LD_PRELOAD using gdb:

q - quit gdb

r - run the program

b - set a breakpoint

s - step over an instruction

si - step into an instruction

info func - show available functions

info break - show available breakpoints

del - delete a breakpoint

Start debugging pew with gdb

1
gdb -q ./pew

Desensamblar main, en búsqueda de llamadas:

1
gef> disassemble main

plt (Dynamic linker) {Función trampolín hacia el printf(), real}:

0x00000000000011f5 <+72>: call 0x1040 <printf@**plt**>

Ahora correremos pew en gdb, y pondremos un breakpoint en main:

1
2
3
gef> b *main
gef> info breakpoints
gef> r

Como se puede observar existen distintas partes como:

stack: donde almacenamos en memoria.

code: en código máquina.

trace: nos dice la ruta dinámica que sigue la función.

Por ahora nos centraremos en code y stack:

Partiendo de lo anterior!

Usaremos si, que nos permite saltar a la siguiente intrucción:

1
gef> si

Lanzaremos varias veces si hasta después de llamar a la función put@plt:

Ahora saltaremos al contenido de la función con con s:

1
gef> s

El dynamic linker resuelve la localicación real de puts en libc:

Estas localizaciones se guardan en la global offset table

La siguiente llamada a puts será jmp hacia la localización en got y no invocará al linker.

Usando got como referencia, podemos preguntar al gdb que nos diga donde se encuentra el símbolo localizado.

1
2
3
4
5
gef> info symbol 0x7fe4f478c5f0
puts in section .text of /lib/x86_64-linux-gnu/libc.so.6

gef> info symbol 0x55728b63d046
printf@plt + 6 in section .plt of /root/code/pew

Fijémonos de manera más cercana en printf:

Disassemble the main function with

1
gef> disas main

Buscar la dirección donde se da la primera llamada a printf@plt

Fijar un breakpoint en la dirección donde ocurre con *addr

  1. Aprendiendo un poco más sobre el dynamic linker, debería ayudarnos a entender como LD_PRELOAD funciona.

  2. Debugeamos pew con LD_PRELOAD:

1
2
3
4
5
6
7
8
9
10
11
gdb -q ./pew

b *main

set environment LD_PRELOAD ./fake_sleep.so

show environment

r

vmmap ó info proc mappings #Ver si fake_sleep.so se ha cargado
1
2
3
4
disas main
b *<direcciónSleep>
c #Continuamos la ejecución
got
1
2
gef> info symbol <direcciónDelSleepConGot>
sleep in section .text of ./fake_sleep.so

break la instrucción que llama al registro RDX:

Continuar la ejecución hasta que el breakpoint es golpeado.

Inspeccionar la dirección dentro de RDX

1
2
3
4
disas sleep
b *<direcciónDelRegistroRDX>
info br
c
1
2
gef>  info symbol $rdx
sleep in section .text of /lib/x86_64-linux-gnu/libc.so.6