Страница 1 из 2

про защиту на мотре ~_^

Добавлено: Ср ноя 22, 2006 4:46 pm
Jerry
Ниже находится мой опус полугодовой давности :)
---

Миф о защищенности мотра родился очень давно, и с подачи дядьки спака, который кстати совсем недавно хвастался, что мол «раньше у нас защита была похожа на тележку с ручкой, а теперь это как реактивный самолет с турбодвигателем», сей миф кочует из уст в уста. Что-ж, статья для тех, кто желает на практике поглядеть, как устроен «самолет с турбиной» %)

Часть 1. ruro.exe

Руро написан задней левой лапой. Это так же очевидно, как и дважды два - четыре. Мало того, что Расул (которому, по древнему преданию, принадлежит авторство руро) поленился хотя бы включить какую-нибудь оптмизацию при сборке (это, впрочем, самый простительный его грех, да и к лучшему - он играет нам на руку, ибо хорошо видно и структуру кода, и что забавно - допущенные ошибки), так кроме того, руро изобилует неиспользуемым и неработающим кодом, а в работающем (почему-то :)) коде допущены тривиальные ошибки типа “if ( x = 100 )”, которые проходят во втором классе. (к чести Расула тот исправил их весьма оперативно. Месяца за два :)). Более того, большинство алгоритмов, которые он применяет, – либо сдвинутые на голову, либо неэффективные, либо нерациональные. А большинство баек о руро, в большинстве своем, не соответствуют действительности. Но это лирическое отступление.

Руро - это своеобразный загрузчик, патчер и античит в одном флаконе. Итак, начнем ковырять с начала – что же скрывается внутри этой хитрой программы, так мешающей нам жить? Если вы захотите открыть руро в отладчике, то скорее всего, ничего осмысленного не увидите. Если вы немного искушеннее обычного пользователя в части знаний в программировании, то вы можете предположить, что екзешник, скорее всего, упакован каким-то паковщиком. Это действительно так, и этот паковщик не UPX, как можно было бы подумать, увидев знакомые буквы в заголовке, а – FSG версии 2.0. Так что, если вы обладаете адвансед скиллами, то наверное даже сможете протрейсить экзешник до получения рабочего образа программы. Но гораздо удобнее иметь уже распакованный образ, и в этом поможет один из имеющихся в сети распаковщиков FSG, они более или менее корректно работают, по крайней мере экзешник потом нормально запускается и работает, несмотря на некоторые глючки. :)

Владеющий распакованным экзешником обладает большой силой :) однако, для ее обладания потребуется открутить от руро проверку собственного размера, и если захочется запускать руро под отладчиком – проверку на отладчик (коих там, по сути, две – на стандартный системный отладчик, и на софтайс). Откручивание проверок заключается как обычно в замене одного байта. Как вы думаете, зачем нужна проверка на софтайс, которая откручивается заменой оператора ? :)

Следующий вопрос, который нам интерсен – “ну и как эта хрень работает?”. Так вот. В задачи руро входит запуск апдейтера (при необходимости), запуск процесса ragexe.exe, патч нужных мест в коде процесса, и – собственно, осуществление работы этого процесса. Кто-то наверняка помнит очередные байки администрации в ключе “наш патчер – это не просто патчер – это умный патчер, который сам находит места патчей, и адаптируется под разные клиенты”. В части это действительно правда – это не просто патчер. :) А в остальном администрация как всегда наврала. Руро жестко привязан к текущей версии ragexe, и просто не будет работать ни с каким другим клиентом. По крайней мере, до тех пор, пока не скачает апдейтером ту версию, для которой он предназначен.

Ключевой момент в руро – это то, что это не просто патчер, а патчер в режиме отладчика. Другими словами, руро выступает в роли дебаггера для процесса ragexe. Кто разбирается в программировании – сразу понимают, что это, фактически, неограниченная власть над процессом. Все байки администрации мотра, мол “мы не можем модифицировать клиент”, “мы не можем исправить ошибки клиента” – все это полнейшая чушь. Руро позволяет делать с клиентом абсолютно все, что угодно. И делает это.

