memcpy() 没有按预期工作
memcpy() not working as expected
我正在尝试通过 Linux 在 C/C++ 中简单实现 Heartbleed Bug(在 vmplayer 上使用 ElementaryOS)。根据我对 heartbleed 错误的理解,它涉及客户端向服务器发送心跳请求,为包含的有效负载指定比有效负载的实际大小更大的大小,这导致服务器包含将要布局的内存中的内容在本地负载缓冲区之后,在响应中。
我目前拥有的是一个 client/server 应用程序。客户端连接到服务器并发送一条敏感信息,在本例中为密码。接下来,客户端向服务器发送心跳请求,指定错误的负载大小。我这样声明局部变量:
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");
在心跳请求中,有效载荷是"payload",大小是45。然后我像这样调用memcpy():
memcpy(payload, temp, payloadSize /* 45 in this case */);
我希望负载变量的值是 "payload",后面是密码变量的内容。但是 payload 仅包含值 "payload"。
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;
}
您使用strtok
的方式是错误的。如果 int payloadSize = atoi(strtok(buffer, " "));
给你 payloadSize
那么当你做 temp = strtok(NULL, "\n");
时你不会在 temp
中有任何东西,因为你已经将缓冲区指针移动到 [= 上下文中的末尾=10=]。
在 memcpy 之前检查 temp 中的内容
C 风格字符串以空终止符 ([=13=]
) 结束,它们存储的缓冲区长度对于 cout
是未知的。当您使用 memcpy
时,它会复制空终止符和字符串以外的所有内容。缓冲区实际上包含字符串后面的所有内容,但它位于空终止符之后,因此不被视为字符串的一部分,这意味着它不会由 cout
.
打印
缓冲区负载可能如下所示
{ 'p', 'a', 'y', 'l', 'o', 'a', 'd', '[=10=]', 'g', 'a', 'r', 'b', 'a', 'g', 'e' }
^^^^ String ends here
因此,当您使用 cout
打印它时,它只会打印到 [=13=]
字符。这意味着它将打印 payload
而不会打印其他内容。
如果你想打印缓冲区中的所有值,你必须一个一个地打印它们。你可以这样做:
for(int i = 0; i < 45; i++)
{
cout << payload[i];
}
cout << endl;
这会将缓冲区的所有单个字符打印到控制台。
由于打印特殊字符可能会产生奇怪的输出,您可能希望打印出字符的数值。要打印字节的数值,您可以使用 printf 执行 @MattMcNabb 建议的操作。代码看起来像这样
for(int i = 0; i < 45; i++)
{
printf("%02X", (unsigned char)payload[i]);
}
我正在尝试通过 Linux 在 C/C++ 中简单实现 Heartbleed Bug(在 vmplayer 上使用 ElementaryOS)。根据我对 heartbleed 错误的理解,它涉及客户端向服务器发送心跳请求,为包含的有效负载指定比有效负载的实际大小更大的大小,这导致服务器包含将要布局的内存中的内容在本地负载缓冲区之后,在响应中。
我目前拥有的是一个 client/server 应用程序。客户端连接到服务器并发送一条敏感信息,在本例中为密码。接下来,客户端向服务器发送心跳请求,指定错误的负载大小。我这样声明局部变量:
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");
在心跳请求中,有效载荷是"payload",大小是45。然后我像这样调用memcpy():
memcpy(payload, temp, payloadSize /* 45 in this case */);
我希望负载变量的值是 "payload",后面是密码变量的内容。但是 payload 仅包含值 "payload"。
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;
}
您使用strtok
的方式是错误的。如果 int payloadSize = atoi(strtok(buffer, " "));
给你 payloadSize
那么当你做 temp = strtok(NULL, "\n");
时你不会在 temp
中有任何东西,因为你已经将缓冲区指针移动到 [= 上下文中的末尾=10=]。
在 memcpy 之前检查 temp 中的内容
C 风格字符串以空终止符 ([=13=]
) 结束,它们存储的缓冲区长度对于 cout
是未知的。当您使用 memcpy
时,它会复制空终止符和字符串以外的所有内容。缓冲区实际上包含字符串后面的所有内容,但它位于空终止符之后,因此不被视为字符串的一部分,这意味着它不会由 cout
.
缓冲区负载可能如下所示
{ 'p', 'a', 'y', 'l', 'o', 'a', 'd', '[=10=]', 'g', 'a', 'r', 'b', 'a', 'g', 'e' }
^^^^ String ends here
因此,当您使用 cout
打印它时,它只会打印到 [=13=]
字符。这意味着它将打印 payload
而不会打印其他内容。
如果你想打印缓冲区中的所有值,你必须一个一个地打印它们。你可以这样做:
for(int i = 0; i < 45; i++)
{
cout << payload[i];
}
cout << endl;
这会将缓冲区的所有单个字符打印到控制台。
由于打印特殊字符可能会产生奇怪的输出,您可能希望打印出字符的数值。要打印字节的数值,您可以使用 printf 执行 @MattMcNabb 建议的操作。代码看起来像这样
for(int i = 0; i < 45; i++)
{
printf("%02X", (unsigned char)payload[i]);
}