Консультация № 184407
08.11.2011, 18:19
100.63 руб.
0 10 1
Здравствуйте! Прошу помощи в следующем вопросе:
это серерное приложение.приложение будет принимать подключение на определенном порту
как только придет некоторый пакет будет вызыватся функция выполняющая некоторые дей ствия с полученными данными после чего приложение завершается.
приложение довести до рабочего, чем компилить,на каком порту подключение,в общем
объясните пожалуйста еще раз именно это приложение
спасибо

Приложение:



void pr(char *str)
{
char buf[500]="";
strcpy(buf,str);//вот
}

int main(int argc,char **argv)
{


int bytesRecv = SOCKET_ERROR;
while (bytesRecv == SOCKET_ERROR)


{
//получаем данные отправленные клиентом
bytesRecv = recv(clientSocket,Message, 5000, 0 );
if (bytesRecv == 0||bytesRecv == WSAECONNRESET)
{
printf( "\nConnection Closed. \n");

break;
}
}
pr (Message);//вызываем функцию которая не проверяет длину
входного буфера при копировании
closesocket(clientSocket);
closesocket(serverSocket);
WSACleanup();
return 0;
}





Обсуждение

давно
Профессор
230118
3054
08.11.2011, 18:31
общий
В приведенном коде, конечно, пропущены важные части типа include.
Вот тут приведена более полная версия.
http://0x80.org/blog/?p=590&print=1
давно
Посетитель
7438
7205
08.11.2011, 21:08
общий
Я работаю над программой
Об авторе:
"Если вы заметили, что вы на стороне большинства, —
это верный признак того, что пора меняться." Марк Твен
давно
Посетитель
7438
7205
09.11.2011, 01:21
общий
это ответ
Здравствуйте, storosh!
Смотрите, изучайте.
Будут вопросы, задавайте в мини-форуме.

Программа может быть скомпилирована в любой студии от Microsoft

[code h=207]#include <winsock2.h>
#include <string.h>
#include <stdio.h>

#pragma comment (lib,"ws2_32.lib") //для работы с сокетами нужна эта dll

#define PORT 4050 //пусть будет номер порта, на котором сервер будет слушать
#define MAXCON 10 //максимальное количество одновременных подключений

void pr(char *to, char *from)
{
strcpy(to, from); //копируем без всяких проверок. Срыв стека неизбежен
}

int main(int argc,char **argv)
{
SOCKET listen_socket, //слушаюший сокет
accept_socket; //сокет для соединения c клиентом
SOCKADDR_IN listen_addr, //структура, описывающая локальный адрес сервера
accept_addr; //адрес клиента, с которым установлено соединение
int accepted_len = sizeof(accept_addr); //длина
WSADATA wsaData; //данные для инициализации WinSock
char Message[5000]= ""; //сюда примем строку от клиента
char buf[50]=""; //а сюда перепишем, без проверки переполнения

// Инициализация WINSOCK, расчитываем на версию 2.0
if(WSAStartup(MAKEWORD(2,0), &wsaData) != 0)
{
printf("WSAStartup() error %i", WSAGetLastError());
return -1;
}

// Создание "слушающего" сокета
// AF_INET задается всегда
// SOCK_STREAM означает TCP
// 0 - оределенный протокол для работы с сокетом не используется
if((listen_socket = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET)
{
printf("socket() error %i", WSAGetLastError());
return -1;
}

// зададим локальный адрес
listen_addr.sin_family = AF_INET;
// IP-адрес, INADDR_ANY = 0.0.0.0 = принимаем с любого адреса
// функция htonl переворачивает байты (теперь первый - старший), таков порядок
listen_addr.sin_addr.s_addr = htonl(INADDR_ANY);
// порт, который слушаем, и тоже в порядке "первый - старший"
listen_addr.sin_port = htons(PORT);

// Привязка "слушающего" сокета к локальному адресу
if(bind(listen_socket, (sockaddr*)&listen_addr, sizeof(listen_addr)) == SOCKET_ERROR)
{
printf("bind() error %i", WSAGetLastError());
closesocket(listen_socket);
WSACleanup();
return -1;
}

// Включение прослушивания на серверном сокете
// MAXCON - максимальное число одновременных подключений (нам достаточно одного)
if(listen(listen_socket, MAXCON) == SOCKET_ERROR)
{
printf("listen() error %i", WSAGetLastError());
closesocket(listen_socket);
WSACleanup();
return -1;
}

// Ждем соединение с клиентом
// получаем сокет соединения вместе с IP-адресом клиента
accept_socket = accept(listen_socket, (sockaddr*)&accept_addr, &accepted_len);
if (accept_socket == INVALID_SOCKET)
{
printf("accept() error %i", WSAGetLastError());
closesocket(listen_socket);
WSACleanup();
return -1;
}

//примем сообщение
int bytesRecv = SOCKET_ERROR;
while( bytesRecv == SOCKET_ERROR ) //будет равно только один раз
{
//принимаем максимум 5000 байт в буфер Message
bytesRecv = (int)recv( accept_socket, Message, 5000, 0 );

//если ничего не приняли или ошибка WSAECONNRESET
//то делаем вывод, что соединение закрылось
if ( bytesRecv == 0 || bytesRecv == WSAECONNRESET )
{
printf("\nConnection Closed.\n");
break;
}
//на всякий случай, закроем строку нулем
Message[bytesRecv] = 0;
}

//копируем в другое место
pr(buf, Message);

//закрываем сокеты
closesocket(listen_socket);
closesocket(accept_socket);
//прекращаем работу с сокетами
WSACleanup();
//выведем принятую строку
printf("Message: %s", Message);
return 0;
}
[/code]
Об авторе:
"Если вы заметили, что вы на стороне большинства, —
это верный признак того, что пора меняться." Марк Твен
Неизвестный
09.11.2011, 09:20
общий
спасибо всем приложение работает но не совсем так как хотелось
игорь витальевич я не вижу функцию которая проверяет длинну входного буфера
а цель моя вызвать в серверном приложении переполнения буфера
давно
Посетитель
7438
7205
09.11.2011, 10:17
общий
09.11.2011, 10:56
Тогда так и надо было акцентировать внимание.
Не проблема. Сейчас подправлю...
Только ж, если сделаю защиту от переполнения, то Вы его не сможете вызвать
Итак, можно сделать так:
Вариант I:
1) в приеме имеем фиксированный буфер
2) принимаем сообщение, ограничивая длиной буфера (пусть 200 байт)
3) копируем в буфер, размер которого равен, допустим, 100 байт, с проверкой на размер
Недостатком является то, что часть пришедшего сообщения может остаться непринятым