Грубо говоря, для своей работы руро расставляет в нужных местах брекпойнты, и корректирует поведение клиента в нужную ему сторону. Через руро проходит загрузка и выгрузка процессом (ragexe) библиотек (системных, и не только), запуст потоков, и тд. Где-то в этом механизме кроется защита от инжектора xkore, и еще несколько сигнатур каких-то редиректоров. Более подробно я этот момент не исследовал, так что конкретно что там делается, сказать не могу. Но если исключить изменение сетевых пакетов, то защита от ботов в руро заканчивается на поиске сигнатур типа “x-kor”, “edire”, и им подобных в библиотеках ragexe.

Основная же работа руро, котрой он занят большинство времени, пока висит в памяти – это патч протокола обмена с сервером. Как вы думаете, почему мотровский клиент не совместим с аутпостом? Именно благодаря своему эксклюзивному механизму, основанном на отладке. Расставив брекпойнты в нужных местах, руро ждет, пока ragexe в них не попадет, изменяет нужным образом регистры и память процесса, после чего возвращает управление. Таких мест не очень много, и их все можно легко вычислить, запустив руро в дебаггере. Их тех, которые ковырял – это момент логина (пакет 0x64), передвижение перса (пакет 0x85) (именно здесь руро по странной причине не переваривает аутпост), атака (пакет 0x89), и использование предметов (не помню уже какой пакет). Но наверняка это не все, и особенности обмена еще вылезут не раз. То есть, грубо говоря, если в ragexe есть код отсылки пакета на сервер типа

Код: Выделить всё

	buf[2] = x;
	buf[3] = y;
	send(buf, 5);
то поставив брекпойнт на 3 строке, и изменив значения в buf, мы сможем послать на сервер совершенно другие значения, в то время, как для самого клиента ничего не изменится. Удобство этого способа еще и в том, что можно легко менять алгоритмы того, какими именно значениями заменять данные, без привязки к екзешнику клиента. Кстати, что и происходит с регулярностью в 2-3 месяца.

Часть 2. Пакет перемещения.

Дисклаймер: все ниже описанные алгоритмы относятся к предыдущей (примерно до мая что-ли) версии руро, и приведены для ознакомления. В данный момент алгоритмы генерации чисел для шифрования изменены.

Каждый раз, когда вы тыкаете в клиенте мышой на землю, на сервер отсылается пакет перемещения с координатами X Y куда надо пойти. Вот так:

Код: Выделить всё

0x85 0x00 bXXXXXXXX bXXYYYYYY bYYYY****
В эмуляторе отведено по 10 бит для каждой координаты, соответственно мы имеем теоретический диапазон размера карты до 1024х1024. Зачем в воспаленный корейский мозг пришла мысль паковать координаты в 3 байта – для меня загадка, если они хотели сэкономить на трафике, то это весьма неудачная попытка, ибо куда большее количество пакетов просто перегружены лишней информацией, и координаты - лишь капля в море лишнего трафика.

Итак, 10 бит. Чистые координаты передаются везде, кроме мотра. Если запустить сниффер на мотре, то все, что мы увидим, это что передаются некоторые числа, отдаленно напоминающие координаты. Проведя минут 10 над ловлей пакетов, можно догадаться, что координаты кодируются примерно следующим образом:

Код: Выделить всё

	hx = h ^ y;
	hy = hy ^ 0x18D;
но здесь это самое простое. Все гораздо запущеннее. Наш гений программистской мысли придумал отобрать старший бит у координаты (я все-таки наивно предполагаю, что он додумался его ксорить, а не насовсем отбирать), и засунуть туда некоторый проверочный бит, типа хеша. То есть следите за мыслью – в пакете 4 свободных бита. Расул запихал проверку в старший бит координат. Вот где силища мысли! Ладно, допустим он его ксорит, а не просто отобрал, сузив диапазон координат. Что мешало ксорить всю координату а не старший бит? Кгам вобщем. А то, КАК именно он придумал вычислять этот проверочный бит – повергает просто в ступор. Вобщем, код.

Код: Выделить всё

