I followed up the login process of the SQL SERVER database server and found that password calculation is very fragile. The password fragility of the SQL SERVER database reflects two aspects:
1. Password encryption algorithm when logging in to the network
2. Password encryption algorithm stored in database.
The following are the following:
1. Password encryption algorithm when logging in to the network
SQL SERVER network encryption passwords have always been very fragile. There are many written comparison tables on the Internet, but none of them are processed in specific algorithms. In fact, I will track SQL.
The SERVER login process is easy to obtain its decryption algorithm: OK, let's demonstrate the assembly process:
The TDS package of login type jumps to 4126a4 to execute
004DE72E: Generate the corresponding buffer of the size according to the received size field for the next copy
004DE748 Copy the LOGIN information from the received TDS BUF offset 8
004DE762: call sub_54E4D0: Push the new copy of the buffer for parameter checking
The information in the TDS packet is processed in turn. Each field climate should have the length of each domain, and the length is compared at offset 0X24.
The following assembly code is an algorithm that implements decryption of network encryption passwords:
.text:0065C880 mov cl, [edi]
.text:0065C882 mov dl, cl
.text:0065C884 xor cl, 5
.text:0065C887 xor dl, 0AFh
.text:0065C88A shr dl, 4
.text:0065C88D shl cl, 4
.text:0065C890 or dl, cl
.text:0065C892 mov [edi], dl
.text:0065C894 inc edi
.text:0065C895 dec eax
.text:0065C896 jnz short loc_65C880
.text:0065C898 jmp loc_4DE7E6
It is easy to change it to C code. It can be seen that its encryption is very simple and is no different from plain text. Haha, you can embed this code in SNIFFER to decrypt the TDS login package you sniffed. In fact, 0XA5 is not a demarcation symbol for a specific SQL SERVER password field. It is just that the encryption algorithm will automatically encrypt 0x0 of the ASC double-byte representation to 0xa5. However, if a double-byte password is allowed, this is not the main reason for judging its demarcation.
void sqlpasswd(char * enp,char* dnp)
{
int i;
unsigned char a1;
unsigned char a2;
for(i=0;i<128;i++)
{
if(enp[i]==0)
break;
a1 = enp[i]^5;
a1 = a1 << 4;
a2 = enp[i]^0xaf;
a2 = a2 >> 4;
dnp[i]=a1|a2;
}
dnp[i]=0;
dnp[i+1]=0;
wprintf(L"passwd:%s\n",(const wchar_t *)dnp);
}
2. Password encryption algorithm stored in database.
The encryption method of SQL SERVER's password to database storage is also weird. The process is as follows:
After obtaining the password for the network decryption password
Call SQLSORT_14 at 005F9D5A, implement a conversion to uppercase password buffer for saving.
Then call a function at 004def6d to retrieve the encrypted PASSWORD in the database, in the form as follows:
2 bytes header 0x0100 (fixed)
4 bytes of HASH plus secret KEY
20 bytes HASH1
20 bytes HASH2
As an example I took out:
fx:0x0100 1751857F DFDEC4FB618D8D18EBA5A27F615639F607CD46BE DFDEC4FB618D8D18EBA5A27F615639F607CD46BE
Fixed
Password is: 123456
SQL first uses 4 bytes of HASH and secret KEY to supplement the buffers of its two passwords, one in uppercase and the other in lowercase. Then its encryption process is as follows: C function
CryptAcquireContextW(&hProv,NULL,L("Microsoft Base Cryptographic Provider v1.0"),1,0xf0000000);
CryptCreateHash(hProv,0x8004,NULL,NULL,&hhash);
CryptCreateHash(hProv,0x8004,NULL,NULL,&hHash);
005F9DFE:
CryptHashData(hhash,passwdbuf,0x12,NULL);passwdbuf is a lowercase passwd buffer, and then a KEY is attached. As shown in the above example, it is correct.
{ { { { { { { { { { { { { �
CryptHashData(hHash,PASSWDBUF,0x12,NULL); PASSWDBUF is a capital passwd buffer, and then a KEY is attached
005F9E3E:
CryptGetHashParam(hhash,2,&passwdout,&outlen,0); Take out the encrypted value of passwdbuf that is lowercase passwd
CryptGetHashParam(hHash,2,&PASSWDOUT,&OUTLEN,0); Take out the encrypted value of passwdbuf that is capitalized by passwd
These two sums are the PASSWORD encryption fields in the real database
Why are the above methods fragile? In fact, its true encryption length is only 20 bytes.
The 40-bit HASH value of the HASH1 spliced in lowercase password + uppercase password is not as safe as a direct 20-bit HASH value. Because everyone knows the causal relationship between these two values,
Provide more information to the decryptor.
As the algorithm is the same, if HASH1=HASH2, it can be judged that the password must not use letters, and only passwords with numbers and symbols are used. For example, the HASH of the 123456 password retrieved above, the two HASHs are exactly equal.
It is because the letters are used, and the solution of the supplementary KEY, algorithm, and two encrypted strings should be greatly simplified.
Of course I have never studied encryption algorithms, but I just feel that this encryption method is really insecure. Haha, I hope the expert in decrypting algorithms will give me some advice.
1. Password encryption algorithm when logging in to the network
2. Password encryption algorithm stored in database.
The following are the following:
1. Password encryption algorithm when logging in to the network
SQL SERVER network encryption passwords have always been very fragile. There are many written comparison tables on the Internet, but none of them are processed in specific algorithms. In fact, I will track SQL.
The SERVER login process is easy to obtain its decryption algorithm: OK, let's demonstrate the assembly process:
The TDS package of login type jumps to 4126a4 to execute
004DE72E: Generate the corresponding buffer of the size according to the received size field for the next copy
004DE748 Copy the LOGIN information from the received TDS BUF offset 8
004DE762: call sub_54E4D0: Push the new copy of the buffer for parameter checking
The information in the TDS packet is processed in turn. Each field climate should have the length of each domain, and the length is compared at offset 0X24.
The following assembly code is an algorithm that implements decryption of network encryption passwords:
.text:0065C880 mov cl, [edi]
.text:0065C882 mov dl, cl
.text:0065C884 xor cl, 5
.text:0065C887 xor dl, 0AFh
.text:0065C88A shr dl, 4
.text:0065C88D shl cl, 4
.text:0065C890 or dl, cl
.text:0065C892 mov [edi], dl
.text:0065C894 inc edi
.text:0065C895 dec eax
.text:0065C896 jnz short loc_65C880
.text:0065C898 jmp loc_4DE7E6
It is easy to change it to C code. It can be seen that its encryption is very simple and is no different from plain text. Haha, you can embed this code in SNIFFER to decrypt the TDS login package you sniffed. In fact, 0XA5 is not a demarcation symbol for a specific SQL SERVER password field. It is just that the encryption algorithm will automatically encrypt 0x0 of the ASC double-byte representation to 0xa5. However, if a double-byte password is allowed, this is not the main reason for judging its demarcation.
void sqlpasswd(char * enp,char* dnp)
{
int i;
unsigned char a1;
unsigned char a2;
for(i=0;i<128;i++)
{
if(enp[i]==0)
break;
a1 = enp[i]^5;
a1 = a1 << 4;
a2 = enp[i]^0xaf;
a2 = a2 >> 4;
dnp[i]=a1|a2;
}
dnp[i]=0;
dnp[i+1]=0;
wprintf(L"passwd:%s\n",(const wchar_t *)dnp);
}
2. Password encryption algorithm stored in database.
The encryption method of SQL SERVER's password to database storage is also weird. The process is as follows:
After obtaining the password for the network decryption password
Call SQLSORT_14 at 005F9D5A, implement a conversion to uppercase password buffer for saving.
Then call a function at 004def6d to retrieve the encrypted PASSWORD in the database, in the form as follows:
2 bytes header 0x0100 (fixed)
4 bytes of HASH plus secret KEY
20 bytes HASH1
20 bytes HASH2
As an example I took out:
fx:0x0100 1751857F DFDEC4FB618D8D18EBA5A27F615639F607CD46BE DFDEC4FB618D8D18EBA5A27F615639F607CD46BE
Fixed
Password is: 123456
SQL first uses 4 bytes of HASH and secret KEY to supplement the buffers of its two passwords, one in uppercase and the other in lowercase. Then its encryption process is as follows: C function
CryptAcquireContextW(&hProv,NULL,L("Microsoft Base Cryptographic Provider v1.0"),1,0xf0000000);
CryptCreateHash(hProv,0x8004,NULL,NULL,&hhash);
CryptCreateHash(hProv,0x8004,NULL,NULL,&hHash);
005F9DFE:
CryptHashData(hhash,passwdbuf,0x12,NULL);passwdbuf is a lowercase passwd buffer, and then a KEY is attached. As shown in the above example, it is correct.
{ { { { { { { { { { { { { �
CryptHashData(hHash,PASSWDBUF,0x12,NULL); PASSWDBUF is a capital passwd buffer, and then a KEY is attached
005F9E3E:
CryptGetHashParam(hhash,2,&passwdout,&outlen,0); Take out the encrypted value of passwdbuf that is lowercase passwd
CryptGetHashParam(hHash,2,&PASSWDOUT,&OUTLEN,0); Take out the encrypted value of passwdbuf that is capitalized by passwd
These two sums are the PASSWORD encryption fields in the real database
Why are the above methods fragile? In fact, its true encryption length is only 20 bytes.
The 40-bit HASH value of the HASH1 spliced in lowercase password + uppercase password is not as safe as a direct 20-bit HASH value. Because everyone knows the causal relationship between these two values,
Provide more information to the decryptor.
As the algorithm is the same, if HASH1=HASH2, it can be judged that the password must not use letters, and only passwords with numbers and symbols are used. For example, the HASH of the 123456 password retrieved above, the two HASHs are exactly equal.
It is because the letters are used, and the solution of the supplementary KEY, algorithm, and two encrypted strings should be greatly simplified.
Of course I have never studied encryption algorithms, but I just feel that this encryption method is really insecure. Haha, I hope the expert in decrypting algorithms will give me some advice.