Тот факт, что функция _dl_map_object_deps()
вызывается из стартового кода, дает в наши руки универсальный способ распаковки elf-файлов, упакованных практически любым упаковщиком. Если только упаковщик не сопротивляется отладчику, достаточно всего лишь установить точку останова на _dl_map_object_deps()
и... дождаться когда она сработает. Тут же в стеке по адресу [ESP+08h] будет адрес возврата из CALL __libc_start_main, а по адресу [ESP+0Ch] указатель непосредственно на саму main. Если, конечно, нам повезет… Проблемы начинаются с того, что gdb с большой неохотой устанавливает точки останова на shared-функции и потому точка останова обязательно должна быть аппаратной, причем срабатывать она может несколько раз. Левые срабатывая распознаются легко. Если по [ESP+08h] и [ESP+0Ch] лежит совсем не то, что ожидалось (а это легко определить по диапазону адресов), пропускаем текущее срабатывание точки останова и продолжаем выполнение программы командой 'c'.
Примерный сеанс работы с отладчиком может выглядеть так:
root@5[elf_crypt]# gdb elfcrypt-demo ; загружаем программу в отладчик
(gdb) hbreak *0x4000BBD0 ; ставим
бряк на _dl_map_object_deps
Hardware assisted breakpoint 1 at 0x4000bbd0
(gdb) r ; запускаем программу
Breakpoint 1, 0x4000bbd0 in _dl_map_object_deps () from /lib/ld-linux.so.2
; первое всплытие установленной точки останова
; сейчас будем проверять - "наше" ли оно или нет
(gdb) x $esp+8 ; смотрим стек
0xbffffa6c: 0x40100498 ; адрес указывает на libc.so.6
(gdb) c ; это "левое" всплытие, идем дальше
Continuing.
Breakpoint 1, 0x4000bbd0 in _dl_map_object_deps () from /lib/ld-linux.so.2
; второе всплытие установленной точки останова
; проверяем - "наше ли оно или нет
(gdb) x $esp+8 ; должен быть ret