Русский
Русский
English
Статистика
Реклама

Ida

Перевод Исправляем кривой запуск первого Mass Effect

23.11.2020 10:05:21 | Автор: admin
image

Часть 1


В последнее время я работал над собственным форком ME3Explorer [неофициальный редактор игр серии Mass Effect], содержащим множество важных улучшений и даже новые инструменты. Также я поработал над Mod Manager 5.1, который имеет удобные новые функции импорта сторонних модов, однако был отодвинут на второй план, пока я работал над новым фронтендом установщика ALOT.

ALOT Installer с манифестом 2017 года

Для его реализации я сотрудничал с CreeperLava и Aquadran; он должен упростить жизнь конечным пользователям, устанавливающим ALOT и его аддон (сторонние текстуры). Одна из моих проблем заключалась в том, что Origin не запускал игру после установки ALOT, если не запустить его с правами администратора. И поскольку запуск Origin при загрузке невозможно выполнить с правами админа, это очень раздражает. К тому же это влияет на мод MEUITM. Поэтому я начал разбираться, почему это происходит. Дело оказалось в идеальном сочетании реализации защиты, плохого кода и желания упростить жизнь других людей.

Давайте посмотрим, как работает Mass Effect с Origin в неизменённом состоянии под Windows 10.

  • Пользователь запускает MassEffect.exe. Файл немедленно запрашивает повышение прав до администраторских.
  • В конце образа MassEffect.exe есть код вызова Origin для запуска игры, это некая DRM. Он вызывает Origin, а затем выполняет выход.
  • Origin проверяет права пользователя на запуск игры, а затем запускает MassEffect.exe в соответствии с указаниями в реестре (не тот, который вы запустили сами), после чего пытается запустить исполняемый файл.
  • Origin не может запустить исполняемый файл, потому что он требует повышения прав. Чтобы DRM работала, она должна иметь возможность взаимодействия с процессом, поэтому она повышает права одного из внутренних сервисов, чтобы он мог общаться с игрой в целях DRM-защиты.
  • MassEffect.exe выполняется с правами администратора. Origin обменивается данными с MassEffect.exe и выполнение игры продолжается, как это было бы в случае с DVD-версией.

Всё это работает (через два UAC-запроса) на немодифицированной игре. Но если установить MEUITM или ALOT, то вы больше не сможете запускать игру через Origin как стандартный пользователь. Что за дела?

Сигнатуры файлов


И MEUITM, и ALOT модифицируют исполняемый файл MassEffect.exe, чтобы он мог использовать Large Address Aware. Это позволяет 32-битному процессу Mass Effect использовать до 4 ГБ ОЗУ вместо обычного 32-битного ограничения в 2 ГБ. При модификации флага LAA цифровая сигнатура MassEffect.exe оказывается поломанной сигнатура используется для проверки того, что файл не модифицирован. После модификации файла сигнатура становится неверной.

Origin при выполнении процесса с повышенными правами проверяет, подписан ли EXE компанией EA и правилен ли он. Если он не подписан EA, то он не повышает права модуля обмена данными DRM. Mass Effect загружается, а затем немедленно закрывается, потому что разблокировка DRM не работает, ведь со стороны Origin ей не с чем общаться, поскольку отказано в повышении прав.

То есть при модификации EXE Origin будет отказываться запускать исполняемый файл игры с повышенными правами. Но нам нужен LAA, поэтому необходимо как-то обойти эту проблему. Наша единственная надежда заключается в том, чтобы помешать MassEffect.exe запускаться с правами администратора. Сначала нужно разобраться, как задан его запуск с правами администратора.

Изучив манифест EXE, я увидел, что он запускается как инициатор вызова пользователь, запускающий EXE. Это означает, что этот исполняемый файл не должен требовать администраторских прав. Я проверил свои параметры совместимости, там тоже ничего не было. Каким-то образом права повышаются при запуске, но не через сам exe и не из-за моих настроек. В чём же хитрость? В Microsoft Windows Compatibility Database.

mirh (я встречался с ним в кругах любителей моддинга) провёл исследование того, почему Mass Effect вынужден запускаться с правами администратора. Он соответствует критериям базы данных в ней есть запись для Mass Effect, в которой указано, что нужно всегда принудительно запускать параметры совместимости. Это логично пользователь не должен конфигурировать параметры, если MS уже знает, какие из них работают (теоретически).


Как видите, для этой игры есть две записи MassEffect.exe (игра) и загрузчик (который, к сожалению, не включён в версию Origin). Для совместимости включается RunAsHighest (что означает права администратора). Критерии включения таковы:

  • EXE имеет название MassEffect.exe
  • Название компании в манифесте: BioWare
  • Название продукта в манифесте: Mass Effect
  • Версия продукта равна или меньше 1.2.0.0.

Эти критерии соответствуют всем известным версиям игры, в том числе, полагаю, и пиратским. Поэтому из-за совпадения всех этих критериев exe принудительно запускается с правами администратора. Это можно легко проверить, переименовав MassEffect.exe, после чего ему не потребуются администраторские права. (Однако Origin будет недоволен).

Исправление


Итак, теперь у нас есть понимание, как это исправить, но почему в базе данных есть эта запись? Поскольку Demiurge/Bioware не поддерживают идею Least User Access (LUA), Mass Effect при самом первом запуске требует прав администратора для выполнения записи в ключ реестра HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432NODE\AGEIA Technologies. Если этот ключ не существует, он пытается создать его без прав администратора у него нет для этого доступа, и игра просто вываливается. Похоже, в этом ключе содержится некая информация о том, что сейчас называется PhysX. Вероятно, запись в реестр мог внести и установщик игры, но разработчики реализовали это в самой игре.

Именно поэтому Microsoft вынуждает игру всегда запускаться с правами администратора, из-за этого единственного пункта. Это логично если заставить её запускаться под администратором, но пользователю не нужно будет беспокоиться о параметрах совместимости. Однако из-за этой комбинации трёх проблем (LAA портит сигнатуру, MS принуждает запускаться игру с правами администратора, Origin отказывается работать с процессами с повышенными правами, имеющими сломанную сигнатуру EA) Mass Effect не запускается с Origin и LAA.

Как же нам это исправить? Просто изменим в EXE название продукта с Mass Effect на Mass_Effect. Серьёзно, это всё. Проверка критериев не срабатывает, игре больше не нужны права администратора и Origin доволен (если не считать постоянного ворчания из-за обновлений). В MEUITM и ALOT Installer мы добавили код, создающий ключ реестра с правами записи для текущего пользователя, поэтому если Mass Effect нужно создать эти ключи (допустим, если его никогда не запускали), то игра будет довольна.

Часть 2


Mass Effect на PC: что ожидать от порта с консолей середины 2000-х


Если вы не знали, Mass Effect вышла на PC в 2008 году, она была портирована с Xbox 360 студией под названием Demiurge, которая также разработала Pinnacle Station для Mass Effect. Это очень посредственный порт, не особо хорошо переживший смену времён. Он приемлем как игра, но имел множество проблем даже на момент выхода. LOD частиц работали неправильно, LOD текстур считывались в обратном порядке, параметры ini случайным образом сбрасывались на значения по умолчанию проблем было довольно много. Но не было ничего, что бы полностью ломало игру.

Ну, или типа того. Была одна проблема, но вызванная не конкретно самой Mass Effect. Серьёзная проблема заключается в том, что Mass Effect требует для запуска прав администратора потому что Demiurge, похоже, считала, что все должны запускать игру как администратор это вполне могло быть приемлемым, если бы игра разрабатывалась во время, когда была только Windows XP, однако на момент выпуска игры уже больше года существовала Windows Vista. Но даже Windows XP имела концепцию LUA (Least User Access) с разделёнными аккаунтами пользователей. Подробнее об этом можно прочитать в первой части статьи.

Ух ты, PhysX, моя любимая библиотека физики!



Наверно, у меня небольшая неприязнь к этому SDK.

Mass Effect для PC работает на немного модифицированной версии Unreal Engine 3, который был выпущен примерно в конце 2006. По словам некоторых бывших разработчиков из BioWare, эта версия Unreal Engine тогда была немного сыроватой, если не сказать больше. Согласно рассказам этих разработчиков, было очень сложно работать с ней, потому что Epic Games сосредоточенно работала над Gears of War и не уделяла особо много времени своим партнёрам, тоже использующим движок.

Для расчёта физических взаимодействий Unreal Engine 3 использует PhysX, поэтому Epic Games создала dll, реализующую интерфейс между PhysX и форматами данных Unreal Engine через файл под названием PhysXLoader.dll, который загружает библиотеки PhysX с обеих сторон. PhysX это библиотека симуляции физики, приобретённая компанией AGEIA Technologies в середине 2000-х перед тем, как саму AGEIA в начале 2008 года купила Nvidia. Возможно, вы помните карты Physics Processing Unit (PPU) они использовали PhysX до того, как Nvidia похоронила эту идею.


PhysXLoader.dll, PhysXCore.dll и NxCooking.dll составляют библиотеки PhysX для Mass Effect.

Все три части Mass Effect используют PhysX, однако Mass Effect 2 и Mass Effect 3 используют установленную в систему PhysX, а Mass Effect локальную PhysX игры. Кроме того, в Mass Effect 2 и Mass Effect 3 применяется современная версия PhysX, а не устаревшая, которая была выпущена AGEIA. После приобретения Nvidia изменила некоторые пути внутри библиотеки, отделив устаревшие части от современных версий.

Но, похоже, это не мешает программе удаления старой PhysX удалять файлы/ключи реестра современной PhysX, поэтому в процессе тестирования моего исправления другие копии Mass Effect 2/3 не работали даже после установки современного дистрибутива PhysX. Очень бесит, что BioWare не смогла просто установить библиотеку на 8 МБ вместе с игрой в комплекте с игрой всё равно поставляется установщик PhysX, то есть это даже не экономило место!

Ну да ладно

Проблема PhysXLoader.dll компании Epic Games в том, что она может загружать PhysXCore.dll локально или из установленной в систему версии


Что? Как это может быть проблемой? Разве нельзя просто загружать локальную dll, и если она не существует, загружать системную? Почему это вообще проблема?


Вы не поверите, сколько фейспалмов я испытывал в процессе создания этого исправления.

При запуске Mass Effect записывает в реестр Windows HKEY_LOCAL_MACHINE два значения:

REG_BINARY HKLM\SOFTWARE\AGEIA Technologies enableLocalPhysXCore [mac-адрес, 6 байт]

REG_DWORD HKLM\SOFTWARE\AGEIA Technologies EpicLocalDllHack [1]

*Mass Effect это 32-битная программа, поэтому на 64-битной системе она выполняет запись в HKLM\SOFTWARE\WOW6432Node\AGEIA Technologies (на случай, если вы захотите проверить сами).

Запомните эти значения реестра, они будут важны в дальнейшем!

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

Нам нужно изменить исполняемый файл, чтобы включить Large Address Aware, благодаря чему игра сможет загружать текстуры повышенного разрешения без переполнения памяти, поэтому нет никакого способа избежать порчи сигнатуры. Это, в свою очередь, привело к тому, что Origin больше не мог запускать игру, потому что он не может повышать права игры без правильной сигнатуры EA. Но если игра не имеет возможности записывать эти ключи реестра при запуске, то она может вылететь

Итак, это само по себе уже длинная цепь проблем, но мы обошли необходимость прав администратора в Mass Effect, просто дав аккаунту пользователя разрешение на этот конкретный ключ реестра AGEIA Technologies. Это позволит процессу игры записывать нужные ему значения. Я предполагал, что игра вылетает, потому что ей запрещался доступ для записи, а Demiurge не озаботилась написать try/catch вокруг кода записи в реестр.

Вероятно, не стоит называть значения реестра hack


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


Два значения реестра, записываемые Mass Effect.

Модератор PC Gaming Wiki под ником mirh долгие годы бил тревогу о том, что мы каким-то образом ломали другие игры в ALOT Installer, даже несмотря на то, что наше приложение никак не меняла способ записи Mass Effect этих значений, поэтом наше изменение никак не может сломать другие игры.

Спустя много месяцев он написал довольно подробное обоснование того, почему ALOT Installer (то есть на самом деле это была Mass Effect) ломает другие игры: находящийся в реестре enableLocalPhysXCore используется другими играми, работающими с PhysXLoader.dll. Когда я писал версию V4 установщика ALOT Installer, то сказал mirh, что серьёзнее рассмотрю его идею решения, не позволяющего ломать другие игры, хотя тогда я ещё не понимал, как ключ реестра с MAC-адресом системы может ломать другие игры и зачем вообще используется MAC-адрес.

