Как пропатчить сервер?

memoryUser

Новичок
Автор темы
2
0
Делаю плагин, который будет менять нетгейм версион на сервере. нашел адрес, выставил права через mprotect и устанавливаю значение. при коннекте игрока, у которого версия 4057, отличающаяся от той, которую я установил, то сервер крашится и выдает segmentation fault. пытался прибавлять к адресу 1 и 2 байта, но при коннекте крашится с ошибкой illegal instruction. что сделать можно? версия сервера 0.3.7
 

loverkis

Участник
136
18
Найди точный адрес версии
Качай Cheat Engine или GDB
Ищи строку "0.3.7" в памяти сервака.
Если адрес неправильный — всё сломаешь. Для 0.3.7-R1 адрес обычно 0x4B17C8, но гугли свою сборку.
Оригинал: 0.3.7\0 (5 символов с нулем в конце).
Твой патч: 4057\0 (тоже 5 символов!). Если пишешь только 4 байта — сервер будет читать мусор и крашиться. Пиши так:
Код:
memcpy((char*)addr, "4057\0", 5);
Перед записью в память:
Код:
uintptr_t page_start = addr - (addr % 4096);
mprotect((void*)page_start, 4096, PROT_READ | PROT_WRITE);
После записи верни права обратно:
Код:
mprotect((void*)page_start, 4096, PROT_READ);
Смотри дамп памяти в GDB:
Код:
gdb -ex "x/8bx 0xадрес" -ex "quit" ./samp03svr
Запусти сервер через GDB и лови креш:
Код:
gdb --args ./samp03svr
(gdb) run
# при краше:
(gdb) bt full
Посмотри, где именно упало (типа crashdetect) конфликтует. Пример через хуки:
Код:
int (*original_check)(const char*);
int my_check(const char* ver) {
    return 0;
}
Где чаще всего косячат:

Не добавили \0 в конце строки
Использовали strcpy вместо memcpy (если оригинал длиннее)
Неправильный адрес версии (проверь через gdb!)
Забыли сделать mprotect перед записью
Если всё это не помогло — ищи, нет ли проверок на CRC или сигнатуры кода. Для 0.3.7 это редко, но бывает в кастомных сборках.
 

memoryUser

Новичок
Автор темы
2
0
Найди точный адрес версии
Качай Cheat Engine или GDB
Ищи строку "0.3.7" в памяти сервака.
Если адрес неправильный — всё сломаешь. Для 0.3.7-R1 адрес обычно 0x4B17C8, но гугли свою сборку.
Оригинал: 0.3.7\0 (5 символов с нулем в конце).
Твой патч: 4057\0 (тоже 5 символов!). Если пишешь только 4 байта — сервер будет читать мусор и крашиться. Пиши так:
Код:
memcpy((char*)addr, "4057\0", 5);
Перед записью в память:
Код:
uintptr_t page_start = addr - (addr % 4096);
mprotect((void*)page_start, 4096, PROT_READ | PROT_WRITE);
После записи верни права обратно:
Код:
mprotect((void*)page_start, 4096, PROT_READ);
Смотри дамп памяти в GDB:
Код:
gdb -ex "x/8bx 0xадрес" -ex "quit" ./samp03svr
Запусти сервер через GDB и лови креш:
Код:
gdb --args ./samp03svr
(gdb) run
# при краше:
(gdb) bt full
Посмотри, где именно упало (типа crashdetect) конфликтует. Пример через хуки:
Код:
int (*original_check)(const char*);
int my_check(const char* ver) {
    return 0;
}
Где чаще всего косячат:

Не добавили \0 в конце строки
Использовали strcpy вместо memcpy (если оригинал длиннее)
Неправильный адрес версии (проверь через gdb!)
Забыли сделать mprotect перед записью
Если всё это не помогло — ищи, нет ли проверок на CRC или сигнатуры кода. Для 0.3.7 это редко, но бывает в кастомных сборках.
в clientjoin сервера, есть netgame_version который в 0.3.7 имеет число 4057, в хексе FD9. если не ошибаюсь, memcpy для строки, у меня целочисленное значение
 

loverkis

Участник
136
18
Запусти сервер и подключись к нему через CE.
В типе поиска выбери 4-байтное значение (int).
Введи текущее значение версии (4057) → First Scan.
Смени версию на другое число (например, через код) → Next Scan.
Найденный адрес будет адресом netgame_version. Вместо memcpy используй запись напрямую в память:
Код:
uintptr_t netgame_version_addr = 0xABCD1234; // Замени на реальный адрес

// Изменить версию на 4057 (0xFD9)
*(int*)netgame_version_addr = 4057;

// Или через memcpy (если над):
int new_version = 4057;
memcpy((void*)netgame_version_addr, &new_version, sizeof(int));
Посмотри дамп памяти для адреса: gdb -ex "x/xw 0xABCD1234" -ex "quit" ./samp03svr Вывод должен содержать 0xfd9 (4057 в hex). Сервер может перезаписывать netgame_version при старте. Найди код инициализации версии через дизассемблер (IDA Pro/Ghidra) и патчи там:
Код:
; Пример для 0x555555:
mov dword ptr [netgame_version_addr], 0xFD9
мб у тебя ошибки по типу использование строк вместо чисел: netgame_version — это int, а не строка. неправильный размер данных: Для 4-байтного int используй sizeof(int), а не длину строки отсутствие mprotect: Даже для чисел нужны права на запись:
Код:
uintptr_t page = netgame_version_addr & ~(4095); // Выравнивание
mprotect((void*)page, 4096, PROT_READ | PROT_WRITE);
*(int*)netgame_version_addr = 4057;
mprotect((void*)page, 4096, PROT_READ);
Если сервер использует проверки целостности:
найди вызовы функций типа CheckNetgameVersion в IDA. Хукни проверку:
Код:
int (*orig_check)(void);
int hook_check() {
    return 1; // Всегда возвращаем "версия валидна"
}
используй библиотеки типа MinHook для перехвата. Если netgame_version — это int, патчь его как число, а не как строку. Для строки версии (например, "0.3.7") используй отдельный адрес (как в предыдущих ответах).