[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Full-disclosure] CodeCrypter mutation engine



Hello list,

does any body know where I can find compiled version of CodeCrypter mutation 
engine writen by Tibbar? I have tried to compile with MS VC++6, but it doesn't 
compile. In case anybody would like to try, attached is source code...

Thank you very much.

-E.

____________________
http://www.email.si/
//#define UPX_CRYPT
/*

CodeCrypt 0.0 Written by Tibbar @ GSO.  You may use this code in your own 
projects
for non-commercial purposes provided you give credit to the author.

This is provided for educational purposes only.
No legal reponsibility is held or accepted by the author for misuse of this 
code.

*/

#include <string.h>
#include <stdio.h> 

#include "windows.h"
#include "limits.h"



void DetourFunctionStart(){}

// this function is copied into EP for exe
__declspec( naked )void DetourFoo()
{
        _asm
        {
                push EAX;
                pop EAX;
                push EBX;
                pop EBX;
                NOP;
                mov EBX, 0x12345678;
                jmp EBX; // replaced by main with actual address
                NOP;
        }
}

void DetourFunctionEnd(){}

void FunctionStart(){}

// this function will be copied into binary and will become the entry point
// it decrypts the code section and jmp's to the original entry point.
__declspec( naked )void DecryptAndStart()
{
        // retrieve original entry point, which will live at eip - 4
        // and codesize at eip - 2
        DWORD eipVal;
        DWORD codeSize;
        DWORD entryPt;
        
        _asm
        {
                // thanks to IDESPinner for this trick
                call jj; // think relative, this means go to next comand
                jj:
                pop EAX; // pop the EIP off the stack into EAX since it got 
pushed by the call


                mov EDX, EAX;
                add EDX, 0x33F;
                mov EBX, DWORD PTR [EDX]; // get seed
                add EDX, 0x4; // function pointer to LCG
                push EDX;
                push EBX;


                mov EBX, EAX; // save eip in ebx - keep it safe for a while

                mov ECX, [EAX - 0x9]; // no of sections
                push ECX; // push no of sections on stack

                mov EAX, 0x11;
                add EAX, ECX;
                add EAX, ECX;
                add EAX, ECX;
                add EAX, ECX;
                add EAX, ECX;
                add EAX, ECX;
                add EAX, ECX;
                add EAX, ECX; // each section info is 8 bytes

                mov EDX, EBX;
                sub EDX, EAX;
                mov ECX, [EDX]; // original entry point rva in ECX (EAX - 0x15 
== storageSpot )

                add EDX, 4;

                mov EAX, [EDX]; // imagebase in EAX

                add EDX, 4; // move to next data item (first section data)

                add ECX, EAX; // actual address of entrypoint in ECX

                push ECX; // keep it on stack for later
                push EAX; // image base on stack
                push EDX; // backward rva from eip initial to current data item


                /////////////CODE TO RESTORE DETOUR OVERWRITE///////
                // we stored bytes stolen for detour at offset stored at 
storagespot-1
                mov EBX, [EDX - 0xC]; // offset to stored copied EP code
                add EBX, EDX; // address of copied data
                
                sub EDX, EDX;
                
detourRestoreLoopStart:
                mov EAX, [EBX];
                CMP EDX, 0x20; // hardcoded detourLength
                jz detourRestoreLoopEnd;

                mov [ECX], EAX;
        
                add EDX, 4;
                add EBX, 4;
                add ECX, 4;
                jmp detourRestoreLoopStart;

detourRestoreLoopEnd:
                // restore registers
                mov EDX, [ESP];
                mov EAX, [ESP+0x4];
                mov ECX, [ESP+0x8];

                ///////////////////////////////////////////////////



                sub EDX, EDX;  // zero at EDX
                
outerLoop:
                mov ECX, [ESP+0xC]; // no  of sections
                CMP EDX, ECX;
                jz theEnd;
                pop ECX; // was EDX earlier for backward rva from eip to data
                push EDX; // save counter for next loop

                // at ECX we have section data item 1

                        // inner loop
                innerLoop:
                        // now retrieve VirtualAddress and Misc.VirtualSize for 
this section
                        mov EBX,[ECX]; // VirtualAddress
                        push EBX;
                        mov EDX, [ECX + 0x4]; // Misc.VirtualSize

                        mov EAX, [ESP + 0x8]; // get imagebase back
                        add EAX, EBX; // so EAX is pointer to section start

                        add ECX, 0x8; // fastforward to next section for next 
loop
                        push ECX; // save this for next loop (eip at entry)

                        // now we loop from [EAX] to [EAX+EDX]
                        mov EBX, EAX; // put code start address in EBX
                        add EDX, EAX; // last item of code to decrypt in EDX
                
                        StartLoop:
                        CMP EBX, EDX; // when these are the same, stop
                        JZ StopLooping
                                // get seed
                                push EDX;
                                push ECX;
                                sub EAX, EAX;
                                mov EAX, [ESP + 0x20]; // seed in EAX
                                mov ECX, [ESP + 0x24]; // LCG foo in ECX

                                mov DL, BYTE PTR [EBX] // get value at address 
EBX
                                sub DL, AL;     // decrypt it
                                
                                mov BYTE PTR [EBX], DL  // put decrypted value 
back in right place
                                inc EBX;
                                call ECX; // get next LCG value
                                mov [ESP + 0x20], EAX; // save LCG value
                                pop ECX;
                                pop EDX;
                        jmp StartLoop;
                        StopLooping:

                // now we must move to next section
                pop EBX;  // get eip back
                pop EAX;  // get section pointer back
                pop EDX;  // get i
                inc EDX; // i++
                push ECX;

                jmp outerLoop;

theEnd:
                pop ECX;
                pop ECX;
                pop ECX;
                jmp ECX;
        }

}

