Apuntes de pwndbg

Share
Apuntes de pwndbg
audio-thumbnail
Disconnected Memory
0:00
/201.72

Comandos

Obtener información

info functions

Obtiene las functiones que se encuentran definidas en el binario.

info functions
  • Salida de ejemplo:
pwndbg> info functions
All defined functions:

Non-debugging symbols:
0x0000000000400528  _init
0x0000000000400550  puts@plt
0x0000000000400560  system@plt
0x0000000000400570  printf@plt
0x0000000000400580  memset@plt
0x0000000000400590  read@plt
0x00000000004005a0  setvbuf@plt
0x00000000004005b0  _start
0x00000000004005e0  _dl_relocate_static_pie
0x00000000004005f0  deregister_tm_clones
0x0000000000400620  register_tm_clones
0x0000000000400660  __do_global_dtors_aux
0x0000000000400690  frame_dummy
0x0000000000400697  main
0x00000000004006e8  pwnme
0x0000000000400756  ret2win
0x0000000000400780  __libc_csu_init
0x00000000004007f0  __libc_csu_fini
0x00000000004007f4  _fini

info registers

Obtiene la información de los registros en el estado actual de la apliación tras su ejecución.

info registers
  • Salida de ejemplo:
pwndbg> info registers
rax            0xb                 0xb
rbx            0x7fffffffdf68      0x7fffffffdf68
rcx            0x7ffff7ea5976      0x7ffff7ea5976
rdx            0x0                 0x0
rsi            0x7ffff7f87643      0x7ffff7f87643
rdi            0x7ffff7f887b0      0x7ffff7f887b0
rbp            0x7fffffffde50      0x7fffffffde50
rsp            0x7fffffffde50      0x7fffffffde50
r8             0x0                 0x0
r9             0x0                 0x0
r10            0x0                 0x0
r11            0x202               0x202
r12            0x0                 0x0
r13            0x7fffffffdf78      0x7fffffffdf78
r14            0x7ffff7ffd000      0x7ffff7ffd000
r15            0x0                 0x0
rip            0x4006d7            0x4006d7 <main+64>
eflags         0x206               [ PF IF ]
cs             0x33                0x33
ss             0x2b                0x2b
ds             0x0                 0x0
es             0x0                 0x0
fs             0x0                 0x0
gs             0x0                 0x0
fs_base        0x7ffff7d9e740      0x7ffff7d9e740
gs_base        0x0                 0x0
pwndbg> 

info breakpoints

Obtiene información sobre los breakpoints que se han establecido.

info breakpoints
  • Salida de ejemplo:
pwndbg> info breakpoints 
Num     Type           Disp Enb Address            What
1       breakpoint     keep y   0x00000000004006d2 <main+59>
	breakpoint already hit 1 time
2       breakpoint     keep y   0x00000000004006d7 <main+64>

Desensamblar

disas main

Desensambla la función main

disas main
  • Salida de ejemplo:
pwndbg> disas main
Dump of assembler code for function main:
   0x0000000000001139 <+0>:	push   %rbp
   0x000000000000113a <+1>:	mov    %rsp,%rbp
   0x000000000000113d <+4>:	sub    $0x210,%rsp
   0x0000000000001144 <+11>:	mov    %edi,-0x204(%rbp)
   0x000000000000114a <+17>:	mov    %rsi,-0x210(%rbp)
   0x0000000000001151 <+24>:	mov    -0x210(%rbp),%rax
   0x0000000000001158 <+31>:	add    $0x8,%rax
   0x000000000000115c <+35>:	mov    (%rax),%rdx
   0x000000000000115f <+38>:	lea    -0x200(%rbp),%rax
   0x0000000000001166 <+45>:	mov    %rdx,%rsi
   0x0000000000001169 <+48>:	mov    %rax,%rdi
   0x000000000000116c <+51>:	call   0x1030 <strcpy@plt>
   0x0000000000001171 <+56>:	mov    $0x0,%eax
   0x0000000000001176 <+61>:	leave
   0x0000000000001177 <+62>:	ret
End of assembler dump.

disas <inicio>, <fin>

Desensambla un rango de instrucciones (indicando las direcciones de memoria de inicio y fin).

disas 0x1144,0x115f
  • Salida de ejemplo:
pwndbg> disas 0x1144,0x115f
Dump of assembler code from 0x1144 to 0x115f:
   0x0000000000001144 <main+11>:	mov    %edi,-0x204(%rbp)
   0x000000000000114a <main+17>:	mov    %rsi,-0x210(%rbp)
   0x0000000000001151 <main+24>:	mov    -0x210(%rbp),%rax
   0x0000000000001158 <main+31>:	add    $0x8,%rax
   0x000000000000115c <main+35>:	mov    (%rax),%rdx
