Ok, finally I have something that you could at least call an alpha.
And I’ve rewritten my old code so now this is pure powershell, no imported c# classes whatsoever. The one thing I couldn’t do in powershell was the Zlib compression/decompression. The Dll is stored as a base64 string in the module psm1 and is loaded directly into memory, it’s never stored on disk, not even temporarily.
This took longer than what I’d hoped for… First I had performance-issues after implementing the idea of .GetVariables(). Logical flaws, since all the other methods were made just for a single variable and, on top of that, chained. Had to rewrite a lot of them from scratch.
Then there was just this one last test, WinPE… There I stumbled upon an “OutOfMemoryException”-error, but only when executing the GetVariables method for the first time.
The module do create one big *ss psobject (hashtable) array and the client I tested it on was a slow virtual machine with dynamic memory but still, another flaw hidden somewhere.
Think that I worked passed both those issues now. Let me know if I haven’t. ;)
So back to the million dollar question mentioned in the last blogpost, how is the reserved1 binary registry value related to AES256 and decrypting the TS environment?
By now I knew that just as with passwords, the password itself is seldom used, but a hash of it. Backtracking using an API monitor I found that there was an array, 20 bytes in size, which somehow lead to the AES-Key used.
After googling it I was pretty sure that the 20 bytes (160-bits) was a SHA1 hash derived from the registry value. Got ahead of myself in the last post, this is where I encountered that the key (hash) was too short to use with AES.
After a lot of late nights I was about to throw in the towel. But then I had the thought “It must be possible to use a SHA1 key hash with AES, I mean, I can’t be the first one ever to have this issue.”
Then I found it. https://crypto.stackexchange.com/questions/32567/need-cryptderivekey-aes-implementation-in-c
using (SHA1 sha1 = SHA1.Create()) {
// The following algorithm is taken from:
// <link>http://msdn.microsoft.com/en-us/library/windows/desktop/aa379916%28v=vs.85%29.aspx</link>
byte[] baseData = sha1.ComputeHash(Encoding.UTF8.GetBytes(plaintextPassword));
byte[] buffer1 = new byte[64];
byte[] buffer2 = new byte[64];
for (int i = 0; i < 64; i++) {
buffer1[i] = 0x36;
buffer2[i] = 0x5C;
if (i < baseData.Length) {
buffer1[i] ^= baseData[i];
buffer2[i] ^= baseData[i];
}
}
byte[] buffer1Hash = sha1.ComputeHash(buffer1);
byte[] buffer2Hash = sha1.ComputeHash(buffer2);
return buffer1Hash.Concat(buffer2Hash).Take(_keySize / 8).ToArray();
}
I still needed to find out the IV-key and padding used but that was a simple game of trials and errors in comparison.
So here we have it: TSEnv3 (1.0_Alpha).
Alpha functions: *Can set any TS-variable to the wanted value, no matter the name of it. *Can add base64-padding to variable values. *Compress and decompress base64 variables *Decrypts the TSEnvironment at the go, no need of ComObjects, API's or Dlls. You own it. Adapt it in any way you want to.
And if you feel really adventurous or just want to take a closer look at the mess that I’ve made.
Try $TSEnv3 | gm -force
And please be kind. This is the first Powershell module I’ve ever made and the first time I’ve ever created a Powershell class.
Comments