@MichaelOne

Хук функции в Android shared object?

Есть приложение для андроида, которое грузит две библиотеки (то есть два .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 или подобные утилиты.
Да, я знаю, что для хука необходимо сохранить пролог функции предварительно, это пропущено здесь для краткости и ясности изложения.
Спасибо.
  • Вопрос задан
  • 158 просмотров
Пригласить эксперта
Ответы на вопрос 1
jcmvbkbc
@jcmvbkbc
http://dilbert.com/strip/1998-08-24
*(unsigned int*)&hookProc[6] = function;  // Заменить 4 байта нужным адресом.

Не, не надо так делать. Правильно будет -- memcpy(hookProc + 6, &function, sizeof(function)).

(void*)(address & 0x0xFFFFF000), sizeof(hookProc)

Скорее всего не является причиной проблемы, но выглядит неправильно. Правильно было бы
(void*)(address & 0xFFFFF000), ((address + sizeof(hookProc) + 0xfff) & 0xfffff000) - (address & 0xfffff000)
.

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

Ты можешь привести дамп (т.е. адреса и байты) этой области памяти до и после записи?
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы