View Single Post
Old 08-06-2004   #11 (permalink)
KoreK
Banned in DC
 
KoreK's Avatar
 
Join Date: Jul 2004
Posts: 102
I got this half-baked cracker, which sometimes can crack wep with less 100,000 IVs. There was a post quite while on netstumbler with a reference to 13% cases. Reinjection greatly speeds up the process (if the users are not using p2p). WEP is really bad. It's just that the tools haven't been made/released. Let's say 200000 IVs are necessary + injection tool (500 packet/s, packets are 100byte long): less than 7minutes/20Megs.

Two flaws I have never seen discussed:
Chopping:
Take a WEP packet. Chop off the last byte. The CRC/ICV is broken. Now if the last byte was 0, you xor last the last 4 bytes with a certain value and the CRC will become valid again. Retransmit the packet. Does it get through? If not, then if the last byte is 1...

What FMS conveniently forgot to say/Demo of other statistical flaws of WEP:
Code:
/* main.c
   Compile with:
   gcc -o main main.c
   Use:
   ./main <byte_number>
   collects statistics for the <byte_number>th byte of the rc4 key 
   (3 for the first byte of the WEP-key,...)  

   Variable p gives the byte to attack in the key K
   Description of the output: 
   * Value of the key
   * Number of times attack 1 worked (% of the total)
   * Number of times attack 2 worked (% of when detection was effective,
     % of the total)
   * Number of times attack 3 worked (% of the total)
   * ...
   * inverted attack!

   Attack 1 [FMS] is part stable/part unstable, so it sometimes gives 
   false positive.
   Attack 2 is consistently stable.
   Attack 3 is unstable: False positive/negative appear from time to time
   (it doesn't work on p=3, works on p=4 (24%!) except there is a false
   positive (18%), works correctly on p=5 (22%)/no false positive)
   Attack 4 and 5 (5%) are unstable, but not as much as 3.

   Attack 6 is an "inverted attack". It helps weeding out guesses. 
   Worst case should be like at most 2 detections for 256000 IVs or 
   less, 3 for 256000-512000, to be adjusted... Quite useful to get 
   rid of false positives.

   FMS Attack gets more and more samples as p increases, so other attacks 
   are useful for cracking wep with as few IV's as possible.

*/

#include <stdio.h>
#include <stdlib.h>

void swap(int *a,int *b) 
{
    int c;
    c=*a;
    *a=*b;
    *b=c;
}