Похоже, mirh был уверен, что эта enableLocalPhysXCore позволяет Mass Effect использовать PhysXCore.dll/NxCooking.dll в локальной папке, а не загружаться из установленного дистрибутива PhysX. Mass Effect не устанавливает дистрибутив PhysX, поэтому не может полагаться на её существование и вынуждена использовать локальные библиотеки.

Держитесь, теперь начинается нечто совершенно тупое:

MAC-адрес, сохраняемый в реестр файлом MassEffect.exe, считывается библиотекой PhysXLoader.dll и сравнивается с MAC-адресом вашей системы, чтобы определить, нужно ли загружать библиотеки PhysX из локальной папки или из системной.


Какой MAC-адрес?

\_()_/


Итак, Mass Effect работает следующим образом:

  1. В самом начале процесса загрузки MassEffect.exe MAC-адрес вашей системы считывается и записывается в реестр как enableLocalPhysXCore (вместе с EpicLocalDllHack)
  2. MassEffect.exe загружает PhysXLoader.dll
  3. PhysXLoader.dll считывает значение enableLocalPhysXCore и сравнивает с ним MAC-адрес вашей системы
  4. Если они совпадают, она использует PhysX из локальной папки, если нет, то версию дистрибутива PhysX из системы

Да, вы всё поняли правильно.

Оказалось, что другие игры, например, Mirrors Edge, имеют PhysXLoader.dll, которая тоже считывает эти значения (так как они основаны на одинаковом коде), но в этих играх нет локальных библиотек PhysX. Поэтому эти игры загружаются, видят enableLocalPhysXCore и пытаются загрузить локальную библиотеку, терпят неудачу и игра не запускается. Эту информацию я получил от mirh сам я не тестировал другие игры, поломанные этим значением реестра.

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


Сложно представить сценарий, при котором это было бы хорошей идеей.

Если вы реализуете интерфейс с библиотекой, имеющей экспорт, который можно вызвать для инициализации/загрузки PhysX SDK, то разве нельзя просто передать ей булево значение, приказывающее ей загрузиться локально? Почему она вообще не начинает с локального поиска? И что за дела с MAC-адресом? Почему он находится в реестре, где ведёт себя как глобальный параметр???

Всё это выглядит как ужасные архитектурные решения, а после дизассемблирования PhysXLoader.dll кажется, что всё это и есть ужасные архитектурные решения. Давайте внимательнее присмотримся к Mass Effect и рассмотрим процесс её исправления от начала до конца.

Находим начальную точку


Предупреждение: я совершенный новичок в реверс-инжиниринге. Я создавал ассемблерные моды для игр Megaman Battle Network (и написал неплохое руководство по созданию хуков), проектировал моды на ActionScript2 P-Code и работал с байт-кодом UnrealScript, но никогда не углублялся в ассемблер x86. Я множество раз открывал IDA и могу находить нужные мне вещи, но никогда не понимал их. Уверен, что для более опытных реверс-инженеров этот процесс намного проще.


Сложно получать удовольствие от реверс-инжиниринга, если почти ничего не понимаешь в том, с чего начать. Это режим графа IDA, который очень помогает визуализировать ассемблер, но его всё равно очень сложно понять в большом двоичном файле на 20 МБ.

Недавно (пару лет назад), Агентство национальной безопасности США (АНБ) выпустило Ghidra бесплатный тулкит для реверс-инжиниринга с открытыми исходниками, который может отреверсировать ассемблерный код в довольно читаемый код на C; его бесконечно проще читать, чем ассемблерные графы IDA. И IDA, и Ghidra имеют свои сильные стороны: в IDA есть отладчик, позволяющий пошагово пройти по ассемблеру и посмотреть, какие пути кода будут выполняться, а также она может находить Unicode-строки (которые используются в Mass Effect ). Ghidra может рекомпилировать ассемблерный код из его декомпилированного кода на C (иногда), имеет преобразователь из ассемблера в C (простите, не знаю его названия), обладает открытыми исходниками и работает на куче платформ и со множеством двоичных форматов.


Ghidra это отличный инструмент для новичков в реверс-инжиниринге, поскольку она позволяет просматривать ассемблер как код на C, хоть и без имён переменных.

Итак, в начале я знал, что Mass Effect записывает enableLocalPhysXCore и EpicLocalDllHack. Давайте начнём с изучения MassEffect.exe, найдём эти строки и посмотрим, что на них ссылается. Открыв шестнадцатеричный редактор, я знал, что это unicode-строки, поэтому я буду искать их в IDA, потому что Ghidra, похоже, не поддерживает эту функцию.


Окно IDA Strings. Я наконец узнал, что эта полезная вкладка открывается по Shift + F12.

Поискав внутри окна IDA Strings строку enableLocalPhysXCore, я её нашёл. При двойном нажатии программа переносит нас к области данных исполняемого файла, в которой она задаётся:


На изображении вы видите, где задаются enableLocalPhysXCore, EpicLocalDLLHack и даже ключ реестра, все они находятся прямо рядом друг с другом.

Выше мы видим задание строк, которые, похоже, связаны с нашей целью. Над заданием текста мы видим DATA XREF, то есть что-то напрямую ссылается на эти данные вероятно, записывает их. Давайте дважды щёлкнем на XREF и посмотрим, куда это нас отправит.


Режим IDA View, а не Graph View.

Изучив это, мы видим, что здесь записывается RegSetValueExW. Я очень слабый разработчик на C, поэтому после гугления я понял, что это подготовка стека для вызова на C метода из Windows API, что можно увидеть по отображаемому IDA названию параметра, например, lpData и dwType. Мы знаем, что значению enableLocalPhysXCore присваивается MAC-адрес системы. Давайте посмотрим, где выполняется это присваивание. Чтобы выглядело логичнее, переключимся на режим графа.


В третьем блоке мы видим, что eax записывается в стек для lpData, а также записывается в стек для этого загадочного вызова sub_10929393. В этой подпроцедуре нет других вызовов с заданными названиями, поэтому вероятно именно там получается MAC. Давайте перейдём к ней.


Похоже, это какая-то подпроцедура-обёртка, или так это трактовала IDA, но она просто указывает на другую подпроцедуру. Давайте перейдём к ней.


Эта подпроцедура содержит названия, взятые из Windows API, и они показывают нам, что это как-то связано с сетью. Нас не волнует MAC-адрес, но давайте зададим название этой подпроцедуре. Назовём её GetMacAddress. Вернёмся к исходной подпроцедуре, которую изучали, и тоже переименуем её похоже, это что-то типа SetupPhysXSDKLoad, поэтому назовём её так.


Это относительно небольшая подпроцедура, всё, что она делает это производит запись двух вышеупомянутых значений реестра. Кроме ранних этапов загрузки двоичного файла, на эту подпроцедуру больше нет других ссылок, поэтому на этом этапе я вполне уверен, что исполняемый файл Mass Effect никогда не считывает эти значения, и пока я не знаю, что же делает EpicLocalDllHack.

Вскрываем PhysXLoader.dll


Теперь мы знаем, что исполняемый файл Mass Effect никогда не считывает этот ключ; значит, это делает одна из dll. Здесь я этого не показал, но в ProcMon (отличном инструменте для моддинга и подобных вещей в целом) я вижу, что значение реестра считывается непосредственно перед загрузкой библиотеки в процессе MassEffect.exe и перед загрузкой локальной dll. Я увидел, что после того, как запретил Mass Effect доступ на запись в эту папку, он считывает системную библиотеку, и игра не загружается, если не установлена системная версия старой PhysX.

Первой из dll загружается PhysXLoader, после которой загружается PhysXCore.dll, поэтому логично будет анализировать её. Давайте откроем её в IDA и посмотрим, где там используется enableLocalPhysXCore. Также я открою эту dll в Ghidra, чтобы лучше понимать, что происходит. Проделав ту же последовательность действий по поиску мест использования строки enableLocalPhysXCore, мы находим подпроцедуру:


Подпроцедуру читать не так уж сложно, особенно в режиме графа мы видим, что есть цикл, идущий из левого блока в блок над ним. Тем не менее, всё это не так просто читать для новичка, поэтому давайте посмотрим, как это выглядит в Ghidra. Я использую адрес этой подпроцедуры, чтобы перейти к ней в Ghidra (0x10001640).


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

Чтобы немного сократить пост, скажу, что эта подпроцедура поиска в реестре и в самом деле является простой обёрткой для получения информации из реестра. После реверс-инжиниринга (который в основном заключался в сопоставлении входящих данных подпроцедуры с тем, чем они являются в вызовах windows api) выяснилось, что её параметры являются подключом, именем значения, возвращаемым указателем на данные и возвращаемым размером данных.

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


Мы знаем, что Mass Effect записала в реестр 6-байтный mac-адрес, и что PhysXLoader.dll просто считала это значение из реестра, и что подпроцедура сравнивает что-то побайтно 6 раз. Логически мы можем предположить, что local_14 с показанного выше изображения это MAC-адрес. Зная это, мы также можем предположить, что FUN_10001580 получает MAC-адрес и задаёт его, поэтому мы переименуем ещё несколько элементов подпроцедуры.

Похоже, что вызов подпроцедуры не выполняет саму загрузку, он просто проверяет ключ и совпадение MAC-адреса. Зная название и информацию о действиях этого ключа, мы можем дать этой подпроцедуре обоснованное название ShouldUseLocalPhysX. Однако сравнение декомпиляции этой подпроцедуры в IDA и Ghidra приводит к немного различающимся результатам, и Ghidra, похоже, ошибается:


IDA показывает, что al присваивается 1 при нормальном выходе из цикла и 0 (xor al,al), если какие-то байты не совпадают. Ghidra этого не показывает, на самом деле она показывает, что возвращаемый тип равен void, что кажется ошибкой.

Немного погуглив информацию для этой части поста, я узнал, что EAX обычно используется как регистр возврата для x86, а регистр al это нижние 8 бит EAX. Я не имею достаточно опыта в Ghidra, чтобы знать, как сменить тип сигнатуры для этого вида возвращаемых нижних 8 битов; возможно, Ghidra пока этого не поддерживает, или я упустил какую-то настройку, которую нужно использовать.


Дизассемблированная подпроцедура, вызывающая ту, которая ищет enableLocalPhysXCore.

Однако если мы взглянем на ссылки на эту подпроцедуру (их две скорее всего, по одной на каждую библиотеку) в IDA и Ghidra, то увидим, что при вызове ShouldUseLocalPhysX она проверяет, не равен ли al нулю. Если он не равен нулю, то она загружает локальную PhysXCore.dll. Если равен, то она ищет библиотеку через системную установку PhysX, которая находится по ещё одному значению реестра в ключе AGEIA Technologies под названием PhysXCore Path. На самом деле это нам неинтересно, потому что мы хотим заставить PhysX всегда загружаться локально, вне зависимости от значения enableLocalPhysXCore.

Посмотрев на другую перекрёстную ссылку, можно и в самом деле увидеть, что она загружает библиотеку NxCooking, используя ShouldUseLocalPhysX таким же образом:


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

Например, если мне нужно было удалить проверку if, то мне приходилось находить способ изменить сравнения таким образом, чтобы они всегда были true или false. Один из способов возврата false проверкой if заключается в изменении ссылок на объект и токенов байт-кода сравнений, чтобы создать условный оператор вида if (objectA != objectA), всегда возвращающий false (если они не равны null). Мне нужно найти способ, чтобы в ShouldUseLocalPhysX всегда получался результат true.

Когда я писал таблицу символов для Megaman Battle Network 3, то научился всегда комментировать всё, что узнал об дизассемблированном коде. Я работал часами, совершенно забывая, что уже сделал, но мог вернуться к своим комментариям, и снова во всём разобраться.

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

Патчим худшую в мире проверку boolean



Нам нужно убедиться, что выполнение всегда доходит до нижнего левого блока, при этом мы не должны касаться стека (который запросто может поломать всю программу). Строго говоря, мы можем переписать часть этой подпроцедуры, но мне хотелось бы вносить здесь минимальные изменения. По сути, нам нужно гарантировать, что переход в нижний правый блок никогда не происходит.

В x86 есть удобная однобайтная команда nop, которая в буквальном смысле не делает ничего, но занимает один байт. Также удобно то, что команда перехода в этот блок занимает 2 байта и состоит из 0x75 (jnz rel8) и 0x19 (относительного смещения).


[ЗАБАВНАЯ ИСТОРИЯ] Увидев это однобайтное смещение, я вспомнил времена, когда я работал над моддингом Megaman Battle Network. Тогда от команд перехода/ветвления зависела возможность моддинга отдельных частей ROM. При написании хука (перенаправляющего счётчик программы к вашему собственному коду) вам нужно найти команду перехода или ветвления, относительное смещение которой можно модифицировать так, чтобы оно указывало на ваш код. Затем нужно записать регистры в стек, запустить код, а затем вернуть стек обратно, чтобы подпроцедура выполняла выход правильным образом.