void FunctionEnd(){}


/*
        Assumes:
        EAX = x_r
        ESP = ret address (put there by call)
        returns x_r+1 in EAX

*/
void GenerateRandomNumberStart(){}

__declspec( naked )void GenerateRandomNumber()
{
        // x_(r+1) = a*x_r + c modulo m
        _asm
        {
                push EBX;
                push ECX;
                push EDX;
                mov EBX, 1277;
                mul EBX; // EAX*1277 answer in EDX
                add EAX, 0; // +c

                sub EDX,EDX;
                mov EBX, 131072;
                div EBX; // m
                mov EAX, EDX;
                
                // we only want a byte of it

        //      mov BL, AL;
        //      sub EAX, EAX;
        //      mov AL, BL;

                pop EDX;
                pop ECX;
                pop EBX;
                ret;
        }

        /*  x := y mod z; {unsigned remainder}
                mov( y, eax );
                mov( 0, edx );       // Zero extend EAX into EDX.
                mod( z, edx:eax );
                mov( edx, x );       // Note that remainder is in EDX.  */
}

void GenerateRandomNumberEnd(){}


ULONG __fastcall GetSizeOfImage(
    IN PVOID pImageBase
    )
{
    // get DOS header
    IMAGE_DOS_HEADER * pDosHeader = (IMAGE_DOS_HEADER *)pImageBase;

    // find an offset to the main PE header ...
    IMAGE_FILE_HEADER * pFileHeader = 
        (IMAGE_FILE_HEADER *)(((LPBYTE)pImageBase) + 
                      pDosHeader->e_lfanew + 
                      sizeof(IMAGE_NT_SIGNATURE));

    // ... and optional PE header
    IMAGE_OPTIONAL_HEADER * pOptHeader = 
        (IMAGE_OPTIONAL_HEADER *)(((LPBYTE)pFileHeader) + 
                      IMAGE_SIZEOF_FILE_HEADER);

    // calculate the size
    ULONG nSizeOfImage = pOptHeader->SizeOfHeaders;

    IMAGE_SECTION_HEADER * pSecHeader = 
        (IMAGE_SECTION_HEADER *)(((LPBYTE)pOptHeader) + 
                     pFileHeader->SizeOfOptionalHeader);

    // sum size of all image sections; this will result in the image
    // size
    for (int i = 0; i < pFileHeader->NumberOfSections; i++, pSecHeader++)
        nSizeOfImage += pSecHeader->SizeOfRawData;

    // return size of the executable
    return nSizeOfImage;
}

IMAGE_SECTION_HEADER* GetSectionHeader(IN PVOID pImageBase)
{
    // get DOS header
    IMAGE_DOS_HEADER * pDosHeader = (IMAGE_DOS_HEADER *)pImageBase;

    // find an offset to the main PE header ...
    IMAGE_FILE_HEADER * pFileHeader = 
        (IMAGE_FILE_HEADER *)(((LPBYTE)pImageBase) + 
                      pDosHeader->e_lfanew + 
                      sizeof(IMAGE_NT_SIGNATURE));

    // ... and optional PE header
    IMAGE_OPTIONAL_HEADER * pOptHeader = 
        (IMAGE_OPTIONAL_HEADER *)(((LPBYTE)pFileHeader) + 
                      IMAGE_SIZEOF_FILE_HEADER);

    // calculate the size
    ULONG nSizeOfImage = pOptHeader->SizeOfHeaders;

    IMAGE_SECTION_HEADER * pSecHeader = 
        (IMAGE_SECTION_HEADER *)(((LPBYTE)pOptHeader) + 
                     pFileHeader->SizeOfOptionalHeader);
        return pSecHeader;
}


