void parse_elf (char* file_name) { init_elf_parser (file_name); if (architecture == ELFCLASS32) { get_num_sections (); get_section_names (); parse_sections (); get_entry_point (); find_main (); } else { get_num_sections64 (); get_section_names64 (); parse_sections64 (); get_entry_point64 (); find_main64 (); } }
sect_info * get_text_section() { int i; sect_info * tex = (sect_info*)malloc(sizeof(sect_info)); byte * tbuf; for (i=0;i< ex_header->num_sections;i++) { if (!strcmp(sects[i]->name,".text")) { text = sects[i]; //printf("%X\n",sects[i]->vaddr); break; } } tbuf = (byte*)malloc(sects[i]->raw_data_size); fseek(fptr,sects[i]->raw_data_ptr,SEEK_SET); fread(tbuf,1,sects[i]->raw_data_size,fptr); tex->data = tbuf; tex->ep = get_text_off(get_entry_point()); tex->size = sects[i]->raw_data_size; tex->va = sects[i]->vaddr; tex->vsize = sects[i]->vsize; //printf("%X %X %X\n",sects[i]->raw_data_ptr,tex->ep,sects[i]->raw_data_ptr+tex->ep-text->vaddr); return tex; }
/** * Initialize PXE. */ void pxe_init(void) { bootp_packet_t *bootp; pxe_device_t *pxe; /* Boot device is set to 0x7f by the PXE boot sector. */ if (bios_boot_device != 0x7f) { return; } if (!get_entry_point()) return; dprintf( "pxe: booting via PXE, entry point at %04x:%04x (%p)\n", pxe_entry_point >> 16, pxe_entry_point & 0xffff, segoff_to_linear(pxe_entry_point)); // When using PXE, 0x8d000 onwards is reserved for use by the PXE stack so // we need to mark it as internal to ensure we don't load anything there. // Also reserve a bit more because the PXE ROM on some machines appears to // take a dump over memory below there as well. memory_protect(0x80000, 0x1f000); // Obtain the BOOTP reply packet. bootp = get_bootp_packet(); // Create a device. pxe = malloc(sizeof(*pxe)); memset(pxe, 0, sizeof(*pxe)); pxe->net.ops = &pxe_net_ops; pxe->net.server_port = PXENV_TFTP_PORT; pxe->mount.device = &pxe->net.device; pxe->mount.ops = &pxe_fs_ops; net_device_register_with_bootp(&pxe->net, bootp, true); pxe->net.device.mount = &pxe->mount; // register a pre-boot hook to shut down the PXE stack loader_register_preboot_hook(shutdown_pxe); }
//Initialize some globals that have to deal with the ELF we're reading //Note: this must be called whether or not you're actually using the parser void init_elf_parser (char* file_name) { init_file_buf (file_name); Elf32_Ehdr* header = (Elf32_Ehdr*)file_buf; Elf64_Ehdr* header64 = (Elf64_Ehdr*)file_buf; //Sanity check header = (Elf32_Ehdr*)file_buf; if (header->e_ident [EI_MAG0] != 0x7f || header->e_ident [EI_MAG1] != 'E' || header->e_ident [EI_MAG2] != 'L' || header->e_ident [EI_MAG3] != 'F') { elf_parser_cleanup (); printf ("CRITICAL ERROR: Not an ELF file.\n"); exit (-1); } if (header->e_shoff > file_size) { elf_parser_cleanup (); printf ("ERROR: ELF file is corrupt. Invalid section header offset. Sections have probably been stripped, please specify a starting address.\n"); exit (-1); } if (header->e_phoff > file_size) { elf_parser_cleanup (); printf ("CRITICAL ERROR: ELF file is corrupt Invalid program header offset.\n"); exit (-1); } architecture = header->e_ident [EI_CLASS]; if (architecture == ELFCLASSNONE) { printf ("CRITICAL ERROR: Invalid architecture"); exit (-1); } else if (architecture == ELFCLASS32) { Elf32_Phdr* program_headers = (Elf32_Phdr*)(file_buf + header->e_phoff); int i; for (i = 0; i < header->e_phnum; i ++) { if (program_headers [i].p_type == PT_LOAD) { base_addr = program_headers [i].p_vaddr; executable_segment_size = program_headers [i].p_filesz; break; } } if (i == header->e_phnum) { printf ("CRITICAL ERROR: No loadable segments\n"); exit (-1); } symbol_table.arch1 = NULL; symbol_table_end.arch1 = NULL; num_relocs = 0; string_table = NULL; get_dyn_syms (); get_entry_point (); get_text (); } else if (architecture == ELFCLASS64) { Elf64_Phdr* program_headers = (Elf64_Phdr*)(file_buf + header64->e_phoff); int i; for (i = 0; i < header64->e_phnum; i ++) { if (program_headers [i].p_type == PT_LOAD) { base_addr = program_headers [i].p_vaddr; executable_segment_size = program_headers [i].p_filesz; break; } } if (i == header64->e_phnum) { printf ("CRITICAL ERROR: No loadable segments\n"); exit (-1); } symbol_table.arch2 = NULL; symbol_table_end.arch2 = NULL; num_relocs = 0; string_table = NULL; get_dyn_syms64 (); get_entry_point64 (); get_text64 (); } else { printf ("CRITICAL ERROR: Invalid ELF class %d", architecture); exit (-1); } }
int main(){ struct Handler *handler_p, *next_handler; unsigned hid; unsigned oep; // This is NOT THE PROPER WAY!!! unsigned siginfo[512]; unsigned baseaddr, memsize; enum __ptrace_request pr, pr2; //struct user_regs_struct regs; //char inst_str[128]; // Test const char *prog = "./try"; //char indirect = 0; //char manual = 0; //char plt = 1; //int pop = 0; //ban = 0x0804841b; int wait_status; struct user_regs_struct regs; init(); pid_t pid = fork(); if (pid == 0){ Ptrace(PTRACE_TRACEME, 0, NULL, NULL); execl(prog, prog, NULL); }else if (pid > 0){ oep = get_entry_point(prog); // On loaded wait(&wait_status); if (WIFSTOPPED(wait_status)){ // Test, wrong memsize = get_memsize(prog); baseaddr = get_baseaddr(prog); add_module(&whitelist, baseaddr, memsize); get_handler(pid, oep, get_trace_option(fopen("/tmp/trace","w"), whitelist)); get_handler(pid, 0x8048380, get_disable_option(API_TYPE_PLT)); Ptrace(PTRACE_CONT, pid, NULL, NULL); } wait(&wait_status); // Withdraw control from plugins while (WIFSTOPPED(wait_status)){ Ptrace(PTRACE_GETSIGINFO, pid, NULL, &siginfo); // Caused by breakpoint if (siginfo[2] == 0x80){ // Discard the 0xcc int 3 instruction // So move the eip upper by 1 Ptrace(PTRACE_GETREGS, pid, NULL, ®s); regs.eip --; Ptrace(PTRACE_SETREGS, pid ,NULL, ®s); } // PTRACE_CONT by default because it has the lowest priority pr = PTRACE_CONT; hid = GETID(regs.eip); for (handler_p=global_handler;handler_p;handler_p=next_handler){ next_handler = handler_p->next_handler; pr2 = dispatch(pid, handler_p); pr = PRIORITY(pr, pr2); pr2 = global_expire(pid, handler_p, &next_handler); pr = PRIORITY(pr, pr2); } for (handler_p=handlers[hid];handler_p;handler_p=next_handler){ next_handler = handler_p->next_handler; pr2 = dispatch(pid, handler_p); pr = PRIORITY(pr, pr2); pr2 = expire(pid, handler_p, hid, &next_handler); pr = PRIORITY(pr, pr2); } Ptrace(pr, pid, NULL, NULL); wait(&wait_status); } }else{ perror("Folk failed: "); exit(-1); } finalize(); return 0; }