Beispiel #1
0
/*
 * brute force search sysent
 * this method works in all versions
 * returns a pointer to the sysent structure
 * Note: 32/64 bits compatible
 */
static void *
bruteforce_sysent(mach_vm_address_t *out_kernel_base)
{
    // retrieves the address of the IDT
    mach_vm_address_t idt_address = 0;
    get_addr_idt(&idt_address);
    LOG_DEBUG("IDT Address is 0x%llx", idt_address);
    // calculate the address of the int80 handler
    mach_vm_address_t int80_address = calculate_int80address(idt_address);
    // search backwards for the kernel base address (mach-o header)
    mach_vm_address_t kernel_base = find_kernel_base(int80_address);
    *out_kernel_base = kernel_base;
    uint64_t data_address = 0;
    uint64_t data_size = 0;
    // search for the __DATA segment
    process_header(kernel_base, &data_address, &data_size);
    uint64_t data_limit = data_address + data_size;
    // bruteforce search for sysent in __DATA segment
    while (data_address <= data_limit)
    {
        if (version_major == YOSEMITE || version_major == EL_CAPITAN)
        {
            struct sysent_yosemite *table = (struct sysent_yosemite*)data_address;
            if((void*)table != NULL &&
               table[SYS_exit].sy_narg      == 1 &&
               table[SYS_fork].sy_narg      == 0 &&
               table[SYS_read].sy_narg      == 3 &&
               table[SYS_wait4].sy_narg     == 4 &&
               table[SYS_ptrace].sy_narg    == 4 &&
               table[SYS_getxattr].sy_narg  == 6 &&
               table[SYS_listxattr].sy_narg == 4 &&
               table[SYS_recvmsg].sy_narg   == 3 )
            {
                LOG_DEBUG("exit() address is %p", (void*)table[SYS_exit].sy_call);
                LOG_DEBUG("no. of args for exit()  %d", table[SYS_exit].sy_narg);
                LOG_DEBUG("Success!! Done here.");
                return (void*)data_address;
            }
        }
        /* mavericks or higher */
        else if (version_major == MAVERICKS)
        {
            struct sysent_mavericks *table = (struct sysent_mavericks*)data_address;
            if((void*)table != NULL &&
               table[SYS_exit].sy_narg      == 1 &&
               table[SYS_fork].sy_narg      == 0 &&
               table[SYS_read].sy_narg      == 3 &&
               table[SYS_wait4].sy_narg     == 4 &&
               table[SYS_ptrace].sy_narg    == 4 &&
               table[SYS_getxattr].sy_narg  == 6 &&
               table[SYS_listxattr].sy_narg == 4 &&
               table[SYS_recvmsg].sy_narg   == 3 )
            {
                LOG_DEBUG("exit() address is %p", (void*)table[SYS_exit].sy_call);
                return (void*)data_address;
            }
        }
        /* all previous versions */
        else
        {
            struct sysent *table = (struct sysent*)data_address;
            if((void*)table != NULL &&
               table[SYS_exit].sy_narg      == 1 &&
               table[SYS_fork].sy_narg      == 0 &&
               table[SYS_read].sy_narg      == 3 &&
               table[SYS_wait4].sy_narg     == 4 &&
               table[SYS_ptrace].sy_narg    == 4 &&
               table[SYS_getxattr].sy_narg  == 6 &&
               table[SYS_listxattr].sy_narg == 4 &&
               table[SYS_recvmsg].sy_narg   == 3 )
            {
                LOG_DEBUG("exit() address is %p", (void*)table[SYS_exit].sy_call);
                return (void*)data_address;
            }
        }
        data_address++;
    }
    return NULL;
}
Beispiel #2
0
int
main(int argc, char ** argv)
{
    	
	header();
    	
	// we need to run this as root
	if (getuid() != 0)
	{
		printf("[ERROR] Please run me as root!\n");
		exit(1);
	}
	
	int8_t kernel_type = get_kernel_type();
	if (kernel_type == -1)
	{
		printf("[ERROR] Unable to retrieve kernel type!\n");
		exit(1);
	}
	
	if((fd_kmem = open("/dev/kmem",O_RDWR)) == -1)
	{
		fprintf(stderr,"[ERROR] Error while opening /dev/kmem. Is /dev/kmem enabled?\n");
		fprintf(stderr,"Add parameter kmem=1 to /Library/Preferences/SystemConfiguration/com.apple.Boot.plist\n");
		exit(1);
	}
	    
	// retrieve int80 address
    idt_t idt_address = get_addr_idt(kernel_type);
    uint64_t int80_address = calculate_int80address(idt_address, kernel_type);
    
    uint64_t kernel_base = find_kernel_base(int80_address, kernel_type);
    if (kernel_base == 0)
    {
        fprintf(stderr, "[ERROR] Could not find kernel base address!\n");
        exit(1);
    }
    uint64_t data_address = 0;
    uint64_t data_size    = 0;
    
    process_header(kernel_base, &data_address, &data_size);
    
    uint8_t *read = malloc((size_t)data_size);
	if (read == NULL)
    {
        printf("[ERROR] Memory allocation failed!\n");
        exit(1);
    }

	// read kernel memory and find sysent
    readkmem(fd_kmem, read, data_address, (size_t)data_size);
    uint64_t sysent_address = find_sysent(read, data_address, data_size);
    
    if (sysent_address)
    {
        printf("[OK] Found sysent address at %p\n",(void*)sysent_address);
    }
    else
    {
        printf("[ERROR] Could not found sysent address!\n");
    }

    free(read);
	return 0;
}