
Uma informação interativa de memória para pwning / exploiting
Como amantes de pwn, enquanto jogamos CTF com exploração de heap, sempre precisamos de um depurador (ex: gdb) para rastrear o layout da memória. Mas não precisamos realmente do gdb se quisermos ver se o layout do heap corresponde à nossa imaginação ou não. Espero que esta pequena ferramenta nos ajude a explorar mais facilmente ;).
HeapInfo é muito útil quando o binário possui limitações anti-depuração, por exemplo, estar com ptrace. HeapInfo ainda funciona porque não utiliza ptrace.
Implementado em Ruby porque amo Ruby :P. Mas posso implementar em Python (se ninguém mais fizer) no futuro.
Se você prefere pwntools para exploração, ainda pode usar o HeapInfo no irb/pry como um pequeno depurador.
Qualquer sugestão de funcionalidades ou relato de bugs é bem-vinda.
HeapInfo ainda está em desenvolvimento para mais funcionalidades, então a versão pode mudar frequentemente :p
$ gem install heapinfo
victim está sendo rastreado! Ou seja, você pode usar ltrace/strace/gdb e HeapInfo simultaneamente!dump - Despejar memória de um endereço arbitrário.layouts - Mostrar os layouts atuais dos bins, muito útil para exploração de heap.offset - Mostrar o offset entre um endereço dado e um segmento. Muito útil para calcular offset relativo.canary - Obter o valor do stack guard!x - Comandos no estilo GDB.s - Comandos no estilo GDB.find - Comandos no estilo GDB.require 'heapinfo'
# ./victim is running
h = heapinfo('victim')
# or use h = heapinfo(20568) to specify a pid
# will present simple info when loading:
# Program: /home/heapinfo/victim PID: 20568
# victim base @ 0x400000
# [heap] base @ 0x11cc000
# [stack] base @ 0x7fff2b244000
# libc-2.19.so base @ 0x7f892a63a000
# ld-2.19.so base @ 0x7f892bee6000
# canary value: 0x84b742f03d94c100
# query segments' info
"%#x" % h.libc.base
#=> "0x7f892a63a000"
h.libc.name
#=> "/lib/x86_64-linux-gnu/libc-2.19.so"
"%#x" % h.elf.base
#=> "0x400000"
"%#x" % h.heap.base
#=> "0x11cc000"
AVISO: Quando o processo não é encontrado, a maioria dos métodos retorna nil. Uma maneira de evitar que algum erro ocorra é usar métodos dentro de debug; o bloco será ignorado durante exploração remota.
h = heapinfo('remote')
# Process not found
h.pid # nil
# wrapper with `debug` so that no error will be raised when pwning remote service
h.debug { fail unless leak_libc_base == h.libc.base }
Consultar conteúdo de um endereço específico.
AVISO: Você DEVE ter permissão para anexar a um programa, caso contrário o dump falhará.
Por exemplo, /proc/sys/kernel/yama/ptrace_scope definido como 0 ou executar como root.
h.debug do
p h.dump(:libc, 8)
#=> "\x7FELF\x02\x01\x01\x00"
p h.dump(:heap, 16)
#=> "\x00\x00\x00\x00\x00\x00\x00\x00\x31\x00\x00\x00\x00\x00\x00\x00"
p h.dump('heap+0x30', 16) # support offset!
#=> "\x00\x00\x00\x00\x00\x00\x00\x00\x81\x00\x00\x00\x00\x00\x00\x00"
p h.dump('heap+0x30 * 3 + 0x8', 16) # and even complex formula!
#=> "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
p h.dump(:program, 8)
#=> "\x7FELF\x02\x01\x01\x00"
p h.dump(0x400000, 8) # or simply give address
#=> "\x7FELF\x02\x01\x01\x00"
end
# invalid example:
# h.dump('meow') # no such segment
h.layouts :fast

h.layouts :unsorted, :small

h.layouts :tcache

h.offset(0x7fda86fe8670)
# 0xf6670 após libc
h.offset(0x1839cd0, :heap) # specific segment name
# 0x20cd0 após heap
h.offset(0x1839cd0)
# 0x20cd0 após heap

h.canary.to_s(16)
#=> '84b742f03d94c100'
h.x 8, :heap

Fornece um buscador de memória, mais fácil de usar do que no (ingênuo) gdb. Suporta busca por inteiro, string e até expressão regular.
h.find(0xdeadbeef, 'heap+0x10', 0x1000)
#=> 6299664 # 0x602010
h.find(/E.F/, 0x400000, 4)
#=> 4194305 # 0x400001
h.find(/E.F/, 0x400000, 3)
#=> nil
# Get relative offset of searching result
h.find('/bin/sh', :libc, rel: true)
#=> 1622391 # 0x18c177
h.offset(h.find('/bin/sh', :libc))
# 0x18c177 after libc
HeapInfo atualmente só executa testes no Ubuntu, as seguintes versões da glibc foram testadas: