воскресенье, 13 марта 2011 г.

Разбираем процесс сетевого общения в деталях. Эмулируем сервер.


Наше дело застопорилось и видимо продвигаться дальше не хочет. Все возможные варианты были перебраны, но присылаемый ответ от сервера нам так и не удалось преобразовать для последующей отправки обратно. Видно уж очень хитрый алгоритм применяется. Как же быть? В нашем случае не нужно рвать волосы на голове или груди, не нужно брать волшебный бубен и исполнять тайный танец. А все потому, что в нашем распоряжении имеется парочка трюков. Итак, приступим к вскрытию этого хитрого алгоритма преобразования полученного сообщения – идентификатора сетевого клиента, который назовем для краткости Id. Есть два пути:
1)      Для этого нам понадобится тысяча часов неустанного наблюдения за посылаемыми пакетами, запись их в экселевкий файл, выделение всех уникальных сообщений, создание математической формулы для расчета преобразования.
2)      Создание собственного сервера, а затем посыл данных каких мы хотим, чтобы узнать, как все-таки отвечает на них клиент.
Ну что, выбираем вариант №2?

Немного поколдовав над кодом программы и немного его видоизменив, получаем уже не клиент, а сервер который будет вместо настоящего сервера игры получать и отправлять данные, общаясь с настоящим клиентом. То есть задумка такая:
1)      Запускаем собственный сервер, который будет ожидать от настоящего клиента сообщения «EFEFEFEF».
2)      Посылаем в ответ «CFCFCFCF» + некоторое сообщение («Х»).
3)      Смотрим, как на это сообщение отреагирует клиент и что пришлет нам.
Так что вместо «Х»? Ну, поскольку, «Х» это кусочек, который имеет размер 4 байта, то значит нужно отсылать все возможные комбинации этих 4 байтов. То есть:
0 0 0 0
0 0 0 1
0 0 0 2
0 0 0 3
0 0 0 255
0 0 1 0
0 0 1 1
0 0 255 255
0 1 0 0
255 255 255 254
255 255 255 255

Солидное количество информации. Количество пакетов, которые нужно отправить и принять умопомрачительное. Если еще учесть, что это потом нужно будет все записать, то волосы встают дыбом.
Предлагаю разбить все общение с клиентом нашего сервера на мини-тесты. Другими словами будем следить за изменениями в шестнадцатеричной системе и изменять за один раз на одну шестнадцатеричную единицу. Что-то похожее на это:
00 00 00 00
00 00 00 01
00 00 00 02
00 00 00 0D
00 00 00 0F

00 00 00 10
00 00 00 20
00 00 00 F0

00 00 01 00
00 00 02 00
00 00 0F 00

10 00 00 00
20 00 00 00
F0 00 00 00

Соответственно отследить 16 разных сообщений проще, чем 4 294 967 296 повторов. И будем надеяться на чудо, что нам повезет, и мы увидим хоть что-то похожее на общую формулу изменения Id.
На практике получается, что нужно запустить цикл с повтором 15 и изменять:
1)      Для увеличения первой шестнадцатеричной единицы будем на каждом шаге прибавлять 1.
2)      Для увеличения второй шестнадцатеричной единицы будем на каждом шаге прибавлять 16.
Все это нужно проделать с каждым из 4 байт.

Пробная версия программы.

Начинаем тестирование. Запускаем NPA в режиме захвата локально траффика. Запускаем наш сервер. Запускаем клиент, пытаемся подключиться. Но неожиданно обнаруживаем, что в ответ на 16 пакетов с разными сообщениями, нам в ответ клиент прислал всего лишь одно. Чувство огорчения пусть не сильно нас тревожит. Ведь нам удалось подделать сервер и заставить думать клиент, что он общается с настоящим сервером. Это большая победа. И теперь осталось всего-навсего вручную, без всяких циклов послать 16 х 16 сообщений и записать все результаты в табличном виде.
Пробная версия программы №2.


Первый результат уже получен, дело за малым. Увеличивать каждый раз на шестнадцатеричную единицу отсылаемое сообщение и фиксировать результат.
Итак, первая пара готова.
Послали: CFCFCFCF00000000 .
Получили: CACACACA7A2B0004 .

Ну и напоследок пара замечаний:
Не стоит волноваться, если ваша программа-сервер начнет занимать 40 – 60 % мощности процессора – это нормально для консольного сервера.
Переменная ans1len нужна, для того чтобы хранить размер передаваемой строки по сети, если же будет использоваться strlen (ans1[]), то размер будет определен неправильно, поскольку в строке имеются спец символы, в частности {0xCF, 0xCF, 0xCF, 0xCF, 0x00, 0x00, 0x00, 0x00, 0}. Это означаем, что после измерения длины строки с помощью функции strlen, мы получим неправильную длину – 4 символа. Ведь 0x00 это ноль, а ноль как известно – признак конца строки.

3 комментария:

  1. Помню что то подобное мне пытался объяснить преподаватель информатики в институте - ничего тогда не понимал , молод был. А оказывается вон оно как - все просто и понятно.

    ОтветитьУдалить
  2. Очень сложный, но интересный процесс.

    ОтветитьУдалить
  3. Да, достаточно сложно. Попробую разобраться.

    ОтветитьУдалить