Добро пожаловать на Pro Pawn - Портал о PAWN-скриптинге.
Показано с 1 по 4 из 4
  1. #1
    Аватар для oukibt
    Пользователь

    Статус
    Оффлайн
    Регистрация
    27.02.2020
    Сообщений
    26
    Репутация:
    3 ±

    Вызов / перехват public-функций

    Приветствую, собственно, появился вопрос, как перехватить или хотя бы вызвать public-функцию (коллбэк) из плагина. Это, по идее, должно делаться примерно также, как и с нативными функциями, так как в структуре AMX_HEADER предусмотрена запись оффесета не только нативных функций, но и public-функций. Код в итоге выглядит примерно вот так, но не работает.

    1. int index;
    2. if(amx_FindPublic(amx, "OnPlayerConnect", &index) != AMX_ERR_NONE) return logprintf("Not found"), 0;
    3.  
    4. AMX_HEADER* hdr = (AMX_HEADER*)amx->base;
    5. AMX_FUNCSTUB* func_stub = GETENTRY(hdr, publics, index);
    6.  
    7. AMX_CALLBACK Callback = (AMX_CALLBACK)func_stub->address;
    8.  
    9. cell retval , PARAMS[] = { 4, 5 };
    10.  
    11. Callback(amx, index, &retval, PARAMS);
    Последний раз редактировалось oukibt; 09.07.2021 в 19:02.

  2. #2
    Аватар для Daniel_Cortez
    "Это не хак, это фича"

    Статус
    Оффлайн
    Регистрация
    06.04.2013
    Адрес
    Novokuznetsk, Russia
    Сообщений
    2,192
    Репутация:
    2589 ±
    Так это ж не нативный код, а интерпретируемый. Вызывать его следует с помощью функции amx_Exec.
    Индивидуально в ЛС по скриптингу не помогаю. Задавайте все свои вопросы здесь (click).

  3. #3
    Аватар для oukibt
    Пользователь

    Статус
    Оффлайн
    Регистрация
    27.02.2020
    Сообщений
    26
    Репутация:
    3 ±
    Об этом я, к сожалению, вспомнил только после этого ответа. А можно ли как-нибудь хукнуть вызов коллбэка?
    Есть, конечно, один вариант, до которого я додумался, но он, как не странно, костыльный.
    Напрямую в павн создавать нужный коллбэк, и вызывать в нём нативную функцию. В плагине она, в принципе, будет выступать, как коллбэк, но опять же, способ не очень из-за костыля
    Последний раз редактировалось oukibt; 09.07.2021 в 22:32.

  4. #4
    Аватар для oukibt
    Пользователь

    Статус
    Оффлайн
    Регистрация
    27.02.2020
    Сообщений
    26
    Репутация:
    3 ±
    Проблема решена. В конечном счёте, я разобрался, и вот решение.

    Я использовал библиотеку subhook от Zeex (https://github.com/Zeex/subhook)
    Пару функций я взял из sampgdk

    Пример будет приведён на коллбэке OnPlayerText

    1. cell* amx_GetParamStart(AMX* amx)
    2. {
    3. unsigned char* data = amx->data != NULL
    4. ? amx->data
    5. : amx->base + ((AMX_HEADER*)amx->base)->dat;
    6. return (cell*)(data + amx->stk);
    7. }
    8.  
    9. void amx_GetParamValue(AMX* amx, int index, cell* param)
    10. {
    11. *param = amx_GetParamStart(amx)[index];
    12. }
    13.  
    14. subhook_t amx_Exec_hook;
    15.  
    16. void amx_Exec_func(AMX* amx, cell* retval, int index)
    17. {
    18. subhook_remove(amx_Exec_hook);
    19.  
    20. logprintf("Public-function index: %d", index);
    21. if (index == 10) // У меня 10 = индексу OnPlayerText
    22. {
    23. int playerid;
    24. char text[145];
    25. int len;
    26. cell* addr;
    27.  
    28. amx_GetParamValue(amx, 0, &playerid);
    29.  
    30. amx_GetAddr(amx, amx_GetParamStart(amx)[1], &addr); // [1] - это номер параметра, как и 0 на строку выше
    31. amx_StrLen(addr, &len);
    32. amx_GetString(text, addr, NULL, len + 1);
    33.  
    34. logprintf("%d | %s", playerid, text);
    35. }
    36.  
    37. amx_Exec(amx, retval, index);
    38.  
    39. subhook_install(amx_Exec_hook);;
    40. }
    41.  
    42. PLUGIN_EXPORT bool PLUGIN_CALL Load(void** ppData)
    43. {
    44. #ifndef WIN32_
    45. amx_Exec_hook = subhook_new((void*)0x401C90, (void*)amx_Exec_func, {}); // Адрес для Виндовс
    46. #else
    47. amx_Exec_hook = subhook_new((void*)0x8096780, (void*)amx_Exec_func, {}); // Адрес для Линукс
    48. #endif
    49. subhook_install(amx_Exec_hook);
    50.  
    51. return true;
    52. }


    Эти адреса - адреса функции amx_Exec непосредственно в samp-server.exe и samp03svr

    В функцию amx_Exec_func в аргумент index приходит индекс коллбэка. Через amx_FindPublic мы можем сравнять индексы, и узнать, какой именно коллбэк был вызван.

    P.S. На линуксе я не тестировал, но уверен, что адрес подойдёт
    Последний раз редактировалось oukibt; 11.07.2021 в 00:30.

  5. Пользователь сказал cпасибо:
    execution (07.11.2021)
 

 

Информация о теме

Пользователи, просматривающие эту тему

Эту тему просматривают: 1 (пользователей: 0 , гостей: 1)

Ваши права

  • Вы не можете создавать новые темы
  • Вы не можете отвечать в темах
  • Вы не можете прикреплять вложения
  • Вы не можете редактировать свои сообщения
  •