11:02 Storing and encrypting passwords microsoft windows | |
About password cracking windows were written many articles, but they all boil down to the use of any software or superficially describes how encryption LM and NT, and very superficially described syskey. I'll try to fix this neodostatok, describing all the details about where the passwords, in what form and how to convert utility syskey. There are 2 options to receive a password - through the registry or to gain direct access to the files, registry hives. In any case, you will either have privileges to user SYSTEM, or theft of treasured files, such as booting from another operating system. Here, I will not describe the possibility of gaining access, but in order to study more clearly will choose the first option, it will not focus on the structure of the hive. A run on the system will help us psExec utility from sysinternals. Of course, for these purposes, you can use the vulnerability of windows, but the article is not about that. V-blockWindows version to Vista's default password is stored in two different heshah - LM and NT. In Vista and later LM-hash is not stored. First take a look where to look for these hashes, and then look at what of themselves they represent. User passwords, as well as other useful information is stored in the registry at HKLM \ SAM \ SAM \ Domains \ Account \ users \ [RID] \ V , known as the V-block. Section SAM is in the appropriate file c: \ Windows \ System32 \ config \ SAM. RID - a unique user ID, you can learn, for example looking into the node HKLM \ SAM \ SAM \ Domains \ Account \ users \ names \ <user name> (parameter Default, the field - the parameter type). For example, RID Administrator account is always 500 (0x1F4), a user "Guest" - 501 (0x1f5). Access to SAM section by default is possible only if the user SYSTEM, but if you really want to see - run regedit c system privileges: PsExec.exe-s-i-d regedit. To observe the V-block in a convenient way possible, for example, export it to a text file (File-Export in Regedit). Here is what we see out there: From 0x0 to 0xCC are the addresses of all data that resides in the V-block size and some additional information about the data. To get a real email address must be to the address that we will add 0xCC. Addresses and sizes are kept on the principle BIG ENDIAN, ie the need to invert the bytes. For each parameter is given by 4 bytes, but in fact all the parameters fit in one or two bytes. Here's where to look for: Enter the user name - 0xS The length of username - 0x10 Address LM-hash - 0x9s The length of the LM-hash - 0xa0 Address NT-hash - 0xa8 length of the NT-hash - 0xac In this case, the user name exists at offset 0xd4 + 0xcc, and its length will 0xc bytes. NT-hash will be located at offset 0x12c + 0xcc, and its size (always the same) = 0x14. Another detail concerning the storage of passwords - as an NT-and to the LM-hash will always be added in the front 4 bytes, a destination where a mystery to me. And 4bayta will be present even if the password is disabled. In this case, it is clear that the length of the LM hash = 4 and if you look at his address, you can see, these 4 bytes in spite of the fact that there was no LM-hash not. Therefore, when searching for the displacement of hashes boldly we add 4 bytes to the address, and taking into account the size - subtract. If you prefer to read the code - that something like this would look search for addresses based inversion extra four bytes, and the addition of the starting offset 0xcc (code C #) int lmhashOffset = userVblock [0x9c] + userVblock [0x9d] * 0x100 + 4 + 0xcc ; int nthashOffset = userVblock [0xa8] + userVblock [0xa9] * 0x100 + 4 + 0xcc; int lmhashSize = userVblock [0xa0] + userVblock [0xa1] * 0x100 - 4; int nthashSize = userVblock [0xac] + userVblock [0xad] * 0x100 - 4; int usernameOffset = userVblock [0xc] + userVblock [0xd] * 0x100 + 0xcc; int usernameLen = userVblock [0x10] + userVblock [0x1a] * 0x100; userVblock - the value HKLM \ SAM \ SAM \ Domains \ Account \ users \ \ V as a byte array. More about the V-block can be read here. AlgorithmsNow sort out the encryption algorithm. The formation of NT-hash: 1. User's password is converted to a Unicode-string. 2. MD4-hash generated based on this line. 3. The resulting hash is encrypted algorithm DES, the key is made on the basis of RID user. The formation of LM-hash: 1. User's password is converted to upper case and padded with zeros to a length of 14 bytes. 2. The resulting string is divided into two halves to 7 bytes, and each of them separately encryption algorithm DES. As a result, we obtain the hash length of 16 bytes (consisting of two independent halves of a length of 8 bytes). 3. The resulting hash is encrypted algorithm DES, the key is made on the basis of RID user. 4. In windows 2000 and above both received hash additionally encrypted aloritmom RC4 using a key known as the "system key" or bootkey, utility-generated syskey, and encrypted rather tricky way. Consider a general sequence of actions to get the original password, and each step separately 1. Obtain bootkey, generate keys based on it for RC4, decrypt hashes using RC4 2. Obtain the keys for the DES from RID'ov users decrypt hashes DES'om 3. The resulting hash brute force attack. BootkeySystem Key (bootkey) is divided into 4 pieces and is in the following registry keys: HKLM \ System \ CurrentControlSet \ Control \ Lsa \ JD HKLM \ System \ CurrentControlSet \ Control \ Lsa \ Skew1 HKLM \ System \ CurrentControlSet \ Control \ Lsa \ GBG HKLM \ System \ CurrentControlSet \ Control \ Lsa \ Data Section system is in the file c: \ Windows \ System32 \ config \ system It should be noted that the "CurrentControlSet" is a reference to a section of controlset and created at boot time. This means that will not be able to find it in the file system, if the system is inactive. If you decide to seek the key to a file - you need to know the value of ContolSet by default in the HKLM \ SYSTEM \ Select \ default. For example if the HKLM \ SYSTEM \ Select \ default = 1 - instead of the HKLM \ System \ CurrentControlSet \ looking for a HKLM \ System \ controlset001 \ Each key Registry is a hidden attribute, known as «class». Regedit so it just does not show, but it can be seen, for example, if you export the registry keys in plain text files. In winapi for this attribute is a function of RegQueryInfoKey. Fragments are stored in the string representation of hexadecimal numbers, and on the principle BIG ENDIAN (ie not a string backwards, and the number). For example, we found here such records: Key Name: HKEY_LOCAL_MACHINE \ SYSTEM \ CurrentControlSet \ Control \ Lsa \ JD Class Name: 46003cdb = {0xdb, 0x3c, 0x00, 0x46} Key Name: HKEY_LOCAL_MACHINE \ SYSTEM \ CurrentControlSet \ Control \ Lsa \ Skew1 Class Name: e0387d24 = {0x24, 0x7d, 0x38, 0xe0} Key Name: HKEY_LOCAL_MACHINE \ SYSTEM \ CurrentControlSet \ Control \ Lsa \ GBG Class Name: 4d183449 = {0x49, 0x34, 0x18, 0x4d} Key Name: HKEY_LOCAL_MACHINE \ SYSTEM \ CurrentControlSet \ Control \ Lsa \ Data Class Name: 0419ed03 = {0x03, 0xed , 0x19, 0x04} A collection of four-part key is an array of bytes: scrambled_key = {0xdb, 0x3c, 0x00, 0x46, 0x24, 0x7d, 0x38, 0xe0, 0x49, 0x34, 0x18, 0x4d, 0x03 , 0xed, 0x19, 0x04}; Further elements of the array are rearranged on the basis of a constant array of p int [] p = {0xb, 0x6, 0x7, 0x1, 0x8, 0xa, 0xe, 0x0, 0x3 , 0x5, 0x2, 0xf, 0xd, 0x9, 0xc, 0x4}; element in this array to determine the position of permutations, ie Key [i] = scrambled_key [p [i]]; In this example, get the array: key [] = {0x4d, 0x38, 0xe0, 0x3c, 0x49, 0x18, 0x19, 0xdb, 0x46, 0x7d, 0x00, 0x04, 0xed, 0x34, 0x03, 0x24}; This array is the so-called bootkey. Just to encrypt passwords will not participate, he and a hash on based bootkey, fragments of f-block and some constants. We call it the Hashed bootkey. Hashed bootkeyfor Hashed bootkey we will need two string constants (ASCII): string aqwerty = "!@#$%^&*() qwertyUIOPAzxcvbnmQQQQQQQQQQQQ )(*@&% \ 0 "; string anum =" 0123456789012345678901234567890123456789 \ 0 " also need the F-box user (HKLM \ SAM \ SAM \ Domains \ Account \ users \ \ F), namely, its 16 bytes: F [0x70: 0x80] Based on these values, glued together into one large array form the MD5 hash, which will be the key for encryption RC4 rc4_key = MD5 (F [0x70: 0x80] + aqwerty + bootkey + anum). The last step is to get hashed bootkey will rc4 encryption (or decryption - in rc4 is one and the same function), receiving the keys fragment F-block F [0x80: 0xA0]; hashedBootkey = RC4 (rc4_key, F [0x80: 0xA0]) Hashed bootkey in our hands, remained with him to learn how to properly handle. Deshifruem passwords using Hashed BootkeyPassword LM and NT, we need 2 more string constants - string almpassword = "LMPASSWORD"; string antpassword = "NTPASSWORD"; as well as the user's RID as a 4-byte (additions zeros) and the first half of the Hashed Bootkey (hashedBootkey [0x0: 0x10]); All this is glued together into a single array of bytes and MD5 is considered by the rules: rc4_key_lm = MD5 (hbootkey [0x0: 0x10] + RID + almpassword); rc4_key_nt = MD5 (hbootkey [0x0: 0x10] + RID + antpassword); received md5 hash - key to rc4, which is encrypted LM and NT hashes V-block user userLMpass = RC4 (rc4_key_lm, userSyskeyLMpass); userNTpass = RC4 (rc4_key_lm, userSyskeyNTpass); At this stage we have the user password in the form in which they would be kept without Encryption syskey, we can say that the hardest thing behind us. proceed to next step DESBased on the four-byte RID'a user through some permutations and bitwise operations create 2 key DES. Here are the functions that implement obfuscation (C #): private byte [] str_to_key (byte [] str) { byte [] key = new byte [8]; key [0] = (byte) (str [0]>> 1); key [1] = (byte) (((str [0] & 0x01) <<6) | (str [1]>> 2) ); key [2] = (byte) (((str [1] & 0x03) <<5) | (str [2]>> 3)); key [ 3] = (byte) (((str [2] & 0x07) <<4) | (str [3]>> 4)); key [4] = (byte) (( (str [3] & 0x0F) <<3) | (str [4]>> 5)); key [5] = (byte) (((str [4] & 0x1F) <<2) | (str [5]>> 6)); key [6] = (byte) (((str [5] & 0x3F) <<1) | ( str [6]>> 7)); key [7] = (byte) (str [6] & 0x7F); for (int i = 0; i <8; i + + ) { key [i] = (byte) (key [i] <<1); } des_set_odd_parity (ref key); return key; } private byte [] sid_to_key1 (byte [] rid) { byte [] s = new byte [7]; s [0] = (byte) (rid [0 ] & 0xFF); s [1] = (byte) (rid [1] & 0xFF); s [2] = (byte) (rid [2] & 0xFF); s [3] = (byte) (rid [3] & 0xFF); s [4] = s [0]; s [5] = s [1] s [6] = s [2]; return str_to_key (s); } private byte [] sid_to_key2 (byte [] rid) { byte [] s = new byte [7]; s [0] = (byte) ((rid [3]) & 0xFF); s [1] = (byte) (rid [0] & 0xFF); s [2] = (byte) ((rid [1]) & 0xFF); s [3] = (byte) ((rid [2]) & 0xFF); s [4] = s [0]; s [5] = s [1]; s [6] = s [2]; return str_to_key (s); } Well here is nothing special comment, except for the function des_set_odd_parity (ref key) - this is one of the functions of libraries openssl, the problem is to add some "odd bits", is used to improve durability Key to attack. Next divide the NT (or LM) hash to 2 parts of 8 bytes and deshifruem DES'om-one-half of the encrypted key function of the formation of sid_to_key1, second - sid_to_key2. obfskey_l = userNTpass [0x0: 0x7 ] obfskey_r = userNTpass [0x8: 0xF] byte [] deskey1 = sid_to_key1 (RID); byte [] deskey2 = sid_to_key2 (RID); byte [] md4hash_l = DES (obfskey_l, deskey1); byte [] md4hash_r = DES (obfskey_r, deskey2); After gluing the two halves we get a md4 hash in the case of NT, or LanMan (DES) - in the case of LM. The resulting hash is ready to attack, brute force. By the way, md4 hash of the password blank - 31d6cfe0d16ae931b73c59d7e0c089c0 The study was conducted on the basis of the source code ophcrack-3.3.1, as well as articles Push the Red Button: SysKey and the SAM | |
|
Total comments: 0 | |