Search code examples
cfileshellcode

Directing Shellcode Output to a File - C


I'm using this code from here: Read and Execute Shellcode from a .txt File

#include <stdio.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <stdlib.h>

int main(void)
{
    FILE *file = fopen("text.txt", "r");
    unsigned char *buf;
    int length = 0;
    struct stat st;
    int v;

    // get file size and allocate. We're going to convert to bytes 
    // from text, so this allocation will be safely large enough
    fstat(fileno(file), &st);
    buf = valloc(st.st_size);
    while (fscanf(file, "\\x%02x", &v) == 1)
    {
        buf[length++] = v;
    }

    fclose(file);

    mprotect(buf, length, PROT_EXEC);

    int (*ret)() = (int (*)())buf;
    ret();

    return 0;
}

And I'm compiling with: gcc -fno-stack-protector -z execstack testshell.c -o testshell

It runs just fine but the shellcode it executes writes to the terminal, but I would like to somehow redirect that to a file.

I tried:

./testshell > output.txt

but couldn't seem to get that to capture the results of the shellcode either.

How can I capture the output of any shellcode it runs, and if possible redirect that to a file?

Update: The shellcode I am using, and it outputs with a sys_write syscall output to a file descriptor (It does a calculation and prints to the screen) -

\xeb\x4d\x5e\x66\x83\xec\x0c\x48\x89\xe0\x48\x31\xc9\x68\x33\x09\x00\x7c\x48\x89\xcf\x80\xc1\x0c\x40\x8a\x3e\x40\xf6\xd7\x40\x88\x38\x48\xff\xc6\x68\x16\x96\xd0\xd9\x48\xff\xc0\xe2\xea\x2c\x0c\x48\x89\xc6\x68\xf2\xf5\x44\x48\x48\x31\xc0\x48\x89\xc7\x04\x01\x48\x89\xc2\x80\xc2\x0b\x0f\x05\x48\x31\xc0\x04\x3c\x0f\x05\xe8\xae\xff\xff\xff\x85\xa7\xaa\xc7\x9e\x87\xa5\xa5\x8e\xb7\x87\xba\x31\x80\xe0\x55\xef\xa1\x93\x0c\x4e\x1c\xdc\x34\x53\xb3\x8b\x43\x48\x68\x30\x1d\x4b\x65\x5b\x52\x41\x4e\x44\x53\x54\x52\x32\x5d

Solution

  • Transferring comments into an answer, giving credit where credit's due.

    Deanie said:

    This should work if the shellcode is writing to stdout and not stderr. Try:

    ./testshell > output.txt 1>&2
    

    To which user2059300, the OP, responded:

    No dice on the 1>&2, the output still occurs in the terminal and not in output.txt

    And David C. Rankin said:

    I think he meant ./testshell > output.txt 2>&1 to redirect both stdout & stderr to output.txt.

    But user2059300 stated:

    Still a no-go on that, … I provided the shellcode I'm testing.

    Then I asked:

    • How does the shell code do the writing? What is it doing? I'm not going to dissect it for you; shell code tends to be very platform specific, and you've not identified which system you're using. Granted, it is reasonably easy to guess that you're using Linux on an Intel machine, but it might be 32-bit or 64-bit Linux, and what the shell code does still needs to be understood to know how to redirect its output. If it opens the terminal and writes to it, you'll be hard put to avoid the output appearing on the terminal, for example.

    And user2059300 stated:

    It's a sys_write syscall output to a file descriptor.

    prompting me to ask:

    • Which file descriptor? 0, 1, 2, or another?

    David C. Rankin noted:

    That's still up in the air. Dumping to assembly shows a call to fprintf, but redirecting both stderr and stdout does nothing. It's almost like a kernel printf is being used.

    And I countered with:

    • That's why I listed 0 as a candidate file descriptor. File descriptor 0 is usually a dup of file descriptors 1 and 2, so you can both write to 0 (standard input) and read from 1 and 2 (standard output and standard error). Of course, doing so is totally unsupported and non-portable (and you can't do it via the file streams stdin, stdout, stderr), but then shell code in general is non-portable.

    And that seems to have been the key. David C. Rankin confirmed:

    Hah! You nailed it. ./testshell > output.txt 0>&1 worked just fine. Learning has occurred… Thanks. That is the first, and hopefully the last time, I'll run across that. I'm too old to be learning those tricks.

    and so did user2059300:

    Thank you guys so much. Learning has indeed occurred. ./testshell > output.txt 0>&1

    Obviously, I didn't know that was going to be the solution, but when the I/O redirection of standard output and standard error failed, it became a possibility. That behaviour has a very long history (7th Edition Unix, probably before that, too), though seldom if ever explicitly documented.