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:
Well after you run this through append_digit you'd end up with:
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:
Now let's take a quick look at the code for append_digit:
gcc append_digit.c -o append_digit
As you can see, the code reads passwords from a file, and there's no way of getting it to read passwords from stdin.
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,"r"); /* Open the dictionary file */
puts("Unable to open dictionary file");
while ( fgets(buffer,sizeof buffer,dict) ) /* Attempt to read a line */
unsigned i = 0;
if (buffer == '\0' || buffer == '\n' ) /* Skip line if bad string */
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);
........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:
If the input file is specified as "GIVE_ME_STDIN", then as you can see, it will return stdin.
FILE *fopen_HIJACKED(const char *filename, const char *mode)
But how exactly do we make sure that this hijacked function gets called... well one method is to use a preproccesor macro:
If this preprocessor macro were to come into force, then wherever the code contains fopen, it gets replace with fopen_HIJACKED.
#define fopen(filename,mode) fopen_HIJACKED(filename,mode)
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:
If you want to edit your own stdio.h, then do this:
inline FILE *fopen_HIJACKED(const char *filename, const char *mode)
After we do this, we recompile append_digit, and then try to get it to read from stdin as follows:
sudo cp /usr/include/stdio.h /usr/include/stdio.h.original
sudo sh -c "cat tail_of_stdio.h >> /usr/include/stdio.h"
...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.
gcc append_digit.c -o append_digit
cat dict.txt | ./append_digit GIVE_ME_STDIN
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:
sudo cp /usr/include/stdio.h.original /usr/include/stdio.h