def funcap(cpu_index, cpu, pc, next_pc): ''' Function to monitor API calls and to resolve symbols. Receives 4 parameters (OPCODE CALLBACK): :param addr: Address from instruction to disassemble :type addr: int :param cpu_index: CPU index :type cpu_index: int ''' global num_ins global logger global pgd_target global process_is_created if process_is_created == 1 and api.is_kernel_running(cpu_index) == False: pgd = api.get_running_process(cpu_index) if pgd_target == pgd: disassemble(pc, cpu_index) if num_ins == MAX_INSTRUCTIONS: api.stop_monitoring_process(pgd) pyrebox_print("[*] Stopped monitoring process") num_ins = 0
def mem_write(cpu_index, vaddr, size, haddr, data): global cm global page_status import api if not api.is_kernel_running(cpu_index): page = vaddr & 0xFFFFF000 page_status[page] = "w"
def opcodes(cpu_index, cpu, pc, next_pc): global pyrebox_print global target_pgd if api.is_kernel_running(cpu_index) == False: pgd = api.get_running_process(cpu_index) if pgd == target_pgd and pc < 0x500000: if cpu.EBX == 0x54474354: api.w_r(0, "EBX", 0x72657661) api.w_r(0, "ECX", 0x33333179) api.w_r(0, "EDX", 0x70796837) pyrebox_print("[*] Hypervisor name check %x" % pc) #start_shell() elif cpu.EBX == 0x756e6547: pyrebox_print("[*] GenuineIntel check %x" % pc) elif cpu.EBX == 0x72695620: api.w_r(0, "EAX", 0x65746e49) api.w_r(0, "EBX", 0x6f63206c) api.w_r(0, "ECX", 0x49206572) api.w_r(0, "EDX", 0x00003936) pyrebox_print("[*] CPU Name check %x" % pc) #start_shell() elif cpu.ECX == 0x80000001: #Not pretty elegant api.w_r(0, "ECX", 0x00000000) pyrebox_print("[*] Hypervisor bit check %x" % pc) else: pyrebox_print("[*] Unknown Check (TODO) %x" % pc)
def block_exec(cpu_index, cpu, tb): global cm global page_status import api if not api.is_kernel_running(cpu_index): pc, size, icount = tb page = pc & 0xFFFFF000 if page in page_status: if page_status[page] == "w": proc = api.get_running_process(cpu_index) pyrebox_print("Written & Executed page PID: %08x PAGE: %08x" % (proc, page)) page_status[page] = "x"
def mem_write(params): global cm global page_status import api cpu_index = params["cpu_index"] vaddr = params["vaddr"] size = params["size"] haddr = params["haddr"] data = params["data"] if not api.is_kernel_running(cpu_index): page = vaddr & 0xFFFFF000 page_status[page] = "w"
def rdtsc_opcode_call(cpu_index, cpu, pc, next_pc): global pyrebox_print global target_pgd global rdtsc_val_lo global rdtsc_val_hi if api.is_kernel_running(cpu_index) == False: pgd = api.get_running_process(cpu_index) if pgd == target_pgd and pc < 0x500000: if rdtsc_val_lo == 0: pyrebox_print("[*] first rdtsc call %x" % pc) rdtsc_val_lo = cpu.EAX rdtsc_val_hi = cpu.EDX else: pyrebox_print("[*] new rdtsc check! %x" % pc) rdtsc_val_lo = rdtsc_val_lo + 500 # this just works for pafish ~cos it has a sleep(500), need to find a more general aproach api.w_r(0, "EAX", rdtsc_val_lo) api.w_r(0, "EDX", rdtsc_val_hi)
def mem_write(params): ''' Callback for memory writes. ''' global cm global page_status global current_layer global UNPACKER_LOG_PATH global UNPACKER_DUMP_PATH import api from cpus import X64CPU, X86CPU # Get callback parameters cpu_index = params["cpu_index"] vaddr = params["vaddr"] size = params["size"] haddr = params["haddr"] data = params["data"] # Get running process, as well as CPU object pgd = api.get_running_process(cpu_index) cpu = api.r_cpu(cpu_index) if not api.is_kernel_running(cpu_index): mask = 0xFFFFF000 if TARGET_LONG_SIZE == 4 else 0xFFFFFFFFFFFFF000 page = vaddr & mask # Set page write status (update with current layer) page_status_w[page] = current_layer # Log the page write pc = cpu.RIP if isinstance(cpu, X64CPU) else cpu.EIP if TARGET_LONG_SIZE == 4: append_log("[W] - PGD [%08x] - PAGE [%08x] - FROM [%08x]" % (pgd, page, pc)) else: append_log("[W] - PGD [%016x] - PAGE [%016x] - FROM [%016x]" % (pgd, page, pc))
def mem_write(params): ''' Callback for memory writes. ''' global cm global page_status_x global page_status_w global current_layer global UNPACKER_LOG_PATH global UNPACKER_DUMP_PATH global section_maps global written_files global ntdll_space import api from cpus import X64CPU, X86CPU # Get callback parameters cpu_index = params["cpu_index"] vaddr = params["vaddr"] size = params["size"] haddr = params["haddr"] data = params["data"] # Get running process, as well as CPU object pgd = api.get_running_process(cpu_index) cpu = api.r_cpu(cpu_index) pc = cpu.RIP if isinstance(cpu, X64CPU) else cpu.EIP if pgd not in page_status_w: page_status_w[pgd] = {} if not api.is_kernel_running(cpu_index): mask = 0xFFFFF000 if TARGET_LONG_SIZE == 4 else 0xFFFFFFFFFFFFF000 page = vaddr & mask overlapping_section_maps = [] # Check if the memory was mapped to file, so we record a file write for such file for base, size, file_offset, file_name in section_maps: if page >= (base & mask) and page < (( (base + size) & mask) + 0x1000): overlapping_section_maps.append( (base, size, file_offset, file_name)) # If it comes from ntdll and affects to a mapped file, just ignore it, # it is likely due to relocations or loader/stuff and is prone to FPs. if (pc >= ntdll_space[0] and pc < (ntdll_space[0] + ntdll_space[1]) ) and len(overlapping_section_maps) > 0: return # Set page write status (update with current layer) page_status_w[pgd][page] = current_layer # Log the page write if TARGET_LONG_SIZE == 4: append_log("[W] - PGD [%08x] - PAGE [%08x] - FROM [%08x]" % (pgd, page, pc)) else: append_log("[W] - PGD [%016x] - PAGE [%016x] - FROM [%016x]" % (pgd, page, pc)) # Only reflect on mapped file if it doesn't come from ntdll, to avoid FPs due to relocation # fixing. # Finally, check if the memory was mapped to file, so we record a file write for such file for base, size, file_offset, file_name in overlapping_section_maps: if file_name not in written_files: written_files[file_name] = [ ((page - (base & mask)) + file_offset, 0x1000) ] else: written_files[file_name].append( ((page - (base & mask)) + file_offset, 0x1000)) append_log( "^^^---> PAGE is section mapped, FILE [%s] - Offset %x - Size %x" % (file_name, (page - (base & mask)) + file_offset, size))