memcpy () не работает должным образом

Я пытаюсь сделать простую реализацию ошибки Heartbleed в C / C ++ поверх Linux (используя ElementaryOS на vmplayer). Исходя из моего понимания ошибки «heartbleed», она подразумевает, что клиент отправляет на сервер запрос сердцебиения, указывая больший размер для включенной полезной нагрузки, чем фактический размер полезной нагрузки, что приводит к тому, что сервер включает содержимое из памяти, которое будет размещено после локального буфера полезной нагрузки, в ответе.

То, что я пока имею, является клиент-серверным приложением. Клиент подключается к серверу и отправляет конфиденциальную информацию, в данном случае пароль. Затем клиент отправляет на сервер запрос сердцебиения, указывая неправильный размер для полезной нагрузки. Я объявляю свои локальные переменные следующим образом:

        char password[30];// = new char[30];    //Some sensitve data, that will be accessed using the Heartbleed Bug
char temp[15];// = new char[15];
char payload[45];// = new char[45];

Я получаю содержимое из сердцебиения, как это:

        int payloadSize = atoi(strtok(buffer, " "));
temp = strtok(NULL, "\n");

В запросе сердцебиения полезной нагрузкой является «полезная нагрузка», а ее размер равен 45. Затем я вызываю функцию memcpy () следующим образом:

        memcpy(payload, temp, payloadSize /* 45 in this case */);

Я ожидаю, что переменная полезной нагрузки будет содержать значение «полезная нагрузка», а затем содержимое из переменной пароля. Однако полезная нагрузка содержит только значение «полезная нагрузка».

        cout<<payload<<endl; //prints payload

Кто-нибудь может указать, что я делаю не так?

Весь код:

int main()
{
ofstream log("ServerLog.txt");

int listeningSocket = socket(AF_INET, SOCK_STREAM, 0);
sockaddr_in serverAddress, clientAddress;
socklen_t clientLen;

serverAddress.sin_addr.s_addr = inet_addr("127.0.0.1");
serverAddress.sin_family = AF_INET;
serverAddress.sin_port = 54321;

if(bind(listeningSocket, (sockaddr *) &serverAddress, sizeof(serverAddress)) < 0)
{
cout<<strerror(errno)<<endl;
}

else
{
cout<<"Socket bound to port 12345"<<endl;

if(listen(listeningSocket, 5) < 0)
{
cout<<strerror(errno)<<endl;
}

else
{
log<<"Listening for connections now..."<<endl;
int commSocket = accept(listeningSocket, (sockaddr *) &clientAddress, &clientLen);

log<<"Now connected to a client..."<<endl;

int N = 0;
char buffer[100];// = new char[100];
char password[30];// = new char[30];    //Some sensitve data, that will be accessed using the Heartbleed Bug
char *temp = new char[15];
char payload[45];// = new char[45];

N = recv(commSocket, password, 100, 0);     //Receive sensitive data, in this case, a password

if(N == 0)          //Check for remote socket close
{
cout<<"The remote connection has been closed."<<endl;
}

else if(N < 0)      //In case there is an error
{
cout<<strerror(errno)<<endl;
}

else        //All good, move on
{
//cout<<N<<" "<<password<<endl;
log<<"Password received from client: "<<password<<" of length: "<<N<<endl;

N = recv(commSocket, buffer, 100, 0);      //recv heartbeat request

if(N == 0)          //Check for remote socket close
{
cout<<"The remote connection has been closed."<<endl;
}

else if(N < 0)      //In case there is an error
{
cout<<strerror(errno)<<endl;
}

else
{
log<<"Heartbeat request received from client: "<<buffer<<endl;

int payloadSize = atoi(strtok(buffer, " "));
temp = strtok(NULL, "\n");

memcpy(payload, temp, 45);

if(N < 0)
{
cout<<strerror(errno)<<endl;
}
}
}
}
}

return 0;
}

-2

Решение

Строки в стиле C заканчиваются нулевым ограничителем (\0), длина буфера, в котором они хранятся, неизвестна cout, Когда вы используете memcpy он копирует нулевой терминатор и все, что находится за пределами строки. Буфер фактически содержит все, что находится за строкой, но это после нулевого терминатора, поэтому он не считается частью строки, что означает, что он не печатается cout,

Полезная нагрузка буфера может выглядеть так

{ 'p', 'a', 'y', 'l', 'o', 'a', 'd', '\0', 'g', 'a', 'r', 'b', 'a', 'g', 'e' }
^^^^ String ends here

Поэтому, когда вы печатаете его с помощью cout он печатает только до \0 персонаж. Смысл это будет печатать payload и ничего больше.

Если вы хотите распечатать все значения в буфере, вам придется распечатать их по одному. Вы могли бы сделать что-то вроде этого:

for(int i = 0; i < 45; i++)
{
cout << payload[i];
}
cout << endl;

который выведет все отдельные символы буфера на консоль.

Поскольку печать специальных символов может привести к странным выводам, вы можете распечатать числовые значения символов. Чтобы напечатать числовые значения байтов, вы можете сделать то, что @MattMcNabb предложил использовать printf. Код будет выглядеть так

for(int i = 0; i < 45; i++)
{
printf("%02X", (unsigned char)payload[i]);
}
2

Другие решения

Как вы используете strtok неправильно. Если int payloadSize = atoi(strtok(buffer, " ")); дает тебе payloadSize тогда вы не будете иметь ничего в temp когда вы делаете temp = strtok(NULL, "\n"); потому что вы переместили указатель буфера до конца в контексте strtok,

Проверьте что в temp перед memcpy

0

По вопросам рекламы [email protected]