UnDesXing
In my own vocabulary, undesxing is the action of decrypting something encrypted with the Microsoft version of the DESX algorithm: a bit obfuscated title but I liked to make a scenographic use of it.
DESX is a variant of the Data Encryption Standard in that a XOR step is added to the plaintext before and after the encryption: you can find a description on wikipedia. So, what is the issue with it? Let me provide the context.
windows lsass
The Windows Local Security Authority (LSA) Subsystem Service (lsass) process is in charge, among other things, to authenticate and log users on to the local system: see Microsoft info here. It's well known that it keeps some sensitive information regarding the logon sessions: for example users' passwords and tokens. This kind of storage - basically due to the SSO capability - is exploited by the never-loved-enough mimikatz, which is able to provide some cool passive (not considering its active operation modalities) information.
This gold mine is kept in lsass process memory, but not all stuffs are in cleartext form. Lsass likes to encrypt some of its (definitely ours!) secrets: obviously lsass has all the data needed to decrypt them. If lsass has that data, we have it too.
Starting from Windows Vista, lsass uses the AES and 3DES to protect that data, without any change to the original algorithms: if you're able to grab the key and the iv (init vector) from the memory (live or dump) you can use any implementation of those algos to decrypt the data.
Before Vista? Lsass processes coming out from the Windows XP family uses different algorithms for the same purpose: RC4 and DESX. Nothing to say about RC4, a couple of caveats about the latter.
some info
Trying to get more technical, when lsass needs to encrypt part of its memory it uses the function LsaEncryptMemory provided by the lsasrv.dll module: the same when it needs to decrypt that data, by simply specifying the modality to use (0 is decrypting, 1 is encrypting). The LsaEncryptMemory has three parameters: the input buffer, the input buffer length and the modality. At this point, both pre-Vista and post-Vista Windows exhibit a similar behaviour: if the input buffer length is not multiple of 8 bytes, RC4 (pre-Vista) and AES are used; otherwise DESX (pre-Vista) and 3DES.
Let's see what happens inside the Windows XP LsaEncryptMemory in the DESX case: in the following example I used an lsasrv.dll module version 5.1.2600.6058 and GUID FC6285E5-A654-4781-BD4C-BA9E9A0B69E.
There is a call to the CBC function, providing the encryption method as a parameter, desx in figure. The CBC (Cipher Block Chaining mode of operation) method is a bit branched, and I isolated only the relevant path, based on how LsaEncryptMemory initialize its parameters and based on testing.
The "call edx" in the previous figure is a call to the function parameter, desx. In the following the desx decryption branch is reported.
In the next figure a partial view of des decryption branch is reported (truly long, since the loop it's unrolled).
So basically there is a Microsoft interpretation of DES-X algorithm, and that is the first issue to be considered. The second one is the key, which is not present inside the memory. Wait, let me elaborate. During the LsaInitializeProtectedMemory execution the (pseudo)random DES (X) key is created and lost, since the key is exploded in its corresponding rounds-subkeys (key scheduling). So what you will find in memory are the 16 round subkeys, 128 bytes, plus two 8 bytes whitening vectors, for a 144 bytes blob. This is exactly what the debug symbol lsasrv!g_pDESXKey is pointing to, coupled with the lsasrv!g_Feedback symbol (used as the first XOR in CBC function).
In the next figure a partial view of des decryption branch is reported (truly long, since the loop it's unrolled).
So basically there is a Microsoft interpretation of DES-X algorithm, and that is the first issue to be considered. The second one is the key, which is not present inside the memory. Wait, let me elaborate. During the LsaInitializeProtectedMemory execution the (pseudo)random DES (X) key is created and lost, since the key is exploded in its corresponding rounds-subkeys (key scheduling). So what you will find in memory are the 16 round subkeys, 128 bytes, plus two 8 bytes whitening vectors, for a 144 bytes blob. This is exactly what the debug symbol lsasrv!g_pDESXKey is pointing to, coupled with the lsasrv!g_Feedback symbol (used as the first XOR in CBC function).
LsaEncryptMemory XP transposition ... LsaDecryptXp
Mimikatz reuse the decryption capability offered by the Windows OS: to be able to decrypt DESX encrypted secrets without native Windows features, you need to reverse the algorithm. That's the reason I wrote LsaDecryptXP Python module. I opted for a quick&dirty approach: if you take a look at the code, you'll understand why I used the word transposition. Anyway, a quite good effort/time result. You can find LsaDecryptXP on github.com/dfirfpi/lsadecryptxp.
It depends: one question and one tip. The question: did you known that the awesome Rekall has a mimikatz plugin? The tip: in the next weeks you could check the Rekall code reviews for some cool refactoring of that plugin, and it will use this addon.
who cares?
It depends: one question and one tip. The question: did you known that the awesome Rekall has a mimikatz plugin? The tip: in the next weeks you could check the Rekall code reviews for some cool refactoring of that plugin, and it will use this addon.
Comments
Post a Comment