void hash_coords(unsigned int x, unsigned int y, unsigned int* hx, unsigned int *hy)
{
	unsigned int hval;
	*hx = 0;
	*hy = 0;

	hval = hash_int(x, 0, 1, 0x00, 0xFFF);	*hx += hash_table[ hval ];
	hval = hash_int(x, 1, hval, 0x2C, 0x3FC);	*hx += hash_table[ hval ];
	hval = hash_int(x, 2, hval, 0x5E, 0x3FC);	*hx += hash_table[ hval ];
	hval = hash_int(x, 3, hval, 0x2B, 0x3FC);	*hx += hash_table[ hval ];
	hval = hash_int(x, 4, hval, 0x39, 0x3FC);	*hx += hash_table[ hval ];
	hval = hash_int(x, 5, hval, 0x53, 0x3FC);	*hx += hash_table[ hval ];
	hval = hash_int(x, 6, hval, 0x41, 0x3ED);	*hx += hash_table[ hval ];
	hval = hash_int(x, 7, hval, 0x4E, 0x3FC);	*hx += hash_table[ hval ];
	hval = hash_int(x, 8, hval, 0x0B, 0x3FC);	*hx += hash_table[ hval ];
	
	hval = hash_int(y, 0, 1, 0x00, 0x3FC);	*hy += hash_table[ hval ];
	hval = hash_int(y, 1, hval, 0x22, 0x3FC);	*hy += hash_table[ hval ];
	hval = hash_int(y, 2, hval, 0x40, 0x3FC);	*hy += hash_table[ hval ];
	hval = hash_int(y, 3, hval, 0x20, 0x3ED);	*hy += hash_table[ hval ];
	hval = hash_int(y, 4, hval, 0x50, 0x3FC);	*hy += hash_table[ hval ];
	hval = hash_int(y, 5, hval, 0x17, 0x3ED);	*hy += hash_table[ hval ];
	hval = hash_int(y, 6, hval, 0x2E, 0x3FC);	*hy += hash_table[ hval ];
	hval = hash_int(y, 7, hval, 0x3A, 0x3FC);	*hy += hash_table[ hval ];
	hval = hash_int(y, 8, hval, 0x11, 0x3FC);	*hy += hash_table[ hval ];

	*hx = x | ((*hx & 0x01) << 9);
	*hy = y | ((*hy & 0x01) << 9);
}

static unsigned int hash_int(unsigned int x, int shift, unsigned int prev, int c, int div)
{
	unsigned int m = (x >> shift) & 1;
	return ((m+1) * prev + c) % div ;
}
x y – это исходные координаты, hx, hy – координаты с битом хеша. Алгоритм - это не просто 5, это все 8. Вы знаете, почему мотр тормозит? Потому что должен счиать такую ахинею. :) Эффективность алгоритма стремится к 0, потому что его с тем же успехом заменяют псевдослучайные последовательности. Грубо говоря, hx |= hash_table[ x ] | 0x200 вместо этой кучи кода ничем не хуже. Это если хеш-таблица правильно составлена. :)
НО расул кроме всего прочего умудрился составить хеш-таблицу таким образом, что она один раз из трех тупо периодическая!
Впрочем, что такое хеш-таблица? Это просто массив случайных значений. Не столь важно каких, главное что не предсказуемых. Генератор:

Код: Выделить всё

static unsigned char	hash_table[0x400];

	magic = data[2] | (data[3]<<8);
	for( i = 0; i < 0x400; i++) {
		magic = (magic << 1) ^ (magic >> 8) ^ (magic << 2) ^ (magic * 3);
		hash_table[i] = magic & 0xFF;
	}
data – это пакет логина

Код: Выделить всё

0x64 00 ML MH …….
А в самом клиенте (т е в руро) magic вычисляется как типа rand(gettickcount())
Вот и все в общих чертах.
Итого: есть некоторое случайное число, которое генерится каждый раз при логине, и передается на сервер. По этому числу генерится хеш-таблица, и с этой таблицей патчится старший бит координат пакета перемещения. Эта таблица еще пригодится нам в дальнейшем. Не забывайте ее :)
Идея вобщем, на четверочку, даже с минусом, реализация – я промолчу. Даже офф с их примитивным паддингом впереди планеты всей

Часть 3. Кто убил Лору Палмер?

Последний на повестке дня у нас пакет “атаки”. Вот такой:

Код: Выделить всё

0x89 0x00 ID.1 ID.2 ID.3 ID.4 TYPE
где ID – идентификатор того, кого атакуем (или свой для приседаний), TYPE=0 – атаковать, TYPE=2/3 – сесть/встать. Так вот, чтоб мне тут много не писать: берется настоящее ID и TYPE, и делается такая фигня:

Код: Выделить всё

