среда, 2 марта 2011 г.

Подделываем сообщение клиента.


Продолжаем развивать и закреплять успех, который был достигнут. Что мы уже знаем? Знаем, как подсмотреть за общением сервера и клиента. Знаем, как выглядят сообщения и что конкретно отправляют друг другу сервер и клиент. Даже умеем отправлять какие-то сообщения и пытались принимать ответ от сервера.
Давайте теперь детально разберемся что и, самое главное, как будет отсылать и принимать от сервера. Для этого обратимся к исходному коду main.cpp, котрый является каркасом нашего собственного клиента. В этом коду уже все, что нам нужно есть.
Функция отправки сообщений по выбранному адресу и порту:

sendto(my_sock,(char*) адрес указателя на ваш массив ,strlen(адрес указателя на ваш массив),0, (sockaddr *) &srv_addr,sizeof(srv_addr));

Для этой функции нужно подготовить массив данных, которые будем отправлять.
Как нам уже известно, инициируется соединение клиентом. Он отсылает на сервер данные «EFEF EFEF». Но вот вопрос как эти данные хранить в нашей программе? И что это за буквы такие? Тут нам поможет значение «length», которое определяет количество байтов. Ага. Значит речь идет о байтах. И получается, что это 4 байта. Но у нас 8 символов непонятных. Не будем гадать на кофейной гуще, а лучше проясним ситуацию. Для представления данных в программах может использоваться несколько вариантов типов данных, один из них это шестнадцатеричное представление, в котором числа представляются в виде от 0 до F (соответствует числу 15). Это как раз наш случай, только записать нужно правильно: 0xEF. Соответственно получаем четыре числа - 0xEF 0xEF 0xEF 0xEF. Если же перевести из шестнадцатеричной системы исчисления в десятичную, то получится четыре числа 239.
Вопрос на засыпку, как связаны байты, символы, и числа? Если вы помните, то в компьютере информация хранится в виде битов, которые принимают значение 0 или 1. Эти самые биты принято хранить в виде наборов по 8 штук, а называют их байтами. 1 байт = 8 бит или 256 различных состояний. То есть этот набор битов разрешает хранить какие-то значения, в количестве 256 штук, ими могут быть, например, числа от 0 до 255. Во многих языках есть специальный тип данных byte. А в Си++ для этих целей используется тип char. Да-да, тот самый char, который предназначен для хранения символьных данных. Но мы-то знаем, что символьный тип хранится как число этого символа в кодовой таблице. В итоге получается, что наше первое настоящее сообщение, отсылаемое серверу, будет хранится в виде символьного массива, примерно так:

char hello1[] = { 239, 239, 239, 239 , 0}; //EFEFEFEF
или
char hello1[] = { 0xEF, 0xEF, 0xEF, 0xEF , 0};

После отправки сообщения выведем на консоль сообщение, что делаем и что посылаем:

printf("%s: %s\n", "Send to server ", &hello1[0]);

И будем придерживаться правила, что после отправки или приема сообщения будем выводить соответствующие уведомления на экран.
Ну и что же. Отправили сообщение серверу, в ответ он тоже что-то ответит нам? Хранить это нужно где-то?

char buff[2*1024+1]; // в этот массив будем принимать сообщения, приходящие от сервера

Все уже готово и есть в исходном коде (в самом начале). На всякий случай возьмем массив побольше, чтоб точно хватило. Однако и этого может не хватить, по ходу разработки будет видно.

Функция приема сообщений по выбранному адресу и порту:

int n=recvfrom(my_sock,&buff[0],sizeof(buff)-1,0, (sockaddr *) &server_addr, &server_addr_size);

После приема сообщения, его содержимое можно найти в массиве buff, а количество символов пришедших от сервера будет лежать в переменной n.
Чтобы правильно формировать массив нужно в конец добавлять символ нуля, иначе при работе с массивом как со строкой могут случится казусы. Значит добавляем в конец массива, что полагается:

buff[n]=0;

Попробуем вывести то, что прислал нам сервер.

printf("%s: %s\n", "Coming from server ", &buff[0]);

Исходный код:  main.cpp
 
Великолепно, все получилось. Даже не нужно обращаться к Network Protocol Analyzer. Пример того, что должно появиться на экране консольного приложения приведен в самом начале статьи.

11 комментариев:

  1. Написал бы, что уже удалось взломать.

    ОтветитьУдалить
  2. Ох ты шалунишка. Чьи это сообщения ты собрался подделывать?

    ОтветитьУдалить
  3. Спасибо за статью!

    ОтветитьУдалить
  4. )) лол, я так делал когда-то

    ОтветитьУдалить
  5. Понемногу разбираюсь. Продолжай в том же духе :)

    ОтветитьУдалить
  6. Ух ты спасибо за инструкцию)

    ОтветитьУдалить
  7. Очень полезная статья. Спасибо.

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