Русское сообщество по скриптингу

Orpheu: Поиск функций в библиотеках

Статьи или фрагменты кода для новичков и уже опытных скриптеров по AMXX.

Модератор: Chuvi

Правила форума
1. Запрещено материться и оскорблять других участников форума.
2. Запрещен флуд, оффтоп, дабл постинг во всех разделах форума, кроме раздела "Болтовня".
3. Запрещено взламывать сайт/форум или наносить любой вред проекту.
4. Запрещено рекламировать другие ресурсы.
5. Запрещено создавать темы без информативного названия. Название темы должно отображать ее смысл.

В данном разделе форума разрешено создавать темы, касающие только обучающему материалу по AMX Mod X.

Orpheu: Поиск функций в библиотеках

Сообщение DJ_WEST » 29 апр 2010, 13:34

Авторы: joaquimandrade
Перевод и редактирование: DJ_WEST

1. Вступление.
Данная статья поможет вам находить функции в библиотечных файлах, для их дальнейщего использования в скриптинге с помощью модуля Вы должны зарегистрироваться, чтобы видеть ссылки.. Поиск функции означает найти ее позицию в библиотечном файле, что обычно называют смещением (offset). Смещение - это количество байтов, начиная с начала библиотеки, которые необходимы пройти, чтобы найти функцию.

В библиотеках, скомпиленных с помощью gcc (linux), смещения помечены символическими именами, с помощью которых можно легко понять, что в них находится. В библиотеках, скомпиленных с помощью VC++ (windows), смещения не помечены именами, поэтому необходимо использовать поиск строк в библиотеке. Потому что с помощью строк вы сможете понять, что выполняет та или функция. К примеру, строка "Terrorists Win" уже говорит нам о том, что мы нашли функцию, которая работает с окончанием раунда.

2. Начало работы с программой.
Итак, для простоты поиска функций мы будем пользоваться библиотекой игры из linux. Для дальнейщего выполнения данной статьи нам понадобится программа IDA Pro Disassembler (не бесплатная). Бесплатная версия данной программы нам не подходит. Просьба не спрашивать на форуме, где можно найти/скачать данную программу, ищите сами с помощью поисковиков.

Запускаем IDA Pro. Затем, как появится данное окно:
ida_pro_1.jpg

Нажимаем New.

Если мы открываем linux библиотеку, то выбираем закладку Unix, затем опцию ELF/COFF Dynamic Library:
ida_pro_2.jpg


Если мы открываем windows библиотеку, то выбираем закладку Windows, затем опцию PE Dynamic Library:
ida_pro_3.jpg


Затем выберите библиотечный файл (к примеру, cs_i386.so или mp.dll) и откройте его.

Нажмите Ctrl + F5. Откроется новое диалоговое окно, в котором можно выбрать директорию, куда нужно сохранить декомпиленный файл библиотеки. Основная возможность программы IDA - это конвертация машинного кода обратно в C код, далеко от читаемого и не всегда схожего с оригинальным, но лучше понимаемого, чем машинный.

3. Поиск функции.
В декомпиленной версии linux библиотеки (в данном случае файл cs_i386.c) можно найти следующий код (он может немного отличаться от вашего, потому что в разных версиях библиотек код мог быть изменен разработчиками):
Код: Выделить всё
//----- (000B3C10) --------------------------------------------------------
int __cdecl InstallGameRules()
{
  int result; // eax@2
  int v1; // eax@2
  int v2; // eax@3

  (*(void (__cdecl **)(_DWORD))&g_engfuncs[156])("exec game.cfg\n");
  (*(void (**)(void))&g_engfuncs[160])();
  if ( *(float *)(gpGlobals + 20) == 0.0 )
  {
    v2 = __builtin_new(0x2C4u);
    result = __18CHalfLifeMultiplay(v2);
  }
  else
  
{
    v1 = __builtin_new(0x2D8u);
    result = __17CHalfLifeTraining(v1);
  }
  return result;
}

Данная функция называется InstallGameRules, в ней мы можем найти использование следующей строки:
Код: Выделить всё
exec game.cfg\n


