В этой статье мы разберём самую базу реверс-инжиниринга на примере простого crackme — программы, созданной для практики «хацкинга». Ничего серьёзного.

Введение

Как бы этого не хотелось, но желательно хоть немного понимать ассемблер для чтения базовых инструкций

  1. Базовые инструкции
    mov rax, rbx — копирует значение из регистра rbx в rax.

    add al, 0x5 — добавляет 5 к регистру rax.

    cmp rax, rbx — сравнивает значения в rax и rbx.

    jmp <адрес> — переходит к указанному адресу в коде.

  2. Системные вызовы (syscalls): Способ взаимодействия программы с операционной системой. Например, syscall с номером 1 в Linux — это запись в стандартный вывод (stdout).

Немного примеров:

mov rax, 10

Записываем число 10 в регистр rax. Теперь rax = 10.

add rax, 5

Прибавляем 5 к rax. Теперь rax = 15.

mov rbx, rax

Копируем значение из rax в rbx. Теперь rbx = 15.

cmp rbx, 12

Сравниваем rbx с 12

Если значения равны — переходим на функцию equal.

je equal

Если не равно — просто переходим в end.

jmp end

Вот функции equal и end

equal:
   inc rbx ; rbx = 13
end:                                             
 push rbx    ; кладём rbx в стек                  
 pop  rcx    ; забираем из стека в rcx → rcx = 13 
 ret         ; возврат из функции

Также рассмотрим syscall

section .text
    global _start

_start:
    mov rax, 1          ; номер системного вызова: sys_write
    mov rdi, 1          ; 1 = stdout
    mov rsi, msg        ; адрес строки
    mov rdx, 1          ; длина — 1 байт
    syscall             ; вызов ядра

    ; Выход из программы
    mov rax, 60         ; sys_exit
    mov rdi, 0          ; код возврата 0
    syscall

section .data
msg:
    db 'A'              ; один байт с символом 'A'

И это выведет «A» при выполнении

Тут описана ОЧЕНЬ малая часть того, что умеет ассемблер, но этого, наверное, для начала хватит.

Практика: Разбор простого crackme

Для практики мы возьмём простую программу с сайта Crackmes.one, где бинарников для «взлома» очень много, хорошее место для практики «хацкинга»

  1. Заходим на Crackmes.one, сортируем по сложности 1 (Для начала) и я выберу платформу (Unix/Linux).

  2. Скачиваем любой crackme, который только пожелаете. Для примера возьмем этот

  3. Распаковываем архив (пароль crackmes.one), получаем исполняемый файл (в нашем случае «hello»).

Запустим для начала программу:

Программа запрашивает имя и пароль, после чего пишет Wrong Credentials. Рассмотрим «внутренности» этого бинарника.

Я буду использовать программу Binary Ninja, но подойдут и другие, такие как Ghidra или IDA.

Откроем файл hello в Binary Ninja.

В центре видим декомпилированный псевдокод (High‑Level IL), который нам, людям, помогает легче читать код программы. Рассмотрим основные моменты:

  1. Начало _start: Программа начинается с функции _start. Она вызывает системный вызов (syscall) с номером 1, что выводит строку «Please enter your name:» в консоль через stdout.

  2. Чтение ввода: Программа использует sys_read (syscall 0) для чтения введённого имени. Введённые данные сохраняются в переменную ret_code начиная с 4-го байта, максимальная длина — 32 байта. Регистр rax содержит количество прочитанных байт. Если rax < 0, программа завершается с ошибкой.

  3. Вывод приветствия: Программа создаёт строку Welcome {Имя пользователя}. Для этого используются два поля: welcome и welcome:6 (начиная с 6-го байта строки welcome).

  4. Запрос пароля: Аналогично имени, программа запрашивает пароль и перезаписывает в ret_code.

Программа содержит цикл, который проверяет пароль:

  • Регистр r15_2 используется как индекс, начиная с длина_пароля — 1 и уменьшаясь на каждом шаге.

  • Программа берёт символ из строки welcome, начиная с 5-го байта, смещённого на r15_2.

  • Условие проверки: каждый символ пароля должен удовлетворять формуле:

    password[i] == welcome[5 + i] + 5

    где i — позиция символа с конца строки.

При успешной проверке программа выводит строку Great H4×0r Skillz!!!!!, что означает прохождение crackme.

Зная, как работает программа, мы введем имя ABC. Тогда:

  • Строка welcome формируется как Welcome ABC.

  • Позиция 5 в welcome указывает на начало имени (A).

  • Пароль вычисляется по «формуле»: password[i] = welcome[5 + i] + 5.

  • Для ABC откроем английский алфавит и пропустим для каждой буквы ещё на 4 позиции вперёд

  • Итоговый пароль: FGH.

Вводим ABC как имя и FGH как пароль — программа выводит Great H4×0r Skillz!

Теперь попробуем «взломать» программу, изменив её поведение с помощью дебаггера Binary Ninja:

  1. В Binary Ninja переключаемся на вид дизассемблера (Disassembly вместо High‑Level IL).

  2. Находим инструкцию, отвечающую за прибавление 5 к символу:

    004010ca  add al, 0x5
  3. Устанавливаем точку остановки (breakpoint) на этой инструкции (F2 / ПКМ — Breakpoint).

  4. Запускаем дебаггер в левой панели Binary Ninja.

  5. Вводим снизу в консоли одинаковые имя и пароль (например, ABC и ABC).

  6. Нажимаем F9 (Resume) для продолжения выполнения до точки останова.

  7. Когда выполнение останавливается на add al, 0×5, щёлкаем ПКМ — Patch — Edit Current Line и изменяем 0×5 на 0×0. Теперь программа прибавляет 0 к символам пароля.

  8. Продолжаем выполнение (F9). Программа принимает пароль ABC и выводит Great H4×0r Skillz!!!!!.

Поздравляю, теперь вы полноценный «хацкер» ну почти.

В этой статье я попытался кратко разобрать «взлом» очень легкой crackme и самых основ реверс-инжиниринга, советую найти любую другую crackme на Crackmes.one той же сложности и попытаться решить её. На легкой сложности задачи не сильно отличаются друг от друга

Если я в статье где‑либо ошибся, прошу поправить в комментариях. Эта статья моя проба пера на Хабре.

Комментарии (1)


  1. Emelian
    02.09.2025 14:57

    Reverse Engineering для самых маленьких

    Для «полусредних» можно предложить разобраться с декомпиляцией бинарного кода в ассемблерный и, обратно, компиляцией ассемблерного кода в бинарный ( https://erfaren.narod.ru ).