How To:

Security-Oriented C Tutorial 0xFB - A Simple Crypter

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.

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.

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.

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

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.

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

After crypting it with our crypter here are the results.

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.

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

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.

14 Comments

Great tutorial, the first on making crypter as far as I know of :)
Cheers,
Washu

Thanks m8. And yeah, when I first found out about crypting I had no idea, I searched around and there wasn't really much on the details. Since I did find out how they worked, I could then start making my own. I hope people can use this knowledge to understand the requirements so that they can make their own regardless of the language.

Packers are compressors.

This still obfuscates code and makes malware undetectable, however, Is the apparent dichotomy based upon the fact that packers are created for the purpose of efficiency versus crypters which are designed strictly for malware?

Yes it does obfuscate the code but it still does not meet the requirement to be categorized as a packer. Packers and crypters may be used for whatever the user wishes whether the intent is malicious or not, they are merely tools to assist them.

Also, how do you recommend designing portable executables designed for windows on a linux machine? Arent there potential compatibility issues and the likes?

For building Windows executables on a Linux machine, you can use MinGW to cross-compile your code. To execute your cross-compiled Windows code on a Linux machine, Wine may be a solution to that problem however, don't count on it being perfect. If you wish to design Windows executables in more depth, i.e. using WinAPI, I would recommend you code in a Windows environment.

For portability, it's probably best to use common headers and functions such as the standard c library or other portable dynamic libraries, else if there are specific functions you require on either side, you can have the respective compiler determine which headers to define, which functions to use, for example, if you wish to use the windows.h header file on a Windows machine, you may have the compiler check with the #ifdef _WIN32 preprocessor directive.

hello dontrustme,
thanks for every things you doing ,

i got error when trying to use crypt.c

Image via imgsafe.org

and after the code run , my folder has only 4 files ,

Image via imgsafe.org

and here is my code that i use, (i done exactly that you says)

http://hostcode.sourceforge.net/view/4905

plz, if you can take look it and tell me what is the wrong thing that i have done, it is very appreciate , thanks you very much ,

Did you fill in the xorFile function? That was the task you were supposed to do from the previous tutorial, I believe. You need to read in the file from argv[2] and write out the XORed bytes to argv[3].

OMG, sorry for my madness,
i include function and now it is working clearly
thanks for quick respond ... good luck friend

I am having trouble with the xorFile funtion. Can I have some help.

Same here, this is the section of the code, could you help me out? Thank you

int xorFile (char infile, char outfile){
int i;
for (i = 0; infilei != '\0'; i++){
infilei ^= XOR_KEY;
}

int main(int argc, char *argv) {
if (argc <= 3){
fprintf (stderr,
"Usage: %s CRYPT | DECRYPT IN FILE OUT FILE\n", argv0);
exit (1);
}
int job;
if (strcmp (argv1, "crypt") == 0){
job = JOB_CRYPT;
} else if (strcmp (argv1, "decrypt") == 0){
job = JOB_DECRYPT;
} else {
fprintf (stderr, "Please select a suitable job");
exit (1);
}

if (job == JOB_CRYPT){
FILE *fp;
FILE *tp;
char buf1024;
fp = fopen (argv2,"r");
tp = fopen (argv3, "w");
fgets (buf, sizeof(buf), fp);
xorFile (argv2, argv3);
fprintf (tp, "%s", fp);
fclose (fp);
fclose (tp);
}

Share Your Thoughts

  • Hot
  • Latest