End of assembler dump.

También se puede hacer así:

disas main+13,main+36
  • Salida de ejemplo:
pwndbg> disas main+13,main+36
Dump of assembler code from 0x1186 to 0x119d:
   0x0000000000001186 <main+13>:	call   0x1070 <malloc@plt>
   0x000000000000118b <main+18>:	mov    %rax,-0x8(%rbp)
   0x000000000000118f <main+22>:	mov    -0x8(%rbp),%rax
   0x0000000000001193 <main+26>:	mov    %rax,%rsi
   0x0000000000001196 <main+29>:	lea    0xe6b(%rip),%rax        # 0x2008
End of assembler dump.
(gdb)

layout asm

Despliega una ventana que muestra el código ensamblador del binario:

layout asm

PD: Para cerrar la ventana se debe presionar Ctrl + x y a.

set disassembly-flavor intel

Cambia la sintaxis de la instrucciones en ensamblador:

set disassembly-flavor intel
  • Salida de ejemplo:
pwndbg> set disassembly-flavor intel
pwndbg> disas 0x1144,0x115f
Dump of assembler code from 0x1144 to 0x115f:
   0x0000000000001144 <main+11>:	mov    DWORD PTR [rbp-0x204],edi
   0x000000000000114a <main+17>:	mov    QWORD PTR [rbp-0x210],rsi
   0x0000000000001151 <main+24>:	mov    rax,QWORD PTR [rbp-0x210]
   0x0000000000001158 <main+31>:	add    rax,0x8
   0x000000000000115c <main+35>:	mov    rdx,QWORD PTR [rax]
End of assembler dump.
pwndbg>

Breakpoints

break

Pone un breakpoint en la dirección de memoria especificada.

break *0x0000000000001169
  • Salida de ejemplo:
pwndbg> break *0x0000000000001169
Breakpoint 1 at 0x1169: file vuln.c, line 6.

delete

Elimina todos los breakpoints.

delete
  • Salida de ejemplo:
pwndbg> delete
Delete all breakpoints, watchpoints, tracepoints, and catchpoints? (y or n) y

Ejecutar el binario

run

Ejecuta el binario que está siendo depurado dentro del depurador (pwndbg). Si se ha establecido un breakpoint, la ejecución de detendrá en la instrucción previa al breakpoint.

run
  • Salida de ejemplo:
pwndbg> run
Starting program: /home/usuario/daemon/labs/ropemporium/ret2win/ret2win 
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
...

run <<< commando

Puedes ejecutar el comando y, si espera una entrada, puedes usar <<< para indicar el el valor que se usará como entrada. Además, puedes ejecutar comandos dentro del depurador para darle al binario una entrada específica. Esto es demostrado en el siguiente post:

ret2win - ROPEmporium
Third District0:00/274.3771421× Antes de continuar Las prácticas que se realizan en este Captura la bandera (CTF) se trata meramente de prácticas formativas que no deberían nunca ser aplicadas a la vida real con fines maliciosos. Han sido avisados. * Sistema operativo: Debian 13 * Herramientas: pwntools, pwndbg, radare2 Un
run <<< $(command)
  • Salida de ejemplo:
pwndbg> run <<< $(whoami)
Starting program: /home/usuario/daemon/labs/ropemporium/ret2win/ret2win <<< $(whoami)
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
ret2win by ROP Emporium
x86_64

For my first trick, I will attempt to fit 56 bytes of user input into 32 bytes of stack buffer!
What could possibly go wrong?
You there, may I have your input please? And don't worry about null bytes, we're using read()!

> Thank you!

Exiting
[Inferior 1 (process 656030) exited normally]

step

Hace avanzar el programa a la siguiente instrucción de memoria.

step
  • Salida de ejemplo:
pwndbg> run
Starting program: /home/usuario/daemon/labs/ropemporium/callme/callme <<< $(python3 -c 'from pwn import *; print(cyclic(100).decode())')
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
callme by ROP Emporium
x86_64
Breakpoint 1, 0x0000000000400882 in main ()
pwndbg> step
Hope you read the instructions...

> 

Detectar offsets

cyclic

Con cyclic es posible crear una cadena de texto que usa la secuencia Bruijn para realizar ROP o buffer overflows.

cyclic
  • Salida de ejemplo:
pwndbg> cyclic 100
aaaabaaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaamaaanaaaoaaapaaaqaaaraaasaaataaauaaavaaawaaaxaaayaaa
pwndbg> 

También puede usarse como entrada en el binario para realizar stack/buffer overflow.

$(python3 -c 'from pwn import *; print(cyclic(100).decode())')
  • Salida de ejemplo:
