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”.
Как сохранить внесенные в код изменения смотреть в конце статьи.