Antichat снова доступен.
Форум Antichat (Античат) возвращается и снова открыт для пользователей.
Здесь обсуждаются безопасность, программирование, технологии и многое другое.
Сообщество снова собирается вместе.
Новый адрес: forum.antichat.xyz
Низкоуровневое исследование клиента игровой платформы Garena |

14.08.2009, 17:04
|
|
Участник форума
Регистрация: 05.06.2009
Сообщений: 127
Провел на форуме: 1313455
Репутация:
249
|
|
Низкоуровневое исследование клиента игровой платформы Garena
Низкоуровневое исследование игровой платформы Garena (или попросту реверсинг популярного игрового клиента)
0) Небольшое вступление (собственно о самом пациенте)
Гарена (англ. Garena, сокр. от Global Arena, до этого называлась GG client) представляет собой платформу для игр через интернет и мгновенного обмена сообщениями, чем-то похожую на Xfire. Распространяется на основе принципа «Free 2 Play», что позволяет не тратить на неё деньги либо тратить деньги на микроплатежи, оплачивая дополнительные возможности. Основной аудиторией являются игроки в DotA Allstars — пользовательскую карту игры Warcraft III The Frozen Throne. Garena набрала популярность среди игроков благодаря возможности играть без лицензионной версии игры с хорошим пингом, наличию защиты от программ-читов и ненадобности производить какие-либо настройки (например, Hamachi имеет аналогичные функции, но требует немало действий для начала игры).
Источник (Более подробное описание)
Так как игровой клиент распространяется на основе принципа «Free 2 Play», см выше, то в нем существует ряд ограничений, которые доступны только после покупки “Gold” статуса. Собственно о возможности снятия этих ограничений и будет рассказано в данной статье.
1) План действий:
a) Уберем защиту от отладки
b) Уберем проверку изменений модулей
c) Уберем проверку изменений исполняемого файла
d) Уберем таймер на вход в комнату
e) Показ ping’a пользователей цифрами
f) Уберем проверку на использование запрещенных программ (читов, например maphack’a)
g) Уберем flood защиту из чата
h) Уберем ограничение на запуск одной копии программы
На этом я предлагаю остановится, так как цель данной статьи (показать основные принципы) считаю достигнутой, а все остальное вы уже сможете сделать и сами.
2) Принятые обозначения:
Что то очень важное
Обозначение разделов
Обозначение чего то что следует выделить (ключевые слова)
Первое упоминание о команде
Справка по команде (функции)
Адрес команды
Переходы
Команда
Название API функций
3) Кнопки на панели инструментов:
- Reopen- Отладчик перезагрузит файл и остановится на точке входа. Hotkey ("Ctrl+F2")
- Run - Запуск программы на выполнение. Hotkey ("F9")
- Pause - Остановка выполнения программы. Hotkey ("F12")
- Step into - Трассируя программу в этом режиме отладчик будет заходить во все вызываемые функции и процедуры. Hotkey ("F7")
- Step over - Отладчик не будет заходить в функцию (он конечно это сделает, но без нас ;D а мы в свою очередь попадем на следующую за только что выполненной командой строку программы). Hotkey ("F8")
- Executable modules - Исполняемые модули программы. Hotkey ("ALT+E")
- Call stack - Отображение текущего стека вызова. Hotkey ("ALT+K")
- Breakpoints - Отображение списка точек останова. Hotkey ("ALT+B")
4) Подготовка
a) Нам потребуется отладчик (1.3 МБ)
b) Справочник по api функциям (16.1 МБ)
Можно скачать уже распакованную версию (6.99 МБ)
c) Сам пациент – клиент игровой платформы Garena (5.6 МБ)
Зеркало (5.61 МБ)
d) Так же желательно наличие поверхностных знания команд ассемблера
5) Настройка отладчика
Запускаем отладчик, идем в меню “ Options” -> “ Debugging options”. В появившемся окне выбираем вкладку " Exceptions" (Исключения), устанавливаем все переключатели (отмечаем их галочкой). Правее есть кнопка “ Add range”, жмем, в поле “ First exceptions in range“ вводим “ 00000000” (8 нулей), в поле “ Last exceptions in range“ вводим “ FFFFFFFF” (8 букв “ F”), жмем “ OK”.
Закрываем окно настроек отладчика нажатием “ OK”. Теперь в случае возникновения исключения во время работы программы, она не будет прерываться и требовать нашего вмешательства ;D
Для более глубокого понимания темы я попросил вас скачать справочную документацию по API функциям os windows. Настроим отладчик на использование данного справочника следующим образом:
Выбираем меню “ Help” -> “ Select API help file”, указываем путь к win32.hlp (извлеченного из “ MSHELP.exe”)
Все, теперь все готово и можно приступать к основной части статьи
6) Исследование программы
a) Уберем защиту от отладки
Апдейт игрового клиента от 11.09.09 приподнес нам небольшой сюрприз в виде защиты от отладки.
Сразу хочу сказать что с антиотладкой мне помог Flint_ta, за что ему огромное спасибо.
Суть антиотладки заключается в загрузке драйвера, который бы скрывал процесс “garena.exe” от диспетчера задач и от оли собственно тоже, вызывается функция “ CreateServiceW” из библиотеки “ ADVAPI32.dll”, которая в свою очередь вызвана из “ Gengine.dll”. Рассмотрим антиотладку более подробно:
В оле уже загружена “ Garena.exe”, но отладчик не запущен на выполнение, мы находимся на точке входа в программу, жмем на листинге правой кнопкой “ Search for” -> “ Name (label) in current module” или жмем “ Ctrl+N”. Начинаем набор текста (активное окно – окно отладчика): “ LoadLibrary”:
Функция LoadLibrary отображает заданный исполняемый модуль в адресное пространство вызывающего процесса. Для загрузки с дополнительными параметрами, используется функция LoadLibraryEx.
СинтаксисHMODULE LoadLibrary(
LPCTSTR lpFileName
);
Параметры:
lpFileName
Указатель на символьную строку с нулем в конце, которая именует исполняемый модуль (или .dll или .exe файл). Указанное имя - это имя файла модуля и оно не связано с именем самого сохраняемого в библиотеке модуля, как это определено ключевым словом LIBRARY в (.def) файле определения модуля.
Если строка определяет путь, но файл не существует в указанном каталоге, функция завершается ошибкой. Когда определяется путь, убедитесь, что использованы наклонные черты влево(обратные слэши (\)), а не прямые слэши (/).
Если символьная строка не определяет путь, функция использует стандартную стратегию поиска файла. Дополнительную информацию см. в разделе Замечания.
Возвращаемые значения:
Если функция завершается успешно, возвращаемое значение - дескриптор модуля.
Функция найдена “ LoadLibraryW”, кликаем на строчку, вызываем контекстное меню, жмем “ Set breakpoint on every reference”, только что мы поставили точку останова каждом вызове этой функции. Теперь можно и запустить отладчик, жмем “ F9”. Грузится какая то библиотека:
Название этой библиотеки мы можем увидеть в стеке (на рисунке отмечено синим прямоугольником). Скажу наперед, нас эта библиотека не интересует (чтобы не терять время мы сразу перейдем к нужной, если хотите, можете методом проб и ошибок выйти на нее ;D). И так нас интересует загрузка библиотеки “ Gengine.dll”, если вы пошли методом проб и ошибок, то после её загрузки вы можете увидеть абсолютно чистую олю, без опкодов, таким образом вам сразу станет ясно, почему стоит уделить внимание именно этой библиотеке. Жмем “ F9”, пока не окажемся тут 4F85DD:
Сейчас происходит загрузка библиотеки “ AvoidCrackPlugin.dll” (название в синем прямоугольнике). Но если вы нажмете “ F9”, то увидите, что по этому же адресу 4F85DD происходит загрузка следующей библиотеки: “ Gengine.dll”. Жмем “ ALT+E” или идем в меню “ View” -> “ Executable modules”, после чего перед нами появляется список всех модулей используемых программой (“Garena.exe”). Нас, как уже было сказано выше, интересует библиотека “ ADVAPI32.dll”. В колонке “ Name” находим название “ ADVAPI32”:
Оля любезно сообщила нам что это системная библиотека, написав после её названия “ (system)”. Двойной щелчек по строке с названием “ ADVAPI32” и мы находимся непосредственно в ней. Жмем “ Ctrl+N”, так как нас интересует список всех функций данного модуля. Начинаем набирать текст: “ CreateService”:
Функция CreateService создает сервис (службу)
SC_HANDLE CreateService(
SC_HANDLE hSCManager, // Указывает на указатель, возвращенный функцией OpenSCManager
LPCTSTR lpServiceName, // Указывает на имя службы
LPCTSTR lpDisplayName, // Указывает на имя, которое будет использовано пользовательским интерфейсом
DWORD dwDesiredAccess, // Флаги определяющие права доступа к службе
DWORD dwServiceType, // Тип создаваемого сервиса
DWORD dwStartType, // Определяет способ запуска службы
DWORD dwErrorControl, // Указывает на способ обработки возникающих ошибок
LPCTSTR lpBinaryPathName, // Указатель на строку (заканчивающуюся нулём), которая содержит полный путь к исполняемому файлу сервиса
LPCTSTR lpLoadOrderGroup, // Указатель на строку (заканчивающуюся нулём), которая содержит имя группы, членом которой является сервис.
LPDWORD lpdwTagId, // Указатель на переменную, в которую будет записан уникальное значение тэга, которое идентифицирует группу, указанную в параметре lpLoadOrderGroup.
LPCTSTR lpDependencies, // Указатель на массив (завершающийся двумя нулями) имён (разделённых нулями) сервисов или групп сервисов, которые система должна запустить до запуска этого сервиса.
LPCTSTR lpServiceStartName, // Указатель на строку (завершающуюся нулём), которая содержит имя аккаунта, с правами которого будет запущен сервис.
LPCTSTR lpPassword // Указатель на строку (заканчивающуюся нулём), которая содержит пароль к аккаунту, указанному в параметре lpServiceStartName.
);
Более подробно о функции можно почитать тут
Функция найдена “ CreateServiceW”, жмем на ней “ F2”, Смотрим список бряков – все ок:
После чего, жмем “ F9” и мы оказываемся тут:
Из рисунка отчетливо видно, что мы сейчас стоим на вызове той самой функции создания сервиса “ CreateServiceW ”, вызванной из модуля “ GEngine”. Параметры вызова с которыми была вызвана функция вы можете увидеть в стеке. Переходим по адресу с которого был произведен вызов: 04874B88 (на рисунке – синий прямоугольник) . Для этого жмем “ ALT+E”, Выбираем в колонке “ Name” модуль “ Gengine”, который собственно только что был загружен (“ LoadLibraryW” по адресу 4F85DD в модуле “ Garena”). Переходим в модуль “ Gengine” по двойному щелчку, после чего жмем “ Ctrl+G”, вводим адрес с которого произошел вызов ( 04874B88), после чего оказываемся тут:
Что мы тут видим? По адресу 04874B88 происходит вызов “ ADVAPI32. CreateServiceW”. Также мы можем увидеть имя драйвера создаваемого драйвера: “ sys_GarenaPEngine.sys”. Нас интересуют переход выше вызова “ CreateServiceW ”, находящийся по адресу 04874B64. Поставим туда брейкпоинт (точку останова), жмем правой кнопкой по адресу перехода: 04874B64, вызываем контекстное меню (правая кнопка мыши) после чего, выбираем “ Breakpoint” -> “ Hardware, on execution”. Убираем бряк с адреса вызова функции “ CreateServiceW” из модуля “ ADVAPI32”, для этого идем в “ View” -> “ Breakpoints”, выделяем строку (она там будет 1), в колонке " Name" у которой будет написано “ ADVAPI32”, жмем “ Del”. Теперь перезапускаем программу в отладчике, жмем “ F9”. Жмем “ F9” на вызове “ LoadLibraryW” в модуле “ Garena” (дважды, так как сначала грузится “ AvoidCrackPlugin.dll”) , после чего прерываемся на бряке. Что говорит оля по поводу перехода?
Меняем флаг “ Z” на противоположный, дважды щелкнув по нему:
Смотрим что с переходом: “ Jump is taken”. Отлично. Заменим условный переход по адресу: 04874B64 на безусловный “ JE” заменим на “ JMP”. Проходим по переходу с помощью “ F8”. Тут надо сказать вам, почему мы не отпускаем программу в свободное плавание, нажав “ F9”, а словно ожидая подвоха, трассируем по “ F8”: Дело в том что я уже само собой проделал все это перед написанием данной статьи и могу вам сказать, что после того как мы выйдем из этого вызова, мы окажемся тут ( 4874448):
Что же мы тут видим? А все очень просто, программа предпринимает еще одну попытку создания сервиса, по адресу 487444F видим переход, который может избавить нас от участи сидеть перед окном пустого отладчика. Меняем условный переход “ JNZ SHORT 048744CB” на “ JMP SHORT 048744CB”. Отлично. При желании можно немного потрассировать программу по “ F8” и убедится, что теперь все в порядке. Но я надеюсь, вы поверите мне на слово. Итак, подведем итог, мы только что сделали 2 изменения в модуле “ Gengine”, который является динамической библиотекой. Мы должны сохранить результат нашей работы. Жмем правую кнопку мыши на листинге, вызывая контекстное меню, выбираем:
“ Copy to executable” -> “ All modifications”, после чего нас спросят действительно ли мы хотим копировать все изменения сделанные в коде программы, жмем “ Copy all”, в появившемся окне жмем правую кнопку, вызывая всплывающее меню, выбираем “ Save file”, указываем имя файла и его местоположение ( %Garena%\plugins\UI\GEngine.dll), после чего жмем “ Сохранить”. Хочу обратить ваше внимание на то, что не лишним будет переименовать оригинальный файл “ GEngine.dll”, на всякий случай ;D После чего уже сохранять изменный. Убираем все брейкпоинты, в том числе и hardware, для этого идем в меню " Debug" -> " Hardware breakpoints", удаляем их и перезапускаем клиента игровой платформы в отладчике. Запускаем на выполнение “ F9”. Опс, что же мы видим?
Garena сообщает нам о ошибке проверки файла. Что тут можно сказать? Не стоит ничего проверять и сейчас мы отучим garen’у делать это.
Еще раз хочу сказать спасибо Flint_ta, за помощь с антиотладкой.
b) Уберем проверку изменений модулей
Перезагружаем программу “ Ctrl+F2”, что же происходит? При загрузке библиотеке garena проверяет контрольную сумму файла, так как мы файл изменили, то и контрольная сумма теперь другая, что же делать? В начале мы с вами уже были на загрузки “ Gengine.dll”, помните? “ LoadLibraryW” по адресу 4F85DD в модуле “ Garena”. Именно оттуда мы начали свой путь. Идем по этому адресу “ Gtrl+G”, вводим “ 4F85DD”, “ OK”. Смотрим что у нас тут:
Выше загрузки библиотеки, по адресу 4F85DA видим переход непосредственно на наш наг, информирующий о ошибке проверки файла (на рисунке выделен зеленым цветом). Выше по адресу: 4F85C8 видим переход, который переносит нас через “ плохой переход”. После загрузки библиотеки по адресу: 4F85E5 также существует проверка условия, в случае если переход будет выполнен (на рисунке отмечен коричневым цветом), мы можем получить еще одно плохое сообщение, которое будет вызвано примерно тут:
Делаем следующее:
1) По адресу 4F85C8 меняем условный переход “ JE SHORT 004F85DC” на безусловный “ JMP SHORT 004F85DC ”, что позволит нам избавится от первого плохого сообщения.
2) По адресу 4F85E5 занопаем переход (забьем командами “ NOP” = ничего не делать). Этим мы избавимся от второго плохого сообщения.
Собственно это все, теперь мы сохраняем сделанные изменения в файле “ Garena.exe” (как? смотри выше).
c) Уберем проверку изменений исполняемого файла
Собственно эта проверка не дает клиенту успешно соединится с сервером игры и авторизовать клиента.
В далеком прошлом, когда еще не было антиотладки и все мапхакеры и прочие читеры жили припеваючи, была написана данная статья: "Снимаем таймер подключения в Garena Client". Именно по ней вы должны убрать проверку изменения исполняемого файла " Garena.exe" сомостоятельно. Зачем я тогда описал пункт " b"? Чтобы вам было удобнее и понятнее, так как были изменения в коде и виртуальные адреса сместились. Ну а проверка изменения исполняемого файла происходит из " AvoidCrackPlugin.dll", который был изменен еще в незапамятные времена, соответсвенно все адреса для этого модуля остались прежними и вам будет довольно удобно (я надеюсь) проделать все описанные в статье изменения. Для тех же у кого возникли трудности, в конце статьи вы найдете файл со всеми изменнеными нами файлами, которые вы сможете поковырять сами ;D
Последний раз редактировалось Dosia; 19.09.2009 в 23:41..
|
|
|
Низкоуровневое исследование post 2 of 4 |

