
Интерактивная информация о памяти для взлома / эксплуатации
Как любители pwn, во время решения CTF-задач с эксплуатацией кучи, мы всегда нуждаемся в отладчике (например, gdb) для отслеживания расположения памяти. Но gdb не всегда нужен, если мы хотим проверить, совпадает ли структура кучи с нашими ожиданиями. Надеюсь, этот небольшой инструмент облегчит эксплуатацию ;).
HeapInfo очень полезен, когда бинарник имеет какие-либо анти-отладчик ограничения, например, когда процесс уже под ptrace. HeapInfo всё равно работает, так как не использует ptrace.
Реализован на Ruby, потому что я люблю Ruby :P. В будущем, возможно, появится реализация на Python (если никто другой этого не сделает).
Если вы предпочитаете pwntools для эксплуатации, вы всё равно можете использовать HeapInfo в irb/pry как небольшой отладчик.
Любые предложения по функционалу или сообщения об ошибках приветствуются.
HeapInfo всё ещё находится в разработке, так что версия может часто меняться :p
$ gem install heapinfo
жертва под трассировкой! То есть, можно одновременно использовать ltrace/strace/gdb и HeapInfo!dump - Дамп памяти по произвольному адресу.layouts - Показать текущие раскладки корзин (bins), очень полезно для эксплуатации кучи.offset - Показать смещение между заданным адресом и сегментом. Очень полезно для вычисления относительных смещений.canary - Получить значение стекового канарейки!x - Команды в стиле GDB.s - Команды в стиле GDB.find - Команды в стиле GDB.require 'heapinfo'
# ./victim запущен
h = heapinfo('victim')
# или используйте h = heapinfo(20568) для указания PID
# при загрузке будет показана простая информация:
# 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
# запрос информации о сегментах
"%#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"
ВНИМАНИЕ: Когда процесс не найден, большинство методов возвращают nil. Чтобы избежать ошибок, можно обернуть методы в блок debug, который будет игнорироваться при удаленной эксплуатации.
h = heapinfo('remote')
# Процесс не найден
h.pid # nil
# обертка с `debug`, чтобы не было ошибок при взломе удаленного сервиса
h.debug { fail unless leak_libc_base == h.libc.base }
Получить содержимое по определенному адресу.
ВНИМАНИЕ: Вы должны иметь разрешение на присоединение к программе, иначе дамп не сработает.
Например, /proc/sys/kernel/yama/ptrace_scope должно быть 0 или запуск от 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) # поддерживает смещения!
#=> "\x00\x00\x00\x00\x00\x00\x00\x00\x81\x00\x00\x00\x00\x00\x00\x00"
p h.dump('heap+0x30 * 3 + 0x8', 16) # и даже сложные выражения!
#=> "\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) # или просто указать адрес
#=> "\x7FELF\x02\x01\x01\x00"
end
# некорректный пример:
# h.dump('meow') # нет такого сегмента
h.layouts :fast

h.layouts :unsorted, :small

h.layouts :tcache

h.offset(0x7fda86fe8670)
# 0xf6670 после libc
h.offset(0x1839cd0, :heap) # указание имени сегмента
# 0x20cd0 после heap
h.offset(0x1839cd0)
# 0x20cd0 после heap

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

Предоставляет поиск по памяти, проще в использовании, чем в (примитивном) gdb.
Поддерживает поиск целых чисел, строк и даже регулярных выражений.
h.find(0xdeadbeef, 'heap+0x10', 0x1000)
#=> 6299664 # 0x602010
h.find(/E.F/, 0x400000, 4)
#=> 4194305 # 0x400001
h.find(/E.F/, 0x400000, 3)
#=> nil
# Получить относительное смещение результата поиска
h.find('/bin/sh', :libc, rel: true)
#=> 1622391 # 0x18c177
h.offset(h.find('/bin/sh', :libc))
# 0x18c177 после libc
HeapInfo в настоящее время запускает тесты только на Ubuntu, протестированы следующие версии glibc: