Опишу задачу и сразу скажу, что познания по ассемблеру поверхностные, изучал для понимания того, что происходит в дебаге IDA, но в целом понятны, логика ясна и хотелось бы решить проблему именно ассемблером.
Поэтому инъекцию dll не предлагать!
Имеется exe файл игры. В файле есть функции для импорта, экспорта текстур. Хотелось бы научить игру запускать их. Для анализа exe была использована IDA PRO 9 и изменить ассемблер код также планировал в IDA. (Но если есть аналоги, ибо IDA не удобная для написания ассемблера, то подскажите варианты). Изучив работу exe файла было принято такое решение:
У игры есть собственное подобие
препроцессора С/С++ и его синтаксиса, написаного разработчиками.(Нет, это не оригинальные препроцессорные команды!) Т.е. есть файл name.ini в папке игры и в нем задаются константы ботов, уровней сложности и т.д. с синтаксисом препроцесса #define, #include, #if и т.п. Пример:
// file.ini
// Cars
#define OFFROAD 0
#define HIGHWAY 1
// и т.д.
// Game difficult
#define EASY 1
#define NORMAL 2
// и т.д.
Чтением этих файлов занимается "функция-парсер-компилятор" gameHandlePreproc. Она проверяет ключевое слово(#define, #include и т.д.), сверяет с шаблонам допустимых значений и решает какую функцию запустить. Я решил добавить в этот шаблон свое ключевое слово(может #skinconverter?), чтобы запускать функции импорта-экспорта. Если правильно понял, то внедрить в середину свою функцию нет возможности. Все адреса сегмента уже заняты и двигать стек нет смысла все сломается. Я так понял, что решением задачи будет создать новый сегмент и там писать свои команды. Таблица сегментов от IDA после дезассемблирования такова + мой сегмент:
┃ Segment name ┃ Start ┃ End ┃ Base ┃
┃ .text ┃ 0x00401000 ┃ 0x00554000 ┃ 0001 ┃
┃ .idata ┃ 0x00554000 ┃ 0x0055432C ┃ 0002 ┃
┃ .rdata ┃ 0x0055432C ┃ 0x0055E000 ┃ 0002 ┃
┃ .data ┃ 0x0055E000 ┃ 0x01661000 ┃ 0003 ┃
┃ .data1 ┃ 0x01661000 ┃ 0x01662000 ┃ 0004 ┃
Мой сегмент:
┃ .text ┃ 0x7FFF0000 ┃ 0x80040000 ┃ 0001 ┃
Почему мой сегмент так далеко. Если запустить игру, то, с учетом dll библиотек, будут заняты адреса от
0x00010000 до +-
0x7FFE0500. Если создать ближе к сегменту data1, то сегменты библиотек и дебага переписывают данные поверх.
Я решил протестировать как это будет работать и как реализовать задумку. В "функции-парсере-компиляторе" есть функция обработки ошибки, которая просто выводит ошибку в log файл. Решил этот участок кода выделить под вызов своей функции и в своей функции описсать всю дальнейшую логику. Но предварительно решил протестировать как это будет работать. Как из одного сегмента вызвать функцию другого сегмента. Для теста перенес вызов вывода ошибки в свою функцию, но после запуска измененного кода получаю ошибку:
// 1. Кусок функции gameHandlePreproc, который обрабатывает ошибку.
// Без изменений!
// Родной .text сегмент
.text:0042164B loc_42164B: ; CODE XREF: gameHandlePreproc+23E↑j
.text:0042164B push edi ; ArgList // в edi хранится слово из file.ini для сверки с шаблонами
.text:0042164C push offset aUndefinedWord ; "Undefined word on line..."
.text:00421651 call tioError // вывод ошибки в лог файл
.text:00421656 add esp, 8
// 2. Что хочу сделать так:
// Родной .text сегмент
.text:0042164B loc_42164B: ; CODE XREF: gameHandlePreproc+23E↑j
.text:0042164B push edi ; ArgList // в edi хранится слово из file.ini для сверки с шаблонами
.text:0042164C push offset aUndefinedWord ; "Undefined word on line..."
.text:00421651 call mySuperFunction
.text:00421656 add esp, 8
...
...
...
// Мой .text сегмент
.text:7FFF0000 ; Segment type: Pure code
.text:7FFF0000 ; Segment permissions: Read/Execute
.text:7FFF0000 _text segment para public 'CODE' use32
.text:7FFF0000 assume cs:_text
.text:7FFF0000 ;org 7FFF0000h
.text:7FFF0000 assume es:nothing, ss:nothing, ds:_data, fs:nothing, gs:nothing
.text:7FFF0000
.text:7FFF0000 ; =============== S U B R O U T I N E ==============================
.text:7FFF0000
.text:7FFF0000 mySuperFunction proc near ; CODE XREF: gameHandlePreproc+271↑p
.text:7FFF0000 call tioError // вывод ошибки в лог файл
.text:7FFF0000 ; ---------------------------------------------------------------------------
.text:7FFF0005 db 0
.text:7FFF0006 db 0
.text:7FFF0007 db 0
.text:7FFF0007 mySuperFunction endp
// Получаю ошибку:
7FFF0000: The instruction at 0x7FFF0000 referenced memory at 0x7FFF0000. The memory could not be executed -> 7FFF0000 (exc.code c0000005, tid 6332)
При том, после запуска программы, функция меняется на:
.text:7FFF0000 mySuperFunction db 0
.text:7FFF0001 db 0
Как правильно реализовать задачу? В чем проблема? В IDA или в ассемблере? Как починить?