Half-Life и Adrenaline Gamer форум

Всё об игре в Халф-Лайф и АГ
Текущее время: 28 мар 2024, 18:32

Часовой пояс: UTC + 5 часов [ Летнее время ]




Начать новую тему Ответить на тему  [ Сообщений: 18 ]  На страницу 1, 2  След.
Автор Сообщение
 Заголовок сообщения: Перехват status
СообщениеДобавлено: 01 июл 2015, 13:25 
Не в сети
Аватара пользователя
Зарегистрирован:
21 мар 2012, 13:21
Последнее посещение:
27 дек 2023, 02:51
Сообщения: 165
Можно ли средствами metamod перехватить команду status, либо подменить её вывод?

Код:
...
REG_SVR_COMMAND("status", my_status);
...
void DLLHIDDEN my_status(void) {
   META_CONS("Hello!!!");
}
...
Если сделать так, то при запуске будет обычное, ожидаемое сообщение:
Цитата:
Cmd_AddCommand: status already defined


Вернуться к началу
 Профиль 
  
 Заголовок сообщения: Re: Перехват status
СообщениеДобавлено: 01 июл 2015, 18:29 
Не в сети
Site Admin
Зарегистрирован:
01 июн 2010, 01:27
Последнее посещение:
26 мар 2024, 21:42
Сообщения: 6864
Через API нельзя.
Только через поиск в памяти и патчинг.


Вернуться к началу
 Профиль 
  
 Заголовок сообщения: Re: Перехват status
СообщениеДобавлено: 01 июл 2015, 19:07 
Не в сети
Аватара пользователя
Зарегистрирован:
21 мар 2012, 13:21
Последнее посещение:
27 дек 2023, 02:51
Сообщения: 165
А каким образом в памяти это искать?

_________________
Портал Half-Life DeathMatch


Вернуться к началу
 Профиль 
  
 Заголовок сообщения: Re: Перехват status
СообщениеДобавлено: 01 июл 2015, 19:42 
Не в сети
Site Admin
Зарегистрирован:
01 июн 2010, 01:27
Последнее посещение:
26 мар 2024, 21:42
Сообщения: 6864
О, блин, полез смотреть как, и понял что сказал неверно.
Можно через API.
https://svn.aghl.ru:8443/svn/HLSDK/trunk/dlls/memory.cpp
Задать где-нибудь структуру
Код:
struct CommandLink
{
   CommandLink *nextCommand;
   char *commandName;
   void (*handler)(void);
   int addedByMod;
};
Привести cl_enginefunc_s к виду
Код:
   void                  ( *pfnGetMousePos )( struct tagPOINT *ppt );
   void                  ( *pfnSetMousePos )( int x, int y );
   void                  ( *pfnSetMouseEnable )( qboolean fEnable );

   int      pfnUnks001[1];

   struct   CommandLink *      ( *pfnGetCommandsList )      ( void );
} cl_enginefunc_t;
Использовать такой код для поиска и подмены:
Код:
void (*g_pOldMotdWriteHandler)(void) = 0;
void MotdWriteHandler(void);

void PatchCommandsList(void)
{
   if (gEngfuncs.pfnGetCommandsList)
   {
      CommandLink *cl;

      // Unhook commands
      cl = gEngfuncs.pfnGetCommandsList();
      while (cl != NULL)
      {
         // Search by address cos some commands has invalidated name references due to unloading process
         if (g_pOldMotdWriteHandler && cl->handler == MotdWriteHandler && !_stricmp(cl->commandName, "motd_write"))
         {
            cl->handler = g_pOldMotdWriteHandler;
            g_pOldMotdWriteHandler = NULL;
         }
         cl = cl->nextCommand;
      }

      // Hook commands
      cl = gEngfuncs.pfnGetCommandsList();
      while (cl != NULL)
      {
         if (!_stricmp(cl->commandName, "motd_write"))
         {
            g_pOldMotdWriteHandler = cl->handler;
            cl->handler = MotdWriteHandler;
         }
         cl = cl->nextCommand;
      }
   }
}
Соответственно есть код для хука и для анхука. Поиск по адресу нужен чтобы не напороться на ссылки на строки в диапазоны адресов уже выгруженных модулей.

Добавлено спустя 1 час 10 минут 29 секунд:
Хотя, в этом случа можно без HookDWord обойтись. Просто заменить значение, оно в области данных находится.


Вернуться к началу
 Профиль 
  
 Заголовок сообщения: Re: Перехват status
СообщениеДобавлено: 02 июл 2015, 00:08 
Не в сети
Аватара пользователя
Зарегистрирован:
21 мар 2012, 13:21
Последнее посещение:
27 дек 2023, 02:51
Сообщения: 165
Погоди, я не настолько крут в написании модулей :)

Пока я дошел до этого:
Вложение:
my_plugin.zip [18.46 КБ]
Скачиваний: 454

Всё, что по сути там делается, это регается команда status2 и после её ввода отправляется ответ. Это всё в my_func.cpp

Что за gEngfuncs? Откуда её взять?
Как я понял, мне нужно еще что-то подключить.


Вернуться к началу
 Профиль 
  
 Заголовок сообщения: Re: Перехват status
СообщениеДобавлено: 02 июл 2015, 00:27 
Не в сети
Site Admin
Зарегистрирован:
01 июн 2010, 01:27
Последнее посещение:
26 мар 2024, 21:42
Сообщения: 6864
Подумал ещё немного и понял что тебе на сервер это надо, а я для клиента написал.
Сейчас напишу как на сервере делать.

