расшифровка файла непосредственно в IDA Pro
Тот факт, что функция _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
из call main
0xbffffafc: 0x080482e1 ; судя по адресу, это возможно так и есть
(gdb) x $esp+0xC ; должен быть указатель на main
0xbffffb00: 0x08048390 ; судя по адресу это так и есть
(gdb) disassemble
0x80482e1 ; проверяем наше предположение
Dump of assembler code for function _start: ; дизассемблер
показывает типичный
0x080482c0 <_start+0>: xor %ebp,%ebp ; стартовый код, значит, приложение
0x080482c2 <_start+2>: pop %esi ; уже распаковано!
0x080482c3 <_start+3>: mov %esp,%ecx
0x080482c5 <_start+5>: and $0xfffffff0,%esp
0x080482c8 <_start+8>: push %eax
0x080482c9 <_start+9>: push %esp
0x080482ca <_start+10>: push %edx
0x080482cb <_start+11>: push $0x8048410
0x080482d0 <_start+16>: push $0x80483b0
0x080482d5 <_start+21>: push %ecx
0x080482d6 <_start+22>: push %esi
0x080482d7 <_start+23>: push $0x8048390
0x080482dc <_start+28>: call 0x80482b0 <_init+56>
0x080482e1 <_start+33>: hlt
End of assembler dump.