Может быть проще просто исправить исполняемый модуль. Добавьте новый код в конец текстового сегмента и переместите его в добавленный код в начале старой функции. Таким образом, вам не придется решать проблемы, которые может вызвать декомпиляционная версия DLL.
Например вот начало существующей функции вы хотите заменить:
000D0880 push ebp
000D0881 mov ebp,esp
000D0883 sub esp,0E0h
000D0889 push ebx
000D088A push esi
000D088B push edi
000D088C lea edi,[ebp-0E0h]
000D0892 mov ecx,38h
000D0897 mov eax,0CCCCCCCCh
Чтобы перенаправить вызов просто добавить инструкцию JMP на D0880. Мы добавляем инструкции NOP после прыжка, чтобы сделать дизассемблированный очиститель вывода во время сеансов отладки. Это не обязательно, но это пригодится.
000D0880 jmp NewFunction
000D0885 nop
000D0886 nop
000D0887 nop
000D0888 nop
000D0889 push ebx
000D088A push esi
000D088B push edi
Теперь вы добавить новый код в конец текстового сегмента и вычислить адрес на основе смещения, когда сегмент загружается. Это значительно облегчает отладку и управление, поскольку вы заранее знаете, где именно в текстовом сегменте находится ваша функция.
Для вызова любой функции из другого исполняемого модуля в процессе работы также можно выполнить. Поскольку вы уже знаете смещения как исходной функции, так и следующей функции, вы можете рассчитать их точное местоположение на основе адреса загрузки модуля.
typedef void (*EXTPROC)(int a, int b);
// Windows loads the dll at 0xC0000
HMODULE hMod = LoadLibrary("some.dll");
// The function is at offset 0x10880 (from start of text segment)
EXTPROC proc = CalculateAddress(hMod, 0x00010880);
// Call proc at 0xd0880
proc(0, 1);
Функция CalculateAddress
извлекает базовый адрес DLL и вычисляет фактический адрес функции и возвращает указатель на него. Результат такой же, как в предыдущем примере - 0xD0880. Теперь, когда у вас есть адрес, вы можете вызвать его через указатель функции. Вы можете применить тот же метод для вызова новой функции, которую вы добавляете, так как вы знаете смещение этой функции.
Если вы хотите пройти лишнюю милю, вы можете даже обновить таблицу экспорта новыми позициями, указывающими на эти смещения, и использовать GetProcAddress
для извлечения адреса без необходимости его вычисления. Это немного усложняет процесс исправления, поскольку вам необходимо обновить дополнительный раздел в DLL.
Чтобы вызвать функцию, существующую в другой DLL, является более сложной задачей, так как вам потребуется выполнить временную палитку исходной функции, чтобы вызвать ее адрес внешнего. Для этого я рекомендую изучить предложение, сделанное в Rich, и создать прокси-библиотеку DLL, как описано в статье this.
Возможно, вам будет проще просто запланировать DLL. Добавьте новый код в конец текстового сегмента и переместите его в добавленный код в начале старой функции. –
На самом деле я просто понял, что это не вариант. Он должен перейти или вызвать функцию из другой dll. Это возможно? – Lukesmith
Если вы можете обновить свой вопрос с помощью дополнительных _details_, как вы хотите вызвать функцию из внешней DLL, я обновлю свой ответ, чтобы отразить изменения. –