Вариант II:
1) в приеме имеем буфер фиксированного размера
2) принимаем сообщение, ограничивая длиной буфера (пусть 50 байт)
3) добавляем в буфер, размер которого равен, допустим, 100 байт, с проверкой на размер
4) повторяем прием, пока принимается. В выходной буфер пишем только когда есть куда.

Вариант III:
1) считаем, что в начале принимаемого соообщения идет длина сообщения (достаточно 2 байта)
2) принимаем длину
3) выделяем память
4) принимаем само сообщение длины не более заданной
5) копируем в буфер, размер которого равен, допустим, 100 байт, с проверкой на размер

Во всех случаях, если длина принятого сообщения превышает 99 байт, то принудительно ограничиваем этой длиной
Выбирайте. Готов выслушать Ваши предложения.
Об авторе:
"Если вы заметили, что вы на стороне большинства, —
это верный признак того, что пора меняться." Марк Твен
Неизвестный
09.11.2011, 11:30
общий
вот защиту от переполнения мне как раз не надо
извините если сразу не обозначил задачу
вот функция которая не проверяет длину входного буфера
void pr (char *str)
{char buf[500]="";
strcpy(buf,str);
}

а вот как ее вызвать
pr(Message);

как все это связать не знаю
спасибо
давно
Посетитель
7438
7205
09.11.2011, 11:43
общий
Изучаете срыв стека?
Ваша цель: "вызвать в серверном приложении переполнения буфера"?
В таком случае, получается, не надо принимать никаких мер по проверке переполнения.
А надо просто копировать, вызывая pr(Message). Так?
В таком случае, делаем следующее:
1) принимаем сообщение в буфер длины, пусть тех же 5000 байт
2) функцией pr копируем в буфер длины, пусть 50 байт
Так годится?
Об авторе:
"Если вы заметили, что вы на стороне большинства, —
это верный признак того, что пора меняться." Марк Твен
Неизвестный
09.11.2011, 12:19
общий
да так годится принцип работы такой:я запускаю приложение в программе ollydbg потом запускаю
клиентское приложеие которое посылет на сервер 1000байт в итоге происходит переполнения стека
и регистр EIP будет перезаписан значением посланным клиентом тоесть в EIP я должен видеть посланные
байты вместо адреса вот это я хотел видеть в oolydbg
сейчас я не вижу что сервер упал он просто подключается принимает байты и завершается
спасибо
давно
Посетитель
7438
7205
09.11.2011, 12:34
общий
Я подправил и заменил программу в ответе.
Пробуйте.
Об авторе:
"Если вы заметили, что вы на стороне большинства, —
это верный признак того, что пора меняться." Марк Твен
Неизвестный
10.11.2011, 07:51
общий
большое спаибо игорь витальевич тема выполнена досвидание удачи
Форма ответа