14.08.2009, 17:05
|
|
Участник форума
Регистрация: 05.06.2009
Сообщений: 127
Провел на форуме: 1313455
Репутация:
249
|
|
Низкоуровневое исследование post 2 of 4
d) Уберем таймер на вход в комнату
Открываем отладчик, жмем “ File” -> “ Open” или " F3", указываем путь к “ Garena.exe”
Отладчик остановился на оригинальной (настоящей) точке входа (OEP), файл ничем не упакован (это к слову).
Жмем “ F9” ( Run) или воспользуемся кнопкой на панели инструментов. Отладчик запускает программу на выполнение.
a) Дальше просто – вбиваем свой логин и пароль и пробуем зайти в какую – нибудь полную комнату (туда где больше 225 человек). Так как мы являемся простыми пользователями, то с большой долей вероятности получаем в ответ нежелательное сообщение (nag screen), говорящий примерно следующее: "Комната переполнена, не желаете ли потратить деньги и купить себе статус привилегированного пользователя?". Назовем это нежелательное сообщение nag1.
Попробовав зайти в комнату еще раз и если не прошло 5 секунд, мы получим второе нежелательное сообщение: "Вы можете попытаться зайти в комнату не чаще одного раза в 5 секунд". Назовем это сообщение nag 2.
Вот их то мы и должны будем убрать.
Заходим в комнату, получаем nag1, переключаемся на отладчик. Внимание! сразу как только вы получили nag1 вы, не закрывая nag возвращаетесь в окно отладчика. Жмем “ F12” ( Pause) или воспользуемся кнопкой на панели инструментов. Также можно воспользоваться меню “ Debug” -> “ Pause”.Отладчик приостанавливает выполнение программы.
Жмем "ALT+K", отладчик показывает текущий стек вызова. Будет что то вроде этого:
Выше вызова (на рисунке фиолетовый прямоугольник):
Код:
0012E6B8 05028C70 AdPlugin.050288B0 AdPlugin.05028C6B
Видим вызов функции " DialogBoxParamW”, дважды кликнем на эту строку (на рисунке фиолетовый прямоугольник):
Код:
0012E6B8 05028C70 AdPlugin.050288B0 AdPlugin.05028C6B
Оказываемся по адресу 050288B0, перед нами процедура:
Именно тут происходит вызов нашего nag1, собственно сам вызов происходит тут (на рисунке синий прямоугольник):
Код:
050288D8 FF15 10220305 CALL DWORD PTR DS:[<&USER32.DialogBoxPar>; USER32.DialogBoxParamW
А 5 параметров, необходимых для её вызова (которые мы уже видели в Call stack) пушатся в стек выше (на рисунке фиолетовый прямоугольник):
Код:
050388CE 50 PUSH EAX
050388CF 68 60880305 PUSH AdPlugin.05038860
050388D4 51 PUSH ECX
050388D5 6A 6D PUSH 6D
050388D7 52 PUSH EDX
Казалось бы решение найдено - занопаем вызов функции и поставленная цель достигнута, но не тут то было ;D Дело в том, что я уже пробовал этот вариант, после него программа падает с ошибкой. Что же нам делать? Посмотрим еще раз на процедуру, в ней мы не видим никаких переходов, так что исправлять по сути нечего, нечего в этой процедуре, а в той из которой была вызвана эта, вполне вероятно можно будет что то исправить, давайте посмотрим. Так как наш nag1 уже вызван и ждет когда мы на него нажмем, то мы поставим брейкпоинт на следующий за вызовом нага ( 050288D8) адрес ( 050288DE), по которому находится команда " RETN 8".
команда RETN (англ. RETURN – возврат) означает конец процедуры или функции и передает управление назад, на следующую инструкцию процедуры(функции), из которой был осуществлен вызов.
Теперь мы снова запустим программу на выполнение, нажав " F9", после чего возвращаемся к окну garena, жмем " Отмена", прерываемся на бряке, смотрим комментарий оли:
Код:
Return to 05028C70 (AdPlugin.05028C70)
Жмем " F8", переходим по адресу возврата (05028C70):
Видим выше вызова 4 перехода (O_o):
1) 05028C0A " JNZ SHORT AdPlugin.05028C87"
2) 05028C1A " JNZ SHORT AdPlugin.05028C87"
3) 05028C26 " JL SHORT AdPlugin.05028C87"
4) 05028C33 " JNZ SHORT AdPlugin.05028C87"
Но все они ведут на один и тот же адрес, нам нужно поправить какой то переход, чтобы он перенес нас через вызов nag1, скажу сразу не на первый ( 05028C0A), так как если вы поставите бряк на первый переход и запустите программу на выполнение, то тут же прерветесь на нем, переход не будет выполнен, очевидно какой то таймер использует этот участок кода. Поменяем второй переход ( 05028C1A), условный переход " JNZ SHORT AdPlugin.05028C87" мы
заменим на безусловный " JMP SHORT AdPlugin.05028C87", для этого щелкнем на строке по адресу 05028C1A, жмем " space bar", после чего набираем " JMP SHORT AdPlugin.05028C87" и жмем " assemble" . После чего запустим программу на выполнение. Попробуем войти в комнату - увидим видоизмененной сообщение, теперь в нем нет рекламной вставки. Значит основная наша задача заключалась именно в том, чтобы убрать nag1(в который потом уже добавляется рекламная вставка). Теперь мы можем заняться именно "каркасом (основой)" nag1
Это сообщение мы уберем другим способом:
Не закрываем " недоделанный nag1". Переходим к окну отладчика, жмем " F12" (" Pause"). Теперь жмем “ ALT+F9”, или идем в меню “ Debug” -> “ Execute till user code”, затем снова возвращаемся к окну игрового клиента и жмем “ Отмена” в nag1, после чего мы оказываемся тут:
Выше мы можем заметить вызов функции “ MessageBoxIndirect”, кликнем на эту строку левой кнопкой мыши и вызовем правой кнопкой всплывающее меню, в нем выбираем пункт “ Help on symbolic name”. Таким образом мы вызовем справку по данной API функции из предусмотрительно скаченного нами файла win32.hlp.
Справка говорит нам что эта функция создает окно с заданными свойствами (текст, заголовок, иконка), не трудно догадаться что это и есть наш nag1, продолжим пошаговое выполнение программы, тут надо напомнить что существует несколько режимов выполнения: " Step into" и " Step over", их описание я дал во введении
несколько раз жмем “ F8” (" Step over)", до тех пор, пока не окажемся тут:
Таким образом, если верить отладчику, наша функция показывающая nag1 начинающаяся по адресу: 00465B50 и заканчивающаяся адресом: 00465C32, передаст управление на адрес: 0049835C, см. скрин. Проверим это, жмем еще раз “F8”, и о чудо, мы оказываемся именно там. Смотрим выше, там находится вызов функции создающей nag1:
Функция создающая наг не содержит других сообщений и призвана только сообщить нам что мы потерпели фиаско, таким образом можно очень просто избавится от nag1, забив вызов по адресу: 00498357 командами "NOP".
выделяем строчку по указанному выше адресу и жмем клавишу “ space bar” или вызываем всплывающее меню нажатием правой кнопки мыши и выбираем опцию “ Assemble”.
После чего в появившееся поле вбиваем команду “ NOP”, жмем “ assemble”. Мы только что убрали вызов функции создающей nag1, код содержащийся в функции никогда не будет исполнен.
Теперь жмем “ F9”, продолжая выполнение программы. Пытаемся зайти в комнату – после того как мы потерпели фиаско при входе не появилось назойливого nag1, перейдем к nag2:
пытаемся войти в какую – нибудь популярную комнату, которая заведомо переполнена. Терпим неудачу, жмем еще раз … и вот он nag2. Для удалении этого нага воспользуемся тем же методом что и для устранения nag1. То есть не будем нажимать на nag2, а сразу перейдем к окну отладчика, нажмем “ Pause” на панели отладчика, затем комбинацию клавиш “ ALT+F9”, после чего возвращаемся к окну игрового клиента и жмем “ OK”. После чего оказываемся тут:
Выше видим вызов функции “ MessageBox”, вызываем контекстное меню щелчком правой кнопки мыши, после чего выбираем пункт “ Help on symbolic name”, видим что функция аналогична “ MessageBoxIndirect”, (которая применялась для создания nag1) и создает сообщение ( nag2) с заданным текстом, заголовком и стилем окна.
Жмем “ F8” и доходим так до команды “ RETN”:
Видим что адрес возврата: 0046AC21, жмем “ F8” оказываемся на адресе возврата. Выше видим вызов функции создания nag2:
Тут надо сказать что просто занопать (забить командами “ NOP”)вызов функции нам не подойдет, так как таймаут (5 сек) от этого никуда не денется и мы просто не будем получать сообщения о нем. Прокрутим окно отладчика чуть выше в поисках переходов, которые могут перенести нас через вызов функции создания нага:
Как видим их всего 3:
1) по адресу: 0046ABD3
2) по адресу: 0046ABD8
3) по адресу: 0046ABFC
Третий мы можем сразу же отброисть , так как этот условный переход используется для создания цикла с условием, что видно из скрина выше (оля заботливо отметила этот участок скобкой)
Второй переход перенесет нас на адрес 0046ABDD, что тоже не позволит нам избежать участи увидеть nag2.
Смотрим что с первым… Первый условный переходпереносит нас через безусловный переход (переход номер 2, который будет обязательно выполнен без какого либо условия) на прямую «дорогу» к вызову функции создания nag2. Хм, что же делать нам не удается миновать функцию создания nag2. Исходя из того что программа не представляет нам другой возможности кроме как лицезреть это сообщение, можно сделать вывод что нам нужна другая процедура, в которой собственно и происходит сравнение текущего времени с временем последней попытки захода и в неблагоприятном для нас случае (прошло меньше 5 секунд) происходит вызов данной функции. Как нам попасть в эту процедуру?
Очень просто! мы продолжаем трассировать программу по “ F8”.
Мы дошли до команды “ RETN”:
Жмем “ F8”, оказываемся на адресе возврата: 00543CC1.
Выше, по адресу: 00543CBC видим вызов процедуры из которой мы только что вышли:
Теперь нам надо разобраться что же тут происходит, а точнее происходило выше:
Все что нам важно я отметил красными прямоугольниками, рассмотрим все по порядку:
По адресу 00543C66 видим вызов функции GetTickCount, выделяем строчку и вызываем справку по API, нажав “ Ctrl+F1 “. Смотрим описание функции:
Считывает вpемя (в миллисекундах), пpошедшее с момента запуска системы. Возвращаемое значение типа Longint.
Вот где происходит получение значения времени, из которого вычитается предыдущее
значение полученное на предидущем запуске.
Смотреть адрес 00543C6E: SUB EAX,DWORD PTR DS:[622448]
Тут из регистра EAX – в котором находится значение только что вызванной нами GetTickCount, вычитается результат выполнения GetTickCount (32-битное значение по адресу: 622448) на попытке входа в комнату предшедствуещего текущей попытке, после чего полученное значение помещается в регистр EAX.
Смотрим дальше:
00543C74 CMP EAX,1388
CMP (англ: compare – сравнение) сравнение 1-го числа со вторым и установка флага
“С”, в случае если числа одинаковы равным 0,в обратном случае равным 1.
Значит тут время между предпоследней и последней попыткой входа в комнату сравнивается с числом 1388h. Зачем я дописал h? это значит hex = шестнадцатеричная система счисления. Возьмем калькулятор и переведем число 1388h в Dec (10 ричная система счисления) получим результат 5000. Именно 5000, так как время в миллисекундах.
Смотрим дальше:
00543С79 JNB SHORT 00543CDB
Условный переход в случае если флаг C = 0 мы переходим по нему и пробуем войти в комнату, если же C =1 то мы получаем nag2.
Проверим на практике: мы поставим на него точку останова ( breakpoint), на которой оля будет прерывать выполнение программы. Жмем на адрес перехода (543C79), после чего жмем “ F2” или вызываем всплывающее меню щелчком правой кнопки мыши и жмем “ Breakpoint” -> “ Toggle”. Теперь при переходе отладчика к этой инструкции, он будет на ней останавливаться.
Пытаемся войти в какую – нибудь переполненную комнату.
Останавливаемся на переходе, быстро жмем “ F9” (командуем оле Run), так как нам нужно исчерпать данную попытку входа в комнату и перейти к следующей.После того как потерпели фиаско, то есть остались там же, ведь теперь нам не будут докучать предложениями о покупке привилегированного статуса, скорее пытаемся зайти опять ( у нас на это есть 5 секунд), после чего оля останавливается на указанной нами команде:
Как видно на скрине, я успел за быстрее чем за 5 секунд совершить повторную попытку входа о чем нам говорит флаг “ C”, который установлен в 1 и не даст мне совершить эту попытку, а отправит меня прямиков на nag2.
Кликнем дважды (дабл клик) по флагу C, тем самым установив его в противоположное значение, смотрим что говорит оля по поводу перехода:
Jump is taken
Ура! теперь нажав “ F9” мы не увидим nag2, а совершим очередную попытку входа в комнату. Но сделать так чтобы мы постоянно могли входить в комнату без смены флага “ C” в ручную? Тут, как обычно, существует несколько вариантов: - По адресу 543C75 заменить команду “CMP EAX,1388” на “CMP EAX,0” (выделить строку по адресу 543C75, нажать пробел, ввести команду “CMP EAX,0”, нажать “assemble”). Тогда программа будет проверять не прошло ли между предпоследней и последней попыткой входа в комнату 0 миллисекунд, если прошло, то флаг “C” будет установлен в 0, что даст нам возможность совершить попытку входа.

- По адресу 543C79 мы заменим команду условного перехода “JNB SHORT 00543CDB” зависящего от значения флага “C” на команду безусловного перехода, не зависящего от флагов “JMP SHORT 00543CDB” (выделить строку по адресу 543C79, нажать пробел, ввести команду “JMP SHORT 00543CDB”, нажать “assemble”). Результат будет тот же самый: таймаут на вход в комнату убран.
Как сохранить внесенные в код изменения смотреть в конце статьи.
Последний раз редактировалось Dosia; 19.09.2009 в 23:35..
|
|
|
Низкоуровневое исследование post 3 of 4 |

14.08.2009, 17:06
|
|
Участник форума
Регистрация: 05.06.2009
Сообщений: 127
Провел на форуме: 1313455
Репутация:
249
|
|
Низкоуровневое исследование post 3 of 4
e) Показ ping’a пользователей цифрами
Предполагается что “ Garena.exe” уже загружена и запущена в вашем отладчике (мы юзаем олю), а также вы уже залогинились и готовы заходить в какую – нибудь свободную комнату (именно свободную или полупустую).
Переходим к окну отладчика, вызываем контекстное меню нажатие правой кнопки мыши на дизассемблированном коде. Выбираем опцию “ Search for” -> “ All referenced text strings”:
Оля нашла нам все строки которые встречаются в программе (незашифрованные). В появившемся окне перейдем к самой верхней строчке текста, это связано с тем, что наш отладчик ищет строки по порядку: сверху – вниз. Жмем правую кнопку мыши, снова вызывая контекстное меню, после чего выбираем опцию “ Search for text”. В появившемся окне введем “ |||” , что это? Именно так у обычных пользователей игровой платформы отображается пинг, то есть не цифрами, а вертикальными чертами (“ |”,” ||”,” |||”, и т.д.).
Жмем “ OK”, после чего оказываемся тут:
Видим похожие строки, это явно то что мы искали. Кликнем два раза (ака дабл клик) на найденной нами строке и окажемся тут:
Как мы можем видеть мы находимся на адресе: 4C012B где содержится команда “ PUSH 5B19D4” которая помещает в стек значение находящееся по адресу 5B19D4, оля заботливо показала нам подсказку, что это текст “ |||”. Осмотрим саму функцию в которой мы находимся: по адресу: 4C00FA идет сравнение EAX, с 190h ( CMP EAX,190) после чего идет команда условного перехода ( JGE SHORT 004C0122) на следующее сравнение ( CMP EAX,258), в случае если перехода не произошло устанавливается количество палок соответствующее данному пингу ( в данном случае две), после чего идет команда RETN – возврат, становится понятно, что в зависимости от пинга именно тут проставляется необходимое колиство палок, но мы то хотим цифры, не так ли?
Сделаем следующее: поставим брекйпоинт на начало данной функции: 4C0080 (щелкнем на строке находящейся по данному адресу, после чего жмем “ F2”). Теперь заходим в комнату (выберите какую нибудь полупустую). Оп, окно отладчика всплывает, наша точка останова стработала.
См. также строку состояния:
Зачем мы тут остановились? чтобы вы могли самостоятельно потрассировать программу по “ F8” до ближайшей команды “ RETN 8”и посмотреть ход её выполнения.
Как только вы остановились на команде “ RETN 8”, жмем однократно “ F8” и оказываемся на адресе возврата: 004C0251:
Но самое интересное уже произошло выше:
Начнем изучение кода:
по адресу 4C024C мы имеем вызов процедуры которая установит пинг в виде вертикальных линий, следовательно, эта сточка, в ходе выполнения программы не должна быть выполнена. Смотрим выше в поисках переходов, позволяющих нам проскочить через “плохую” строчку. Имеем таковой по адресу: 4C023E, он переносит нас через вызов процедуры (по адресу 4C024C ) и последующий за ним безусловный переход ( 4C0251). Выше перехода ( 4C023C)видим сравнение “ TEST BL,BL”. Тут надо сказать что опкод TEST Выполняет логическую операцию “И” над числами и по результату (не помещая его в получатель) устанавливает флаг Z. Если в BL будет 0, то переход “JNZ” не будет выполнен и мы будем видеть вертикальные линии вместо цифер. Также на скрине видно, что на это сравнение есть несколько условных переходов: “Jumps from 004C01F5, 004C0203, 004C0218, 004C0223”. С четырех адресов, найдем самый верхний по адресу: 4C01F5. Как я уже говорил в сравнении на которое мы можем попасть с этого условного перехода “ JE SHORT 004C023C” проверяется значение регистра BL, значит оно где то устанавливается? Логично? Посмотрим чуть выше в поисках команды mov BL, (что нибудь) или вызова какой либо процедуры.
Чуть выше первого перехода на сравнение, на котором мы сейчас находимся ( 4C01F5) по адресу: 4C01E5 видим команду MOV BL,AL, а выше нее ( 4C01E0) вызов процедуры по находящейся по адресу 004D2710, кликнем левой кнопкой мыши по адресу 4C01E0, где находится вызов нашей процедуры, после чего нажмем “ Enter” и мы окажемся в процедуре. Сразу надо сказать что в этой процедуре устанавливается значение регистра AL, так как мы уже рассмотрели что после вызова данной процедуры находится команда MOV BL,AL , которая копирует содержимое регистра AL в регистр BL. А так же нам следует помнить что необходимо чтобы AL не был равен нулю, иначе на сравнении мы не перейдем по условному переходу. Ставим точку останова на начало данной процедуры ( 4D2710), после переходим к окну Garena и входим в комнату, останавливаемся на брейпоинте:
Тут следует сказать почему мы немного углубились в изучение кода, а не пошли по более легкому пути и просто напросто исправили переход по адресу: 4C023E с условного JNZ SHORT 004C0256 на безусловный JMP SHORT 004C0256, что также решило бы проблему отображения цифрового пинга, как видно на скрине выше, эта процедура вызывается не с 1 фиксированного адреса, а с разных адресов, следовательно более правильно будет исправить именно значение возвращаемое этой функцией, нежели просто исправить переход. Это как функция проверки регистрация программы, в которой она проверяет зарегистрированная ли это версия и возвращает соответствующий результат, так вот, это функция может быть вызвана из разных мест программы, для того чтобы программа знала следует ли вводить ограничение на что – либо. И гораздо удобнее будет исправить значение возвращаемое этой функцией, нежели править все возможные переходы, проверяющие результат возвращенный функцией.
Мы на брейкпоинте ( 4D2710), трассируем программу по “ F8”, пока не найдем нечто похожее на MOV AL, (что - либо). Находим нечто похожее:
Видим что по этому адресу ( 4D27F7) в регистр AL заносится значение находящееся по адресу EDX+44, оля любезно сообщила нам, что этот адрес 0100AE94, а значение находящееся по нему равно 0 ( DS:[0100AE94]=00), также видим что текущее значение AL = B0.
Жмем “ F8”.
AL = 0 – пинг вертикальными чертами. Изучаем оставшийся код до команды “ RENT 4”, больше нигде AL не устанавливается, значит мы на верном пути. Жмем на адрес 4D27F7 – команду “ MOV AL,BYTE PTR DS:[EDX+44]" заменим на команду “ MOV AL,1” (кликаем на строку, жмем “ space bar”,вводим команду “ MOV AL,1”, жмем “ assemble”), этим мы заставим программу думать что мы привилегированные пользователи.
Как сохранить внесенные в код изменения смотреть в конце статьи.
f) Уберем проверку на использование запрещенных программ
Переходим к окну отладчика, вызываем контекстное меню нажатие правой кнопки мыши на дизассемблированном коде. Выбираем опцию “ Search for” -> “ All referenced text strings”. В появившемся окне перейдем к самой верхней строчке текста, это связано с тем, что наш отладчик ищет строки по порядку: сверху – вниз. Жмем правую кнопку мыши, снова вызывая контекстное меню, после чего выбираем опцию “ Search for text”. В появившемся окне введем “ Path:%s” , что это? это путь к запрещенной программе, которую Garena передает на сервер, вместе с ip и логином заблокированного пользователя. Жмем “ OK”, совпадение найдено, двойной щелчок на найденной строке и мы тут:
Осмотрев код сразу становится понятно, что мы зашли по адресу. Чуть ниже можно заметить вызов функции “ PostMessage”, оля даже смогла определить что параметром “ Message” для нее будет “ WM_QUIT”, что означает закрытие окна после уличения пользователя в использовании запрещенных программ.
function PostMessage(Wnd: HWnd; Msg, wParam: Word; lParam: Longint): Bool;
Напpавляет сообщение окну пpикладной задачи.
Прокрутив листинг чуть выше можно заметить вызов следующих функций:
GetWindowText, GetWindowThreadProcessId , FindWindow полезным будет прочитать API help по ним, вызвав справку(как это сделать вы уже знаете). Позвольте вам разъяснить как идет проверка на наличие запрещенных программ:
с помощью функции FindWindow идет поиск окон с заданными заголовками (аля maphack …), если таковое окно найдено, то все выше упомянутые (и некоторые другие, смотрите сами) функции будут выполнены с целью получения пути к исполняемому файлу запрещенной программы. И все это происходит в найденной нами процедуре.
Найдем начало процедуры, прокрутив листинг чуть выше. Адрес 4DBF40 является началом процедуры, кликаем левой кнопкой мыши на строке и видим что оля знает откуда происходит вызов:
Жмем правой кнопкой мыши на подсказке оли и выбираем команду “ Go to CALL from 004DC1B5”. Оказываемся тут ( 004DC1B5):
Выше видим условие( 004DC1A4) и условный переход ( 004DC1A8), условный переход переносит нас через вызов процедуры поиска запрещенных программ, он же является условием выхода из цикла, начинающегося с адреса ( 004DC1A4) и заканчивающегося ( 004DC1CF), где стоит безусловный переход на проверку условия. Я думаю что здесь все понятно и наша задача сводится к тому, чтобы код начинающийся с адреса ( 004DC1B5) никогда не выполнялся. Для этого меняем условный переход по адресу ( 004DC1A8) “ JNZ 004DC2F6” на безусловный “ JMP 004DC2F6”.
Как сохранить внесенные в код изменения смотреть в конце статьи.
Последний раз редактировалось Dosia; 19.09.2009 в 23:36..
|
|
|

