Security-Oriented C Tutorial 0xFB - A Simple Crypter

Jan 24, 2016 08:13 AM
Jan 24, 2016 08:43 AM
635891703021507805.jpg

Welcome to a tutorial on crypting technology. In this article, we will be discussing types of crypters, how they work and why they work. After defining these, we will then make our own basic crypter using the function I gave to you as a task to complete by yourself in the previous tutorial.

What Is a Crypter?

A crypter is a program which is used to assist malware with evading antivirus signature-based detection. How it does this is it applies an obfuscation method onto the malware so that the antivirus cannot successfully match it with any signature. It then outputs a seemingly "harmless" file called the stub. Once the stub is opened by the victim, it will decrypt the malware and execute it.

Types of Crypters

There are two types of crypters: scantime and runtime. As their name suggests, scantime crypters only evade antivirus detected as an idle file on disk. The runtime crypter is a scantime crypter with the ability to decrypt the malware while it is running. Scantime crypters are only capable of decrypting the malware in disk before executing it.

Runtime crypters are able to do this with the Windows API using a function called CreateProcess. There is a flag CREATE_SUSPENDED which allows the malware to be decrypted and then loaded into memory as a process before being executed.

635891728488910878.jpg

Creating a Concept

So now that we know how crypters work, we can attempt to create one. We will need to gather what we know before we can start planning the code. Let's do a checklist:

  • File I/O to read our malware and write to an obfuscated malware. Check.
  • Method of obfuscation. Check.

Obviously, we do not have the knowledge to create the runtime crypter because we are not familiar with either the Windows API or how executables are loaded into memory, so we will have to settle with a scantime.

Step 1: Planning with Pseudocode

We've completed our checklist and understand how crypters work. Let's now create a plan on how to code our crypter.

  1. Open our malware from disk with a binary read.
  2. Open an output file to disk with a binary write.
  3. Extract the contents one-by-one from our malware.
  4. Obfuscate the contents.
  5. Write the obfuscated contents into the output file.
  6. Close our streams! Don't forget this!

As for the deobfuscation part, remember that XOR can decrypt the encrypted as long as we use the same key. So our deobfuscation routine will be exactly the same! How wonderfully convenient!

If you have completed the task I assigned in the previous tutorial the hard part is done.

Step 2: Finding Functions

We have yet to discover a function which will execute a file (I do not recommend using the system function). Fear not, for I have found a suitable one for us. It's called execve. Head over to the manpage for execve for complete details. Overall, the execve requires a char *[] array which has pointers to the name of our target executable file as a string and environment arguments (which we do not need for this so it will just be NULL). Essentially:

char *args[] = {targetFileName, NULL};

execve (args[0], args, NULL);

On a linux machine, when we output a file, it may not have the necessary permissions to be executed. Because of this, we may require a function to programmatically and automatically do this for us. In the command line, we can do this with the chmod utility. In C, we have a function which can do the same job and guess what it's called. That's right, chmod .

Like execve, we require a pointer to a string of our target file's name. We also need a mode which are detailed in the man page. Since we require execution permissions we'll use the S_IXUSR flag (keep in mind that this will make the permissions of the file only executable). An example use of this function:

chmod (targetFileName, S_IXUSR);

If we are on a Windows machine, we simply require the output file to have the .exe extension to be able to execute.

Step 3: Prototyping

We've planned our pseudocode and have the necessary functions so let's begin making our basic prototype.

635891805313719029.jpg

We need to define the headers which have our functions execve and chmod, i.e. unistd.h and sys/stat.h respectively. We also want to define the XOR_KEY and our crypting jobs JOB_CRYPT and JOB_DECRYPT. This is for better readability - the given values for the jobs are just for convenience and they do not matter but of course, they cannot be the same.

We also require our xorFile function here which will apply the de/obfuscation on our files.

Let's continue onto main.

635891812170905354.jpg

We want to have our program parse the command line like so:

./crypt [JOB MODE] [IN FILE] [OUT FILE]

This has 4 arguments so we need to check if the user has entered less than what we need by comparing argc. If there aren't enough arguments, we print to the standard error stream to inform the user on how to use the program.

We then need to check if the user has input a suitable job mode, either "crypt" or "decrypt", but of course, we know there is no difference between the two. We only require JOB_DECRYPT so that we can execute the deobfuscated program.

Next, we run our xorFile function to de/obfuscate the input file to produce the output file. After completing the function, we check if the job mode is JOB_DECRYPT. If it is, we set up a char *[] array for execve and use the chmod function to make our deobfuscated output file have the permission to be executable. Once that's finished, execve will replace our crypter's process with the output file's.

Remember that we need to error check in this stage. If any errors should pop up we will know about it and can fix it.

Compiling and Running

635891835419204682.jpg

First, we compile our code. The file I have chosen to test will be the xorString program from the previous tutorial. I run it just to make sure it's the correct program. I then use our crypter to crypt the program and then again to decrypt and run. As we can see, it was successful. If I really wanted to be sure, I could use the diff utility to compare the decryptedfile and a.out.

Virus Scanning Malware

From our virus tutorial, we learned how to make a recursive virus which recursively swept through directories and infected files. Here is a virus scan on VirusTotal.

635891845731585754.jpg

A detection ratio of 2/54, not bad for a first malware!

After crypting it with our crypter here are the results.

635891847547328688.jpg

No detection! Excellent!

Let's try something a bit more realistic. Something like Dark Comet. For those who do not know, Dark Comet is an incredibly popular RAT and because of this, it has a huge detection ratio on VirusTotal.

635891888679134180.jpg

Let's try crypting it and then see its results.

635891890006595751.jpg

It has more than halved its detection ratio however, some of the popular antiviruses such as AVG, Avira, Bitdefender still detect it. This is a problem indeed. Since we are only using a single byte to encrypt our malware, it is not properly secured. A simple brute force deobfuscation with 255 single bytes could easily reveal the signature.

How will we defeat this? We can use more than a single key, i.e. multiple keys. For those who are keen and want a challenge, try to come up with a method which will incorporate a multi-key array which will be cycled through while obfuscating and writing to an output file.

Conclusion

Crypters are a simple method to get a piece of malware onto a system without detection. Using methods such as encryption or packing to obfuscate it, signatures are hidden from antivirus software so they seem innocent.

We've created our own single-byte XOR-obfuscating scantime crypter however it's still not quite as effective we require it. In the next tutorial, I will be going over the multi-key method which will only be a slight modification to our original code. See you then!

dtm.

Comments

No Comments Exist

Be the first, drop a comment!