PIMAGE_SECTION_HEADER FindLastVirtualSection(DWORD* pImageBase)
{
    // get DOS header
    IMAGE_DOS_HEADER * pDosHeader = (IMAGE_DOS_HEADER *)pImageBase;
        
        // get NT header
    IMAGE_NT_HEADERS * pNtHeaders = 
(IMAGE_NT_HEADERS*)((DWORD)pImageBase+pDosHeader->e_lfanew);

        // find an offset to the main PE header ...
    IMAGE_FILE_HEADER * pFileHeader = 
        (IMAGE_FILE_HEADER *)(((LPBYTE)pImageBase) + 
                      pDosHeader->e_lfanew + 
                      sizeof(IMAGE_NT_SIGNATURE));

    // ... and optional PE header
    IMAGE_OPTIONAL_HEADER * pOptHeader = 
        (IMAGE_OPTIONAL_HEADER *)(((LPBYTE)pFileHeader) + 
                      IMAGE_SIZEOF_FILE_HEADER);

    IMAGE_SECTION_HEADER * sectionHeader = 
        (IMAGE_SECTION_HEADER *)(((LPBYTE)pOptHeader) + 
                     pFileHeader->SizeOfOptionalHeader);

        DWORD newSectionOffset;
        DWORD SectionNum = pNtHeaders->FileHeader.NumberOfSections;

        DWORD currentMaxVA = 0;
        int pos = 0;

        IMAGE_SECTION_HEADER* tempHeader = sectionHeader;
        DWORD headerSize = sizeof(IMAGE_SECTION_HEADER);
        for(int i = 0; i < SectionNum; i++)
        {
                if((DWORD)(tempHeader->VirtualAddress) > currentMaxVA) 
                {
                        currentMaxVA = (DWORD)(tempHeader->VirtualAddress);
                        pos = i;
                }
                tempHeader = (IMAGE_SECTION_HEADER*)((DWORD)tempHeader + 
headerSize);
        }

        IMAGE_SECTION_HEADER* lastSectionHeader = 
(IMAGE_SECTION_HEADER*)((DWORD)sectionHeader + 
pos*sizeof(IMAGE_SECTION_HEADER));
        return lastSectionHeader;
}

PIMAGE_SECTION_HEADER FindLastPhysicalSection(DWORD* pImageBase)
{
    // get DOS header
    IMAGE_DOS_HEADER * pDosHeader = (IMAGE_DOS_HEADER *)pImageBase;
        
        // get NT header
    IMAGE_NT_HEADERS * pNtHeaders = 
(IMAGE_NT_HEADERS*)((DWORD)pImageBase+pDosHeader->e_lfanew);

        // find an offset to the main PE header ...
    IMAGE_FILE_HEADER * pFileHeader = 
        (IMAGE_FILE_HEADER *)(((LPBYTE)pImageBase) + 
                      pDosHeader->e_lfanew + 
                      sizeof(IMAGE_NT_SIGNATURE));

    // ... and optional PE header
    IMAGE_OPTIONAL_HEADER * pOptHeader = 
        (IMAGE_OPTIONAL_HEADER *)(((LPBYTE)pFileHeader) + 
                      IMAGE_SIZEOF_FILE_HEADER);

    IMAGE_SECTION_HEADER * sectionHeader = 
        (IMAGE_SECTION_HEADER *)(((LPBYTE)pOptHeader) + 
                     pFileHeader->SizeOfOptionalHeader);

        DWORD newSectionOffset;
        DWORD SectionNum = pNtHeaders->FileHeader.NumberOfSections;

        DWORD currentMaxPA = 0;
        int pos = 0;

        IMAGE_SECTION_HEADER* tempHeader = sectionHeader;
        DWORD headerSize = sizeof(IMAGE_SECTION_HEADER);
        for(int i = 0; i < SectionNum; i++)
        {
                if((DWORD)(tempHeader->PointerToRawData) > currentMaxPA) 
                {
                        currentMaxPA = (DWORD)(tempHeader->PointerToRawData);
                        pos = i;
                }
                tempHeader = (IMAGE_SECTION_HEADER*)((DWORD)tempHeader + 
headerSize);
        }

        IMAGE_SECTION_HEADER* lastSectionHeader = 
(IMAGE_SECTION_HEADER*)((DWORD)sectionHeader + 
pos*sizeof(IMAGE_SECTION_HEADER));
        return lastSectionHeader;
}

PIMAGE_SECTION_HEADER FindFirstSection(DWORD* pImageBase)
{
    // get DOS header
    IMAGE_DOS_HEADER * pDosHeader = (IMAGE_DOS_HEADER *)pImageBase;
        
        // get NT header
    IMAGE_NT_HEADERS * pNtHeaders = 
(IMAGE_NT_HEADERS*)((DWORD)pImageBase+pDosHeader->e_lfanew);

        // find an offset to the main PE header ...
    IMAGE_FILE_HEADER * pFileHeader = 
        (IMAGE_FILE_HEADER *)(((LPBYTE)pImageBase) + 
                      pDosHeader->e_lfanew + 
                      sizeof(IMAGE_NT_SIGNATURE));

    // ... and optional PE header
    IMAGE_OPTIONAL_HEADER * pOptHeader = 
        (IMAGE_OPTIONAL_HEADER *)(((LPBYTE)pFileHeader) + 
                      IMAGE_SIZEOF_FILE_HEADER);

    IMAGE_SECTION_HEADER * sectionHeader = 
        (IMAGE_SECTION_HEADER *)(((LPBYTE)pOptHeader) + 
                     pFileHeader->SizeOfOptionalHeader);

        return sectionHeader;
}


PIMAGE_SECTION_HEADER FindNextSection(DWORD* pImageBase, PIMAGE_SECTION_HEADER 
currentSection)
{
    // get DOS header
    IMAGE_DOS_HEADER * pDosHeader = (IMAGE_DOS_HEADER *)pImageBase;
        
        // get NT header
    IMAGE_NT_HEADERS * pNtHeaders = 
(IMAGE_NT_HEADERS*)((DWORD)pImageBase+pDosHeader->e_lfanew);

        // find an offset to the main PE header ...
    IMAGE_FILE_HEADER * pFileHeader = 
        (IMAGE_FILE_HEADER *)(((LPBYTE)pImageBase) + 
                      pDosHeader->e_lfanew + 
                      sizeof(IMAGE_NT_SIGNATURE));

    // ... and optional PE header
    IMAGE_OPTIONAL_HEADER * pOptHeader = 
        (IMAGE_OPTIONAL_HEADER *)(((LPBYTE)pFileHeader) + 
                      IMAGE_SIZEOF_FILE_HEADER);

    IMAGE_SECTION_HEADER * sectionHeader = 
        (IMAGE_SECTION_HEADER *)(((LPBYTE)pOptHeader) + 
                     pFileHeader->SizeOfOptionalHeader);

        DWORD newSectionOffset;
        DWORD SectionNum = pNtHeaders->FileHeader.NumberOfSections;

        if(SectionNum <= 1) return NULL;

        IMAGE_SECTION_HEADER* prevHeader = sectionHeader;
        IMAGE_SECTION_HEADER* currHeader = 
(IMAGE_SECTION_HEADER*)((DWORD)sectionHeader + sizeof(IMAGE_SECTION_HEADER));
        DWORD headerSize = sizeof(IMAGE_SECTION_HEADER);
        for(int i = 0; i < SectionNum - 1; i++)
        {
                if(prevHeader == currentSection) return currHeader;
                prevHeader = currHeader;
                currHeader = (IMAGE_SECTION_HEADER*)((DWORD)currHeader + 
sizeof(IMAGE_SECTION_HEADER));
        }

        return NULL;
}

PIMAGE_SECTION_HEADER FindSection(DWORD* pImageBase, DWORD sectionbase)
{
    // get DOS header
    IMAGE_DOS_HEADER * pDosHeader = (IMAGE_DOS_HEADER *)pImageBase;
        
        // get NT header
    IMAGE_NT_HEADERS * pNtHeaders = 
(IMAGE_NT_HEADERS*)((DWORD)pImageBase+pDosHeader->e_lfanew);

        // find an offset to the main PE header ...
    IMAGE_FILE_HEADER * pFileHeader = 
        (IMAGE_FILE_HEADER *)(((LPBYTE)pImageBase) + 
                      pDosHeader->e_lfanew + 
                      sizeof(IMAGE_NT_SIGNATURE));

    // ... and optional PE header
    IMAGE_OPTIONAL_HEADER * pOptHeader = 
        (IMAGE_OPTIONAL_HEADER *)(((LPBYTE)pFileHeader) + 
                      IMAGE_SIZEOF_FILE_HEADER);

    IMAGE_SECTION_HEADER * sectionHeader = 
        (IMAGE_SECTION_HEADER *)(((LPBYTE)pOptHeader) + 
                     pFileHeader->SizeOfOptionalHeader);

        DWORD newSectionOffset;
        DWORD SectionNum = pNtHeaders->FileHeader.NumberOfSections;

        DWORD currentMaxVA = 0;
        int pos = 0;

        IMAGE_SECTION_HEADER* tempHeader = sectionHeader;
        DWORD headerSize = sizeof(IMAGE_SECTION_HEADER);
        for(int i = 0; i < SectionNum; i++)
        {
                if(tempHeader->VirtualAddress == sectionbase) 
                {
                        return tempHeader;
                }
                tempHeader = (IMAGE_SECTION_HEADER*)((DWORD)tempHeader + 
headerSize);
        }

        return NULL;
}

