Я опишу задачу, с которой планирую работать. У меня есть лишь поверхностные знания по ассемблеру — изучал его для понимания работы в дебаге IDA, и, хотя в целом логика мне ясна, я хотел бы решить свою проблему именно с помощью ассемблера. <b>Поэтому инъекцию dll рассматривать не стоит!</b> В наличии имеется исполняемый файл игры, который содержит функции для импорта и экспорта текстур. Я хотел бы научить игру использовать эти функции. Для анализа exe файла я использовал IDA PRO 9 и планировал изменять ассемблерный код там. Если есть более удобные альтернативы для работы с ассемблером, то буду признателен за рекомендации. Изучив структуру exe файла, я пришел к следующему выводу: игра использует собственный аналог препроцессора C/C++, созданный разработчиками. Это не настоящие препроцессорные команды! В папке с игрой есть файл name.ini, в котором заданы константы для ботов, уровней сложности и других параметров, используя синтаксис препроцессора, такой как #define, #include, #if и тому подобное. Например: <pre><code class="cpp">// file.ini // Cars #define OFFROAD 0 #define HIGHWAY 1 // и т.д. // Game difficulty #define EASY 1 #define NORMAL 2 // и т.д.</code></pre> Чтением этих файлов занимается "функция-парсер-компилятор" под названием gameHandlePreproc. Она проверяет ключевые слова (#define, #include и пр.), сверяет их с допустимыми значениями и определяет, какую функцию нужно вызвать. Я хотел бы добавить в этот шаблон своё собственное ключевое слово (например, #skinconverter?), чтобы запускать функции импорта и экспорта. Если я правильно понял, внедрить свою функцию в середину существующих функций невозможно, так как все адреса сегмента уже заняты, а сдвиг стека приведет к поломке. Я предполагаю, что решение заключается в создании нового сегмента, где я смогу записать свои команды. Для этого я ознакомился с таблицей сегментов в IDA.
Вы правильным образом подходите к задаче, рассматривая детали работы с ассемблером и структурой исполняемого файла. Давайте рассмотрим основные шаги для вызова одной функции из другого сегмента кода в ассемблере.
### 1. Определение функции
Прежде всего, вам нужно будет определить вашу новую функцию. Например, вы можете использовать следующий шаблон:
```asm
section .text
global myFunction
myFunction:
; Ваш код здесь
ret
```
### 2. Добавление нового сегмента
Как вы упомянули, возможно создание нового сегмента для вашей функции. В IDA это можно сделать путем:
1. Перейдите в окно сегментов и создайте новый сегмент.
2. Задайте ему имя (например, `.myseg`) и укажите его адрес.
3. В этом новом сегменте разместите вашу функцию.
### 3. Вызов функции из другого сегмента
После того как ваша функция будет создана и готова к вызову, вам нужно будет обеспечить корректный переход к ней. В Асемблере это можно сделать с помощью инструкции `call`. Пример вызова функции может выглядеть так:
```asm
section .text
extern myFunction ; Объявляем функцию как внешнюю
someFunction:
; Предварительные действия
call myFunction ; Вызов вашей функции
; Остальной код
ret
```
### 4. Обработка переходов и стека
При вызове функции важно правильно обрабатывать стек. Если ваша функция использует какие-либо параметры, не забудьте правильно их передать через стек или регистры, в зависимости от используемого соглашения о вызовах (calling convention).
### 5. Изменение кода парсера `gameHandlePreproc`
Теперь вам нужно найти и модифицировать функцию `gameHandlePreproc`, чтобы она распознавала ваше новое ключевое слово (`#skinconverter`) и вызывала вашу функцию.
Примерно это может выглядеть так:
```asm
gameHandlePreproc:
; Предыдущий код
cmp eax, #skinconverter_key ; Сравниваем ключевое слово
je call_myFunction ; Если найдено, переходим к вызову вашей функции
; Остальной код
ret
call_myFunction:
call myFunction ; Вызов вашей функции
ret
```
### 6. Компиляция и тестирование
После внесения всех изменений скомпилируйте и протестируйте ваш исполняемый файл. Убедитесь, что новая функция корректно вызывается при обработке нового ключевого слова.
### Важные заметки:
- Обязательно сделайте резервную копию оригинального файла, прежде чем вносить изменения.
- В зависимости от архитектуры и платформы разные моменты могут иметь разное поведение, поэтому убедитесь, что вы хорошо понимаете контекст выполнения (например, 32-бит или 64-битная архитектура).
- Если у вас есть доступ к отладчику (например, GDB), это будет полезно для проверки правильности выполнения вашего кода.
### Инструменты для работы с ассемблером:
- **IDA Pro** - вы уже используете это мощное средство для статического анализа и редактирования кода.
- **Radare2** - это более доступное свободное ПО для анализа и редактирования, поддерживающее множество форматов.
- **Ghidra** - еще один инструмент для реверс-инжиниринга, который стал популярным за свои функции и гибкость.
С учетом всех этих аспектов вы сможете успешно реализовать вашу идею. Удачи в ваших исследованиях!
// Получаю ошибку:
7FFF0000: The instruction at 0x7FFF0000 referenced memory at 0x7FFF0000. The memory could not be executed -> 7FFF0000 (exc.code c0000005, tid 6332)
В чем проблема?
По видимому в том, что вызвать функцию получилось, но память по адресу7FFF0000-- не исполняемая.
Как починить?
Начать с того, что сделать память по адресу7FFF0000исполняемой. После этого вывод в лог должен заработать, но будет падать после него, потому что функцияmySuperFunctionне возвращается.