recv 覆盖 char[]

发布于 2024-09-02 20:15:30 字数 2537 浏览 7 评论 0原文

我正在尝试制作一个小的客户端-服务器脚本,就像我过去所做的许多其他脚本一样。
但在这一点上我遇到了问题。如果我发布代码及其给出的输出,那就更好了。
代码:

#include <mysql.h> //not important now
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <string.h>

//constant definition
#define SERVER_PORT 2121
#define LINESIZE 21

//global var definition
char victim_ip[LINESIZE], file_write[LINESIZE], hacker_ip[LINESIZE];

//function
void leggi (int); //not use now for debugging purpose
//void scriviDB (); //not important now

main () {

int sock, client_len, fd;

struct sockaddr_in server, client;

// transport end point
if((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
  perror("system call socket fail");
  exit(1);
}

server.sin_family = AF_INET;
server.sin_addr.s_addr = inet_addr("10.10.10.1");
server.sin_port = htons(SERVER_PORT);

// binding address at transport end point
if (bind(sock, (struct sockaddr *)&server, sizeof server) == -1) {
  perror("system call bind fail");
  exit(1);
}

//fprintf(stderr, "Server open: listening.\n");
listen(sock, 5);

/* managae client connection */
while (1) {
  client_len = sizeof(client);
  if ((fd = accept(sock, (struct sockaddr *)&client, &client_len)) < 0) 
     { perror("accepting connection"); exit(1);  }

  strcpy(hacker_ip, inet_ntoa(client.sin_addr));
  printf("1 %s\n", hacker_ip); //debugging purpose
  //leggi(fd);

//////////////////////////
//receive client 
  recv(fd, victim_ip, LINESIZE, 0);
  victim_ip[sizeof(victim_ip)] = '\0';
  printf("2 %s\n", hacker_ip); //debugging purpose
  recv(fd, file_write, LINESIZE, 0);
  file_write[sizeof(file_write)] = '\0';
  printf("3 %s\n", hacker_ip); //debugging purpose
  printf("%s@%s for %s\n", file_write, victim_ip, hacker_ip);

  //send to client
  send(fd, hacker_ip, 40, 0); //now is hacker_ip for debug

/////////////////////////

  close(fd);

}//end while

exit(0);
} //end main

客户端发送字符串:./send -i 10.10.10.4 -f filename.ext
因此脚本在服务器上发送 -i (IP) 和 -f (FILE)。
这是我的输出服务器端:

1 10.10.10.6
2 10.10.10.6
3
[电子邮件受保护]

如您所见printf(3) 和 printf(ip,file,ip) 失败。
我不知道如何以及在哪里,但有人覆盖了我的 hacker_ip 字符串。
感谢您的帮助! :)

I'm trying to make a little client-server script like many others that I've done in the past.
But in this one I have a problem. It is better if I post the code and the output it give me.
Code:

#include <mysql.h> //not important now
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <string.h>

//constant definition
#define SERVER_PORT 2121
#define LINESIZE 21

//global var definition
char victim_ip[LINESIZE], file_write[LINESIZE], hacker_ip[LINESIZE];

//function
void leggi (int); //not use now for debugging purpose
//void scriviDB (); //not important now