void MakeAllSectionsWritable(DWORD* pImageBase)
{
    // get DOS header
    IMAGE_DOS_HEADER * pDosHeader = (IMAGE_DOS_HEADER *)pImageBase;
        
        // get NT header
    IMAGE_NT_HEADERS * pNtHeaders = 
(IMAGE_NT_HEADERS*)((DWORD)pImageBase+pDosHeader->e_lfanew);

        // find an offset to the main PE header ...
    IMAGE_FILE_HEADER * pFileHeader = 
        (IMAGE_FILE_HEADER *)(((LPBYTE)pImageBase) + 
                      pDosHeader->e_lfanew + 
                      sizeof(IMAGE_NT_SIGNATURE));

    // ... and optional PE header
    IMAGE_OPTIONAL_HEADER * pOptHeader = 
        (IMAGE_OPTIONAL_HEADER *)(((LPBYTE)pFileHeader) + 
                      IMAGE_SIZEOF_FILE_HEADER);

    IMAGE_SECTION_HEADER * sectionHeader = 
        (IMAGE_SECTION_HEADER *)(((LPBYTE)pOptHeader) + 
                     pFileHeader->SizeOfOptionalHeader);

        DWORD newSectionOffset;
        DWORD SectionNum = pNtHeaders->FileHeader.NumberOfSections;

        DWORD currentMaxVA = 0;
        int pos = 0;

        IMAGE_SECTION_HEADER* tempHeader = sectionHeader;
        DWORD headerSize = sizeof(IMAGE_SECTION_HEADER);
        for(int i = 0; i < SectionNum; i++)
        {
                tempHeader->Characteristics |= IMAGE_SCN_MEM_WRITE;
                tempHeader = (IMAGE_SECTION_HEADER*)((DWORD)tempHeader + 
headerSize);
        }

        return ;
}

PIMAGE_SECTION_HEADER AddSection(DWORD* pImageBase, DWORD codeVirtualStart, 
DWORD codeSize)
{
    // get DOS header
    IMAGE_DOS_HEADER * pDosHeader = (IMAGE_DOS_HEADER *)pImageBase;
        
        // get NT header
    IMAGE_NT_HEADERS * pNtHeaders = 
(IMAGE_NT_HEADERS*)((DWORD)pImageBase+pDosHeader->e_lfanew);

        // find an offset to the main PE header ...
    IMAGE_FILE_HEADER * pFileHeader = 
        (IMAGE_FILE_HEADER *)(((LPBYTE)pImageBase) + 
                      pDosHeader->e_lfanew + 
                      sizeof(IMAGE_NT_SIGNATURE));

    // ... and optional PE header
    IMAGE_OPTIONAL_HEADER * pOptHeader = 
        (IMAGE_OPTIONAL_HEADER *)(((LPBYTE)pFileHeader) + 
                      IMAGE_SIZEOF_FILE_HEADER);

    IMAGE_SECTION_HEADER * sectionHeader = 
        (IMAGE_SECTION_HEADER *)(((LPBYTE)pOptHeader) + 
                     pFileHeader->SizeOfOptionalHeader);

        DWORD newSectionOffset;
        DWORD SectionNum = pNtHeaders->FileHeader.NumberOfSections;

        newSectionOffset = (DWORD)sectionHeader
                
+pNtHeaders->FileHeader.NumberOfSections*sizeof(IMAGE_SECTION_HEADER) - 
(DWORD)pImageBase;

        // check whether there's room for a new section
        
if(pNtHeaders->OptionalHeader.SizeOfHeaders<(newSectionOffset+sizeof(IMAGE_SECTION_HEADER)))
        {
                return NULL;
        }

        // increase SizeOf

        // create a new section

        IMAGE_SECTION_HEADER* newsection = 
(IMAGE_SECTION_HEADER*)((DWORD)pImageBase + newSectionOffset);

        // start to build the new section
        DWORD n = sizeof(IMAGE_SECTION_HEADER);
        CopyMemory(newsection,
                           (IMAGE_SECTION_HEADER*)((DWORD)newsection - n),
                           sizeof(IMAGE_SECTION_HEADER));

        // VirtualAddress...

        // update the PE header
        pNtHeaders->FileHeader.NumberOfSections++;
        // newsection -> will be returned
        return (PIMAGE_SECTION_HEADER)newsection;
}


