Рубрики
Uncategorized

Обратный инженерный исполняемый файл Linux — Hello World

Узнайте, как обратитьсящую инженеру исполняемого исполнителя Linux — Hello World в этой статье Reginald Wong, свинцовой анти-вредоносной программой в Vipre Security, Global Company J2, охватывающую различную безопасность …

Автор оригинала: PACKT.

Узнайте, как обратным инженером исполняемого исполняемого в Linux — Hello World в этой статье Reginald Wong, исследователь ведущих болеводомохозяйств в Vipre Security, Global Company J2, охватывающую различные технологии безопасности, ориентированные на атаки и вредоносные программы.

Многие наши инструменты отлично работают в Linux. Эта статья обсудит, как изменить файл ELF, исследуя инструменты реверсива.

Для начала, давайте создадим Hello World Program. До того, как все остальное нам нужно убедиться, что инструменты, необходимые для его создания, установлены. Откройте терминал и введите следующую команду. Это может потребовать, чтобы вы ввести свой пароль Super User:

sudo apt install gcc

Compiler Common Compiler CREAD, GCC, обычно предустановлена в Linux. Откройте любой текстовый редактор и введите строки следующего кода, сохраняя его как Hello.c:

#include 
void main(void)
{
    printf ("hello world!\n");
}

Вы можете использовать VIM в качестве текстового редактора, запустив VI из терминала. Чтобы компилировать и запустить программу, используйте следующие команды:

1.png.

Файл Hello — это наш исполняемый файл Linux, который отображает сообщение в консоли. Теперь, на обращении этой программы.

Dlrow olleh

В качестве примера хорошей практики процесс обратного изменения программы сначала должен начать с правильной идентификации. Давайте начнем с файла:

2.png.

Это 32-разрядный тип файла ELF. Файлы ELF — это нативные исполнители на платформах Linux. Следующая остановка, давайте возьмем быстрый взгляд на текстовые строки с командой строк:

3.png.

Эта команда будет производить что-то вроде следующего выхода:

/lib/ld-linux.so.2
libc.so.6
_ IO_stdin_used
puts
__ libc_start_main
__ gmon_start__
GLIBC_2.0
PTRh
UWVS
t$,U
[^_ ]
hello world!
;* 2$"(
GCC: (Ubuntu 5.4.0-6ubuntu1~16.04.10) 5.4.0 20160609
crtstuff.c
__ JCR_LIST__
deregister_tm_clones
__ do_global_dtors_aux
completed.7209
__ do_global_dtors_aux_fini_array_entry
frame_dummy
__ frame_dummy_init_array_entry
hello.c
__ FRAME_END__
__ JCR_END__
__ init_array_end
_ DYNAMIC
__ init_array_start
__ GNU_EH_FRAME_HDR
_GLOBAL_OFFSET_TABLE_
__ libc_csu_fini
_ ITM_deregisterTMCloneTable
__ x86.get_pc_thunk.bx
_ edata
__ data_start
puts@@GLIBC_2.0
__ gmon_start__
__ dso_handle
_ IO_stdin_used
__ libc_start_main@@GLIBC_2.0
__ libc_csu_init
_ fp_hw
__ bss_start
main
_ Jv_RegisterClasses
__ TMC_END__
_ ITM_registerTMCloneTable
.symtab
.strtab
.shstrtab
.interp
.note.ABI-tag
.note.gnu.build-id
.gnu.hash
.dynsym
.dynstr
.gnu.version
.gnu.version_r
.rel.dyn
.rel.plt
.init
.plt.got
.text
.fini
.rodata
.eh_frame_hdr
.eh_frame
.init_array
.fini_array
.jcr
.dynamic
.got.plt
.data
.bss
.comment

Строки перечислены в порядке с начала файла. Первая часть списка содержит наше сообщение и информацию компилятора. Первые две строки также показывают, какие библиотеки используются программой:

/lib/ld-linux.so.2
libc.so.6

Последняя часть списка содержит имена разделов файла. Мы только знаем о нескольких битах текста, которые мы поместили в наш C-код. Остальные помещаются туда на сам компилятор, как часть его кода, который готовится и заканчивает изящное исполнение нашего кода.