main () {

int sock, client_len, fd;

struct sockaddr_in server, client;

// transport end point
if((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
  perror("system call socket fail");
  exit(1);
}

server.sin_family = AF_INET;
server.sin_addr.s_addr = inet_addr("10.10.10.1");
server.sin_port = htons(SERVER_PORT);

// binding address at transport end point
if (bind(sock, (struct sockaddr *)&server, sizeof server) == -1) {
  perror("system call bind fail");
  exit(1);
}

//fprintf(stderr, "Server open: listening.\n");
listen(sock, 5);

/* managae client connection */
while (1) {
  client_len = sizeof(client);
  if ((fd = accept(sock, (struct sockaddr *)&client, &client_len)) < 0) 
     { perror("accepting connection"); exit(1);  }

  strcpy(hacker_ip, inet_ntoa(client.sin_addr));
  printf("1 %s\n", hacker_ip); //debugging purpose
  //leggi(fd);

//////////////////////////
//receive client 
  recv(fd, victim_ip, LINESIZE, 0);
  victim_ip[sizeof(victim_ip)] = '\0';
  printf("2 %s\n", hacker_ip); //debugging purpose
  recv(fd, file_write, LINESIZE, 0);
  file_write[sizeof(file_write)] = '\0';
  printf("3 %s\n", hacker_ip); //debugging purpose
  printf("%s@%s for %s\n", file_write, victim_ip, hacker_ip);

  //send to client
  send(fd, hacker_ip, 40, 0); //now is hacker_ip for debug

/////////////////////////

  close(fd);

}//end while

exit(0);
} //end main

Client send string: ./send -i 10.10.10.4 -f filename.ext
so the script send -i (IP) and -f (FILE) at the server.
Here's my output server side:

1 10.10.10.6
2 10.10.10.6
3
[email protected] for

As you can see the printf(3) and the printf(ip,file,ip) fail.
I don't know how and where but someone overwrite my hacker_ip string.
Thanks for your help! :)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

谜泪 2024-09-09 20:15:30

TCP 提供的是流,而不是数据包。因此,不能保证您发送的数据
1 次 send() 调用需要 1 次 receive() 调用才能接收。可能需要多次recv()调用才能接收一个send()调用发送的内容,或者可能需要1次recv()调用才能接收多个send()调用发送的内容 - 以某种方式你必须处理这个问题。

特别是,您应该检查 recv() 的返回值以了解您收到了多少字节,也许这可以是一个开始,这样您至少不会在字符串中打印垃圾。

ssize_t bytes = recv(fd, victim_ip, LINESIZE, 0);
 if(bytes == 0) {
   //remote closed the connection, handle it
 } else if (bytes < 0) {
    //handle error
 } else {
   victim_ip[bytes] = '\0';
   printf("%s\n", victim_ip); 
}

TCP provides a stream, not packets. Thus, you are not guaranteed that the data you send with
1 send() call takes 1 recv() call to receive. It could take several recv() calls to receive what one send() call sent, or it could take 1 recv() call to receive what several send() calls sent - somehow you have to handle that.

In particular, you should check the return value of recv() to know how many bytes you received, maybe this can be a start so you are atleast not printing garbage in your strings.

ssize_t bytes = recv(fd, victim_ip, LINESIZE, 0);
 if(bytes == 0) {
   //remote closed the connection, handle it
 } else if (bytes < 0) {
    //handle error
 } else {
   victim_ip[bytes] = '\0';
   printf("%s\n", victim_ip); 
}
煮酒 2024-09-09 20:15:30

您应该更正如下行:

victim_ip[sizeof(victim_ip)] = '\0';

file_write[sizeof(file_write)] = '\0';

This is this 覆盖 hacker_ip 字符串的行。

它在数组末尾写入一个零(sizeof(file_write) == LINE_SIZE)。如果你想写一个看门狗零,你应该将数组的维度设置为一个字符,例如file_write[LINE_SIZE+1]

这除外,它应该可以工作。对于像这里这样的非常小的数据块(21 字节),数据包不太可能被分割(标准以太网帧约为 1400 字节)。但如果您发送了多次,它们肯定会合并在同一个数据包中。

看到发件人代码会很有趣。你每次都发送一个完整的缓冲区吗? (应该看看你的recv())。

You should correct lines like:

victim_ip[sizeof(victim_ip)] = '\0';

and

file_write[sizeof(file_write)] = '\0';

This is this one that overwrite the hacker_ip string.

It write a zero after the end of the array (sizeof(file_write) == LINE_SIZE). If you want to write a watchdog zero you should set dimension of array to one more char like file_write[LINE_SIZE+1].

This excepted, it should work. For very small data chunks like here (21 bytes), it is unlikely that the packet will be splitted (standard ethernet frames are about 1400 bytes). But if you did several send they will certainly be merged in the same packet.

It would be interresting to see the sender code. Did you send a full buffer every time ? (should be looking at your recv()).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文