/*
        EncryptSection uses LCG to modify each byte.  Seed is based on ticks, 
returned by function
*/

DWORD EncryptSection(IMAGE_SECTION_HEADER* codeSection, DWORD* imageBase, DWORD 
seed)
{
        DWORD rawCodePosition = codeSection->PointerToRawData;

        DWORD virtualCodeSize = codeSection->SizeOfRawData;//->Misc.VirtualSize;

        DWORD startpos = (DWORD)imageBase + (DWORD)rawCodePosition;
        
        if(stricmp((char*)codeSection->Name, ".rsrc") == 0) startpos = startpos 
+ 0x11;

        DWORD endpos = startpos + virtualCodeSize;

        // unprotect code
        BOOL diditwork = VirtualProtect((void*)startpos, virtualCodeSize, 
PAGE_READWRITE, NULL);
        DWORD x = GetLastError();

        _asm
        {
                sub EAX, EAX;
                mov EAX, seed;

                mov EBX, startpos;
                mov EDX, endpos;
StartLoop:
                CMP EBX, EDX; // when these are the same, stop
                JZ StopLooping
                        mov CL, BYTE PTR [EBX] // get value at address EBX
                        add CL, AL;     // crypt it
                        mov BYTE PTR [EBX], CL  // put decrypted value back in 
right place
                        inc EBX;
                        call GenerateRandomNumber; // get next LCG value
                jmp StartLoop;
StopLooping:
                mov seed, EAX;
        }
        return seed;
}

DWORD GetSeed()
{
        DWORD seed = 0;
        seed = GetTickCount();
/*      _asm
        {
                // get seed
                mov EBX, 0x7FFE0000;
                sub EAX, EAX;
                mov EAX, DWORD PTR [EBX];
                mov seed, EAX;
        }*/
        return seed;
}