Теперь используя данную строку для поиска функции в декомпиленной версии windows библиотеки (в данном случае файл mp.c), мы найдем следующий код (он может немного отличаться от вашего, потому что в разных версиях библиотек код мог быть изменен разработчиками):
Код: Выделить всё
//----- (10088530) --------------------------------------------------------
int __cdecl sub_10088530()
{
  double v0; // st7@1
  int v1; // eax@2
  int v3; // eax@4

  dword_101623DC("exec game.cfg\n");
  dword_101623E0();
  v0 = *(float *)(LODWORD(dword_101625B8) + 20);
  if ( v0 == 0.0 )
  {
    v1 = (int)operator new(0x2E8u);
    if ( v1 )
      return sub_100C5EF0(v1, v0);
  }
  else
  
{
    v3 = (int)operator new(0x2D0u);
    if ( v3 )
      return sub_10093D80(v3, v0);
  }
  return 0;
}


Из данного наблюдения понятно, что мы имеем дело с той же самой функций, так как больше такую строку в коде мы не встретим.

Это означает, что по смещению 88530 в windows библиотеке игры Counter-Strike мы найдем функцию InstallGameRules. Из кода видно, что функция имеет псевдо-имя sub_10088530. Игнорируя часть имени sub_10, мы получим HEX число - 0x88530, которое и будет нашим смещением.

