Как перехватить вызов функции на x64?

Тема в разделе "WASM.BEGINNERS", создана пользователем MikhailKM, 30 окт 2010.

  1. MikhailKM

    MikhailKM New Member

    Публикаций:
    0
    Регистрация:
    4 фев 2010
    Сообщения:
    18
    На x86 делаю так:
    Код (Text):
    1. char* pFunc = (char*) GetProcAddress( hModule, FunctionName );
    2.  
    3. char* pAddr1 = pFunc + 1 + sizeof( int );
    4. char* pAddr2 = (char*) &MyFunction;
    5. int RelativeAddr = pAddr2 - pAddr1;
    6.  
    7. char arr[ 1 + sizeof( RelativeAddr ) ];
    8. arr[ 0 ] = (char) 0xE9;  // JMP absolute
    9. memcpy( arr + 1, &RelativeAddr, sizeof( RelativeAddr ) );
    10.  
    11. SIZE_T bytesWritten;
    12. WriteProcessMemory( GetCurrentProcess(), pFunc, arr, sizeof( arr ), &bytesWritten );
    Как написать аналогичный перехват на x64?
     
  2. max7C4

    max7C4 New Member

    Публикаций:
    0
    Регистрация:
    17 мар 2008
    Сообщения:
    1.203
    MikhailKM
    В реализации на си мало что изменится, если понимаете, что тут происходит.
     
  3. MikhailKM

    MikhailKM New Member

    Публикаций:
    0
    Регистрация:
    4 фев 2010
    Сообщения:
    18
    Видимо надо использовать команду
    FF /4 JMP r/m64 Jump near, absolute indirect, RIP = 64-Bit offset from register or memory
    но не знаю, как машинными кодами сослаться на память, где сохранен адрес функции
     
  4. ziral2088

    ziral2088 New Member

    Публикаций:
    0
    Регистрация:
    16 авг 2009
    Сообщения:
    283
    MikhailKM
    возьми откомпиль в фасме код и глянь что он сгенерирует.
     
  5. MikhailKM

    MikhailKM New Member

    Публикаций:
    0
    Регистрация:
    4 фев 2010
    Сообщения:
    18
    Давайте подробнее, я раз в год программируемую на ассемблере, фасма нет, зато есть VS2010.

    Как смоделировать jmp не понимаю, если писать в коде goto label на метку в своем коде, то C++ использует переход E9 на четырехбайтовое смещение относительно текущего адреса, а мне нужен переход на далекий адрес.

    Можно посмотреть на call, он похоже кодируется
    FF /2 CALL r/m64 Call near, absolute indirect, address given in r/m64.

    В отладчике вижу такое
    Код (Text):
    1.         // Получаю адрес функции, которая может находиться далеко от текущего кода, дальше 4 млрд. байт
    2.         FARPROC fp= GetProcAddress( hModule, FunctionName );
    3. 000000013F57F15A  lea         rdx,[string FunctionName (13F59AA90h)]  
    4. 000000013F57F161  mov         rcx,qword ptr [rsp+30h]  
    5. 000000013F57F166  call        qword ptr [__imp_GetProcAddress (13F5A9070h)]  
    6. 000000013F57F16C  mov         qword ptr [rsp+38h],rax  
    7.  
    8.         // Смотрим, как C++ делает вызов
    9.         fp();
    10. 000000013F57F171  call        qword ptr [rsp+38h]
    Смотрим в память
    Код (Text):
    1. 0x000000013F57F171  ff 54 24 38 48 8d 15 14 b9 01 00 48 8b
    Пожалуйста, видим FF, следующие байты объясняют, что именно эти FF делают, откуда берется адрес, даже +38h видны.

    Пока не понятно, как эти упражнения помогут добиться перехвата на x64.
     
  6. ziral2088

    ziral2088 New Member

    Публикаций:
    0
    Регистрация:
    16 авг 2009
    Сообщения:
    283
    фасм ставить 30 секунд. Ты пост гораздо дольше писал, уже давно бы глянул как он генерирует прыжки.

    Код (Text):
    1. use64
    2. jmp far [rax]
    генерирует:
    0xFF , 0x28

    Код (Text):
    1. use64
    2. call far [rax]
    0xFF , 0x18

    запишите в начало функции:
    Код (Text):
    1. use64
    2. mov rax  ,123456789h;offset of hook
    3. jmp rax
    Сгерененый код:
    0x48, 0xB8, 0x89, 0x67, 0x45, 0x23, 0x01, 0x00, 0x00, 0x00, 0xFF, 0xE0

    это самое простое что есть.
     
  7. MikhailKM

    MikhailKM New Member

    Публикаций:
    0
    Регистрация:
    4 фев 2010
    Сообщения:
    18
    ziral2088, спасибо!