int main( int argc, char* argv[] ) 
{
        if(argc != 3)
        {
                printf("*** Code Crypter 0.3 by Tibbar@xxxxxxxxxxxxxxxxxxxxxx 
***\n");
                printf("***                                                   
***\n");
                printf("*** Usage: codecrypt filename.exe N                   
***\n");
                printf("*** N = 0 --> encrypt all but .rsrc                   
***\n");
                printf("*** N = 1 --> encrypt .rsrc as well                   
***\n");
                printf("*** It also encrypts resources under assumption       
***\n");
                printf("*** that .idata is NOT merged with .rsrc              
***\n");
                printf("*** Disclaimer: This software is for educational      
***\n");
                printf("*** purposes only.  No responsibility is held or      
***\n");
                printf("*** accepted for misuse.                              
***\n");
                return 0;
        }

        BOOL cryptRSRC = FALSE;
        if(*argv[2] == '1') cryptRSRC = TRUE;

        HANDLE hFile = CreateFile(
                                                        argv[1],
                                                        GENERIC_WRITE | 
GENERIC_READ,
                                                        FILE_SHARE_READ | 
FILE_SHARE_WRITE,
                                                        NULL,
                                                        OPEN_EXISTING,
                                                        FILE_ATTRIBUTE_NORMAL,
                                                        NULL);
        if(hFile == NULL)
        {
                printf("Invalid filename...exiting!");
                return 0;
        }
        // get size of file
        LARGE_INTEGER bigInt;
        BOOL diditWork = GetFileSizeEx(hFile, &bigInt);
        // assume it's DWORD or less
        DWORD fileSize = bigInt.LowPart;
        if(fileSize + 0x2000 >= ULONG_MAX) return 0;


        HANDLE hFileMap = CreateFileMapping(
                                                        hFile,
                                                        NULL,
                                                        PAGE_READWRITE,// | 
SEC_IMAGE,
                                                        bigInt.HighPart,
                                                        bigInt.LowPart + 0x2000 
,
                                                        "myfile");
        if(hFileMap == NULL)
        {
                printf("Unable to create file mapping! Exiting...");
                return 0;
        }

// map file into memory
        LPVOID hMap = MapViewOfFile(
                                                hFileMap,
                                                FILE_MAP_WRITE,
                                                0,
                                                0,
                                                0);
        if(hMap == NULL)
        {
                printf("Unable to map file into memory! Exiting...");
                return 0;
        }

        HMODULE hModule = (HMODULE)hMap;
        PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)hModule;
  
        IMAGE_NT_HEADERS * pNtHeaders = (IMAGE_NT_HEADERS*)((DWORD)hModule + 
pDosHeader->e_lfanew);

        IMAGE_OPTIONAL_HEADER* optionHeader =(IMAGE_OPTIONAL_HEADER *) 
((BYTE*)hModule+pDosHeader->e_lfanew+24);        

        VOID* pBaseCode = (VOID*)optionHeader->BaseOfCode;
        DWORD codeSize = optionHeader->SizeOfCode;

        IMAGE_SECTION_HEADER* sectionHeader = GetSectionHeader(hModule);


        // crypt sections

        IMAGE_SECTION_HEADER* sectionHeaderArray[20];
        for(int i = 0 ;i < 20; i++) sectionHeaderArray[i] = NULL;

        BOOL encryptedSectionArray[20];
        for(int i = 0 ;i < 20; i++) encryptedSectionArray[i] = FALSE;

        sectionHeaderArray[0] = FindFirstSection((DWORD*)hModule);

        DWORD seed = 0;
        while(true)
        {
                seed = GetSeed();
                if(LOBYTE(seed) != 0) break;
        }
        DWORD currentLCGValue = 0;
        currentLCGValue = EncryptSection(sectionHeaderArray[0], 
(DWORD*)hModule, seed);
        encryptedSectionArray[0] = TRUE;

        int j = 1;
        while(true)
        {
                sectionHeaderArray[j] = FindNextSection((DWORD*)hModule, 
sectionHeaderArray[j-1]);
                if(sectionHeaderArray[j] == NULL) break;
#ifdef UPX_CRYPT
                if(stricmp((char*)sectionHeaderArray[j]->Name, ".rsrc") == 0)// 
|| stricmp((char*)sectionHeaderArray[j]->Name, "UPX1") == 0) 
                {       
                        j++;
                        continue;
                }       
#endif
                if(stricmp((char*)sectionHeaderArray[j]->Name, ".idata") == 0 
|| stricmp((char*)sectionHeaderArray[j]->Name, ".reloc") == 0 || 
stricmp((char*)sectionHeaderArray[j]->Name, ".rdata") == 0 || 
stricmp((char*)sectionHeaderArray[j]->Name, ".tls") == 0 || 
stricmp((char*)sectionHeaderArray[j]->Name, ".bss") == 0 || 
sectionHeaderArray[j]->SizeOfRawData == 0) 
                {       
                        j++;
                        continue;
                }
                if(cryptRSRC == FALSE && 
stricmp((char*)sectionHeaderArray[j]->Name, ".rsrc") == 0 )
                {
                        j++;
                        continue;
                }
                encryptedSectionArray[j] = TRUE;
                currentLCGValue = EncryptSection(sectionHeaderArray[j], 
(DWORD*)hModule, currentLCGValue);
                j++;
                //break;//////////////////////
        }

        int numCrypedSections = 0;
        for(int i = 0 ;i < 20; i++) numCrypedSections += 
encryptedSectionArray[i];

        
        // store rva from new entry point to original entry point at position 
pBaseCode + fileSize + 2

        DWORD numOfSections = pNtHeaders->FileHeader.NumberOfSections;

        IMAGE_SECTION_HEADER* lastSection = 
FindLastPhysicalSection((DWORD*)hModule);

#ifdef UPX_CRYPT
        DWORD* storageSpot = (DWORD*)((DWORD)hModule + 
(DWORD)lastSection->SizeOfRawData + 
(DWORD)lastSection->PointerToRawData);//(DWORD)lastSection->Misc.VirtualSize + 
(DWORD)lastSection->PointerToRawData);
#else
        DWORD* storageSpot = (DWORD*)((DWORD)hModule + 
(DWORD)lastSection->SizeOfRawData + 
(DWORD)lastSection->PointerToRawData);//(DWORD)lastSection->Misc.VirtualSize + 
(DWORD)lastSection->PointerToRawData);
#endif
        *(storageSpot) = (DWORD)optionHeader->AddressOfEntryPoint; 

        *(storageSpot + 1) = (DWORD)optionHeader->ImageBase;

        int pos = 0;
        for(i = 0; i < numOfSections; i++)
        {
                if(encryptedSectionArray[i] == TRUE)
                {
                        *(storageSpot + 2 + 2*pos) = 
(DWORD)sectionHeaderArray[i]->VirtualAddress;
                        if(stricmp((char*)sectionHeaderArray[i]->Name, ".rsrc") 
== 0 ) *(storageSpot + 2 + 2*pos) += 0x11;
                        *(storageSpot + 2 + 2*pos + 1) = 
(DWORD)sectionHeaderArray[i]->SizeOfRawData;//->Misc.VirtualSize;
                        if(stricmp((char*)sectionHeaderArray[i]->Name, ".rsrc") 
== 0 ) *(storageSpot + 2 + 2*pos + 1) -= 0x11;
                        pos ++;
                }
        }

        *(storageSpot + 2 + 2*numCrypedSections) = 
numCrypedSections;//pNtHeaders->FileHeader.NumberOfSections;

        // now we need to add our decryption routine to storageSpot + 4 (say)
        int dSize = (PBYTE)FunctionStart -  (PBYTE)FunctionEnd;
        DWORD start = (DWORD) FunctionStart;
        DWORD end = (DWORD) FunctionEnd;
        DWORD length = (end - start);
        CopyMemory(storageSpot + 2 + 2*numCrypedSections + 1,
                                DecryptAndStart, length);

        // next we must record our seed!
        *(storageSpot + 2 + 2*numCrypedSections + 1 + length + 1) = seed;

        // LCG function also:
        DWORD start1 = (DWORD) GenerateRandomNumberStart;
        DWORD end1 = (DWORD) GenerateRandomNumberEnd;
        DWORD length1 = (end - start);
        CopyMemory(storageSpot + 2 + 2*numCrypedSections + 1 + length + 2,
                                GenerateRandomNumber, length1);

        


        // set new code as executable
//      IMAGE_SECTION_HEADER* newsection = AddSection((DWORD*)hModule, 
(DWORD)storageSpot + 4 - (DWORD)hModule, length);

        // to do this we will simply find the last section (i.e. one with 
highest RVA
        // and extend this by size needed
        // and set it to executable

        lastSection->Misc.VirtualSize += 0x2000;
        lastSection->SizeOfRawData += 0x2000;
        lastSection->Characteristics =  IMAGE_SCN_MEM_WRITE|
                                                                        
IMAGE_SCN_MEM_READ|
                                                                        
IMAGE_SCN_MEM_EXECUTE|
                                                                        
IMAGE_SCN_CNT_UNINITIALIZED_DATA |
                                                                        
IMAGE_SCN_CNT_INITIALIZED_DATA|
                                                                        
IMAGE_SCN_CNT_CODE;//0xE00000E0;

        // set new entry point
        optionHeader->SizeOfImage += 0x2000;
        optionHeader->SizeOfCode += 0x2000;
        optionHeader->SizeOfInitializedData += 0x2000;


        // finally we add a detour at EP to our stub
        

        DWORD stubEPrva = (DWORD)lastSection->VirtualAddress + 
(DWORD)lastSection->SizeOfRawData + 12 + 2*4*numCrypedSections - 0x2000; 

        DWORD detourStart = (DWORD) DetourFunctionStart;
        DWORD detourEnd = (DWORD) DetourFunctionEnd;
        DWORD detourLength = (detourEnd - detourStart);
  
        // copy first few bytes to (storageSpot + 2 + 2*numCrypedSections + 1 + 
length) + 4
  
        DWORD* target = (storageSpot + 2 + 2*numCrypedSections + 1 + length + 2 
+ length1 + 1) + 4;

        // store offset to it at storageSpot-1
        *(storageSpot - 1) = (DWORD)target - (DWORD)storageSpot - 8;

#ifdef UPX_CRYPT
        DWORD* pointerToEPonDisk = (DWORD*)((DWORD)hModule + 
(DWORD)optionHeader->AddressOfEntryPoint - 
                ((DWORD)sectionHeaderArray[1]->VirtualAddress - 
(DWORD)sectionHeaderArray[1]->PointerToRawData ));
#else
        DWORD* pointerToEPonDisk = (DWORD*)((DWORD)hModule + 
(DWORD)optionHeader->AddressOfEntryPoint - 
                ((DWORD)sectionHeaderArray[0]->VirtualAddress - 
(DWORD)sectionHeaderArray[0]->PointerToRawData ));
#endif
        CopyMemory(target, pointerToEPonDisk, detourLength);

        // now copy detour code to original EP

        CopyMemory(pointerToEPonDisk,   DetourFoo, detourLength);

        // set correct jmp address

    *((WORD*)pointerToEPonDisk + 4) = HIWORD((DWORD)optionHeader->ImageBase + 
(DWORD)stubEPrva);
        *((WORD*)pointerToEPonDisk + 3) = LOWORD((DWORD)optionHeader->ImageBase 
+ (DWORD)stubEPrva);


        // finally we need to set the main code section as writable for our 
stub to decrypt it!
        
        MakeAllSectionsWritable((DWORD*)hModule);       
        printf("Crypted file successfully!");
}
_______________________________________________
Full-Disclosure - We believe in it.
Charter: http://lists.grok.org.uk/full-disclosure-charter.html
Hosted and sponsored by Secunia - http://secunia.com/