09.09.2009, 00:58
|
|
Познающий
Регистрация: 11.05.2009
Сообщений: 36
Провел на форуме: 21519
Репутация:
17
|
|
статья супер! жаль не силен в програмировании.
былобы великолепно еслиб выложили актуальною статью покупки голда... это единственное что ценится в гарене
сниф в wpepro чтоб попроще... такое видео было на ютубе но для оч старой гарены...
вот это был бы мега способ... а вообще програмеры в гарене рулят! Уважуха.
|
|
|

09.09.2009, 14:45
|
|
Познающий
Регистрация: 11.05.2009
Сообщений: 36
Провел на форуме: 21519
Репутация:
17
|
|
ну все что тут изложено не слишком нужное...
я просто намекнул что лучше копать в направлении голда.. это единственное что важно
|
|
|

10.09.2009, 01:46
|
|
Новичок
Регистрация: 03.03.2008
Сообщений: 15
Провел на форуме: 167719
Репутация:
0
|
|
а как на это реагирует проверка клиента на обновления???
|
|
|

10.09.2009, 01:56
|
|
Участник форума
Регистрация: 05.06.2009
Сообщений: 127
Провел на форуме: 1313455
Репутация:
249
|
|
Сообщение от Zalp
а как на это реагирует проверка клиента на обновления???
В смысле апдейтится ли клиент? Да, конечно, это по - прежнему полностью работоспособная программа.
|
|
|

