Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C - Junk characters on output

Let's say, I have two programs - input.c & output.c All I want to do is send some payload/characters in "half pyramid" format into another one using execl() function.

input.c

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>

#define SIZE 1024

int length;

int main(int argc, char *argv[])
{
    pid_t pid;
    char *target;
    //char payload[length+1];
    char payload[SIZE + 1];
    int status;
    int i = 0;

    if(argc < 2)
    {
        printf("Usage %s <length> <target>\n", argv[0]);
        exit(EXIT_FAILURE);
    }

    length = atoi(argv[1]);
    target = argv[2];

    while(i < length)
    {
        pid = fork();

        if(pid != 0)
        {
            waitpid(-1, &status, 0);
            //exit(0);
        }

        if(pid == 0)
        {
            payload[i] = 'A';
            payload[i + 1] = '\0';
            execl(target, target, payload, NULL);
            //printf("%s\n", payload);
        }
        ++i;
    }
    return 0;
}

Commented passages are just for debugging purposes. Because As you can see (while trying), when you want just print it, everything works properly.

output.c (or if you want 'target.c')

#include <stdio.h>
#include <string.h>

int main(int argc, char *argv[])
{
    char buffer[30];
    strncpy(buffer, argv[1], sizeof(buffer));
    printf("Output: %s\n", buffer);

    return 0;
}

When I compile input.c like:

gcc input.c -o input

& output.c:

gcc output.c -o output

Ok. Now, everything is prepared. Let's say, I'd like to send a payload - length 6

./input 6 ./output

but all I get on output is just this (or simply with another junks characters):

Output: A
Output: 0A
Output: 0,A
Output: 0,�A
Output: 0,�8A
Output: 0,�8�A

I tried so many things, but all of them failed and output was still the same, as you can see above.

I'd be very grateful if anyone can help me and possibly show me where is problem. Can be problem in using fork() and execl() functions together?

like image 226
Yeez Avatar asked Apr 16 '15 16:04

Yeez


People also ask

How to print special characters in C?

Just use,putchar(specialCharName). It displays the entered special character. Save this answer.

What is garbage character C?

What it refers to is any byte that resides in a variable that wasn't assigned in some well-defined way. The character A can be a garbage character if it happens to appear in (for example) a block of memory returned by malloc or an uninitialized char variable.

What does %[ n s do in C?

So scanf("%[^\n]", s); will read all characters until you reach \n (or EOF ) and put them in s . It is a common idiom to read a whole line in C.

What is print character in C?

This function prints the character on standard output and returns the number of character printed, the format is a string starting with % and ends with conversion character (like c, i, f, d, etc.).


2 Answers

Got it, you should not update payload in the child block code...

Here's a fix (cannot test it now) :

 while(i < length)
    {
        pid = fork();
        payload[i] = 'A';
        payload[i + 1] = '\0';

        if(pid != 0)
        {
            waitpid(-1, &status, 0);
            //exit(0);
        }

        if(pid == 0)
        {
            execl(target, target, payload, NULL);
            //printf("%s\n", payload);
        }
        ++i;
    }

[removed unrelated sentence]

EDIT (additional explanations) : payload updating must be in both parent and child code. If you don't understand why, I can add more explanation.

EDIT2 (as requested). You want update payload for the next forked child process. In your code, all child code is replaced by execl() into target code. So the fork() is executed only by the first parent process (the root one).

You have to update payload by the first parent and make it accessible too all the children. Putting it into this block won't work either :

// block only executed by the first parent.
if(pid != 0)
{
    waitpid(-1, &status, 0);
}

Therefore, You must update it in a place both accessible by the parent and the child : after the fork(), before if(pid == 0) block.

In your code, you increment i in the common block, but the parent's payload is never updated. So in the child block, just before the execl(), your adding 'A\0' at the end of an uninitialized C string.

like image 97
Amessihel Avatar answered Oct 21 '22 13:10

Amessihel


When your program forks, it creates a new process. This new process, after if(pid == 0), alters the payload, and runs exec (ie executes output, which then dies. I.e, your change of payload stays in the child, and does not affect the parent process. Only ++i does, which is why you're seeing unitialized data.

Move payload change before fork (or at least out of child-only block), so it's in the parent as well.

like image 41
che Avatar answered Oct 21 '22 14:10

che