Разборка в Linux — это просто командная линия. Используя параметр -D-параметр команды objdump, мы должны иметь возможность показать разборку исполняемого кода. Возможно, вам придется трусить вывод в файл, используя эту командную строку:

objdump -d hello > disassembly.asm

Выходной файл, разборка .asm, должен содержать следующий код:

4.png.

Если вы заметите, что синтаксис разборки отличается от формата языка Intel Assembly язык, который мы узнали. Вот что мы видим, — это синтаксис разборки AT & T. Чтобы получить синтаксис Intel, нам нужно использовать параметр Intel -m, следующим образом:

objdump -M intel -d hello > disassembly.asm

Вывод должен дать нам этот результат разборки:

5.png.

Результат показывает код разборки каждой функции. Таким образом, было в общей сложности 15 функций из исполняемых разделов:

Disassembly of section .init:
080482a8 <_ init>:

Disassembly of section .plt:
080482d0 :
080482e0 :
080482f0 <__libc_start_main@plt>:

Disassembly of section .plt.got:
08048300 <.plt.got>:

Disassembly of section .text:
08048310 <_ start>:
08048340 <__ x86.get_pc_thunk.bx>:
08048350 :
08048380 :
080483c0 <__ do_global_dtors_aux>:
080483e0 :
0804840b 
: 08048440 <__libc_csu_init>: 080484a0 <__libc_csu_fini>: Disassembly of section .fini: 080484a4 <_ fini>:

Разборка нашего кода обычно находится в разделе .Text. И, поскольку это компиляция GCC-скомпилированная программа, мы можем пропустить весь код инициализации и отправиться прямо к основной функции, в которой находится наш код:

6.png.

Я подчеркнул вызов API на поставленных классах. PUTS API также является версией Printf. GCC был достаточно умным, чтобы выбрать, набрал Printf по той причине, что строка не была интерпретирована как строка форматирования стилей C-стилей. Строка форматирования или форматировала, содержит управляющие символы, которые обозначены с помощью% знака, такими как% DVer Integer и% s для строки. По сути, MEDS используется для неформатных строк, в то время как printf используется для форматированных строк.

Что мы собрались до сих пор?

Предполагая, что у нас нет идеи исходного кода, это информация, которую мы набрали до сих пор: • Файл является 32-разрядным исполняемым ELF. • Он был составлен с использованием GCC. • Он имеет 15 исполняемых функций, включая функцию Main (). • Код использует общие библиотеки Linux: libc.co и ld-inux.so. • На основании кода разборки программа, как ожидается, просто покажет сообщение. • Ожидается, что программа отобразит сообщение, используя PUT.

Динамический анализ

Теперь давайте сделаем какой-то динамический анализ. Помните, что динамический анализ должен быть сделан в среде песочницы. Существует несколько инструментов, которые обычно предустановлены в Linux, которые можно использовать для отображения более подробной информации. Мы представляем LTRACE, STRACE и GDB для этой реверсирующей активности.

Вот как используется ltrace:

7.png.

Выход Ltrace показывает читаемый код того, что сделала программа. Ltrace зарегистрированные библиотеки функционируют, что программа вызывается и получена. Это называется, чтобы отобразить сообщение. Он также получил выходной статус 13, когда программа прекращена.

Адрес 0x804840B также является адресом основной функции, перечисленной в результатах разборки.

stroce — это другой инструмент, который мы можем использовать, но это системные вызовы журналов. Вот результат беговой стрелки в нашей главной программе Hello:

8.png.

Race зарегистрирована каждая система, которая произошла, начиная с того, когда он выполняется системой. Execve — это первый системный вызов, который был зарегистрирован. Вызова Execve запускает программу, указанную в файле имени файла в его функциональном аргументе. Открыть и читайте системные вызовы, которые используются здесь для чтения файлов. MMAP2, MPROTECT и BRK несут ответственность за действия памяти, такие как распределение, разрешения и граничные настройки сегмента.

Глубоко внутри кода ставят, в конечном итоге он выполняет вызов системы записи. Пишите, в общем, пишет данные на объект, на который он был указан. Обычно он используется для записи в файл. В этом случае первый параметр записи имеет значение 1. Значение 1 обозначает STDOUT, которая является ручкой для вывода консоли. Второй параметр — это сообщение, таким образом, он записывает сообщение на STDOUT.

Идти дальше с отладкой

Во-первых, нам нужно установить GDB, запустив следующую команду:

sudo apt install gdb

Установка должна выглядеть что-то подобное:

9.PNG

Затем используйте GDB для отладки программы Hello, следующим образом:

gdb ./hello

GDB можно управлять с помощью команд. Команды полностью перечислены в онлайн-документации, но просто поступление помощи может помочь нам с основы.

Вы также можете использовать GDB, чтобы показать разборку указанных функций, используя команду dissass. Например, давайте посмотрим, что произойдет, если мы используем основную команду разряда:

10.PNG

Затем, опять же нам дали разборку в синтаксисе AT & T. Чтобы установить GDB для использования синтаксиса Intel, используйте следующую команду:

set disassembly-flavor intel

Это должно дать нам синтаксис языка ассамблеи Intel следующим образом:

11.PNG

Чтобы разместить точку останова в главной функции, команда будет B * Main.

После размещения точки останова мы можем запустить программу, используя команду запуска. Мы должны в конечном итоге по адресу основной функции:

12.PNG

Чтобы получить текущие значения регистров, введите информационные реестры. Поскольку используются в 32-битной среде, используются расширенные регистры (то есть EAX, ECX, EDX, EBX и EIP). 64-битная среда будет отображать регистры с префиксом R-префикса (то есть Rax, RCX, RDX, RBX и RIP).

Теперь, когда мы находимся в главной функции, мы можем запустить каждую инструкцию с помощью STEPT в (команду STEPI) и шага (команду nexti). Обычно мы следуем за этим с помощью команды info регистров, чтобы увидеть, какие значения изменены.

Следите за входом в SI и раздирание, пока вы не достигнете линии, содержащей звонок 0x80482e0, ставит @ PLT. Вы должны в конечном итоге с этими раздиральными и информационными регистрами Регистрация:

13.png

The => найдено на левой стороне, указывает, где находится указатель инструкции. Регистры должны выглядеть аналогично этому:

14.png.png.

До появления функции MEDS мы можем проверить, какие значения были нажаты в стек. Мы можем просмотреть это с x/8x $ ESP:

15.png

Далее нам нужно сделать шаг через (в) линии инструкции вызовов. Это должно отобразить следующее сообщение:

16.png.png.

Но если вы использовали Si, указатель инструкции будет в The Trust Code Code. Мы все еще можем вернуться к тому, где мы остановились, используя до команды, сокращенные как U. Просто используя до нескольких шагов команд в одной инструкции. Вам придется указать место адреса, где он остановится. Это как временная точка останова. Не забудьте разместить звездочку перед адресом:

17.PNG

Остальные 6 строк кода восстанавливают значения EBP и ESP сразу после ввода основной функции, затем возвращаясь с RET. Помните, что инструкция звонков будет хранить обратный адрес в верхней части стека, прежде чем фактически переходить на адрес функции. Инструкция RET будет прочитать значение возврата, указанного на Espregister.

Значения ESP и EBP, сразу после ввода основной функции должны быть восстановлены до ретинструкции. Как правило, функция начинается с настройки собственной кадры стека для использования с локальными переменными функции.

Вот таблица, показывающая изменения в значении регистров ESP, EBP и ECX после инструкции по данному адресу.

18.png

Вы можете продолжать изучать код очистки после RET, либо просто заставить программу в конечном итоге завершаться с помощью продолжения или его сокращения, C, следующим образом:

19.PNG

Если вы нашли эту статью интересную, вы можете исследовать Оснащение обратной машины Чтобы реализовать методы обратного инженерных технологий для анализа программного обеспечения, используйте цели программного обеспечения и защищать от угроз безопасности, таких как вредоносные программы и вирусы. Если вы хотите проанализировать программное обеспечение, чтобы использовать свои слабости и укрепить свою защиту, то вам следует исследовать Оснащение обратной машины Отказ

Оригинал: «https://www.codementor.io/@packt/reverse-engineering-a-linux-executable-hello-world-rjceryk5d»