A crypter is code that decrypts a previously encrypted payload, in this case a shellcode, and will then execute it. To encrypt it I chose one of the algorithms that went through the final round of AES: Twofish. But to make this one unique, I decided not to request the password to decrypt the payload from the user (usually as the first parameter to the executable in the command line) but, instead, to get it from a DNS request (CNAME record) to the host “password.andrelima.info” which will return the password in the following format: <password>.andrelima.info
But first things first. While I did quite a lot of rewriting, adapting, and debugging, the code I’ll be presenting is mostly derived from a Twofish optimised C implementation by Drew Csillag, and a DNS query code in C by Silver Moon. The latter was chosen due to only using linux sockets, reducing any external library dependencies to a minimum.
1. Shellcode / Payload
The payload used in an execve stack implementation, which means that, after executing it, a command line prompt should present itself, as follows:
As previously stated, the code base for the Twofish encryption was downloaded here, as it was the fastest implementation, in a reliable source, I could find. I then proceeded with adapting it to encrypt a shellcode and produce its output in hexadecimal format.
The password, that the code will be using, shall be set as a command line parameter (argv). The 128 bit encryption key is first set to all zeroes (cleanup for consistency certainty in the decryption process) and only then the given password is copied into the 16 bytes (128b) char array.
It is important to note that Twofish is a 128 bit block cipher. This means that, in the case of the shellcode, if its size is not an exact multiple of the block size, some padding will exist. In my first implementation I had the padding all set to zeroes. But in order to avoid any known-plaintext attacks, I later decided to generate a random stream of bytes. These random bytes will be of no consequence to the shellcode when decrypted, because after the last instruction (syscall – Figure 1, Line 18) nothing else will be executed. As stated by the execve documentation:
execve() does not return on success, and the text, data, bss, and stack of the calling process are overwritten by that of the program loaded.
This means that after the syscall instruction, we can have any random bytes and they’ll be of no consequence to the code execution. This is great, because I don’t need to worry about removing them at all.
One final note, regarding the compilation of the Crypter.c file, is that it requires giving GCC the “-O3” and “-fomit-frame-pointer” flags, as stated in the original code’s initial comments. The code uses some C optimisation techniques and it requires these flags to be able to compile it correctly. Another issue to be careful about, is the fact that the header file tables.h doesn’t exist originally in the Twofish download. It is actually generated by the provided python script as follows:
python makeCtables.py > tables.h
gcc -O3 -fomit-frame-pointer Crypter.c tables.h -o Crypter
After executing the crypter (which will produce a different output – actually just the last 128 bit block – every time it’s executed, due to the random byte stream generated to pad the original shellcode):
The password to decrypt the shellcode is set in the command line to the crypter: secret123
3. The DNS setup
The DNS setup is how I decided to store the password for decrypting the shellcode. The point is to have it as a CName DNS record associated with the host password.andrelima.info :
This can be easily verified with the dig tool (dig password.andrelima.info cname +short):
Of course one could set a local DNS server and test this functionality (e.g. bind9), but I already owned the domain “andrelima.info” and all I had to do was go in the DNS management page and add a record (Figure 5), which I’ll leave as is, for anyone who wishes to quickly test the code.
Now that the password is set, its retrieval is exactly the first thing the Decrypter will need to do:
The ngethostbyname will basically get the DNS record type specified as the second parameter (CName), which is associated with the host in the first parameter. It then proceeds to extracting the password from the retrieved string <password>.andrelima.info.
An improvement to this code will be to encode the password to make it possible to use any special characters in it. Hex format would be great, as it would be acceptable in the URL format to have something like 03f78b…a18d.andrelima.info.
So after getting the password, the code moves on to decrypting the encrypted shellcode shown in Figure 4:
To compile this, we run:
gcc -O3 -fomit-frame-pointer -fno-stack-protector -z execstack Decrypter.c tables.h -o Decrypter
This command now has the flags -fno-stack-protector -z execstack to allow for the execution of code in the stack – our decrypted shellcode.
And it then runs smoothly as expected (with some unnecessary but convenient debugging information):
You can find all the files on my gitlab account.
Thanks to Vivek Ramachandran and the Pentester Academy team, as I have enjoyed every second of this course since I’ve learned so many interesting things. All this, inspired me to learn even more and push the posts to always do a little bit more as well. Appreciate your work!
This blog post has been created for completing the requirements of the SecurityTube Linux Assembly Expert certification:
Student ID: PA-2109