void hash_ids(unsigned int *id, char *type)
{
	unsigned char i;
	
	i = 0;
	i = (*id & 0x01) << 3;
	i = i | ((*id >> 1) & 0x01) << 2;
	i = i | ((*id >> 3) & 0x01) << 1;
	i = i | ((*id >> 5) & 0x01);
	i = i ^ (hash_table[(i % 0x3FC)] & 0x0F);
	i = ((i ^ 0x0A) << 4);

	*type = *type | i;
	*type = * type ^ (*id & 0xFF);

	*id = *id ^ 0x83FA229C;
}
После чего полученные ID и TYPE отсылаются в пакете. Помните нашу замечательную hash_table из предыдущей части? Вот тут она самая тоже есть. Видимо, в этом месте фантазия у расула закончилась, и он решил особо не мудрить с алгоритмами. Я, вобщем, тоже утомился подробно распространяться, засим откланиваюсь. :)

Добавлено: Ср ноя 22, 2006 5:17 pm
piroJOKE
"Спосибо, подрочил!" (с) :) Весьма интересно.

1) Но отчего же, имея возможность шифровать всё подряд ("брейк на строке №3") они этого не делают?... (Странно)

2) Модные упаковщики, использующие всякие бяки, типо того же "ХакШильда" или "СтарФорса" могли бы здорого уменьшить потенциал изучающих exe-шники. Вероятно, они просто довольно дорогие и не доступные г-дам админчегам?... Я не верю, что они про них не в курсе. (Странно)

Ну и по мелочам...
Jerry писал(а):Все байки администрации мотра, мол “мы не можем модифицировать клиент”, “мы не можем исправить ошибки клиента” – все это полнейшая чушь. Руро позволяет делать с клиентом абсолютно все, что угодно. И делает это.
Ковярять то они его могут, но найти большие ошибки и исправить - это не отладочный код навесить, тут надо усилия совсем другого рода прикладывать. Так что в принципе, это не байки.

Добавлено: Ср ноя 22, 2006 5:24 pm
Jerry
про байки я уже не помню конкретно, но там была всякая ахинея типа "ой а можно сделть телепорт одной кнопкой" и прочая мелочевка, без всяких багов и отладки. т е то, что во всем мире давно в хекснутых клиентах, на мотре они этого "сделать не могут" :) Вообще речь не про возможность, а про очковтирательство спакума в наивных юзверей.

Добавлено: Чт дек 21, 2006 4:06 pm
Inik
пост прикольный, тока у меня возник вопрос, а как ты сишниковские коды выдираешь с екзешника? Оо Ну черт с ним распаковывается он нахаляву, но как код выдрать я не в курсе :o

Добавлено: Чт дек 21, 2006 4:14 pm
Jerry
:D никак
это просто обратная интерпретация кода на асме.

Добавлено: Чт дек 21, 2006 4:26 pm
Inik
хм а что сервер тоже генерит у себя на каждого игрока хэштаблицу? оО

Добавлено: Чт дек 21, 2006 4:30 pm
Jerry
конешно

Добавлено: Чт дек 21, 2006 4:46 pm
piroJOKE
Перенесено из "около-ро-шных разговоров" в раздел "другие сервера ро".

Добавлено: Вс янв 14, 2007 8:48 am
Redael
Про обновлению шифров пакетов правда... Часто на мотре юзаю WPE PRO чтоб облегчить жизнь (обб делаю например). Часто бывает, что старые макросы не подходят =\

Добавлено: Вс янв 14, 2007 6:32 pm
Гость
так что дают все эти действия?

Добавлено: Пн янв 15, 2007 8:45 am
kLabMouse
Gashish
Знания мой юный Падаван :)

=)

Добавлено: Вт янв 16, 2007 3:29 pm
Гость
Так, значит настроить бота на моторе все таки можно?

Добавлено: Вт янв 16, 2007 3:38 pm
kLabMouse
pupa
Читаем господин. Читаем. :)

Добавлено: Ср янв 17, 2007 11:58 am
aZZaZZeLL
Что то не могу exe-шник открыть, может кто уже пробовал, распаковщик подскажите или дайте ссылку.

Добавлено: Вс янв 21, 2007 11:22 am
aZZaZZeLL
Что то я понять не могу, почему этот топик забросили? Или я один только хочу запустить бота на мотре?
Вот провел кое какие исследования, пакер оказывается уже не FSG, а EXECryptor 2.2.4. Может кого то заинтересует?