Здравствуйте. Пишу сюда, тк столкнулся с такой проблемой: При установке хука на FreeHeap под 64bit получаю эксепшн. При отладке выяснилось следующее: Опкод FFh 15h содержит относительный адрес, а не абсолютный, как в x86-32: Опкод 32: Код (Text): 0x75B50000 ff 15 ec 05 d5 75 Студия интерпретирует как: Код (Text): 0x75B50000 call dword ptr ds:[75D505ECh]) Адрес абсолютный, по нему действительно можно найти __imp__RtlFreeHeap Опкод 64: Код (Text): 0x000007FFFFB90004 ff 15 26 a0 07 00 Студия интерпретирует как: Код (Text): 0x000007FFFFB90004 call qword ptr [7FFFFC0A030h] ; 7FFFFC0A030h == 0x000007FFFFB90004 + 0x6 + 0x7A026 Адрес относительный и соответственно, при создании трамплина, мы должны учитывать дельту м-ду оригинальной функцией и трамплином. Однако открываю "Intel 64 and IA-32 Architectures Software Developer's Manual, Volume 2a", page 188: ---------------------------------------------------------------------------------------------------------------- Opcode | Instruction | Op/En | 64-bit Mode | Compat/ Leg Mode | Description ---------------------------------------------------------------------------------------------------------------- FF /2 CALL r/m32 B N.E. Valid Call near, absolute indirect, address given in r/m32. FF /2 CALL r/m64 B Valid N.E. Call near, absolute indirect, address given in r/m64. Укажите, пожалуйста, на ошибку в моих рассуждениях/дыру в знаниях. Brest regards, Fukki.
Есть много способов, чтобы обойти это ограничение. Например вместо call, использовать последовательность инструкций любой_оффсет - это уже абсолютный 8-байтный аддресс.
Я может немного неясно выразился, но у меня не стоит вопроса в том, чтобы совершить прыжок по 64-битному RVA. Вопрос в следующем: в документации ясно сказано, что прыжок должен быть относительный, а мои глаза и дизассемблер говорят обратное. Ведь не может же быть ошибки, а значит я не прав, непонятно лишь где.
r/m64 значит что в регистре/по адресу лежит абсолютный адрес прыжка. однако сам адрес, по которому лежит этот абсолютный адрес для перехода является относительным.
какая разница про что? если разобрать механизм, то будет видно что имело в виду intel, когда писали "absolute indirect"
Допустим, что так. Тогда что с r/m32, ведь следуя вашей логике, это относительный адрес, по которому лежит абсолютный, только уже размером в dword, а не qword. Хотя, в приведенном мною примере под x32, за опкодом следует само Значение прыжка, а не адрес, где оно содержится. И еще, если вы правы, то пройдя по RIP + 0x6 + 0x7A026 (опкод: ff 15 ec 05 d5 75) я должен извлечь оттуда абсолютный адрес __imp__RtlFreeHeap, но там находится сама функция а не ее RVA. Создается впечатление, что мы говорим о разных вещах.. может FF 15 это вовсе не FF/2 r/m32(64) ?? :P Я выделяю память под трамплин в том же сегменте, так что уместится.
> Тогда что с r/m32 r/m32 - абсолютная адресация. в этом одно из отличий 64-битного режима. > но там находится сама функция а не ее RVA. > call qword ptr [7FFFFC0A030h] малость не соответствует.
слышал звон на rdsn что непосредственная адресация в х64 приказала долго жить и необходимо городить фиктивное базирование (по базе 0)
>r/m64 значит что в регистре/по адресу лежит абсолютный адрес прыжка. Только что специально зашел под отладчиком посмотреть а так ли. Итак, процесс 64бит, отладчик ВС, Идем по HeapFree: Код (Text): HeapFree: 0000000077692C70 sub rsp,28h 0000000077692C74 call qword ptr [__imp_RtlFreeHeap (7770CCA0h)] ; ff 15 26 a0 07 00 0000000077692C7A movzx eax,al 0000000077692C7D add rsp,28h 0000000077692C81 ret Т.о., исходя из выше сказанного, по адресу 0000000077692C7A + 0x7a026 должен находится абсолютный адрес __imp_RtlFreeHeap. Идем туда: Код (Text): __imp_RtlFreeHeap: 000000007770CCA0 rcr byte ptr [rsi+rcx*4],1 ; d0 1c 8e 77 00 00 00 00 000000007770CCA3 ja __imp_RtlFreeHeap+5 (7770CCA5h) 000000007770CCA5 add byte ptr [rax],al 000000007770CCA7 add byte ptr [rax+778CB5h],dh 000000007770CCAD add byte ptr [rax],al Как видно, в операнде находится не адрес с RVA функции, а само смещение на нее (относительное). PS: Спасибо, что пытаетесь помочь.
Fukki Другими словами если в ModRM задает адрес ячейки, то он будет вычисляться относительно RIP следующей команды (в аргументе хранится относительный адрес). В тоже время значение в этой ячейке (на примере с CALL [...]) будет представлять из себя абсолютный адрес.
Fukki А вот и не видно. Чем Вам 778E1CD0, находящийся по адресу 7770CCA0, — не адрес функции? (кстати в операнде находится относительное смещение области памяти, содержащей не RVA, а VA функции)
> Т.о., исходя из выше сказанного, по адресу 0000000077692C7A + 0x7a026 должен находится абсолютный адрес __imp_RtlFreeHeap. Идем туда: угу, я его и вижу, например. ну да, как я и писал в одном из ранних постов.