4. Поиск вызова функции.
В качестве бонуса, найдем в декомпиленной версии linux библиотеки вызов функции InstallGameRules:
Код: Выделить всё
//----- (0011163C) --------------------------------------------------------
int *__usercall CWorld__Precache<eax>(long double a1<st0>, int a2)
{
  unsigned int v2; // edi@8
  __int16 v3; // fps@15
  long double v4; // fst6@15
  char v5; // c0@15
  char v6; // c2@15
  char v7; // c3@15
  int v8; // eax@16
  int v9; // ecx@18
  int v10; // eax@19
  int v11; // ST1C_4@23
  int *result; // eax@25
  int v13; // [sp-10h] [bp-58h]@16
  float v14; // [sp-Ch] [bp-54h]@16
  int v15; // [sp-8h] [bp-50h]@22

  g_pLastSpawn = 0;
  g_pLastCTSpawn = 0;
  g_pLastTerroristSpawn = 0;
  (*(void (__cdecl **)(_DWORD, char[4]))&g_engfuncs[240])("sv_gravity", "800");
  (*(void (__cdecl **)(_DWORD, char[4]))&g_engfuncs[240])("sv_maxspeed", "900");
  (*(void (__cdecl **)(_DWORD, _DWORD))&g_engfuncs[240])("sv_stepsize", "18");
  (*(void (__cdecl **)(_DWORD, _DWORD))&g_engfuncs[240])("room_type", "0");
  if ( g_pGameRules )
    __builtin_delete((void *)g_pGameRules);
  g_pGameRules = InstallGameRules();


Из последней строки данного кода видно, что функция InstallGameRules вызывается из CWorld__Precache (реальное имя функции CWorld::Precache). Теперь вернемся снова в декомпиленную версию windows библиотеки. Делаем поиск по sub_10088530 и находим:
Код: Выделить всё
//----- (100DD350) --------------------------------------------------------
int __usercall sub_100DD350<eax>(int a1<ecx>, double a2<st0>)
{
  int v2; // ebp@1
  int v3; // eax@3
  int v4; // ecx@3
  int v5; // esi@4
  int v6; // eax@6
  int v7; // ecx@7
  int v8; // eax@8
  signed int v9; // esi@17
  int v10; // eax@28
  int v11; // ecx@29
  int result; // eax@33
  float v13; // [sp-4h] [bp-10h]@25
  signed int v14; // [sp-4h] [bp-10h]@31

  v2 = a1;
  dword_10162EFC = 0;
  dword_10163D00 = 0;
  dword_10163D04 = 0;
  dword_10162430("sv_gravity", "800");
  dword_10162430("sv_maxspeed", "900");
  dword_10162430("sv_stepsize", "18");
  dword_10162430("room_type", L"0");
  if ( dword_10162304 )
    operator delete(dword_10162304);
  dword_10162304 = (void *)sub_10088530();

И мы находим функцию CWorld__Precache (смещение 0xDD350).

5. Получаем необходимые данные.
После изучения и понимания этой статьи вы сможете найти необходимые вам функции. Также возможно вам понадобится знать тип функции. Вы можете узнать его в IDA из списка функций linux библиотеки:
ida_pro_4.jpg

Для того чтобы узнать тип, который функция возвращает, можно воспользоваться HL SDK. Из файла gamerules.cpp:
Код: Выделить всё
CGameRules *InstallGameRules( void )
{
    SERVER_COMMAND( "exec game.cfg\n" );
    SERVER_EXECUTE( );

    if ( !gpGlobals->deathmatch )
    {
        // generic half-life
        g_teamplay = 0;
        return new CHalfLifeRules;
    }
    else
    
{
        if ( teamplay.value > 0 )
        {
            // teamplay

            g_teamplay = 1;
            return new CHalfLifeTeamplay;
        }
        if ((int)gpGlobals->deathmatch == 1)
        {
            // vanilla deathmatch
            g_teamplay = 0;
            return new CHalfLifeMultiplay;
        }
        else
        
{
            // vanilla deathmatch??
            g_teamplay = 0;
            return new CHalfLifeMultiplay;
        }
    }
}

Видно, что в данном случае возвращаемый тип CHalfLifeMultiplay.

6. Использование функции в Orpheu.
Теперь нужно применить полученные данные к модулю Orpheu. В директории configs/orpheu/functions создаем файл InstallGameRules со следующим содержимым:
Код: Выделить всё
{
    "name" : "InstallGameRules",
    "library" : "mod",
    "return" :
    {
        "type" : "CHalfLifeMultiplay *"
    },
    "identifiers":
    [
        {
            "os" : "windows",
            "mod" : "cstrike",
            "value" : 0x88530
        }
    ]
}

Не забывайте, что если функция принадлежит классу, то необходимо создать папку с именем класса и поместить файл туда.

7. Заключение.
Полученные смещения гарантирует нам то, что функции будут всегда по указанному адресу, каждый раз при загрузке библиотеки сервером. Но при обновлении версии библиотечных файлов смещение может поменяться, поэтому прийдется искать его снова или нужно находить сигнатуры функций, которые позволяют находить необходимое смещение даже при обновленных библиотеках.
Не пишите мне в ЛС: если вам нужна помощь на бесплатной основе. Любые вопросы на форум.
Аватара пользователя
DJ_WEST
Администратор
 
Сообщения: 3641
Зарегистрирован: 22 авг 2009, 00:38
Благодарил (а): 48 раз.
Поблагодарили: 2209 раз.
Опыт программирования: Больше трех лет
Языки программирования: Counter-Strike 1.6
Counter-Strike: Source
Left 4 Dead
Left 4 Dead 2

Re: Orpheu: Поиск функций в библиотеках

Сообщение Fedcomp » 29 апр 2010, 17:50

Отлично. Непонятно два момент - IDA что из ассемблера даже в си переводит? и ещё - искать сигнатуры намного труднее? dproto новый именно так работает?
Не помогаю в ЛС - есть форум.
Плагины тоже не пишу, на форуме достаточно хороших скриптеров.


"я ставлю зависимости потому что мне приятно" - subb98 @ 2017
Аватара пользователя
Fedcomp
Администратор
 
Сообщения: 4936
Зарегистрирован: 28 авг 2009, 20:47
Благодарил (а): 813 раз.
Поблагодарили: 1317 раз.
Языки программирования: =>
pawn / php / python / ruby
javascript / rust

Re: Orpheu: Поиск функций в библиотеках

Сообщение DJ_WEST » 29 апр 2010, 22:14

Непонятно два момент - IDA что из ассемблера даже в си переводит?

Да, но, конечно, не в лучшем варианте.
и ещё - искать сигнатуры намного труднее?

Сложней.
dproto новый именно так работает?

Без понятия, не видел/не юзал.
Не пишите мне в ЛС: если вам нужна помощь на бесплатной основе. Любые вопросы на форум.
Аватара пользователя
DJ_WEST
Администратор
 
Сообщения: 3641
Зарегистрирован: 22 авг 2009, 00:38
Благодарил (а): 48 раз.
Поблагодарили: 2209 раз.
Опыт программирования: Больше трех лет
Языки программирования: Counter-Strike 1.6
Counter-Strike: Source
Left 4 Dead
Left 4 Dead 2

Re: Orpheu: Поиск функций в библиотеках

Сообщение navigator » 05 май 2011, 22:01

Вопрос может ли меняться сигнатура в зависимости от версии библиотеки?
Аватара пользователя
navigator
 
Сообщения: 65
Зарегистрирован: 03 фев 2011, 21:35
Откуда: Уфа.
Благодарил (а): 18 раз.
Поблагодарили: 3 раз.
Опыт программирования: Меньше месяца
Языки программирования: Counter-Strike 1.6

Re: Orpheu: Поиск функций в библиотеках

Сообщение 6a6kin » 06 май 2011, 00:18

navigator, да, может.
Суть сигнатуры - УНИКАЛЬНАЯ подпись функции. Поэтому сигнатура функции меняется при изменении самой функции, так как меняются её составляющие - машинные команды.
На заказ не пишу.
Аватара пользователя
6a6kin
Скриптер
 
Сообщения: 332
Зарегистрирован: 09 мар 2010, 16:40
Благодарил (а): 38 раз.
Поблагодарили: 278 раз.

Re: Orpheu: Поиск функций в библиотеках

Сообщение navigator » 06 май 2011, 01:54

Значит не правду начальник написал!
DJ_WEST писал(а):7. Заключение.
Полученные смещения гарантирует нам то, что функции будут всегда по указанному адресу, каждый раз при загрузке библиотеки сервером. Но при обновлении версии библиотечных файлов смещение может поменяться, поэтому прийдется искать его снова или нужно находить сигнатуры функций, которые позволяют находить необходимое смещение даже при обновленных библиотеках.

Да уж, уже руками сам дошёл проковырявшись в дизасемблере часа 3, смысла тогда в сигнатуре не вижу так и так искать функцию придётся при обновлении dll-ок а смещение быстрее найти,(хотя это может быть только в моём случае так)!
Аватара пользователя
navigator
 
Сообщения: 65
Зарегистрирован: 03 фев 2011, 21:35
Откуда: Уфа.
Благодарил (а): 18 раз.
Поблагодарили: 3 раз.
Опыт программирования: Меньше месяца
Языки программирования: Counter-Strike 1.6

Re: Orpheu: Поиск функций в библиотеках

Сообщение 6a6kin » 06 май 2011, 12:58

Может, но не обязательно всегда. Я же написал ниже, что "сигнатура функции меняется при изменении самой функции".
На заказ не пишу.
Аватара пользователя
6a6kin
Скриптер
 
Сообщения: 332
Зарегистрирован: 09 мар 2010, 16:40
Благодарил (а): 38 раз.
Поблагодарили: 278 раз.

Re: Orpheu: Поиск функций в библиотеках

Сообщение kalash1k » 15 май 2011, 08:22

Можно узнать, какую версию IDA вы использовали? Ибо у меня почему-то не работает такое сочетание клавиш, как CTRL + F5 :-D

Аватара пользователя
kalash1k
 
Сообщения: 210
Зарегистрирован: 17 янв 2010, 14:08
Откуда: СССР
Благодарил (а): 15 раз.
Поблагодарили: 20 раз.
Опыт программирования: Больше трех лет
Языки программирования: Counter-Strike 1.6

Re: Orpheu: Поиск функций в библиотеках

Сообщение DJ_WEST » 16 май 2011, 12:53

navigator, смысл в том, что при обновлении библиотеки, шанс, что твоя функция изменится 1%.
Не пишите мне в ЛС: если вам нужна помощь на бесплатной основе. Любые вопросы на форум.
Аватара пользователя
DJ_WEST
Администратор
 
Сообщения: 3641
Зарегистрирован: 22 авг 2009, 00:38
Благодарил (а): 48 раз.
Поблагодарили: 2209 раз.
Опыт программирования: Больше трех лет
Языки программирования: Counter-Strike 1.6
Counter-Strike: Source
Left 4 Dead
Left 4 Dead 2


Вернуться в Статьи / фрагменты кода

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

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