user1573235
user1573235

Reputation: 103

passing shell argument to c program on mac osx

I'm trying, for educational purposes, to run a program which uses a buffer overflow to overwrite a function pointer address. I have determined the location of the function pointer I want to overwrite using nm. I then want to pass the address of the new function pointer to argv. I'm trying to use

perl -e 'print "aa\xc0\x0c\x00\x00\x01\x00\x00\x00\"'| ./a.out

where \xc0\x0c\x00\x00\x01\x00\x00\x00\ is little endian for the address of the new function pointer and aa is just to fill the char buffer. The problem is this doesn't seem to pipe the output to a.out as argc is always 1. I also tried

perl -e 'print "aa\xc0\x0c\x00\x00\x01\x00\x00\x00\n"' > a.bin cat a.bin - | ./a.out

and argc is still 1.

I attached a copy of my program for easier following. Also is there an easier way to pass formatted bytes directly to a c program instead of using perl, without changing the current structure of my program?

so can I do ./a.out and have it run?

Thanks

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

typedef struct user_s{
    char name[2];
    void (*print_name)();
}user;

user a;

void print_name1(){
    printf("hello\n");
}

void print_name2(){
    printf("hi\n");
}

void usage(char * msg){
    printf("usage: %s <name>\n", msg);
}

void fill_name (char * name_to_fill, char *filler){
    int i, len;
    len = strlen(filler);
    printf("length of filler is %d\n", len);
    for (i = 0 ; i < len; i ++){
        *(name_to_fill + i) = *(filler+i);
    }
}

int main(int argc, char * argv[]){
    printf("argc = %d",argc);
    if (argc != 2){
        usage(argv[0]);
        return 0;
    }
    a.print_name = print_name1;
    a.print_name();
    fill_name(a.name, argv[1]);
    a.print_name();
    return 1;
}

Upvotes: 0

Views: 246

Answers (3)

user1157391
user1157391

Reputation:

With bash you can just do:

./a.out $'aa\xc0\x0c\x00\x00\x01\x00\x00\x00'

Upvotes: 1

stonesam92
stonesam92

Reputation: 4457

Like John says, you're confusing arguments with stdin. To pass the output of a program as an argument you can use command substitution by wrapping it in $(command), so for your example you should do

./a.out $(perl -e 'print "aa\xc0\x0c\x00\x00\x01\x00\x00\x00\"')

Upvotes: 1

John Auld
John Auld

Reputation: 486

You're confusing command-line arguments with stdin. Your command:

perl -e 'print "aa\xc0\x0c\x00\x00\x01\x00\x00\x00\"'| ./a.out

will write to the program's stdin. If you want to do the same thing as a command-line argument, try:

perl -e 'print "aa\xc0\x0c\x00\x00\x01\x00\x00\x00\"'| xargs ./a.out

see: http://ss64.com/bash/xargs.html

Upvotes: 2

Related Questions