Page 1 of 2 12 LastLast
Results 1 to 10 of 14

Thread: Make it so that any program can read from STDIN

  1. #1
    Very good friend of the forum Virchanza's Avatar
    Join Date
    Jan 2010
    Posts
    863

    Cool Make it so that any program can read from STDIN

    OK so I started a thread recently where I said I was gonna alter Aircrack so that it can read a dictionary from stdin.

    What I would have done is found the piece of code that calls the "fopen" function. When you supply a program like Aircrack with a dictionary filename, it will open the file something like:

    Code:
    FILE *dictfile = fopen(path_to_dictionary,"r");
    What I would have done is designated a "special file name" that makes the program read from STDIN. Basically, if you specified the file name as something like "I_LIKE_TO_WATCH", then it would read from stdin. The code would look something like:

    Code:
    FILE *dictfile;
    
    if ( !strcmp(path_to_dictionary, "I_LIKE_TO_WATCH") )
        dictfile = stdin;
    else
        dictfile = fopen(path_to_dictionary,"r");
    That would have worked fine. But then something occurred to me. . .

    Instead of altering the code for Aircrack, I could actually go into the C Standard Library source files and alter the code for the "fopen" function.

    I could alter the "fopen" function making it return stdin if the filename is something like "I_LIKE_TO_WATCH". Also, if a file is being opened for writing, I can make it return stdout if the filename is "I_LIKE_TO_WATCH".

    If these changes are made to the actual C library, then there will be no need to alter the source code of programs like Aircrack. You could literally just download the source code for any C program, compile it, and have it work straight away.

    For instance you could just re-compile Aircrack and then run it as follows:

    Code:
    crunch 8 8 | aircrack-ng -w I_LIKE_TO_WATCH *.cap
    I haven't had breakfast yet so I think I'll get started on this later in the day. Should be fun.
    Ask questions on the open forums, that way everybody benefits from the solution, and everybody can be corrected when they make mistakes. Don't send me private messages asking questions that should be asked on the open forums, I won't respond. I decline all "Friend Requests".

  2. #2
    Very good friend of the forum Virchanza's Avatar
    Join Date
    Jan 2010
    Posts
    863

    Default

    First thing I did was make a guinea pig program that needs to take its input from a file specified at the command line. The guinea pig program is not able to read from stdin. The objective is to alter the C Standard Library so that the guinea pig program will be able to read from stdin without having to alter the guinea pig program's code.

    I made a simply little guinea pig program that would append a single digit to passwords, it's called append_digit.

    Let's say for instance that you started off with the following dictionary file:

    Code:
    dog
    cat
    fish
    Well after you run this through append_digit you'd end up with:

    Code:
    dog0
    dog1
    dog2
    dog3
    dog4
    dog5
    dog6
    dog7
    dog8
    dog9
    cat0
    cat1
    cat2
    cat3
    cat4
    cat5
    cat6
    cat7
    cat8
    cat9
    fish0
    fish1
    fish2
    fish3
    fish4
    fish5
    fish6
    fish7
    fish8
    fish9
    For anyone who wants to play around with this, you can download the dictionary file and the source code for append_digit and try it out as follows:

    Code:
    cd
    mkdir hijack_fopen
    cd hijack_fopen
    wget http://virjacode.com/projects/hijack_fopen/dict.txt
    wget http://virjacode.com/projects/hijack_fopen/append_digit.c
    gcc append_digit.c -o append_digit
    ./append_digit dict.txt
    Now let's take a quick look at the code for append_digit:

    Code:
    #include <stdio.h>
    #include <string.h>
    
    int main(int argc, char **argv)
    {
        char buffer[62+1+1]; /* Buffer to hold line taken from file:
                                63 for password (not 64 because we're appending a digit)
                                1 for newline character
                                1 for null terminator*/
    
        FILE *dict = fopen(argv[1],"r");  /* Open the dictionary file */
    
        if (!dict)
        {
            puts("Unable to open dictionary file");
            return 0;
        }
    
        while ( fgets(buffer,sizeof buffer,dict) )  /* Attempt to read a line */
        {
            unsigned i = 0;
    
            if (buffer[0] == '\0' || buffer[0] == '\n' ) /* Skip line if bad string */
                continue;
    
            if (buffer[strlen(buffer)-1] == '\n')
                buffer[strlen(buffer)-1] = '\0'; /* Remove the trailing new line if present */
           
            do printf("%s%u\n",buffer,i); /* Print out the new password with number appended */
            while (++i != 10);
        }
    
        fclose(dict);
    }
    As you can see, the code reads passwords from a file, and there's no way of getting it to read passwords from stdin.

    ........so here's where the hijacking comes in. We need to hijack the call made to fopen, and replace it with a call to the following function:

    Code:
    FILE *fopen_HIJACKED(const char *filename, const char *mode)
    {
        if (!strcmp(filename,"GIVE_ME_STDIN"))
            return stdin;
    
        return fopen(filename,mode);
    }
    If the input file is specified as "GIVE_ME_STDIN", then as you can see, it will return stdin.

    But how exactly do we make sure that this hijacked function gets called... well one method is to use a preproccesor macro:

    Code:
    #define fopen(filename,mode) fopen_HIJACKED(filename,mode)
    If this preprocessor macro were to come into force, then wherever the code contains fopen, it gets replace with fopen_HIJACKED.

    But as I said, we don't want to edit the source code for append_digit, so where will we put this preprocessor macro? We navigate to where fopen is declared, in the C Standard Library in a little header file called stdio.h.

    We need to open up /usr/include/stdio.h and append the following to the end of it:

    Code:
    #include <string.h>
    
    inline FILE *fopen_HIJACKED(const char *filename, const char *mode)
    {
        if (!strcmp(filename,"GIVE_ME_STDIN"))
            return stdin;
    
        return fopen(filename,mode);
    }
    If you want to edit your own stdio.h, then do this:

    Code:
    sudo cp /usr/include/stdio.h /usr/include/stdio.h.original
    wget http://virjacode.com/projects/hijack_fopen/tail_of_stdio.h
    sudo sh -c "cat tail_of_stdio.h >> /usr/include/stdio.h"
    After we do this, we recompile append_digit, and then try to get it to read from stdin as follows:

    Code:
    gcc append_digit.c -o append_digit
    cat dict.txt | ./append_digit GIVE_ME_STDIN
    ...and it works! It won't be as simple though for bigger programs (you'll get problems such as multiple-definition errors if stdio.h is included more than once). Also, there will be more complications if other functions in the fopen family are called.

    If anyone can think of a program that they'd like to add this functionality to, then post here and I'll give it a go.

    Now don't forget to put your stdio.h file back to the way it was:

    Code:
    sudo cp /usr/include/stdio.h.original /usr/include/stdio.h

    Ask questions on the open forums, that way everybody benefits from the solution, and everybody can be corrected when they make mistakes. Don't send me private messages asking questions that should be asked on the open forums, I won't respond. I decline all "Friend Requests".

  3. #3
    Junior Member
    Join Date
    Jan 2010
    Posts
    79

    Default

    Additionally, if you specify a hyphen as the "file name" then unix/Linux redirects to stdin/stdout. So, for example:
    crunch 8 8 | aircrack-ng -w - *.cap

    should work.

    Another common example would be:
    gzip -dc somefle.gz | tar xvf -

  4. #4
    Very good friend of the forum Virchanza's Avatar
    Join Date
    Jan 2010
    Posts
    863

    Default

    Quote Originally Posted by armedpilot View Post
    Additionally, if you specify a hyphen as the "file name" then unix/Linux redirects to stdin/stdout. So, for example:
    crunch 8 8 | aircrack-ng -w - *.cap

    should work.

    Another common example would be:
    gzip -dc somefle.gz | tar xvf -
    That's not built into Unix -- that's actually specifically written into the programs you mentioned.

    You can try it out with a simple program:

    Code:
    #include <stdio.h>
    
    int main(void)
    {
        FILE *donkey = fopen("-","r");
    
        fputs("hello",donkey);
    
        return 0;
    }
    I compiled and ran this program on Backtrack, but I got "Segmentation Fault", so that indicates that the hyphen thing is not a feature built into Linux.

    It wouldn't be hard at all to add this "hyphen functionality" to the C Standard Library, and that's pretty much what I'm doing in this thread. I've chosen a "special word" instead of a hyphen though because the hyphen might interfer with the program parsing its command line arguments (because the hyphen is typically used as a switch before a letter).

    Anyone got an idea for a program to try this out on? Since pureh@te was saying Aircrack doesn't work with piping hash symbols into it then I might start on that.
    Ask questions on the open forums, that way everybody benefits from the solution, and everybody can be corrected when they make mistakes. Don't send me private messages asking questions that should be asked on the open forums, I won't respond. I decline all "Friend Requests".

  5. #5
    Member
    Join Date
    Jan 2010
    Posts
    70

    Default

    Seems like a lot of work for something that LD_PRELOAD can take care of without having to modify your standard C library.

    As an example - hxxp://aconole.brad-x.com/programs/libmemchk-0.0.2.tar.gz wraps malloc, free, mmap, munmap, etc. without modifying the standard C library, and has the additional benefit of being able to remove the functionality without having to recompile the program. (NOTE: replace the x's with t's)

    -Aaron

  6. #6
    Junior Member
    Join Date
    Jan 2010
    Posts
    81

    Default

    Make a suggestion to the makers of the Aircrack with your hijack implementation instead of modifying C functions.

  7. #7
    Just burned his ISO
    Join Date
    Dec 2009
    Posts
    2

    Default

    As far as I know, every application that takes a filename as an argument can also read from stdin (at least on recent Linux-based OS):

    Code:
    $ echo "hi, reading from stdin" | cat /dev/fd/0
    Of course, this example is a bit silly since cat can already read from stdin when you specify no argument or the infamous '-' argument.

  8. #8
    Very good friend of the forum Virchanza's Avatar
    Join Date
    Jan 2010
    Posts
    863

    Default

    I've been on holidays the last two weeks so I haven't been paying attention. I just got back now.

    As far as I know, every application that takes a filename as an argument can also read from stdin (at least on recent Linux-based OS):
    Holy crap! That's absolutely fantastic!

    I had to do a web search for "/dev/fd/0" because I've never heard of it before. It really drills home the point that "everything is a file" in Unix! On modern Linux systems, you can even type "/dev/stdin" instead of "/dev/fd/0".

    I was able to get it working with my own guinea pig program... but for some reason I can't get this to work:

    Code:
    /pentest/passwords/crunch/crunch 8 8 | aircrack-ng -w /dev/stdin /pentest/wireless/aircrack-ng/test/wpa.cap
    It's late now so I'm gonna go to bed... but I'll look into it tomorrow.

    Nice catch Hexanol! To think, I would have gone playing around with stuff like LD_PRELOAD and even editing the Standard Library, when all I had to do was specify the filename as "/dev/stdin"!

    Here's a good page I found on the net:

    InformIT: Advanced Programming in the UNIX® Environment: UNIX File I/O > /dev/fd
    Ask questions on the open forums, that way everybody benefits from the solution, and everybody can be corrected when they make mistakes. Don't send me private messages asking questions that should be asked on the open forums, I won't respond. I decline all "Friend Requests".

  9. #9
    Just burned his ISO
    Join Date
    Dec 2009
    Posts
    2

    Default

    Well, I have taken a look at your problem, and indeed, it seems like aircrack-ng isn't really flexible when it comes to handling wordlist files that don't support seeking (i.e. FIFO files and the likes).

    But before giving more details, I have to say that, as of version 1.0, aircrack-ng can take a '-' as argument for the -w option. So yes, this:
    Code:
    $ cat /usr/share/dict/words | aircrack-ng -e myessid -w - mycap.cap
    will work just fine. And by looking at the ChangeLog in the aircrack source code, it seems this features as been there since at least 0.8.

    Anyway. Guess it's problem solved. At least we learned something!

  10. #10
    Very good friend of the forum Virchanza's Avatar
    Join Date
    Jan 2010
    Posts
    863

    Default

    Anybody been playing around with this some more? I still can't see why Aircrack won't work when you specify "/dev/stdin".
    Ask questions on the open forums, that way everybody benefits from the solution, and everybody can be corrected when they make mistakes. Don't send me private messages asking questions that should be asked on the open forums, I won't respond. I decline all "Friend Requests".

Page 1 of 2 12 LastLast

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •