Реверсим MIPS и Golang — основы реверса. Решение задач на реверсинг с r0от-мi. Часть 2

в 19:57, , рубрики: ctf, Go, ralf_reverse, информационная безопасность
image

В данной статье разберемся с декомпиляцией MIPS бинарника в Ghidra и пореверсим программу, написанную на golang, в IDA.

Часть 1 — C, C++ и DotNet decompile.

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

  • PWN;
  • криптография (Crypto);
  • cетевые технологии (Network);
  • реверс (Reverse Engineering);
  • стеганография (Stegano);
  • поиск и эксплуатация WEB-уязвимостей.

Вдобавок к этому я поделюсь своим опытом в компьютерной криминалистике, анализе малвари и прошивок, атаках на беспроводные сети и локальные вычислительные сети, проведении пентестов и написании эксплоитов.

Чтобы вы могли узнавать о новых статьях, программном обеспечении и другой информации, я создал канал в Telegram и группу для обсуждения любых вопросов в области ИиКБ. Также ваши личные просьбы, вопросы, предложения и рекомендации рассмотрю лично и отвечу всем.

Вся информация представлена исключительно в образовательных целях. Автор этого документа не несёт никакой ответственности за любой ущерб, причиненный кому-либо в результате использования знаний и методов, полученных в результате изучения данного документа.

ELF MIPS

image

Скачиваем и проверяем файл.

image

Это 32-x битный исполняемый файл для процессоров архитектуры MIPS. Для решения этого задания будем использовать Ghidra. Открываем гидру, создаем новый проект и добавляем в наш исполняемый файл.

image

Теперь открываем исследуемый файл, и перемещаемся в окно Symbol Tree. В поиске набираем main, чтобы найти точку входа программы.

image

При выборе функции, она сразу открывается в декомпиляторе.

image

Давайте преобразуем код.

image

Видим, что в переменную local_54 считывается 64 байта, давайте переименнуем ее в input (hotkey L) и сделаем из нее char массив длинной 64 символа (hotkey Ctrl+L). Также можно переименовать переменную sVar1.

image

image

После некоторого преобразования, код стал выглядеть чуть красивее.

image

Анализируем код. Вводимая нами строка должна состоять из 19 символов. На какой позиции какой символ должен быть понятно из кода. При этом с 8-ой по 17-ю должен быть символ ‘i’. Восстанавливаем, сдаем пароль.

Golang basic

image

В данном задании нам предоставляют исполняемый файл написанный на языке Go. Можно даже выяснить какая версия. Я закидываю в IDA. Стоит сразу сказать, что основная функция не называется main, а называется main_main. Поэтому выполним поиск по функциям и перейдем на реальную основную.

image

Давайте разбирать код. Начнем с самого начала.

image

Присутствуют определения a, key, input. Левый блок отвечает за завершение функции main_main. Рассмотрим левый блок.

image

Функция fmt_Scanln предназначена для считывания строки из консоли. Также наблюдаем уже сохраненные в программе данные main_statictmp_2.

image

Далее вызывается функция runtime_stringtoslicebyte, по коду можно предположить, что она берет первые 6 байт со следующей строки.

image

На начало этого среза будет указывать key.ptr. Глянем что идет дальше.

image

Взависимости от сравнения обнуленного регистра r9 и регистра rsi, где расположена длина пользовательского ввода. Отсюда можно сделать вывод, что r9 будет скорее всего счетчиком. Давайте заглянем в правый блок, куда перейдет управление, после прохрода по введенной нами строке.

image

Вызывается функция bytes_Compare, которая взависимости от результата сравнения выводит одну из строк.

image

image

С выводом программы разобрались, теперь пойдем посмотрим на преодразования строк (по левой ветке).

image

В регистр r10 заносится символ из пользовательского ввода, а далее идет куча сложного кода для и сравнений для контроля исключений типа panic divide и panic index. Я подсветил ветку выполнения программы.

image

Таким образом, в EDX помещается байт из статически заданной строки и ксорится с r10, где находится байт из среза. Далее счетчик r9 увеличивается. Два средних смежных блока скорее всего нужны для контроля длины среза.

Совместим все воедино: введенная строка ксорится со срезом и сравнивается со статически заданной строкой. Давайте проксорим, чтобы узнать верный пароль.

image

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

На этом пока все. Продолжение следует… Вы можете присоединиться к нам в Telegram. Там можете предлагать свои темы и участвовать в голосовании на выбор темы для следующих статей.

Автор: RalfHacker

Источник


* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js