Пример #1
0
uint64_t 
calculate_int80address(const uint64_t idt_address, uint8_t kernel_type)
{
  	// find the address of interrupt 0x80 - EXCEP64_SPC_USR(0x80,hi64_unix_scall) @ osfmk/i386/idt64.s
	struct descriptor_idt *int80_descriptor = NULL;
	uint64_t int80_address = 0;
	uint64_t high       = 0;
    uint32_t middle     = 0;

	int80_descriptor = malloc(sizeof(struct descriptor_idt));
	// retrieve the descriptor for interrupt 0x80
    // the IDT is an array of descriptors
	readkmem(fd_kmem, int80_descriptor, idt_address+sizeof(struct descriptor_idt)*0x80, sizeof(struct descriptor_idt));

    // we need to compute the address, it's not direct
    if (kernel_type)
    {
        // extract the stub address
        high = (unsigned long)int80_descriptor->offset_high << 32;
        middle = (unsigned int)int80_descriptor->offset_middle << 16;
        int80_address = (uint64_t)(high + middle + int80_descriptor->offset_low); 
    }
    else
    {
        int80_address = (uint32_t)(int80_descriptor->offset_middle << 16) + int80_descriptor->offset_low;
    }
	printf("[OK] Address of interrupt 80 stub is %p\n", (void*)int80_address);  
    return(int80_address);
}
Пример #2
0
Файл: kmem.c Проект: taysom/tau
/*
 * r - read data from kernel
 * p - put data to kernel
 * pr - print data to screen
 */
static void rdata (addr address, void *data, unint size)
{
	unint	n;

	n = readkmem(address, data, size);
	if (n < size) {
		err_jmp("not enough data");
	}
}
Пример #3
0
uint64_t 
find_kernel_base(const uint64_t int80_address, uint8_t kernel_type)
{
    uint64_t temp_address   = int80_address;
    // the step amount to search backwards from int80
    uint16_t step_value     = 500; // step must be at least sizeof mach_header and a segment_command
    uint16_t length         = step_value;
    uint8_t *temp_buffer    = malloc(step_value);

    if (kernel_type) // 64bits
    {
        struct segment_command_64 *segment_command = NULL;
        while (temp_address > 0)
        {
            // read the kernel mem contents
            readkmem(fd_kmem, temp_buffer, temp_address, length);
            // iterate thru buffer contents, searching for mach-o magic value
            for (uint32_t x = 0; x < length; x++)
            {
                if (*(uint32_t*)(temp_buffer+x) == MH_MAGIC_64)
                {
                    segment_command = (struct segment_command_64*)(temp_buffer+x+sizeof(struct mach_header_64));
                    if (strncmp(segment_command->segname, "__TEXT", 16) == 0)
                    {
                        printf("[OK] Found kernel mach-o header address at %p\n", (void*)(temp_address+x));
                        return((uint64_t)(temp_address+x));
                    }
                }
            }
            // verify if next block to be read is valid or not
            // adjust the step value to a smaller value so we can proceed
            while(readkmem(fd_kmem, temp_buffer, temp_address-step_value, length) == -2)
            {
                step_value = 1; // we could find out which is the biggest acceptable value
                                // but it seems like a waste of time - I'm an Economist :P
                                // we can read smaller values to avoid overlapping
                length = sizeof(struct mach_header_64) + sizeof(struct segment_command_64);
            }
            // check for int overflow
            if (temp_address - step_value > temp_address)
                break;
            temp_address -= step_value;
        }           
    }
    else // 32bits
    {
        struct segment_command *segment_command = NULL;
        while (temp_address > 0)
        {   
            readkmem(fd_kmem, temp_buffer, temp_address, length);
            for (uint32_t x = 0; x < length; x++)
            {
                if (*(uint32_t*)(temp_buffer+x) == MH_MAGIC)
                {
                    segment_command = (struct segment_command*)(temp_buffer+x+sizeof(struct mach_header));
                    if (strncmp(segment_command->segname, "__TEXT", 16) == 0)
                    {
                        printf("[OK] Found kernel mach-o header address at %p\n", (void*)(temp_address+x));
                        return((uint32_t)(temp_address+x));
                    }
                }
            }
            if(readkmem(fd_kmem, temp_buffer, temp_address-step_value, length) == -2)
            {
                step_value = 1;
                length = sizeof(struct mach_header) + sizeof(struct segment_command);
            }
            // check for int overflow
            if (temp_address - step_value > temp_address)
                break;
            temp_address -= step_value;
        }
    }
    return(0);
}
Пример #4
0
uint8_t
process_header(const uint64_t target_address, uint64_t *data_address, uint64_t *data_size)
{
    uint8_t *header_buffer = malloc(1000);
    readkmem(fd_kmem, header_buffer, target_address, 1000);
    
    // verify if it's a valid mach-o binary
    uint8_t *address    = NULL;
    uint32_t nrLoadCmds = 0;
    
    uint32_t magic = *(uint32_t*)(header_buffer);
    if (magic == MH_MAGIC)
	{
        struct mach_header *machHeader = (struct mach_header*)(header_buffer);
        nrLoadCmds = machHeader->ncmds;        
        // first load cmd address
        address = (uint8_t*)(header_buffer + sizeof(struct mach_header));
	}
    else if (magic == MH_MAGIC_64)
    {
        struct mach_header_64 *machHeader = (struct mach_header_64*)(header_buffer);
        nrLoadCmds = machHeader->ncmds;        
        // first load cmd address
        address = (uint8_t*)(header_buffer + sizeof(struct mach_header_64));
    }
    // error
    else
    {
        return(1);
    }
    
    // find the last command offset
    struct load_command *loadCommand = NULL;
    
    for (uint32_t i = 0; i < nrLoadCmds; i++)
    {
        loadCommand = (struct load_command*)address;
        switch (loadCommand->cmd)
        {
            case LC_SEGMENT:
            {
                struct segment_command *segmentCommand = (struct segment_command *)(loadCommand);
                
                if (strncmp(segmentCommand->segname, "__DATA", 16) == 0)
                {
                    *data_address   = segmentCommand->vmaddr;
                    *data_size      = segmentCommand->vmsize;
                    printf("[OK] Found __DATA segment at %p (size:0x%llx)\n", (void*)*data_address, *data_size);
                }
                break;
            }
            case LC_SEGMENT_64:
            {
                struct segment_command_64 *segmentCommand = (struct segment_command_64 *)(loadCommand);
                
                if (strncmp(segmentCommand->segname, "__DATA", 16) == 0)
                {
                    *data_address   = segmentCommand->vmaddr;
                    *data_size      = segmentCommand->vmsize;
                    printf("[OK] Found __DATA segment at %p (size:0x%llx)\n", (void*)*data_address, *data_size);
                }
                break;
            }
        }
        // advance to next command
        address += loadCommand->cmdsize;
    }
    return 0;
}
Пример #5
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;
}