Добавлено спустя 1 час 21 минуту 40 секунд:
Вобщем, наиболее оптимальным будет найти функцию Cmd_GetFirstCmd
Код:
typedef struct cmd_function_s
{
   struct cmd_function_s *next;
   char *name;
   xcommand_t function;
   int flags;
} cmd_function_t;

struct cmd_function_s *Cmd_GetFirstCmd(void);

Под линуксом поиск по имени, под виндой по сигнатуре:
Код:
   "A1D83E0002C39090 9090909090909090 6800000000 6800000000 E8",
   "FF00000000FFFFFF FFFFFFFFFFFFFFFF FF00000000 FF00000000 FF",

Дальше использовать как в коде выше. CommandLink - это и есть cmd_function_t.
Вместо
Код:
cl = gEngfuncs.pfnGetCommandsList();
Использовать найденную функцию.


Вернуться к началу
 Профиль 
  
 Заголовок сообщения: Re: Перехват status
СообщениеДобавлено: 02 июл 2015, 14:57 
Не в сети
Аватара пользователя
Зарегистрирован:
21 мар 2012, 13:21
Последнее посещение:
27 дек 2023, 02:51
Сообщения: 165
Что-то делаю не так.

Код:
#include <extdll.h>
#include <meta_api.h>

#include "sdk_util.h"
#include "my_func.h"

typedef void ( *xcommand_t ) ( void );

typedef struct cmd_function_s
{
   struct cmd_function_s *next;
   char *name;
   xcommand_t function;
   int flags;
} cmd_function_t;

struct cmd_function_s *Cmd_GetFirstCmd(void);

void PatchCommandsList(void)
{
   cmd_function_s *cm;
   cm = Cmd_GetFirstCmd();
   
   while (cm != NULL) {
      // Search by address cos some commands has invalidated name references due to unloading process
      if (!strcasecmp(cm->name, "status")) {
         cm->function = NULL;
      }
      cm = cm->next;
   }   
}

void run_my_func()
{
   SERVER_PRINT("All okay\n");
   REG_SVR_COMMAND("status2", my_status);
   PatchCommandsList();
}

void my_status()
{
   SERVER_PRINT("HI!!!\n");
}

В этом случае модуль не грузится (BAD Load).
Если закомментировать
Код:
cm = Cmd_GetFirstCmd();
То произойдёт crash, что итак понятно.
А если вместе с while закомментировать, то модуль запускается. Разве, что нужная подмена status не работает.


Вернуться к началу
 Профиль 
  
 Заголовок сообщения: Re: Перехват status
СообщениеДобавлено: 02 июл 2015, 17:40 
Не в сети
Site Admin
Зарегистрирован:
01 июн 2010, 01:27
Последнее посещение:
26 мар 2024, 21:42
Сообщения: 6864
Код:
struct cmd_function_s *Cmd_GetFirstCmd(void);
Это был лишь прототип функции из движка, чтобы было понятнее о чем речь идет.
Тебе надо так:
Код:
typedef struct cmd_function_s *Cmd_GetFirstCmd_Type(void);
Cmd_GetFirstCmd_Type *pCmd_GetFirstCmd = NULL;

   cm = pCmd_GetFirstCmd();
Т.е. надо указатель на функцию использовать, и для этого надо найти адрес этой функции.
У тебя, похоже, линукс, так что это не сложно:
Код:
size_t HIDDEN FindSymbol(const char* symbolName)
{
   size_t moduleHandle = (size_t)dlopen("engine_i486.so", RTLD_NOW);   // lock from unloading
   size_t address;
   address = (size_t)dlsym((void *)moduleHandle, symbolName);
   return address;
}

   pCmd_GetFirstCmd = (Cmd_GetFirstCmd_Type *)FindSymbol("Cmd_GetFirstCmd");
И ты не можешь просто занулить адрес хендлера
Код:
cm->function = NULL;
Тебе надо свой туда прописать (например my_status). Иначе упадет при вызове в движке.


Вернуться к началу
 Профиль 
  
 Заголовок сообщения: Re: Перехват status
СообщениеДобавлено: 02 июл 2015, 18:27 
Не в сети
Аватара пользователя
Зарегистрирован:
21 мар 2012, 13:21
Последнее посещение:
27 дек 2023, 02:51
Сообщения: 165
Благодарю! Получилось.
Результат ниже, может кому ещё пригодится.
 Результат


Вернуться к началу
 Профиль 
  
 Заголовок сообщения: Re: Перехват status
СообщениеДобавлено: 29 июл 2015, 23:46 
Не в сети
Аватара пользователя
Зарегистрирован:
07 мар 2015, 19:26
Последнее посещение:
30 июл 2015, 15:57
Сообщения: 5
Здраствуйте. Хотелось бы отойти от темы т.к. я знаком разве, что с такими языками как html/pawn,для начала хотел бы узнать, как компилировать плагины для метомода и, что для этого нужно.
И второе, если перехватывать команду status таким способом, возможно ли посредствам amxx плагина выводить свою информацию (где эта информация будет выводится при вводе status), не будит ли она блокирована т.к. команда status будет перехвачена.
Спасибо :)


Вернуться к началу
 Профиль 
  
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 18 ]  На страницу 1, 2  След.

Часовой пояс: UTC + 5 часов [ Летнее время ]


Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 2


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

Найти:
Перейти:  
cron
Создано на основе phpBB® Forum Software © phpBB Group
Русская поддержка phpBB