[SourcePawn] Вызов функций из других плагинов

  • Автор DeathScore13
  • Дата публикации
  • Обновлено
  • Article read time 3 min read
Эта статья подойдёт для тех, кто пытается взломать/защитить приватные работы или столкнулся с отсутствием нормального апи

Сразу скажу, что вызвать функцию которой нет в секции .publics не получится, т.к. такую функцию можно считать "истинно локальной", вызвать которую можно разве что из-под более низкоуровневого яп чем сп. Функции может не быть там по 2-м причинам:
  1. Плагин собирался на версии компилятора ниже 1.7;
  2. Кто-то заморочился при сборке, поскольку компилятор явно был модифицирован.
Форварды, каллбеки и функции с модификатором public всегда находятся в .publics

Итак, допустим следующий код был собран на 1.10:
C-подобный:
#include <sourcemod>

public void OnPluginStart()
{
    func("test");
}

void func(const char[] text)
{
    PrintToServer(text);
}
Запускаем и видим в консоли "test"

Теперь начинается какое-то волшебство:
  1. Открываем smxviewer (надеюсь, не надо разжёвывать как его собрать или хотя бы где взять уже собранный)
  2. Ищем имя функции. Если был указан модификатор public, то имя останется таким же, если нет, то к нему будет добавлен адрес в формате .адрес.имя
    1690654192792.png

  3. Набрасываем следующий код, где 1 - идентификатор функции из секции .publics
    C-подобный:
    #include <sourcemod>
    
    public void OnPluginStart()
    {
        PrivateForward fwd = new PrivateForward(ET_Ignore, Param_String);
    
        // в 1.10 здесь будет предупреждение, которое можно проигнорировать, но в 1.11+
        // приведение к типу Function вызовет ошибку и плагин не соберётся
        fwd.AddFunction(FindPluginByFile("test.smx"), view_as<Function>(1));
    
        Call_StartForward(fwd);
        Call_PushString("test2");
        Call_Finish();
    }
    Запускаем и видим в консоли "test2"

    Версия для 1.11+ (используется эксплойт с не определённым размером массива):
    C-подобный:
    #include <sourcemod>
    
    int ptr[1];
    Function func;
    
    void memset(int[] p, int off, int val)
    {
        p[off] = val;
    }
    
    Function getFunc(int f)
    {
        memset(ptr, 1, f);
        return func;
    }
    
    public void OnPluginStart()
    {
        PrivateForward fwd = new PrivateForward(ET_Ignore, Param_String);
        fwd.AddFunction(FindPluginByFile("test.smx"), getFunc(1));
    
        Call_StartForward(fwd);
        Call_PushString("test2");
        Call_Finish();
    }
Либо сделайте автоматическое получение идентификатора функции из имени через GetFunctionByName. Локальные имена придётся указывать в формате .адрес.имя

Единственное что 100% советую делать при использовании этой плюхи - выносить идентификаторы/имена функций в геймдату (см. след. страницу), ибо пересобирать решение после каждого обновления целевого плагина, которое может всё сломать, - не комильфо

А теперь приступим к "защите". У сторонних плагинов нет доступа к .data секции, поэтому если записывать туда данные, передавать в функцию и сверять их, то это можно считать как решение нашей головной боли
C-подобный:
#include <sourcemod>

int protect;

public void OnPluginStart()
{
    protect = GetRandomInt(1, 100500);
    func(protect, "test")
}

void func(int data, const char[] text)
{
    if (data != protect)
        SetFailState("Гэндальф неодобрительно покачивает головой");
 
    PrintToServer(text);
}
Старайтесь не использовать эксплойт с не определённым размером массива, поскольку в этом случае у других плагинов будет доступ к .data секции (пример), либо соберите плагин с "истинно локальными" функциями используя компилятор по ссылке ниже

Модификация последней версии из стабильной ветки (1.11-dev) с "истинно локальными" функциями: Releases · deathscore13/sourcepawn-publics
Об авторе
DeathScore13
Їду я якось до магазину. До магазину прикиньте, а я у Дніпрі живу. Ну, на дні Дніпра. Та немає там магазинів, там одна рибка пливе і така: "буль-буль". Я такий: "Хо хо, щось сєлєдь сьодні дешева"

Комментарии

Нет комментариев для отображения.

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

Автор
DeathScore13
Article read time
3 min read
Просмотры
1,288
Последнее обновление

Ещё в Разработка

Поделиться этой статьёй

Сверху Снизу