Есть приложение для андроида, которое грузит две библиотеки (то есть два .so) файла. Мне необходимо с помощью кода во второй библиотеке заменить функцию из первой библиотеки - то есть простыми словами, сделать хук на свою функцию.
Есть адрес нужной функции, её дизассемблированый вариант (то есть я знаю, что места для установки хука достаточно) и написан такой код:
void hook(unsigned int address, unsigned int function) {
unsigned char hookProc[] = {
0xFA, 0x46,
0xF0, 0x00, 0xF8, 0x5F,
0x00, 0x00, 0x00, 0x00
};
// Функция хукаемой библиотеки использует THUMB режим инструкций"
// Первые два байта - это инструкция 'mov r10, pc' - чтобы знать, куда возвращаться после выполнения своего кода.
// Следующие 4 байта - это инструкция 'ldr pc, [pc, #-4]' - загрузка в PC адреса куда нужно перейти. Следующие после этого 4 байта и есть этот адрес для перехода.
*(unsigned int*)&hookProc[6] = function; // Заменить 4 байта нужным адресом.
mprotect((void*)(address & 0x0xFFFFF000), sizeof(hookProc), PROT_READ | PROT_WRITE);
// "снять защиту" с участка памяти чтобы иметь возможность записи туда.
memcpy((void*)address, (void*)hookProc, sizeof(hookProc));
// Скопировать код хука по указанному адресу.
__builtin___clear_cache((char*)address, (char*)(address + sizeof(hookProc)));
// ClearCache в версии для андроида.
mprotect((void*)(address & 0x0xFFFFF000), sizeof(hookProc), PROT_READ | PROT_EXEC);
}
Проблема в том, что код модифицируется прекрасно, однако, если встречается инструкция перехода (условный или нет - не важно), то она остаётся не тронутой. То есть, имели:
push {r1, lr} sub
sp, #4
blx _Foobar
mov r1, #1
...
И после копирования стало так:
mov r10, pc
ldr pc, [pc, #-4]
blx _Foobar
mov r1, #1
...
То есть видно, что не изменилась инструкция перехода со сменой режима. Исходя из описания функции builtin_clear_cache, она должна делать всё тоже самое, что и cacheflush - вызвать инструкции isb, idm и прочее.
Почему так происходит? Как это можно исправить, чтобы код при копировании заменял всё, что нужно, а не оставлял инструкции перехода нетронутыми?
Нет, я не могу модифицировать первую библиотеку "руками". Нет, я не хочу использовать FRIDA или подобные утилиты.
Да, я знаю, что для хука необходимо сохранить пролог функции предварительно, это пропущено здесь для краткости и ясности изложения.
Спасибо.