int main(int argc,char **argv)
{
    unsigned int i,j,o1,o2,tmp,jp,p;
    unsigned int S[256];
//    unsigned int K[16]={0x00,0x00,0x00,0x45,0x15,0xa1,0x42,0x96,
//			0x45,0x23,0x53,0x53,0x56,0x16,0x44,0x32};
//    unsigned int K[16]={0x00,0x00,0x00,0x1f,0x58,0xa1,0xb2,0x86,
//			0x45,0x13,0x53,0x6e,0xa6,0x16,0x84,0xc2};
    unsigned int K[16]={0x00,0x00,0x00,0x1f,0x58,0xa1,0xb2,0x86,
			0x04,0x13,0x53,0x6e,0xa6,0x16,0x84,0xc2};
    int stat1[256],tstat1;
    int stat2[256],pstat2[256],tstat2;
    int stat3[256],tstat3;
    int stat4[256],tstat4;
    int stat5[256],tstat5;
    int stat6[256];

    if (argc>1) p=atoi(argv[1]);
    else p=3;

    for (i=0; i<256; i++) {
	stat1[i]=0;
	stat2[i]=0;
	pstat2[i]=0;
	stat3[i]=0;
	stat4[i]=0;
	stat5[i]=0;
	stat6[i]=0;
    }

    for (K[0]=0; K[0]<256; K[0]++) 
	for (K[1]=0; K[1]<256; K[1]++)
	    for (K[2]=0; K[2]<256; K[2]++) {
		// first get the data
		for (i=0; i<256; i++) S[i]=i;
		for (i=0,j=0; i<256; i++) {
		    j=(j+K[i & 0x0f]+S[i]) & 0xff;
		    swap(S+i,S+j);
		}
		i=1;
		j=S[1];
		tmp=(S[i]+S[j]) & 0xff;
		swap(S+i,S+j);
		o1=S[tmp];
		i=2;
		j=(j+S[2]) & 0xff;
		tmp=(S[i]+S[j]) & 0xff;
		swap(S+i,S+j);
		o2=S[tmp];

		// then do the attacks
		for (i=0; i<256; i++) S[i]=i;
		for (i=0,j=0; i<p; i++) {
		    j=(j+K[i & 0x0f]+S[i]) & 0xff;
		    swap(S+i,S+j);
		}
	     
		// first type of attack FMS 5%
		if ((S[1] < p) && ((S[1]+S[S[1]]) == p)) {
		    jp=o1;
		    stat1[(jp-j-S[p]) & 0xff]++;
		}

		// second type of attack 13%
		if (S[1] == p) {
		    for (jp=0; S[jp]!=0; jp++);
		    if (o1 == p) {
			stat2[(jp-j-S[p]) & 0xff]++;
		    }
		    // for statistical purposes
		    pstat2[(jp-j-S[p]) & 0xff]++;
		}

		// another one
		if ((o2 == 0) && (S[p] == 0) && (S[2] != 0)) {
		    stat3[(2-j-S[p]) & 0xff]++;
		}
		
		// and two more (well there are still about 10 of 'em left:)
		if ((S[1] > p) && (((S[2]+S[1]-p) & 0xff) == 0)) {
		    if (o2 == S[1]) {
			for (jp=0; S[jp] != ((S[1]-S[2]) & 0xff); jp++);
			if ((jp!=1) && (jp!=2)) stat4[(jp-j-S[p]) & 0xff]++;
		    }
		    else if (o2 == ((2-S[2]) & 0xff)) {
			for (jp=0; S[jp] != o2; jp++);
			if ((jp!=1) && (jp!=2)) stat5[(jp-j-S[p]) & 0xff]++;
		    }
		}

		// inverted attack
		if (S[2] == 0) {
		    if ((S[1] == 2) && (o1 == 2)) {
			stat6[(1-j-S[p]) & 0xff]++;
			stat6[(2-j-S[p]) & 0xff]++;
		    }
		    else if (o2==0) {
			stat6[(2-j-S[p]) & 0xff]++;
		    }
		}
		if ((S[1] == 1) && (o1 == S[2])) {
		    stat6[(1-j-S[p]) & 0xff]++;
		    stat6[(2-j-S[p]) & 0xff]++;
		}
		if ((S[1] == 0) && (S[0] == 1) && (o1 == 1)) {
		    stat6[(-j-S[p]) & 0xff]++;
		    stat6[(1-j-S[p]) & 0xff]++;
		}

		if ((K[1]==0) && (K[2]==0)) fprintf(stderr,".");

	    }

    fprintf(stderr,"\n");
		    
    tstat1=0;
    tstat2=0;
    tstat3=0;
    tstat4=0;
    tstat5=0;
    for (i=0 ; i<256 ;i++) {
	tstat1+=stat1[i];
	tstat2+=stat2[i];
	tstat3+=stat3[i];
	tstat4+=stat4[i];
	tstat5+=stat5[i];
    }
	
    for (i=0; i<256; i++) 
	printf("0x%02x: %3d(%4.1f%%) %2d(%4.1f%%-%4.1f%%) "
	       "%3d(%4.1f%%) %2d(%4.1f%%) %2d(%4.1f%%) %5d(%s)\n",i,
	       stat1[i],(100.0*stat1[i])/tstat1,
	       stat2[i],(100.0*stat2[i])/pstat2[i],(100.0*stat2[i])/tstat2,
	       stat3[i],(100.0*stat3[i])/tstat3,
	       stat4[i],(100.0*stat4[i])/tstat4,
	       stat5[i],(100.0*stat5[i])/tstat5,
	       stat6[i],(stat6[i] < 32 ? "possible" : "impossible"));

    return 0;

}
KoreK is offline