|
Регистрация | Файлы | Правила | Альбомы | Дневники | Справка | Пользователи | Календарь | Поиск | Сообщения за день | Все разделы прочитаны |
Опкоды, Формулы, Клиент Разбор и изучение взаимодействия клиента с сервером |
|
Опции темы | Поиск в этой теме | Опции просмотра |
02.07.2010, 16:59 | #81 | ||
WowCore Dev
Регистрация: 31.03.2010
Сообщений: 468
Сказал(а) спасибо: 73
Поблагодарили 106 раз(а) в 70 сообщениях
|
похвально. спрашивайте, поможем. какой формат снифов используете?
Цитата:
ну понятно, по проксёвому пути пошли. ну что ж, ждем продолжения. Цитата:
так собственно он получается на лету из памяти процесса существует два принципиально разных способа, один требует так называемой точки входа для поиска ключа, другой эту точку входа самостоятельно ищет и поиск адреса тут проще. в первом случае конечно тоже существуют методы автоматического поиска точки входа по wow.exe, этот адрес просто меняется от билда к билду. а адрес, по которому находится ключ может меняться каждый раз при загрузке игры. одну из реализаций первого метода вы можете посмотреть в исходниках tiawps. |
||
02.07.2010, 17:34 | #82 | |||
Умный
Регистрация: 02.07.2010
Сообщений: 434
Сказал(а) спасибо: 27
Поблагодарили 73 раз(а) в 45 сообщениях
|
Пока до записи снифов на диск дело не дошло, разбираюсь пока с самим протоколом вов и как там что шифруется ...
Планирую использовать Ваш формат, почитал описание, на мой взгляд весьма удачный. Цитата:
Цитата:
насчет бана уверен что его никогда не будет. Сам по себе проксификатор - абсолютно легальное решение. И может использоваться на компьютере для совершенно не связяных с вов задач. К тому же я играл как-то год назад через проксификатор наверно недели 2 на офе, когда у нашего провайдера были какие-то проблемы с маршрутом, пакеты терялись по пути в европу и играть было совершенно невозможно. Нашел прокси в инете, до которого был хороший маршрут без потери пакетов и через него отлично играл. А определить трафик какого приложения проксификатор заворачивает на прокси - невозможно, это делается в ядерном драйвере. Цитата:
тем более на работе не всегда бывает время полностью посвятить себя програмированию, иногда приходится работать ;-) Последний раз редактировалось Йоха; 02.07.2010 в 17:37. |
|||
02.07.2010, 17:46 | #83 |
WowCore Dev
Регистрация: 11.03.2010
Сообщений: 112
Сказал(а) спасибо: 10
Поблагодарили 51 раз(а) в 25 сообщениях
|
|
02.07.2010, 18:05 | #84 |
RuDB Dev
Регистрация: 01.02.2010
Адрес: localhost
Сообщений: 592
Сказал(а) спасибо: 323
Поблагодарили 283 раз(а) в 122 сообщениях
Записей в дневнике: 2
|
С проксей сейчас туговато, раньше нужный коннект определялся исходя из того какой адресс приходит в пакете с опкодом 4, а сейчас ввели криптовку и стало плохо.
приходится извращатся Код:
if (!Regex.IsMatch(search.ToString(), @"213.248.127.\d{3}:1119") && first && search.Port != 80) { first = false; return new WowReactor(Conn); } |
02.07.2010, 18:54 | #85 |
Умный
Регистрация: 02.07.2010
Сообщений: 434
Сказал(а) спасибо: 27
Поблагодарили 73 раз(а) в 45 сообщениях
|
|
02.07.2010, 22:30 | #86 | |||
WowCore Dev
Регистрация: 31.03.2010
Сообщений: 468
Сказал(а) спасибо: 73
Поблагодарили 106 раз(а) в 70 сообщениях
|
Цитата:
спрашивайте, все расскажем покажем. Цитата:
Код:
procedure OnSessionCreate(Sender: TObject; hTcpSession : Pointer; var Need : LongBool); procedure OnSessionDelete(Sender: TObject; hTcpSession : Pointer); procedure OnSessionConnect(Sender: TObject; hTcpSession : Pointer); procedure OnClientData(Sender: TObject; hTcpSession : Pointer; pData : Pointer; DataSize : Integer); procedure OnServerData(Sender: TObject; hTcpSession : Pointer; pData : Pointer; DataSize : Integer); procedure OnSessionClose(Sender: TObject; hTcpSession : Pointer; var Need : LongBool); 100%. инфа от новосибирских знакомых, которые там только так и играют - через прокси. там странные схемы, но в итоге уменьшающие пинг. с близзами они препираются, близзы говорят долбите провов (насчет маршрутов). ну а что может сделать рядовой абонент, вы прекрасно знаете. но вот пока не банят. умеют они палить это, вощем. на офф форумах на эту тему очень много тем, извиняюсь за каламбур. Цитата:
со своей стороны могу сказать только следующее: раз близзы упираются на то, что бы айпишник не меняли и трафик не перенаправляли, - значит они не любят этого. ну и нечего дразнить гусей, я считаю. тем более они умеют это отслеживать. но с точки зрения реализации прокся - самый простой вариант. начните с нее, я тоже с нее начинал у меня лично нет цели вклиниваться в трафик, мне интересен контент. поэтому меня устраивают pcap-о подобные схемы |
|||
02.07.2010, 22:46 | #87 | |
WowCore Dev
Регистрация: 31.03.2010
Сообщений: 468
Сказал(а) спасибо: 73
Поблагодарили 106 раз(а) в 70 сообщениях
|
Цитата:
1. коннект на 213.248.127.130:1119 - это однозначно коннект на BattleNet2 2. коннект на любой порт на подсеть адресов 62.67.*.* - это коннект на реалм. первая проверка уже потеряла актуальность - раньше в этом трафике я выдирал реалм лист, из него айпишники и названия реалмов. а так же билд клиента. по этим данным строилось имя файла. сейчас с битстримом лень делать разбор реалмлиста (тем более вон шифрование добавили), названия файлов у меня сейчас выглядят так: 11723_[01ED]_62.67.45.88.3724_4C2139F3.raw 11723_[0512]_62.67.45.85.6112_4C2139F4.raw 11723_[01ED]_62.67.45.88.3724_4C213BB5.raw 11723_[0512]_62.67.45.85.1119_4C213BB6.raw как видите, видно "вторую сессию" кстати, про вторую сессию. любой новый коннект на 62.67.*.* я считаю новой сессией и открываю новый снифф. вот и всё. всё просто. и не важно сколько "переконнектов" еще сделает клиент (я пробовал менять несколько раз реалм), откроется новая сессия (как понятно - 512ая ) и все будет чики-пуки ЗЫ. насчет сорри, не удержался. смачный смайлик |
|
02.07.2010, 23:02 | #88 |
Супер-модератор
Регистрация: 07.03.2010
Сообщений: 647
Сказал(а) спасибо: 100
Поблагодарили 252 раз(а) в 123 сообщениях
|
У нас с Konctantin получилась универсальная прокся, но даже сам WoW (в частности BN2) лезет куда-то по http, плюс скачивает себе модули. Я подумал определять по первому пакету (как раз ваши 1EDh и 512h), и в противном случае отключаться от соединения (наша реализация это позволяет).
|
03.07.2010, 08:40 | #89 | |
RuDB Dev
Регистрация: 01.02.2010
Адрес: localhost
Сообщений: 592
Сказал(а) спасибо: 323
Поблагодарили 283 раз(а) в 122 сообщениях
Записей в дневнике: 2
|
Цитата:
И у вас и у нас на данном этапе корявое определение, ибо кто знает что они за коннект еще добавят, и постоянно надо это дело мониторить. |
|
03.07.2010, 09:39 | #90 |
Умный
Регистрация: 02.07.2010
Сообщений: 434
Сказал(а) спасибо: 27
Поблагодарили 73 раз(а) в 45 сообщениях
|
У меня получился вот такой расклад по коннектам:
Это запуск клиента, логин и вход и игровой мир, потом выход Код:
CONNECT 213.248.127.130:1119 CONNECT 213.248.127.132:1119 CONNECT 62.67.45.98:3724 CONNECT 213.248.127.132:1119 CONNECT 213.248.127.132:1119 CONNECT 213.248.127.132:1119 CLOSE 213.248.127.132:1119 CLOSE 213.248.127.132:1119 CLOSE 213.248.127.132:1119 CLOSE 213.248.127.132:1119 CONNECT 62.67.45.157:3724 CLOSE 62.67.45.98:3724 CONNECT 213.248.127.132:1119 CLOSE 213.248.127.132:1119 CONNECT 213.248.127.132:1119 CLOSE 213.248.127.132:1119 CLOSE 62.67.45.157:3724 CLOSE 213.248.127.130:1119 62.67.45.98:3724 и 62.67.45.157:3724 это явно игровые миры |
03.07.2010, 10:43 | #91 | |
RuDB Dev
Регистрация: 01.02.2010
Адрес: localhost
Сообщений: 592
Сказал(а) спасибо: 323
Поблагодарили 283 раз(а) в 122 сообщениях
Записей в дневнике: 2
|
Цитата:
ЗЫ. Надо снифонуть этот трафик по этому коннекту, и посмотреть что за пакеты в нем ходят |
|
03.07.2010, 11:44 | #92 | |
WowCore Dev
Регистрация: 31.03.2010
Сообщений: 468
Сказал(а) спасибо: 73
Поблагодарили 106 раз(а) в 70 сообщениях
|
Цитата:
сейчас проверил. итак: 213.248.127.130:1119 - это БН2. 62.67.45.174:6114 - это мой реалм. и большинство "наших" - все на русских аккаунтах играет, не так ли? ну да ладно. меняю реалм - 195.12.236.164, однако. 80.239.233.88 внимание! - 213.248.123.52 пробежался по реалмлисту, других подсетей не обнаружил. в большинстве конечно в подсети 80.239.*.*. в общем могу сказать, что определение не корявое, а вполне себе четкое. список айпишников надо пополнить, только и всего. собственно об этом я даже не сомневался. а коннекты надо мониторить постоянно и всегда а думали это на всю жизнь чтоли? )) нее, это у них постоянно что то меняется. я ведь не первый год снифаю, поверьте опыту. в идеальном случае надо сделать как у меня было раньше - читать из БН трафика реалм лист и коннекты фильтровать в соответствии с этим листом. и всё. вот схема "на всю жизнь". а сейчас мы просто упрощаем. |
|
03.07.2010, 12:01 | #93 | ||
RuDB Dev
Регистрация: 01.02.2010
Адрес: localhost
Сообщений: 592
Сказал(а) спасибо: 323
Поблагодарили 283 раз(а) в 122 сообщениях
Записей в дневнике: 2
|
Цитата:
Цитата:
если бы знать, от куда вытаскивать ключик сессии, и знать от куда выташищить сиды, вполне возможно было бы декриптовать БНет трафик и от туда черпать нужную инфу, но опять же таки увы.. |
||
03.07.2010, 12:44 | #94 |
Умный
Регистрация: 02.07.2010
Сообщений: 434
Сказал(а) спасибо: 27
Поблагодарили 73 раз(а) в 45 сообщениях
|
Коннект на адрес 213.248.127.132_1119
Код:
GET /b03a85262f8f83f767da530c046dd36315e503887bf4bc36656f62b5335209f3.pfty HTTP/1.1 User-Agent: Battle.net Web Client Host: EU.depot.battle.net:1119 Accept: */* Код:
HTTP/1.1 404 Not Found Server: Apache Content-Type: text/html; charset=iso-8859-1 Content-Length: 338 Date: Sat, 03 Jul 2010 09:35:38 GMT X-Varnish: 2119243220 2086117285 Age: 241637 Via: 1.1 varnish Connection: keep-alive <!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN"> <html><head> <title>404 Not Found</title> </head><body> <h1>Not Found</h1> <p>The requested URL /b03a85262f8f83f767da530c046dd36315e503887bf4bc36656f62b5335209f3.pfty was not found on this server.</p> <hr> <address>Apache Server at eu.depot.battle.net Port 1119</address> </body></html> *.pfty потом запрос каких-то *.xml Но на все запросы, ответ был один: HTTP/1.1 404 Not Found |
03.07.2010, 15:05 | #96 |
Супер-модератор
Регистрация: 07.03.2010
Сообщений: 647
Сказал(а) спасибо: 100
Поблагодарили 252 раз(а) в 123 сообщениях
|
О чем я и говорил...
|
03.07.2010, 15:22 | #97 |
Ученый
|
Последний раз редактировалось LordJZ; 03.07.2010 в 15:39. |
03.07.2010, 15:42 | #98 |
Умный
Регистрация: 02.07.2010
Сообщений: 434
Сказал(а) спасибо: 27
Поблагодарили 73 раз(а) в 45 сообщениях
|
коллеги подскажите где взять полный перечень опкодов ?
|
03.07.2010, 15:45 | #99 |
Супер-модератор
Регистрация: 07.03.2010
Сообщений: 647
Сказал(а) спасибо: 100
Поблагодарили 252 раз(а) в 123 сообщениях
|
|
Пользователь сказал cпасибо: | Йоха (03.07.2010) |
04.07.2010, 11:09 | #100 |
Умный
Регистрация: 02.07.2010
Сообщений: 434
Сказал(а) спасибо: 27
Поблагодарили 73 раз(а) в 45 сообщениях
|
простите за глупые вопросы, просто раньше никогда не разбирал вов-трафик.
Я получаю в своем приложении поток данных, в котором начало "\xed\x01" или "\x12\x05". Как дальше разбирать пакеты, подскажите описание формата пакетов вов |
04.07.2010, 11:29 | #101 |
RuDB Dev
Регистрация: 01.02.2010
Адрес: localhost
Сообщений: 592
Сказал(а) спасибо: 323
Поблагодарили 283 раз(а) в 122 сообщениях
Записей в дневнике: 2
|
Первые 2 пакета идут не зашифрованные, после начинается поток уже шифрованных пакетов.
Но шифруются пакеты не полностью, а только их заголовки. Алгоритм шифрования ARC4 http://github.com/mangos/mangos/tree...c/shared/Auth/. описание пакета: Код:
Заголовок: 2 байта - размер пакета Если Пакет идет от клиента к серверу тогда 4 байта Опкод иначе 2 байта опкод далее идут данные Последний раз редактировалось Konctantin; 04.07.2010 в 11:35. |
Пользователь сказал cпасибо: | Йоха (04.07.2010) |
04.07.2010, 12:08 | #102 | ||
Умный
Регистрация: 02.07.2010
Сообщений: 434
Сказал(а) спасибо: 27
Поблагодарили 73 раз(а) в 45 сообщениях
|
Цитата:
Цитата:
А что там еще было насчет "больших пакетов", как я успел понять, у них есть какой-то признак... и немного по другому обрабатываются они |
||
04.07.2010, 12:39 | #103 |
RuDB Dev
Регистрация: 01.02.2010
Адрес: localhost
Сообщений: 592
Сказал(а) спасибо: 323
Поблагодарили 283 раз(а) в 122 сообщениях
Записей в дневнике: 2
|
вот так у нас в прокси:
Код:
Header.AddRange(pkt, 0, SizeLength + OpcodeLength); AuthCrypt.Process(d, pkt, 0, SizeLength + OpcodeLength); bool large = (pkt[0] & 0x80) != 0; if (large) { Header.Add(pkt[SizeLength + OpcodeLength]); AuthCrypt.Process(d, pkt, SizeLength + OpcodeLength, 1); SizeLength += 1; } int i = 0; /// Size includes OpcodeLength, but doesn't include SizeLength. int Size = 0; for (int j = 0; j < SizeLength; ++j) Size = (Size << 8) | (pkt[i++] & (j == 0 ? 0x7F : 0xFF)); int Opcode = 0; for (int j = 0; j < OpcodeLength; ++j) Opcode |= (pkt[i++] & 0xFF) << (j * 8); |
05.07.2010, 20:19 | #104 | ||
Новичок
Регистрация: 31.03.2010
Сообщений: 22
Сказал(а) спасибо: 2
Поблагодарили 23 раз(а) в 8 сообщениях
|
Цитата:
Цитата:
Последний раз редактировалось user456; 05.07.2010 в 21:06. |
||
07.07.2010, 15:55 | #105 |
Умный
Регистрация: 02.07.2010
Сообщений: 434
Сказал(а) спасибо: 27
Поблагодарили 73 раз(а) в 45 сообщениях
|
Подскажите я правильно понял суть алгоритма расшифровки ?
- создаем экземпляр класса AuthCrypt - вызываем функцию Init(BigNumber), в качестве параметра передается выдраный из памяти вов session key - для расшифровки заголовка пакета вызываем функцию DecryptRecv Последний раз редактировалось Йоха; 07.07.2010 в 15:57. |
07.07.2010, 17:27 | #106 |
Супер-модератор
Регистрация: 07.03.2010
Сообщений: 647
Сказал(а) спасибо: 100
Поблагодарили 252 раз(а) в 123 сообщениях
|
Эти функции вам предстоит написать.
|
07.07.2010, 19:15 | #107 |
Умный
Регистрация: 02.07.2010
Сообщений: 434
Сказал(а) спасибо: 27
Поблагодарили 73 раз(а) в 45 сообщениях
|
в смысле ? реализация же есть в мангосе
или это не то ? |
07.07.2010, 19:25 | #108 |
Умный
Регистрация: 02.07.2010
Сообщений: 434
Сказал(а) спасибо: 27
Поблагодарили 73 раз(а) в 45 сообщениях
|
просто я уже сделал прокси который сохраняет на диск так сказать raw поток обмена между клиентом и сервером. Как объяснили первые два пакета идут нормальные, а потом начинается шифрованный обмен. Вот собственно и вопрос возник. В исходниках мангоса есть реализация класса AuthCrypt. Я спрашивал как раз касательно его применения.
|
07.07.2010, 19:35 | #109 | |
YTDB Dev
Регистрация: 01.02.2010
Сообщений: 288
Сказал(а) спасибо: 125
Поблагодарили 97 раз(а) в 53 сообщениях
|
Цитата:
|
|
07.07.2010, 19:45 | #110 | |
Супер-модератор
Регистрация: 07.03.2010
Сообщений: 647
Сказал(а) спасибо: 100
Поблагодарили 252 раз(а) в 123 сообщениях
|
Цитата:
|
|
07.07.2010, 20:41 | #111 | |
WowCore Dev
Регистрация: 31.03.2010
Сообщений: 468
Сказал(а) спасибо: 73
Поблагодарили 106 раз(а) в 70 сообщениях
|
Цитата:
утилитку вам подарю с исходниками. ну и можно попробовать прислать ваш raw, за одно и проверим. |
|
Пользователь сказал cпасибо: | Йоха (08.07.2010) |
08.07.2010, 09:44 | #112 |
Умный
Регистрация: 02.07.2010
Сообщений: 434
Сказал(а) спасибо: 27
Поблагодарили 73 раз(а) в 45 сообщениях
|
Большое спасибо RomanRom2 за бесценные советы
Сделал запись снифа в raw формат, но что-то с ключом не то у меня, вроде читается нечто из памяти, но утилитка конвертирующая raw файлы в pkt зависает на моих файлах -( со вторым, или более подключением проблем нет. Я сделал проверку по начальному адресу соединения, и если это бнет или какой-то там еще левый сервер на который идут HTTP запросы, то для этих соединений не включается флаг записи на диск, данные с остальных соединений скидываются в файл. |
08.07.2010, 14:04 | #113 | |
Умный
Регистрация: 02.07.2010
Сообщений: 434
Сказал(а) спасибо: 27
Поблагодарили 73 раз(а) в 45 сообщениях
|
Итак, снифер готов. с ключом оказалось все в порядке.
Косяк оказался с форматом raw снифа. Вроде на сайте написано что формат такой: Цитата:
В общем все работает, спасибо всем кто помогал, и отдельное спасибо RomanRom2! Теперь план таков - переписать программу так, что бы все было красиво, а то сейчас код выглядит не очень симпатично. А так же теперь надо вкорячить в снифер расшифровку пакетов на лету. Последний раз редактировалось Йоха; 08.07.2010 в 14:11. |
|
08.07.2010, 21:54 | #114 |
WowCore Dev
Регистрация: 31.03.2010
Сообщений: 468
Сказал(а) спасибо: 73
Поблагодарили 106 раз(а) в 70 сообщениях
|
|
08.07.2010, 23:40 | #115 |
Ученый
Регистрация: 17.05.2010
Сообщений: 148
Сказал(а) спасибо: 18
Поблагодарили 25 раз(а) в 22 сообщениях
|
хмммм... двойные стандарты?
На логах снифера которые лежали недавно на фтп size был последним как и в описании. Кому верить? |
09.07.2010, 01:51 | #116 |
WowCore Dev
Регистрация: 31.03.2010
Сообщений: 468
Сказал(а) спасибо: 73
Поблагодарили 106 раз(а) в 70 сообщениях
|
все верно. мой фолт.
итак, в raw-файлах длина лежит в начале, в pkt-файлах - в конце. вот такой косяк, уж не знаю как так вышло, простите христа ради опять исправил на сайте, спасибо alien за наблюдательность. Последний раз редактировалось RomanRom2; 09.07.2010 в 01:57. |
17.07.2010, 19:25 | #117 |
Умный
Регистрация: 02.07.2010
Сообщений: 434
Сказал(а) спасибо: 27
Поблагодарили 73 раз(а) в 45 сообщениях
|
Что-то я запутался немного с расшифровкой заголовков пакетов
за основу взял код из tiawps Инициализация выглядит так: Код:
BYTE digest[SHA_DIGEST_LENGTH]; ZeroMemory(&digest, SHA_DIGEST_LENGTH); HMAC_CTX ctx; HMAC_CTX_init(&ctx); HMAC_Init_ex(&ctx, seed, SEED_KEY_SIZE, EVP_sha1(), NULL); HMAC_Update(&ctx, m_sessionkey, SESSION_KEY_LENGTH); uint32_t length = 0; HMAC_Final(&ctx, digest, &length); HMAC_CTX_cleanup(&ctx); EVP_CIPHER_CTX_init(&m_key); EVP_EncryptInit_ex(&m_key, EVP_rc4(), NULL, NULL, NULL); EVP_CIPHER_CTX_set_key_length(&m_key, SHA_DIGEST_LENGTH); EVP_EncryptInit_ex(&m_key, NULL, NULL, digest, NULL); // drop first 1024 bytes BYTE trash; for(int i = 0; i < 1024; ++i) { DecryptData(&trash, 1); } Код:
void CCrypt::DecryptData(BYTE *data, int len) { int outlen = 0; EVP_EncryptUpdate(&m_key, data, &outlen, data, len); EVP_EncryptFinal_ex(&m_key, data, &outlen); } В самом tiawps разобраться по человечески не получается, там такой дикий код что можно его выставлять как пример к лозунгу "как не нужно писать программы на С" Подскажите что я упустил ? |
17.07.2010, 19:48 | #118 |
Супер-модератор
Регистрация: 07.03.2010
Сообщений: 647
Сказал(а) спасибо: 100
Поблагодарили 252 раз(а) в 123 сообщениях
|
Первые 2 пакета — не зашифрованы вообще, следовательно, у вас расшифровка не работает вообще. По этому куску кода нельзя судить о правильности...
P.S. tiawps просто написан на Function C |
17.07.2010, 20:11 | #119 | |
Умный
Регистрация: 02.07.2010
Сообщений: 434
Сказал(а) спасибо: 27
Поблагодарили 73 раз(а) в 45 сообщениях
|
Цитата:
P.S. запутался еще больше ... другой файлик нормально расшифровывается ... закономерность не могу уловить Последний раз редактировалось Йоха; 17.07.2010 в 20:18. |
|
18.07.2010, 12:43 | #120 |
Умный
Регистрация: 02.07.2010
Сообщений: 434
Сказал(а) спасибо: 27
Поблагодарили 73 раз(а) в 45 сообщениях
|
разобрался вроде, мелкие ошибки были везде и в декодировании и в основной программе...
Сейчас расшифровывается нормально второе соединение, после SMSG_AUTH_CHALLENGE. А первый поток - нет. Видимо сиды в tiawps нерабочие. Там такие: const uint8_t serverSeed[SEED_KEY_SIZE] = { 0xCC, 0x98, 0xAE, 0x04, 0xE8, 0x97, 0xEA, 0xCA, 0x12, 0xDD, 0xC0, 0x93, 0x42, 0x91, 0x53, 0x57 }; const uint8_t clientSeed[SEED_KEY_SIZE] = { 0xC2, 0xB3, 0x72, 0x3C, 0xC6, 0xAE, 0xD9, 0xB5, 0x34, 0x3C, 0x53, 0xEE, 0x2F, 0x43, 0x67, 0xCE }; а на данный момент другие ? Последний раз редактировалось Йоха; 18.07.2010 в 12:48. |
Опции темы | Поиск в этой теме |
Опции просмотра | |
|
|