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”). Результат будет тот же самый: таймаут на вход в комнату убран.
Как сохранить внесенные в код изменения смотреть в конце статьи.