Несколько вопросов о синтаксисе ассемблера и интерпретация кода дизассемблера

Я пытаюсь выполнить обратный инжиниринг исполняемого файла в рамках части упражнения / задачи.

Я открыл файл в IDA64 дизассемблером. Большая часть кода скрыта, но видны три подпрограммы (включая Пуск). Мой основной опыт работы со сборкой был с MIPS в школе - поэтому у меня есть несколько вещей, которые я озадачиваю:

  1. Что означает эта строка? значение по адресу ebx равно 0 или это только первый байт?

    mov     byte ptr [ebx], 0
    
  2. Когда я вижу эти две строки кода, каков адрес "1000h"? Смысл - где я могу найти это и что в нем? Весь код в IDA начинается с 401000.

    mov     ebx, 1000h
    xor     [ebx], eax
    
  3. Существуют ли какие-либо соглашения в отношении регистров eax, ebx и esi, и что я должен предположить, что они есть в начале кода? Исполняемый файл запрашивает ввод от пользователя - могу ли я предположить, что этот ввод находится в каком-либо конкретном регистре?

1 ответ

Архитектура x86 является типичной архитектурой CISC, она может выполнять хранилища разных размеров.
mov [ebx], 0 является неоднозначным (какой размер используется?), но mov byte [ebx], 0 фиксирует размер до 8 бит
ptr это просто украшение, так что инструкция читается как почти самодокументируемая: перейти к байту, указанному ebx ноль
Это также объясняет семантику инструкции, в Интернете есть множество учебных пособий по режимам адресации x86.
Я взял первый.

1000h это странный адрес, он, вероятно, находится за пределами рабочего набора процесса, и это также типичный RVA (относительный виртуальный адрес) .text раздел.
Это заставляет меня думать, что есть запись перемещения, указывающая на операнд этой инструкции.
IDA free не может отладить, но x64dbg может, попробуйте отладку программы, чтобы увидеть, превращается ли адрес в что-то вроде BASE_ADDRESS + 1000h,
IDA покажет вам статическое представление разделов PE после загрузки, так что вы можете проверить начальное значение глобальных переменных, но чтобы увидеть оперативный вид памяти, вы должны отладить программу.

Официально в точке входа PE регистры имеют неопределенные значения, но поскольку выполнение начинается в библиотеке пользовательского режима, некоторые значения теряются, хотя это не является надежным ABI.
Есть несколько соглашений о вызовах, используемых компилятором и API, вы должны привыкнуть к этому.
Каждый компилятор также имеет свой типичный алгоритм распределения регистров, но он может быть слишком сложным, чтобы демонстрировать шаблон, но в очень простых процедурах.
Входные значения, вероятно, будут в каком-то регистре в какой-то момент, но выяснить, когда и где самая сложная часть.
Изучая поведение приложения, вы можете записать набор возможных API-интерфейсов ввода, которые программа будет использовать и разбивать на каждом из них.
После возврата к коду программы у вас будет входная строка (IO основывается на строке). Кроме того, вы с самого начала перепроектируете приложение, обученный аналитик может найти WinMain довольно легко, и если программа не запутана или написана на очень абстрактном языке, будет быстро найти, где ввод читается.
Третий способ - написать урезанное двойное приложение с технологией, очень близкой к оригинальной, а затем проанализировать последнее.
Таким образом, у вас также есть исходный код, чтобы пройти сквозь туман разборки.

Другие вопросы по тегам