I’ve always thought the concepts that Hyperion utilizes to encrypt and hide an executable are very interesting. As a result, I thought it would be a fun exercise to try to create a Veil payload that utilizes the following concepts:
- Encrypt the shellcode stored within the executable
- Only contain part of the decryption key within the executable
- Make the payload brute force itself to find the complete decryption key
Hopefully, it’ll be worthwhile to walk you through how this payload works, so that’s what I’ll do. 🙂
Encrypting and decrypting shellcode is the easy part, this is something that is already done in Veil’s AES, DES, and ARC4 encrypting payloads. But I needed to create a script that attempts to decrypt our ciphertext, thousands of times until it finds the decryption key. I incorrectly assumed that when using the incorrect decryption key, and exception would be thrown, but that isn’t the case. The decryption routine is still run on our ciphertext, and garbage data is returned as out “cleartext” data. Since I can’t trigger an event based on an exception of the wrong decryption key being used, I needed a different method to determine when the real key has been found. My implementation is to encrypt a known string with the same key used to encrypt the shellcode.
Each round of the decryption routine will decrypt the ciphertext containing our known cleartext string. The decrypted value is then compared to the known plaintext string. If they don’t match, then the code assumes the wrong decryption key was used, and changes to another key. If the decrypted string matches our known string, the code then assumes that the real key has been found.
The picture above is the obfuscated source code to the brute-forcing payload. Line 5 contains our partial decryption key, but not all of it. They key was artificially constrained to ensure the final few ascii characters used as the decryption key are numerical. The numbers chosen are within a known range, so while we don’t know the exact number used, we can simply try all numbers within the known keyspace until the correct decryption key is identified.
Line 8 creates a for loop which will loop through all numbers within the known keyspace, and line 9 creates a decryption key by concatenating our partial key plus the “current number” of our for loop. Line 11 is our attempt to decrypt our known string, and line 12 is checking the decrypted value against our known string. If it’s a match, we can assume that this is our decryption key.
Once the key has been found, the script then drops into the if statement, and acts like any of Veil’s other encrypted payloads; system memory is allocated for use, the shellcode is decrypted, placed into memory, and then the decrypted shellcode is executed in memory.
The timeframe it takes it receive the callback from this payload obviously varies based on the “random” number that was generated and used in the decryption key. This payload will be released shortly as one of Veil’s upcoming V-Days.
7 thoughts on “Developing a Self-Brute Forcing Payload for Veil”
I think I love you. This is awesome!
Holy shit, this is sick.
this is awesome I love the idea
So the main draw back of this seems to be that the decryption has to be checked against a ‘known’ decryption key. So here’s my thing. I’m thinking that you don’t need to validate that the decryption key matches a ‘known’ key, but because you’re decrypting a known executable payload, why not just compare the first couple bytes of the decrypted string so that it can be validated as a executable or not, and thus decrypted, as it seems unlikely that you would have that problem with decrypting the data AND the invalid decryption key being able to create executable bytes at the beginning.
Sorry if this is not applicable because I don’t understand the concept.
I’ve uploaded a gist of the idea of what I mean, in it you can see it randomly choose from between 1 and 20 showing what the text is when it decodes, looping when the decrypted string can’t be executed successfully.
Yeah, that absolutely looks like another way of doing this. Only obvious difference is you’re performing exception handling vs. me verifying a known plaintext string. To be honest, I have no idea which is more efficient, but I really like this method/logic too, as it’s a new way I didn’t even think about.
Thanks for posting it!