10.09.2009, 11:01
|
|
Участник форума
Регистрация: 05.06.2009
Сообщений: 127
Провел на форуме: 1313455
Репутация:
249
|
|
Сообщение от struk666
ну все что тут изложено не слишком нужное...
я просто намекнул что лучше копать в направлении голда.. это единственное что важно
Именно это и было сделано в статье: описано получение частичных привилегий голд аккаунта, если прочитаеш статью, возможно у тебя получится получить и некоторые администраторские привилегии (появятся дополнительные меню).
ЗЫ: Сорри за дабл постинг. Так уж вышло...
|
|
|

11.09.2009, 17:07
|
|
Постоянный
Регистрация: 15.06.2007
Сообщений: 527
Провел на форуме: 1734541
Репутация:
214
|
|
ps после последнего апдейта гарены олька ругается при логине
memory at address 7c812aeb is not readable try to change EIP .... bla bla bla
постаили защиту от дебага?
Последний раз редактировалось svesve; 11.09.2009 в 17:21..
|
|
|

11.09.2009, 20:11
|
|
Участник форума
Регистрация: 05.06.2009
Сообщений: 127
Провел на форуме: 1313455
Репутация:
249
|
|
да, добавлена антиотладка, походу у статьи будет продолжение ...
|
|
|
|
 |
|
|
Здесь присутствуют: 1 (пользователей: 0 , гостей: 1)
|
|
|
|