ARM (а конкретнее THUMB) имеет ограниченные команды ветвления, использующие в качестве относительных смещений разные размеры, которые не всегда могли перейти в любую точку ROM из-за своего местоположения в ROM. Так как игра была написана на ассемблере, находить свободное место временами было сложновато иногда приходилось соединять в цепочку несколько хуков, пока не удавалось переместить счётчик программы в свободную область, чтобы писать новый ассемблерный код. Этот jnz использует опкод 0x75, что даёт jnz rel8, то есть он может переходить только на расстояние до 128 байт (или, если переход возможен только вперёд, на 255?), что было бы настоящей проблемой, если бы я выполнял моддинг ассемблера так же, как мы работали раньше, когда не было мощных инструментов наподобие IDA и Ghidra. [КОНЕЦ ЗАБАВНОЙ ИСТОРИИ]

После замены nop-ами этого jnz наша подпроцедура ShouldUseLocalPhysX выглядит так:


Теперь в блок условия неравенства попасть нельзя. Проверка по-прежнему выполняется, но она никогда не возвращает false. Будет всегда использоваться локальное ядро PhysX.

Недостатки


Файл PhysXLoader.dll подписан Epic Games, поэтому это очевидно разрушает сигнатуру, ведь мы модифицировали файл. Игра не проверяет сигнатуры при загрузке, поэтому это не проблема. Некоторые антивирусы могут жаловаться на сломанные сигнатуры, но со временем обычно перестают. Кроме написания патча внутри памяти (как мы делаем это в загрузчике мода asi), нам нужно будет модифицировать двоичный файл библиотеки.

Получившееся поведение


Благодаря пропатченной dll игра работает как со значением реестра, так и без него, то есть Mass Effect для запуска больше не требуются права администратора. Дизассемблирование этого кода сопровождалось сильной руганью, потому что я не мог смириться с тупостью реализации этой проверки проверяется не только значение в реестре, но и MAC-адрес. В процессе отладки и пошагового выполнения команд я на самом деле сломал игру, потому что включил VPN и мой MAC-адрес сменился.

Этот процесс оказался хорошим опытом учёбы, я намного больше узнал о Ghidra и IDA, а также о других проблемах в PC-версии Mass Effect. Этот патч автоматически применяется в процессе установки ALOT Installer, поэтому пользователям не придётся беспокоиться о задании ключа enableLocalPhysXCore. Также мы модифицировали исполняемый файл Mass Effect для записи значения enableLocalPhysXCor_, чтобы наши пропатченные версии не записывали значение, портящее игры. Ванильные исполняемые файлы Mass Effect всё равно портят другие игры, но защита программ от криво написанных загрузчиков PhysX уже не входит в мои задачи.

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

Разве добавление параметра PreferLocalSDK для PhysXLoader.dll это слишком сложно для Epic Games?
Подробнее..

Что нам стоит patch построить, нарисуем будем жить

21.08.2020 08:14:52 | Автор: admin

Сказ о суровых российских инженерах.


1. С чего все началось


Ангелы и демоны кружили надо мной
Рассекали тернии и Млечные Пути

Origa Inner Universe

В одном, не очень отечественном САПР, есть возможность конвертировать чертежи сразу в PDF. Но то ли программисты не очень понимают, как их САПР используется, то ли просто забыли добавить возможность сохранения настроек. В итоге, САПР, при экспорте в PDF, всегда конвертирует только "текущий лист", если не забраться в параметры и принудительно не выбрать "Все листы". В нашем инженерном деле, документы из одного листа крайне редки, народ страдает и продолжает из раза в раз выкладывать, отправлять, генерировать и просто тратить процессорные мощности на однолистные PDF'ки. Томным, пятничным вечером, потягивая купажированный виски и покуривая сигару, я задумался можно ли с этим что-нибудь сделать?


Disclaimer
  • Помните, внесение изменений в программное обеспечение может нарушать лицензионный договор. Все дальнейшие совпадения случайны. Статья носит исключительно развлекательный характер.
  • Автор не является программистом и тестировщиком, а работает скромным инженером-проектировщиком всяких аббревиатурных систем типа АСУ ТП, САУ ВО\ДГ и прочих промышленных систем. Из-за этого в статье могут содержаться неточности, ошибочные утверждения и бредовые предположения.



Рисунок 1. Окно настроек PDF.


2. и чем могло закончиться.


Первая и самая очевидная идея пойти в настройки САПРа и изменить стандартные параметры. Я бы не писал этот текст, окажись все так просто. Доступных галочек, кнопочек, полей и прочих пользовательских интерфейсов отвечающих за настройки экспорта PDF в приложении не оказалось.


Вторая, менее очевидная для обывателя идея пойти в реестр и поискать там. Многие приложения хранят в HKEY_LOCAL_MACHINE\SOFTWARE\ (или HKEY_CURRENT_USER) свои настройки, параметры и прочую сервисную информацию необходимую для работы. Реестр для того и задумывался. Можно догадаться, найдись там с ходу, что-либо годное для решения проблемы, этой заметки не было.


Третье и последнее поискать в конфигурационных файлах. Часто программы хранят параметры не в реестре, а во всяких config.ini, settings.xml и прочих текстовых файлах. Вдумчивый поиск и пристальное рассматривание каталогов показали отсутствие текстовых настроек.


3. Just Do It!


Мастерами кунг-фу не рождаются
Мастерами кунг-фу становятся

Мумий Троль Мастера Кунг-Фу

Очевидные вещи закончились, пора заныривать в чертоги памяти и призывать весь свой опыт работы с IT-системами. Прежде всего, реестр. Возможно, параметр отвечающий за "печать всех листов", хранится не так явно. Скажем, есть в реестре запись с названием "Options", имеет она значение "1,1,2,3,1,0,1" и вторая единичка, как раз отвечает за то, какой пункт меню выбран. Возникает два вопроса: "Где взять хороший вискарь?" и "Как найти эти самые опции?"


Если над первым еще можно поломать голову, то со вторым все просто в составе Sysinternals существует замечательное приложение Process Monitor(procmon).



Рисунок 2. Окно Process Monitor


Сначала, пришлось определиться с фильтрами, т.к. Procmon ловит вообще все события от любого приложения, коих в windows работает с пару-тройку десятков, и событий налетает тысяч 10-20 за пару секунд. Окей, указываем отображать только события связанные с САПР и исключить всякую фигню. Далее, открываем приложение, запускаем сбор событий, нажимаем кнопку "параметры", останавливаем сбор событий Вуаля скромный лог "всего" на 700+ строк. Предположительно содержащий обращение к реестру для чтения настроек экспорта. После скрупулёзного изучения, были замечены строки 19:46:29,4265774, однозначно намекающие мол САПР считал (и записал) данные 1391,7901,0,0.


"Ха! Вот оно!" подумал я, предположив, что 1 или 0 отвечают, как раз за настройки.
"Хе!" подумал САПР, и категорически отказался, что-либо менять в окне параметров, не смотря на различные комбинации подсовываемых нулей, единичек и прочих цифр.


Суббота. Смеркалось. Других обращений к реестру не было и становилось очевидно путь реестра ведет в никуда.


Воскресенье выдалось суетным, впереди маячила новая рабочая неделя, хотелось завалиться на диван, обнять жену, включить какой-нибудь фильм и наслаждаясь Джонни Пешеходом, окунуться в приятную негу однако, на периферии сознания свербела мысль "откуда то же САПР читает настройки". Рабочая неделя не предвещала ничего хорошего, жена занималась своими девочковыми делами, Джонни оказался слишком резок, смотреть фильм не получалось. Пришлось открыть ноутбук.


Если САПР не хранит настройки в реестре, значит хранит их в файлах, вопрос лишь в котором из 20 000? Скорее всего, опция хранятся в виде нуля (первый пункт меню, для программистов нулевой), а может единички, если код писал криворукий индус. В любом случае, таких нулей и единичек в САПРе, аж три биллиона (10^9)


Я смотрел на САПР. САПР смотрел на меня и издевательски моргал курсором в поле "векторное разрешение". Поле это динамическое, туда можно ввести любое значение и получить документ соответствующего качества. Стоп. Поле данныхлюбое число но там же есть текст "DPI". Значит, поле текстовое, и текст "400 DPI" уникален (в пределах файлов). Хм. И он (текст) где-то хранится, вероятно даже рядом с остальными настройками


TotalCommader > поиск файлов > *.* c текстом "400 DPI". Томительное ожидание и ничего не найдено. Потому что файлы, в большинстве своем, не текстовые, а бинарные, и искать надо в HEX-е (заодно, выбрав все доступные кодировки). Вуаля искомая комбинация встречается всего в одном файле:
imgUI.dll (название файла изменено)
Вау! Так просто? А вот фигушки. DLL динамик лоад лайбери, если открыть его редактором, то можно увидеть нечто-подобное:



Рисунок 3. Текст DLL


Нипоня-я-ятно однако, в каталоге с imgUI.dll встретились img.dll и imgUtils.dll. Этож-ж-ж не спроста. А еще, так как САПР не отечественный, но на русском языке, то в каталоге Rusians (ага, именно с одной s) нашлась еще парочка файлов imgRes.dll и imgUIRes.dll. Чтож к утру понедельника у меня было пять файлов:


  • imgUI.dll UI, скорее всего сокращение "User Interface", в нем то и нашлось "400 DPI". Можно предположить этот файл отвечает за отрисовку интерфейса.
  • imgUIRes.dll очевидно, файл ресурсов для отображения пользовательского интерфейса
  • imgUtils.dll файл содержащий утилиты, выполняющие преобразование в pdf, или просто всякие вспомогательные штуки(?)
  • img.dll что делает не ясно, но раз имеет общее имя с файлами выше, надо обратить внимание и запомнить.
  • imgRes.dll ??? Файл ресурсов для работы img.dll ???

4.We need to go deeper (Заныриваем глубже).


All in all it was just a brick in the wall.
All in all it was just the bricks in the wall.

Pink Floyd Another Brick In the Wall (Part 2)

Понедельник выдался нервным.
Единственное, что я понимал на тот момент: после того как программист нарисовал окошечко, оно складывается в res-файл и существуют приложения способные эти файлы открыть. Отдельное спасибо игровому детству и разработчикам небезызвестных ArtMoney и Restorator. При помощи последних мы читирили меняли в res-файлах различные опции, получая тем самым горы золота, шмоток и просто нереальных (по игровым меркам) персонажей.


Логично было предположить в res-файле могут содержаться данные с настройками или окно параметров содержащие те же настройки (те кто разрабатывал графические интерфейсы на С++-подобных языках сейчас улыбнулись).


В imgRes.dll ничего интересного не нашлось, а вот imgUIRes.dll встретил знакомым окном параметров.
Еееее! порадовался я, сейчас я какаааак сделаю что-то Хм, а действительно, что?
Радость улетучилась. Res-файл не содержит кода, по сути, это набор элементов которые можно подвигать, изменить размер, шрифт, текст а ведь это именно то что мне требуется! Почему бы просто не поменять местами два текста пусть "Все листы" станет первым в списке, тогда САПР всегда будет выбирать его по умолчанию!


Сказано, сделано, сохранено.
Запуск САПРа>Экспорт>Параметры>OK>Экспорт. И полный облом. Не смотря на то что "чек-бокс" стоит там, где надо ничего не изменилось.



Рисунок 4. Измененный интерфейс.


Программисты сейчас должны умилиться моей наивности. Во-первых, если проводить проверку по тексту чек-бокса, то необходимо учитывать все языки, а не только русский. (САПР то международный, ага). Во-вторых, каждый элемент в окне имеет ID и работают, как раз через него. Выглядит это так (цифра после первой запятой ID):



Рисунок 5. ID в Res-файле.


Хотелось верить, что где-то здесь, в цифрах, зашита заветная опция "использовать этот пункт по умолчанию ", но увы нет.


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


5.Еще!


Run rabbit run
Dig that hole, forget the sun,
And when at last the work is done
Don't sit down it's time to dig another one

Pink Floyd Breathe

Помнится лет 10 назад, нам, студентам информационно-измерительных систем, по какой-то одному деканату известной причине, читали курс по защите ПО. Преподаватель, понимая, что за семестр невозможно впихнуть в нас хоть сколько-нибудь внятные знания по всем этим DES, AES и прочим приоткрытым ключам, сделал единственный верный шаг начал рассказывать, что нужно сделать чтобы код от наших гипотетических приборов не уперли конкуренты и какими методами они это будут пытаться сделать. Лабораторные работы строились по принципу пишешь код, а потом твой сосед пытается его сломать. С тех времен память сохранила сокращения- HEX, ASM, IDA.