pwndbg> run <<< $(python3 -c 'from pwn import *; print(cyclic(100).decode())')
Starting program: /home/usuario/daemon/labs/ropemporium/ret2win/ret2win <<< $(python3 -c 'from pwn import *; print(cyclic(100).decode())')
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
ret2win by ROP Emporium
x86_64

For my first trick, I will attempt to fit 56 bytes of user input into 32 bytes of stack buffer!
What could possibly go wrong?
You there, may I have your input please? And don't worry about null bytes, we're using read()!

> Thank you!

Program received signal SIGSEGV, Segmentation fault.
0x0000000000400755 in pwnme ()
LEGEND: STACK | HEAP | CODE | DATA | WX | RODATA
─────────────────────────────────────────────────────────────────────────────[ LAST SIGNAL ]──────────────────────────────────────────────────────────────────────────────
Program received signal SIGSEGV (fault address: 0x0).

cyclic_find / cyclic -l

Puede ser usado para encontrar el offset después de recibir un SIGSEGV (crasheo) del programa usando el valor hexadecimal que ha quedado en el RIP tras el crasheo.

cyclic -l <hex_value_inside_rip>
  • Salida de ejemplo:
pwndbg> cyclic -l 0x6161616c6161616b
Finding cyclic pattern of 4 bytes: b'kaaa' (hex: 0x6b616161)
Found at offset 40
pwndbg> 

Examinar la memoria

x/o

Muestra la memoria dentro de una dirección/registro en formato octal.

x/o <memory_address/register>
  • Salida de ejemplo:
pwndbg> x/o 0x0000555555555141
0x555555555141 <main+8>:	077042707

x/x

Muestra la memoria dentro de una dirección/registro en formato hexadecimal.

x/x <memory_address/register>
  • Salida de ejemplo:
pwndbg> x/x $rip
0x555555555141 <main+8>:	0x00fc45c7

x/u

Muestra la memoria dentro de una dirección/registro en formato unsigned estándar de base 10.

x/u <memory_address/register>
  • Salida de ejemplo:
pwndbg> x/u $rip
0x555555555141 <main+8>:	16532935

x/t

Muestra la memoria dentro de una dirección/registro en formato binario

x/t <memory_address/register>
  • Salida de ejemplo:
pwndbg> x/t $rip
0x555555555141 <main+8>:	00000000111111000100010111000111

x/b

Muestra la memoria dentro de una dirección/registro en formato single byte.

x/b <memory_address/register>
  • Salida de ejemplo:
pwndbg> x/b $rip
0x555555555141 <main+8>:	0xc7

x/h

Muestra la memoria dentro de una dirección/registro en formato halfword (dos bytes)

x/h <memory_address/register>
  • Salida de ejemplo:
pwndbg> x/h $rip
0x555555555141 <main+8>:	0x45c7

x/w

Muestra la memoria dentro de una dirección/registro en formato word (cuatro bytes)

x/w <memory_address/register>
  • Salida de ejemplo:
pwndbg> x/w $rip
0x555555555141 <main+8>:	0x00fc45c7

x/g

Muestra la memoria dentro de una dirección/registro en formato giant (ocho bytes)

x/g <memory_address/register>
  • Salida de ejemplo:
pwndbg> x/w $rip
0x555555555141 <main+8>:	0xeb00000000fc45c7

Información adicional

No solo es posible examinar lo que contiene una dirección, sino también las direcciones que la acompañan. Por ejemplo, es posible examinar el rango de direcciones desde 0x0000555555555141 hasta el 0x0000555555555160 de direcciones (32 bytes en memoria) usando el siguiente comando:

x/32<o/h/u/t/b/h/w/g> <memory address>
  • Salida de ejemplo:
pwndbg> x/32b $rip
0x555555555141 <main+8>:	0307	0105	0374	0	0	0	0	0353
0x555555555149 <main+16>:	023	0110	0215	05	0263	016	0	0
0x555555555151 <main+24>:	0110	0211	0307	0350	0327	0376	0377	0377
0x555555555159 <main+32>:	0203	0105	0374	01	0203	0175	0374	011

También es posible mezclar los formatos. Por ejemplo, para mostrar 32 bytes formateados en hexadecimal, haría esto:

x/32xb <address/register>
  • Salida de ejemplo:
pwndbg> x/32xb $rip
0x555555555141 <main+8>:	0xc7	0x45	0xfc	0x00	0x00	0x00	0x00	0xeb
0x555555555149 <main+16>:	0x13	0x48	0x8d	0x05	0xb3	0x0e	0x00	0x00
0x555555555151 <main+24>:	0x48	0x89	0xc7	0xe8	0xd7	0xfe	0xff	0xff
0x555555555159 <main+32>:	0x83	0x45	0xfc	0x01	0x83	0x7d	0xfc	0x09

Read more