Понимание ассемблерного кода

Может ли кто-нибудь дать некоторое представление о следующем коде сборки:

Дополнительная информация:

Загрузчик на самом деле представляет собой небольшой 16-битный загрузчик, который расшифровывается с помощью расшифровки Xor, более крупный загрузчик Linux, расположенный в секторах с 3 по 34. (1 сектор на этом диске составляет 512 байт).

Все это представляет собой систему защиты для exec, работающего на встроенном Linux.

версия со снятой защитой имеет уже расшифрованный загрузчик linux (мы смогли его реверсировать с помощью IDA), поэтому мы предполагаем, что ключ xor должен быть сделан только с нулями в версии без защиты.

если мы посмотрим на смещение от 0x800 до 0x8FF в версии со снятой защитой, оно не заполнено нулями, поэтому это не может быть ключом, иначе эта версия не может быть загружена, она будет использовать xor для простых данных и загружать только мусор.

секторы 3->34 зашифрованы в исходной версии и открыты в нашей версии (защита снята), но код MBR (маленький загрузчик) идентичен в обеих версиях.

Так может быть в ассемблерном коде MBR есть небольшая деталь, которая немного меняет место ключа xor?

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


person Unity    schedule 07.06.2013    source источник
comment
Если уточните, может быть мы сможем вам помочь, я написал загрузчики, но я не думаю, что у нас достаточно данных. Вы должны объяснить, что есть два буфера, которые объединяются XOR вместе. Буфер назначения меняется с ES:0000 на ES:3FFF. Источник (может быть, это то, что вы называете ключом) идет от DS:0800 до... может быть, DS:08BF, используется циркулярно... Мы не знаем, из каких секторов они берутся, так как мы не видим начала MBR-код.   -  person migle    schedule 08.06.2013
comment
Поскольку сообщение называется «понимание сборки...», вы видите, что SI устанавливается на 800h, затем увеличивается с помощью LODSW на 2, затем AND SI, 0ffbfh выполняет оставшуюся часть операции деления, которая поддерживает циклическое сканирование буфера ключей. Принимая во внимание, что буфер назначения, скажем, зашифрованный текст, находится в ES:0000-3FFF.   -  person migle    schedule 08.06.2013
comment
Спасибо, теперь я добавил полную MBR, указанную выше.   -  person Unity    schedule 08.06.2013
comment
Надеюсь, это поможет понять, откуда берется ключ   -  person Unity    schedule 08.06.2013
comment
Да, но это тоже немного работы... Подождите, я думаю, что это исходит от MBR.   -  person migle    schedule 08.06.2013
comment
Этот код MBR написан не очень хорошо, что довольно необычно для программного обеспечения с открытым исходным кодом. Почему не читаете исходники загрузчика (вместо дизассемблирования, в котором много чего не хватает)? На github есть один от меня, github.com/migle/BootDuet. Там много комментариев...   -  person migle    schedule 08.06.2013


Ответы (1)


Что ж, чтение ассемблерного кода — это большая работа. Я просто буду отвечать, откуда берется «ключ».

  • BIOS загружает MBR по адресу 0000:7C00 и устанавливает DL на диск, с которого он был загружен.
  • Во-первых, ваш MBR устанавливает стек, увеличивающийся с 0000:7C00.
  • Затем он копирует себя в 0000:0600-0000:07ff и делает дальний переход, который, как я предполагаю, к следующей инструкции, но в скопированной версии 0000:061D. (РЕДАКТИРОВАТЬ: эта копия является довольно стандартной вещью для MBR, как правило, по этому адресу, она оставляет указанное выше адресное пространство свободным) (РЕДАКТИРОВАТЬ: она полностью копирует себя, я неправильно понял).
  • Затем он 5 раз пытается прочитать сектор 2 в 0000:0700-0000:08ff и останавливается с сообщением об ошибке, если это не удается (loc_78).
  • Затем он 5 раз пытается прочитать 32 сектора, начиная с сектора 3, в 2000:0-2000:3FFF (абсолютный адрес 20000-23FFF, это 16 КБ, начиная со 128 КБ).
  • Если все пойдет хорошо, мы находимся на loc_60 и знаем, что у нас в памяти.
  • Цикл на loc_68 будет использовать в качестве места назначения буфер, содержащий эти 32 сектора.
  • Он будет использовать в качестве источника буфер, начинающийся с 0000:0800 (это вторые 256 байт буфера, которые мы читаем в 0:0700-0:08ff, вторые 256 байтов сектора 2 диска).
  • На каждой итерации LODSW добавляет 2 к SI.
  • Когда SI достигает 840, он снова устанавливается на 800 по И. Следовательно, «ключевой» буфер изменяется с 800 на 83F, то есть на 64 байта, начиная с байта 256 сектора 2 диска.
  • У меня сложилось впечатление, что XOR не хватает на один байт... что CX нужно было установить на 4000h, а не на 3FFF. Я думаю, что это ошибка в коде.
  • После того, как 16-килобайтный буфер по физическому адресу 20000 подвергся циклической операции XOR с этим «ключевым» буфером, мы переходим к нему с дальним переходом на 2000:0.

Верно? Это подходит? Там ключ?

person migle    schedule 07.06.2013
comment
Об этой ошибке... на самом деле, этот код выполняет операцию XOR для 32 КБ минус 2 байта... вместо 16 КБ, которые мы читаем с диска. Я думаю, нет ничего плохого в том, чтобы выполнять XOR мусора, занимая в два раза больше времени, но это показывает некоторую неряшливость. Кроме того, копирование MBR на 0600 было довольно бесполезным, так как мы загружаем целевую программу по адресу 20000, в этом не было необходимости. Теперь вы удовлетворите наше любопытство и расскажете нам, откуда это. - person migle; 08.06.2013
comment
Спасибо, я добавил еще несколько вопросов и информации к исходному сообщению, приняв во внимание все ваши замечания. - person Unity; 08.06.2013
comment
64-байтовый ключ xor находится в байте 256 второго сектора, но это смещение 0x300-0x3FF на диске - person Unity; 08.06.2013
comment
Конечно... Каждый сектор имеет размер 512 байт, поэтому 256-й байт второго сектора - это 768-й байт на диске, 0x300. Но с тех пор это всего 64 байта, так что это от 0x300 до 0x33f, а не 0x3ff. Или, скажем, каждый сектор равен 0x200, половина сектора 0x100, и мы могли бы продолжать и продолжать ссылаться на один и тот же адрес по-разному... - person migle; 08.06.2013
comment
О, я вижу, вы неправильно поняли адрес от 0x800 до 0x83F, это адрес буфера памяти, а не адрес диска. - person migle; 08.06.2013
comment
Да, теперь я понимаю. Спасибо за всю помощь, которую вы оказали, это было очень полезно - person Unity; 08.06.2013