С последней и было решено начать, благо есть бесплатная версия(freeware, а не то что все подумали). Ollydbg казался сомнительным, т.к. САПР х64 и была не нулевая вероятность получить неправильный код. Microsoft Debugger можно было бы попробовать, но IDA уже была скачена и установлена.


Итак, есть две сущности:


  • ID элементов из окна параметров (от 1001 до 1014)
  • Текст "400 DPI"

которые надо найти, очевидно, в imgUI.dll. Почему очевидно? Во-первых, потому что поиск текста "400 DPI" указал именно на этот файл, а во-вторых, из названия файла.
Закинув DLL в IDA я, честно признаюсь, знатно так 302A79452F5C:



Рисунок 6. IDA.


Что это? Нет, понятно что это 1. ассемблер 2. последовательность выполнения чего-то, за чем-то в зависимости от чего-то. Переключение в "TextView" так же не прибавило понимания, а родило с десяток новых вопросов как объявляются переменные, что это за 800+ функции sub_18, где хранятся данные, циклы, условия где все это?, что это за регистры, где мой вискарь и котъ!?


В общем, для неподготовленного меня, последний раз писавшего программы на скриптовых-языках высокого уровня (PowerShell и VBA), все это выглядело примерно так же как и для тебя, мой дорогой читатель выглядят расчеты селективности, токов короткого замыкания, кривые отключения и прочие электрические гадости.


Но, как говорится "фигня война, главное маневр". Что искать в файле было ясно заранее radiobutton с ID 1004\1005. и-и-и поиск ничего не дал. А не дал он ничего, потому что IDA нифига не дружелюбна и хранит все данные в шестнадцатеричном виде. Окей, запускаем калькулятор, переводим в "программистский режим" и получаем 1004 это 3ECh в HEX (h на конце собственно об этом и говорит). Запускаем поиск по новой успех, данное сочетание найдено 3 раза в 2х функциях. Причем, значение ID 1005 (3EDh) находится рядышком только в тех самых двух функциях. Место найдено и выглядело оно примерно так:



Рисунок 7. ID 1005


Чего происходит, нипонятно да, честно говоря, понимания и не требовалось. Осталось лишь поменять эти два значения местами, чтобы кнопка "Текущий лист" стала распознаваться ПО как "Все листы", а "Все листы", как "Текущий лист". И тут меня ждал первый облом редактировать ассемблерный код IDA не дает. А вот байт-код пожалуйста. Честно говоря, всегда думал ассемблер самый "близкий" к железу язык, оказалось нифигашечки. Итак, байт-код. Каждый процессор имеет набор команд, большей частью стандартизированных, и каждая команда имеет свой код в виде байт(подозреваю что на самом деле бит), а ассемблер это "отображение" этих байт в более-менее читаемом виде. Команда mov edx, 3EC в байт-коде выглядит так:


BA EC 03 00 0  

А mov edx, 3ED так:


BA ED 03 00 00

Впрочем, к черту лишние знания, надо же EC заменить на ED и наоборот! Закидываю DLL в САПР, открываю "параметры", никаких видимых изменений, но их и не должно быть жмакаю ОК>Сохранить и ДА!!! PDF-ка, генерируется сразу вся ЕЕЕЕЕ! СДЕЛАНО! Интеллектуальный оргазм, победа!


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


6. Hardcore только hardcore.


Мы уже думали, что опустились на самое дно, но тут снизу постучали
Народная мудрость.

Казалось бы все конец, ответ на вопрос вселенной и всего такого найден, но, увы меня ждала подлянка.
Оказалось, внезапно, кто бы мог подумать если НЕ заходить в "Параметры", то окно не вызывается, изменение настроек НЕ происходит и по умолчанию PDF сохраняется с 1 листом. Т.е. по сути ничего не изменилось для генерации полноценного PDF'а, надо было все равно, хотя бы раз заползти в параметры.



Рисунок 8. Фиаско


И что в такой ситуации делать? Правильно, занырнуть поглубже!


Как гласит название одной хорошей книги "just for fun" загрузил imgUtils.dll. Понимания как все работает и что делать дальше не прибавилось, все было примерно так же как и в imgUI.dll, за исключением одного ряд функций имели вполне себе читаемые названия вида: OptionsPDFExport::SetResol, OptionsPDFExport::SetBW, OptionsPDFExport::GetStartSheet и прочие. Оппачки! Слишком уж говорящие названия! Но опять таки радость была недолгой, т.к. большинство ф-ций имело вид:


mov     [rcx+15h], dl  Retn

Т.е. понятно, нечто из DL переносится в rcx со смещением (по адресу?) но Чё за dl? Чё за регистр rcx? Впрочем, что будет если ф-ция GetBW всегда будет писать в регистр rcx+15h значение 1 (или 0, потом разберемся)?
Второе неожиданное открытие невозможность вставить кусок кода. Совсем. Никак. Связанно это с указателями часть команд (и не только) говорят, мол прыгни на 99 команд вверх, или считай значение по вот этому адресу Когда мы вставляем код, то фактически адреса съезжают и нам надо перепрыгнуть уже через 100 команд, т.е. переписать их все. ИДА такого делать не умеет (или, что скорее, я не нашел).
Возвращаясь к mov rcx+15h, dl. В байт-коде это выглядит так:


88 51 14

а чтобы написать mov rcx+15h, 1, надо вставить:


C7 81 14 00 00 00 01 00 00 00

Т.е. надо добавить 14 байт. (Для тех кто знает ассемблер да-да-да надо использовать другой байт-код, и вообще какого фига я сравниваю х86-64, но это наглядно).


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


Но что делать дальше? Изучать ассемблер и полностью реверс-инжинирить каждую функцию в этих двух файлах? Нет, долго. Надо было вернуться к началу и пройти правильным путем запустить мониторинг и посмотреть какие ф-ции вызываются в процессе генерации PDF без заползания в параметры и уже после этого лезть в ассемблерный код.
На просторах интернета была найдена программа API Monitor v2. В качестве "наблюдаемых" файлов были выбраны imgUtils.dll и imgUI.dll чтож лог получился на 233 вызова. Не то чтобы очень мало, но зато у меня был порядок вызова ф-ций.
Описанные выше GetBW\SetBW\GetStartSheet встречались, но ближе к середине, т.е. они были не первыми.


В начале лога мое внимание привлекла ф-ция с названием OptionsXPSExport. Хм а какого собственно черта, при генерации PDF'а, вызывается ф-ция от другого формата? И после нее как раз и начинались разнообразные Get'ы и Set'ы
Открыл в ИДА. Функция оказалась не маленькой, строк на 300 ассемблерного кода. Старый добрый вопрос что искать? ID кнопок бессмысленно, оставалось только "400 DPI".
Переводим 400 в 16-ричную систему, получаем 190h. Поиски найдена 1 строка:



Рисунок 9. Настройки.


Встает вопрос как узнать, что именно этот сегмент отвечает за стандартные настройки? Легко! Почему бы не изменить известный параметр и не посмотреть что будет! Ок, 190h заменено на 96h (число 150). Запуск САПР>Экспорт в PDF>Параметры и вместо 400 DPI красовалось 150 DPI. Йухууу! Можно было сделать вывод место хранения "дефолтных" настроек найдено. Оставалось два вопроса где именно лежит нужный параметр и как его найти в 300 строках, примерно такого же кода.
Кстати, что это за код? Что за r12 и r13? Ответ нашелся вначале функции:



Рисунок 10. R2D2.


В регистр r12 записывалась единичка, а в r13 ноль, что ни разу не очевидно, т.к. для этого используется команда xor, а не mov. Разница в том что xor делается быстрее чем mov, поэтому его и используют когда надо обнулить переменную.
Возвращаясь к коду выше, было очевидно, что по адресу rbp+330h записывается 0, а по адресу 32Сh - 1.
Окей, полдела сделано появилась возможность изменять значение параметров с вкл (1) на откл (0).


Однако, особых идей где именно находится параметр отвечающий за листы все еще не было. Попытка подключить ИДА к дебаггеру и поймать момент смены того или иного байта "на лету" провалилась, по не известной мне причине дебаггер отваливался при запуске САПРа. Оставался самый тупой способ перебор.


Заменил r13b на r12b в строке с адресом [rbp+326h], и оказалось, что этот mov отвечает за удаление веса линий. А mov выше за печать исключенных листов. Набросав простенький проект проверил работает ли это все без открытия параметров экспорта. И да. Проект экспортировался без весов линий. Что еще раз подтвердило я смотрю в правильный кусок кода.


Потратив несколько дней на игры с заменой 1 и 0, появилось ощущение нового тупика. Замена оставшихся значений не приводило к сколько-нибудь заметному результату галочки в параметрах не ставились, а иногда приложение просто крашилось. Стоит отметить параметров было много и после замены каждого проверять САПР было долго, по этому я менял 10-20 значений и смотрел изменилось ли что-нибудь.


В один из вечеров я смотрел на приведенный выше код и думал "да чтож с тобой не так? почему 5 из 7 параметров находятся здесь?" К слову, строка 0FFFFFFh отвечала за "До", а строка ниже за "От".


Абсолютно логично все настройки отвечающие за параметры сгруппированы в одном месте и mov rpb+314, r12 должен отвечать как раз за выбор диапазона печати. Но там не 0, там 1! Помните я говорил про индусов? О том, что не для всех первый элемент массива кнопок является нулевым. Тогда логично, что моя замена 1 на 0 ничего не показала. Окей, нет ничего проще меняем mov rpb+314 r12 на mov rpb+314 r13 и барабанная дробь при входе в параметры ни один из пунктов меню "диапазон печати" выбран не был!
Да, это та самая строка, тот самый кусок кода который я искал на протяжении недели. Гребаные 14 байт.


Оставалось лишь изменить значение на правильное и можно открывать шампанское. Итак 0 не выбрано ничего, 1 первый пункт, продолжая ряд выходило что нужно прописать 2.
Тут появлялась старая, добрая проблема mov rpb+314 r12 занимало меньше байт чем mov rpb+314 00002h
На счастье, парой строк выше можно заметить вот такой кусок кода:



Рисунок 11. Е2Е4.


Т.е. в регистр eax ложится двойка, а команда mov rpb+314 eax занимает на 2 байта меньше чем mov rpb+314 r12!


Ассемблер Байт-код
mov rpb+314, r12 44 89 A5 14 03 00 00
mov rpb+314, eax 89 85 0C 03 00 00

Вопрос что делать с этими двумя байтами? Оставить как есть нельзя. Но, на счастье из родного Политеха я смог вынести несколько сакральных знаний:


  • Как работает реле (что позволило найти инженерную работу)
  • Всегда заземляйся (если вы понимаете о чем =)
  • Ассемблерный nop просто пропуск команды
  • Шаверму перед парами. кхм, впрочем к делу это не относится.

Очевидное решение заNOPать, т.к. в байт-коде команда NOP это "90".
Запуск САПР и да, это оно. Файл конвертируется в многостраничный PDF. А окно параметров открывается по умолчанию так:



Рисунок 11. Окно настроек PDF.


7.Заключение.


We've come too far to give up who we are
So let's raise the bar and our cups to the stars

Daft Punk Get Lucky

Ответ на вопрос, заданный в начале статьи, найден. Путь был тернист и заставил пошевелить мозгами, вспомнить университетский курс программирования и узнать много нового. За рамками осталось несколько "тупиковых веток", вида JMP'нуть в кусок кода, изменить регистры и прыгнуть назад, или попытки найти исходники, но вряд ли это кому-то интересно.
Немного обидно, что эти знания никогда не уйдут в "продакшн", а инженеры продолжат страдать из-за пары программистов, но Cest La Vie, таков лицензионный договор.
Надеюсь, эта заметка сможет вдохновить кого-нибудь на совершенствование рабочих инструментов, даже если вы инженер-проектировщик и весьма далеки от реверс-инжиниринга.

Подробнее..

Категории

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

  • Имя: Макс
    24.08.2022 | 11:28
    Я разраб в IT компании, работаю на арбитражную команду. Мы работаем с приламы и сайтами, при работе замечаются постоянные баны и лаги. Пацаны посоветовали сервис по анализу исходного кода,https://app Подробнее..
  • Имя: 9055410337
    20.08.2022 | 17:41
    поможем пишите в телеграм Подробнее..
  • Имя: sabbat
    17.08.2022 | 20:42
    Охренеть.. это просто шикарная статья, феноменально круто. Большое спасибо за разбор! Надеюсь как-нибудь с тобой связаться для обсуждений чего-либо) Подробнее..
  • Имя: Мария
    09.08.2022 | 14:44
    Добрый день. Если обладаете такой информацией, то подскажите, пожалуйста, где можно найти много-много материала по Yggdrasil и его уязвимостях для написания диплома? Благодарю. Подробнее..
© 2006-2024, personeltest.ru