static void patch_bugcheck_data(WinDumpHeader64 *h, Error **errp) { uint64_t KiBugcheckData; if (cpu_memory_rw_debug(first_cpu, h->KdDebuggerDataBlock + KDBG_KI_BUGCHECK_DATA_OFFSET64, (uint8_t *)&KiBugcheckData, sizeof(KiBugcheckData), 0)) { error_setg(errp, "win-dump: failed to read KiBugcheckData"); return; } if (cpu_memory_rw_debug(first_cpu, KiBugcheckData, h->BugcheckData, sizeof(h->BugcheckData), 0)) { error_setg(errp, "win-dump: failed to read bugcheck data"); return; } /* * If BugcheckCode wasn't saved, we consider guest OS as alive. */ if (!h->BugcheckCode) { h->BugcheckCode = LIVE_SYSTEM_DUMP; } }
char* parse_unicode_strptr(uint64_t ustr_ptr, CPUState *cpu) { json_object* ustr = NULL; field_info* f_info = NULL; uint16_t length, max_length; uint64_t buf_ptr; int offset; uint8_t *buf; char* str; int i; ustr = memfrs_q_struct("_UNICODE_STRING"); f_info = memfrs_q_field(ustr, "MaximumLength"); offset = f_info->offset; cpu_memory_rw_debug( cpu, ustr_ptr+offset, (uint8_t*)&max_length, sizeof(max_length), 0 ); memfrs_close_field(f_info); f_info = memfrs_q_field(ustr, "Length"); offset = f_info->offset; cpu_memory_rw_debug( cpu, ustr_ptr+offset, (uint8_t*)&length, sizeof(length), 0 ); memfrs_close_field(f_info); printf("String with size %d/%d\n", length, max_length); if(length == 0 || length > 256 || max_length ==0 || max_length > 256) return NULL; f_info = memfrs_q_field(ustr, "Buffer"); offset = f_info->offset; cpu_memory_rw_debug( cpu, ustr_ptr+offset, (uint8_t*)&buf_ptr, sizeof(buf_ptr), 0 ); memfrs_close_field(f_info); //printf("Address: %" PRIx64 "\n", buf_ptr); buf = (uint8_t*)malloc(max_length+2); str = (char*)malloc(max_length+1); memset(str, 0, max_length+1); cpu_memory_rw_debug( cpu, buf_ptr, buf, max_length, 0 ); //Hardcode Unicode Parse //wcstombs(str, (const wchar_t *)buf, max_length); for(i=0; i<max_length; i+=2) str[i/2] = buf[i]; str[i] = 0x00; //printf("Filename %ls\n", (wchar_t*p)buf); printf("Filename %s\n", str); free(buf); return str; }
static uint32_t nand_dev_read_file(nand_dev *dev, uint32_t data, uint64_t addr, uint32_t total_len) { uint32_t len = total_len; size_t read_len = dev->erase_size; int eof = 0; NAND_UPDATE_READ_THRESHOLD(total_len); do_lseek(dev->fd, addr, SEEK_SET); while(len > 0) { if(read_len < dev->erase_size) { memset(dev->data, 0xff, dev->erase_size); read_len = dev->erase_size; eof = 1; } if(len < read_len) read_len = len; if(!eof) { read_len = do_read(dev->fd, dev->data, read_len); } #ifdef TARGET_I386 if (kvm_enabled()) cpu_synchronize_state(cpu_single_env, 0); #endif cpu_memory_rw_debug(cpu_single_env, data, dev->data, read_len, 1); data += read_len; len -= read_len; } return total_len; }
UT_array* memfrs_scan_virmem( CPUState *cpu, uint64_t start_addr, uint64_t end_addr, const char* pattern, int length ) { uint64_t i; if(start_addr >= end_addr) { printf("end_addr is not less than start_addr\n"); return NULL; } uint8_t* buf = (uint8_t*)malloc(length); UT_array *match_addr; memset(buf, 0, length); if(buf == NULL) { printf("Cannot allocate memory for do_show_memory_taint_map()\n"); return NULL; } utarray_new( match_addr, &adr_icd); printf("Scan for pattern %s\n", pattern); for(i = start_addr; i < end_addr-length+1; i++) { cpu_memory_rw_debug(cpu, i, buf, length, 0); if(memcmp(buf, pattern, length)==0) { printf("pattern found %lx\n", i); utarray_push_back(match_addr, &i); } } return match_addr; }
static uint32_t nand_dev_write_file(nand_dev *dev, uint32_t data, uint64_t addr, uint32_t total_len) { uint32_t len = total_len; size_t write_len = dev->erase_size; int ret; NAND_UPDATE_WRITE_THRESHOLD(total_len); do_lseek(dev->fd, addr, SEEK_SET); while(len > 0) { if(len < write_len) write_len = len; #ifdef TARGET_I386 if (kvm_enabled()) cpu_synchronize_state(cpu_single_env, 0); #endif cpu_memory_rw_debug(cpu_single_env, data, dev->data, write_len, 0); ret = do_write(dev->fd, dev->data, write_len); if(ret < write_len) { XLOG("nand_dev_write_file, write failed: %s\n", strerror(errno)); break; } data += write_len; len -= write_len; } return total_len - len; }
int PEMU_read_mem(uint32_t vaddr, int len, void *buf) { // PIN_SafeCopy(buf, (VOID*)vaddr, 15); // memcpy(buf, (void*)vaddr, len); // return 0; return cpu_memory_rw_debug(cpu_single_env, vaddr, buf, len, 0); }
static void goldfish_bus_write(void *opaque, target_phys_addr_t offset, uint32_t value) { struct bus_state *s = (struct bus_state *)opaque; switch(offset) { case PDEV_BUS_OP: switch(value) { case PDEV_BUS_OP_INIT: goldfish_bus_op_init(s); break; default: cpu_abort (cpu_single_env, "goldfish_bus_write: Bad PDEV_BUS_OP value %x\n", value); }; break; case PDEV_BUS_GET_NAME: if(s->current) { #ifdef TARGET_I386 if(kvm_enabled()) cpu_synchronize_state(cpu_single_env, 0); #endif cpu_memory_rw_debug(cpu_single_env, value, (void*)s->current->name, strlen(s->current->name), 1); } break; default: cpu_abort (cpu_single_env, "goldfish_bus_write: Bad offset %x\n", offset); } }
/* Get LENGTH bytes from info's buffer, at target address memaddr. Transfer them to myaddr. */ static int target_read_memory (bfd_vma memaddr, bfd_byte *myaddr, int length, struct disassemble_info *info) { cpu_memory_rw_debug(cpu_single_env, memaddr, myaddr, length, 0); return 0; }
static void patch_mm_pfn_database(WinDumpHeader64 *h, Error **errp) { if (cpu_memory_rw_debug(first_cpu, h->KdDebuggerDataBlock + KDBG_MM_PFN_DATABASE_OFFSET64, (uint8_t *)&h->PfnDatabase, sizeof(h->PfnDatabase), 0)) { error_setg(errp, "win-dump: failed to read MmPfnDatabase"); return; } }
int safe_memory_rw_debug(CPUOldState *env, target_ulong addr, uint8_t *buf, int len, int is_write) { #ifdef TARGET_I386 if (kvm_enabled()) { kvm_get_sregs(env); } #endif return cpu_memory_rw_debug(env, addr, buf, len, is_write); }
static inline int target_memory_rw_debug(CPUState *cpu, target_ulong addr, uint8_t *buf, int len, bool is_write) { CPUClass *cc = CPU_GET_CLASS(cpu); if (cc->memory_rw_debug) { return cc->memory_rw_debug(cpu, addr, buf, len, is_write); } return cpu_memory_rw_debug(cpu, addr, buf, len, is_write); }
int safe_memory_rw_debug(CPUState *cpu, target_ulong addr, uint8_t *buf, int len, int is_write) { #ifdef TARGET_I386 if (kvm_enabled()) { kvm_get_sregs(cpu); } #endif return cpu_memory_rw_debug(cpu, addr, buf, len, is_write, "goldfish_safe_mem_rw_dbg"); }
/* Get LENGTH bytes from info's buffer, at target address memaddr. Transfer them to myaddr. */ static int target_read_memory (bfd_vma memaddr, bfd_byte *myaddr, int length, struct disassemble_info *info) { CPUDebug *s = container_of(info, CPUDebug, info); cpu_memory_rw_debug(s->cpu, memaddr, myaddr, length, 0); return 0; }
/* * NTSTATUS NtCreateFile( __out PHANDLE FileHandle, __in ACCESS_MASK DesiredAccess, __in POBJECT_ATTRIBUTES ObjectAttributes, __out PIO_STATUS_BLOCK IoStatusBlock, __in_opt PLARGE_INTEGER AllocationSize, __in ULONG FileAttributes, __in ULONG ShareAccess, __in ULONG CreateDisposition, __in ULONG CreateOptions, __in PVOID EaBuffer, __in ULONG EaLength ); * */ void NtCreateFile_ret_handler(void *opaque) { monitor_printf(default_mon, "NtCreateFile_ret\n"); uint32_t esp, offset; uint32_t i,j; CPUState *cpu; cpu = cpu_single_env; UNICODE_STRING ObjectName; char *Buffer = NULL; ULONG Length=0; uint8_t unicode_str[1024]; POBJECT_ATTRIBUTES po = NULL; /* Populate out arguments */ esp = cpu->regs[R_ESP]; //offset = esp; uint32_t stack_data[11]; DECAF_read_mem(cpu,esp,4*11,(void *)stack_data); uint64_t data_temp=(uint64_t)stack_data[2]; po = malloc(sizeof(OBJECT_ATTRIBUTES)); ; DECAF_read_mem(cpu,stack_data[2],sizeof(OBJECT_ATTRIBUTES),(void *)po); if(po->ObjectName){ DECAF_read_mem(cpu,(uint32_t)po->ObjectName, sizeof(UNICODE_STRING), (void *)&ObjectName); monitor_printf(default_mon, "\t\tObjectName.Length: %d\n", ObjectName.Length); monitor_printf(default_mon, "\t\tObjectName.MaximumLength: %d\n", ObjectName.MaximumLength); monitor_printf(default_mon, "\t\tObjectName.Buffer: 0x%p\n", ObjectName.Buffer); if(ObjectName.Buffer && ObjectName.Length){ Buffer = (char *) malloc (sizeof(char) * ObjectName.Length); if(Buffer != '\0') { cpu_memory_rw_debug(cpu_single_env, (target_ulong)ObjectName.Buffer, (uint8_t *)&unicode_str, ObjectName.Length, 0); for (i = 0, j = 0; i < ObjectName.Length; i+=2, j++) Buffer[j] = unicode_str[i]; Buffer[j] = '\0'; DECAF_printf("%s\n",Buffer); monitor_printf(default_mon, "\t\t\tBuffer: %s \n", Buffer); free(Buffer); } } } }
void qmp_memsave(int64_t addr, int64_t size, const char *filename, bool has_cpu, int64_t cpu_index, Error **errp) { FILE *f; uint32_t l; CPUArchState *env; uint8_t buf[1024]; if (!has_cpu) { cpu_index = 0; } for (env = first_cpu; env; env = env->next_cpu) { if (cpu_index == env->cpu_index) { break; } } if (env == NULL) { error_set(errp, QERR_INVALID_PARAMETER_VALUE, "cpu-index", "a CPU number"); return; } f = fopen(filename, "wb"); if (!f) { error_set(errp, QERR_OPEN_FILE_FAILED, filename); return; } while (size != 0) { l = sizeof(buf); if (l > size) l = size; cpu_memory_rw_debug(env, addr, buf, l, 0); if (fwrite(buf, 1, l, f) != l) { error_set(errp, QERR_IO_ERROR); goto exit; } addr += l; size -= l; } exit: fclose(f); }
/******************************************************************* int memfrs_get_virmem_content( CPUState *cpu, uint64_t cr3, uint64_t target_addr, uint64_t target_length, uint8_t* buf) Get the memory content in virtual memory INPUT: CPUState *cpu Current cpu uint64_t cr3 CR3 value, 0 if no specific process uint64_t target_addr The target address uint64_t target_length The length to be getten uint8_t* buf The buffer to save the memory content OUTPUT: int -1 indicate fails *******************************************************************/ int memfrs_get_virmem_content( CPUState *cpu, uint64_t cr3, uint64_t target_addr, uint64_t target_length, uint8_t* buf) { X86CPU copied_cpu; int ret; memcpy(&copied_cpu, X86_CPU(cpu), sizeof(copied_cpu)); if(cr3 != 0) { copied_cpu.env.cr[3] = cr3; } ret = cpu_memory_rw_debug((CPUState *)&copied_cpu, target_addr, (uint8_t*)buf, target_length, 0); if(ret != 0) { //printf("Fail to read virtual memory\n"); return -1; } return 0; }
flx_disassembly* flx_disas_bbl(uint32_t addr){ uint32_t size = flx_disas_bbl_size(addr); if(!size) return NULL; uint8_t* buf = malloc(size); if(cpu_memory_rw_debug(current_environment, addr, buf, size, 0) != 0){ free(buf); return NULL; } int fds[2]; if(pipe(fds)){ free(buf); return NULL; } FILE* disas_read = fdopen(fds[0],"r"); FILE* disas_write = fdopen(fds[1],"w"); disas_relative(disas_write, buf, size, addr); fclose(disas_write); free(buf); const uint8_t buf_size = 128; uint32_t tmp_size = buf_size; uint8_t* tmp_buf = malloc(tmp_size); uint32_t disas_size = 0; while(fread(&tmp_buf[disas_size], 1, 1, disas_read)){ disas_size++; if(disas_size >= tmp_size){ tmp_size += buf_size; tmp_buf = realloc(tmp_buf, tmp_size); } } if(ferror(disas_read)){ free(tmp_buf); return NULL; } fclose(disas_read); return flx_disas_alloc(tmp_buf, disas_size); }
void ski_debug_memory(CPUState* env){ char* addr; char buf[8]; int i; SKI_TRACE("ski_debug_memory\n"); SKI_TRACE("ski_debug_memory IDT.base=%x IDT.limit=%x\n", env->idt.base, env->idt.limit); for(addr = env->idt.base ; addr < env->idt.base + env->idt.limit ; addr+=sizeof(buf)){ int len = MIN((env->idt.base + env->idt.limit) - env->idt.base, sizeof(buf)); if(len>=8){ cpu_memory_rw_debug(env,addr, buf, sizeof(buf), 0); //cpu_physical_memory_rw(addr, buf, sizeof(buf), 0); //SKI_TRACE("IDT i: %02d %8x %8x\n", i, e1, e2); SKI_TRACE("IDT i: %02d %8x %8x\n", i, ((int*)buf)[0],((int*)buf)[1]); } i++; } }
void qmp_memsave(int64_t addr, int64_t size, const char *filename, bool has_cpu, int64_t cpu_index, Error **errp) { FILE *f; uint32_t l; CPUState *cpu; uint8_t buf[1024]; if (!has_cpu) { cpu_index = 0; } cpu = qemu_get_cpu(cpu_index); if (cpu == NULL) { error_set(errp, QERR_INVALID_PARAMETER_VALUE, "cpu-index", "a CPU number"); return; } f = fopen(filename, "wb"); if (!f) { error_setg_file_open(errp, errno, filename); return; } while (size != 0) { l = sizeof(buf); if (l > size) l = size; cpu_memory_rw_debug(cpu, addr, buf, l, 0); if (fwrite(buf, 1, l, f) != l) { error_set(errp, QERR_IO_ERROR); goto exit; } addr += l; size -= l; } exit: fclose(f); }
/******************************************************************* bool memfrs_kpcr_self_check( uint64_t kpcr_ptr ) Hueristic check if certain address contain the data structure _KPCR INPUT: uint64_t kpcr_ptr, the 64bit address of possible KPCR pointer OUTPUT: bool, return true if kpcr found, else retuen false *******************************************************************/ bool memfrs_kpcr_self_check( uint64_t kpcr_ptr ) { uint64_t self_ptr = 0; json_object* jkpcr =NULL; field_info* f_info = NULL; int offset_self_to_kpcr = 0; //Check if the global data structure info is load, if not abort check. if(g_struct_info == NULL) { return false; } // Find the struct _KPCR jkpcr = memfrs_q_struct("_KPCR"); // Query field name Self in _KPCR structure f_info = memfrs_q_field(jkpcr, "Self"); offset_self_to_kpcr = f_info->offset; memfrs_close_field(f_info); // Read the concrete memory value in Self field if( cpu_memory_rw_debug(current_cpu, kpcr_ptr + offset_self_to_kpcr, (uint8_t*)&self_ptr, sizeof(self_ptr), 0) != 0 ) { g_kpcr_ptr = 0; return false; } // Check if the Self pointer point back to _KPCR structure, which is the hueristic check of _KPCR if( kpcr_ptr == self_ptr ) { g_kpcr_ptr = kpcr_ptr; printf("KPCR found %lx\n", g_kpcr_ptr); return true; } g_kpcr_ptr = 0; return false; }
static void check_kdbg(WinDumpHeader64 *h, Error **errp) { const char OwnerTag[] = "KDBG"; char read_OwnerTag[4]; uint64_t KdDebuggerDataBlock = h->KdDebuggerDataBlock; bool try_fallback = true; try_again: if (cpu_memory_rw_debug(first_cpu, KdDebuggerDataBlock + KDBG_OWNER_TAG_OFFSET64, (uint8_t *)&read_OwnerTag, sizeof(read_OwnerTag), 0)) { error_setg(errp, "win-dump: failed to read OwnerTag"); return; } if (memcmp(read_OwnerTag, OwnerTag, sizeof(read_OwnerTag))) { if (try_fallback) { /* * If attempt to use original KDBG failed * (most likely because of its encryption), * we try to use KDBG obtained by guest driver. */ KdDebuggerDataBlock = h->BugcheckParameter1; try_fallback = false; goto try_again; } else { error_setg(errp, "win-dump: invalid KDBG OwnerTag," " expected '%.4s', got '%.4s'", OwnerTag, read_OwnerTag); return; } } h->KdDebuggerDataBlock = KdDebuggerDataBlock; }
static void goldfish_tty_write(void *opaque, target_phys_addr_t offset, uint32_t value) { struct tty_state *s = (struct tty_state *)opaque; //printf("goldfish_tty_read %x %x %x\n", offset, value, size); switch(offset) { case TTY_PUT_CHAR: { uint8_t ch = value; if(s->cs) qemu_chr_write(s->cs, &ch, 1); } break; case TTY_CMD: switch(value) { case TTY_CMD_INT_DISABLE: if(s->ready) { if(s->data_count > 0) goldfish_device_set_irq(&s->dev, 0, 0); s->ready = 0; } break; case TTY_CMD_INT_ENABLE: if(!s->ready) { if(s->data_count > 0) goldfish_device_set_irq(&s->dev, 0, 1); s->ready = 1; } break; case TTY_CMD_WRITE_BUFFER: if(s->cs) { int len; target_phys_addr_t buf; buf = s->ptr; len = s->ptr_len; while (len) { char temp[64]; int to_write = sizeof(temp); if (to_write > len) to_write = len; cpu_memory_rw_debug(cpu_single_env, buf, temp, to_write, 0); qemu_chr_write(s->cs, temp, to_write); buf += to_write; len -= to_write; } //printf("goldfish_tty_write: got %d bytes from %x\n", s->ptr_len, s->ptr); } break; case TTY_CMD_READ_BUFFER: if(s->ptr_len > s->data_count) cpu_abort (cpu_single_env, "goldfish_tty_write: reading more data than available %d %d\n", s->ptr_len, s->data_count); cpu_memory_rw_debug(cpu_single_env,s->ptr, s->data, s->ptr_len,1); //printf("goldfish_tty_write: read %d bytes to %x\n", s->ptr_len, s->ptr); if(s->data_count > s->ptr_len) memmove(s->data, s->data + s->ptr_len, s->data_count - s->ptr_len); s->data_count -= s->ptr_len; if(s->data_count == 0 && s->ready) goldfish_device_set_irq(&s->dev, 0, 0); break; default: cpu_abort (cpu_single_env, "goldfish_tty_write: Bad command %x\n", value); }; break; case TTY_DATA_PTR: s->ptr = value; break; case TTY_DATA_LEN: s->ptr_len = value; break; default: cpu_abort (cpu_single_env, "goldfish_tty_write: Bad offset %x\n", offset); } }
static #endif uint32_t nand_dev_do_cmd(nand_dev_controller_state *s, uint32_t cmd) { uint32_t size; uint64_t addr; nand_dev *dev; if (cmd == NAND_CMD_WRITE_BATCH || cmd == NAND_CMD_READ_BATCH || cmd == NAND_CMD_ERASE_BATCH) { struct batch_data bd; uint64_t bd_addr = ((uint64_t)s->batch_addr_high << 32) | s->batch_addr_low; cpu_physical_memory_read(bd_addr, (void*)&bd, sizeof(struct batch_data)); s->dev = bd.dev; s->addr_low = bd.addr_low; s->addr_high = bd.addr_high; s->transfer_size = bd.transfer_size; s->data = bd.data; } addr = s->addr_low | ((uint64_t)s->addr_high << 32); size = s->transfer_size; if(s->dev >= nand_dev_count) return 0; dev = nand_devs + s->dev; switch(cmd) { case NAND_CMD_GET_DEV_NAME: if(size > dev->devname_len) size = dev->devname_len; #ifdef TARGET_I386 if (kvm_enabled()) cpu_synchronize_state(cpu_single_env, 0); #endif cpu_memory_rw_debug(cpu_single_env, s->data, (uint8_t*)dev->devname, size, 1); return size; case NAND_CMD_READ_BATCH: case NAND_CMD_READ: if(addr >= dev->max_size) return 0; if(size > dev->max_size - addr) size = dev->max_size - addr; if(dev->fd >= 0) return nand_dev_read_file(dev, s->data, addr, size); #ifdef TARGET_I386 if (kvm_enabled()) cpu_synchronize_state(cpu_single_env, 0); #endif cpu_memory_rw_debug(cpu_single_env,s->data, &dev->data[addr], size, 1); return size; case NAND_CMD_WRITE_BATCH: case NAND_CMD_WRITE: if(dev->flags & NAND_DEV_FLAG_READ_ONLY) return 0; if(addr >= dev->max_size) return 0; if(size > dev->max_size - addr) size = dev->max_size - addr; if(dev->fd >= 0) return nand_dev_write_file(dev, s->data, addr, size); #ifdef TARGET_I386 if (kvm_enabled()) cpu_synchronize_state(cpu_single_env, 0); #endif cpu_memory_rw_debug(cpu_single_env,s->data, &dev->data[addr], size, 0); return size; case NAND_CMD_ERASE_BATCH: case NAND_CMD_ERASE: if(dev->flags & NAND_DEV_FLAG_READ_ONLY) return 0; if(addr >= dev->max_size) return 0; if(size > dev->max_size - addr) size = dev->max_size - addr; if(dev->fd >= 0) return nand_dev_erase_file(dev, addr, size); memset(&dev->data[addr], 0xff, size); return size; case NAND_CMD_BLOCK_BAD_GET: // no bad block support return 0; case NAND_CMD_BLOCK_BAD_SET: if(dev->flags & NAND_DEV_FLAG_READ_ONLY) return 0; return 0; default: cpu_abort(cpu_single_env, "nand_dev_do_cmd: Bad command %x\n", cmd); return 0; } }
/******************************************************************* int memfrs_enum_proc_list( uint64_t kpcr_ptr, CPUState *cpu ) Eumerate the running process INPUT: uint64_t kpcr_ptr, the address of _KPCR struct CPUState *cpu, the pointer to current cpu OUTPUT: int, return 0 if sucess, and not 0 otherwise *******************************************************************/ int memfrs_enum_proc_list( uint64_t kpcr_ptr, CPUState *cpu ) { uint64_t kthread_ptr, eprocess_ptr; uint64_t cr3; uint8_t buf[STRLEN]; uint64_t eprocess_ptr_init = 0; json_object* jkpcr =NULL; int offset_curthread_to_kpcr = 0; json_object* jkthread =NULL; int offset_process_to_kthread = 0; json_object* jeprocess = NULL; int offset_cr3_to_eprocess = 0; int offset_blink_to_eprocess = 0; int offset_entry_list_to_eprocess = 0; int offset_process_name_to_eprocess = 0; field_info* f_info, *f_info2 = NULL; //Check if the data structure information is loaded if(g_struct_info ==NULL) { printf("Data structure information is not loaded\n"); return -1; } //Check if kpcr is already found if(kpcr_ptr == 0) { printf("Not yet find kpcr address\n"); return -1; } //Check the cpu pointer valid if(cpu == NULL) { printf("CPU state is null\n"); return -1; } // Retrieve the _KPCR structure jkpcr = memfrs_q_struct("_KPCR"); // Query Prcb field in _KPCR struct f_info = memfrs_q_field(jkpcr, "Prcb"); // Query Prcb for the sub-field name CurrentThread f_info2 = memfrs_q_field(f_info->jobject_type, "CurrentThread"); // Calculating the offset of CurrentThread in _KPCR offset_curthread_to_kpcr = f_info->offset + f_info2->offset; //Cleaning ... memfrs_close_field(f_info2); memfrs_close_field(f_info); // Retrieve the _KTHREAD structure jkthread = memfrs_q_struct("_KTHREAD"); // Query PROCESS field in _KTHREAD struct f_info = memfrs_q_field(jkthread, "Process"); offset_process_to_kthread = f_info->offset; memfrs_close_field(f_info); // Read the concrete memory value of kthread_ptr(CurrentThread) via _KPCR address cpu_memory_rw_debug( cpu, kpcr_ptr + offset_curthread_to_kpcr, (uint8_t*)&kthread_ptr, sizeof(kthread_ptr), 0 ); // Read the concrete memory value of PROCESS via CurrentThread // Get the first PROCESS cpu_memory_rw_debug( cpu, kthread_ptr + offset_process_to_kthread, (uint8_t*)&eprocess_ptr, sizeof(eprocess_ptr), 0 ); // Retrieve the _EPROCESS structure jeprocess = memfrs_q_struct("_EPROCESS"); // Query Pcb field in _EPROCESS struct f_info = memfrs_q_field(jeprocess, "Pcb"); // Query Pcb for the sub-field name DirectoryTableBase, which is CR3 value f_info2 = memfrs_q_field(f_info->jobject_type, "DirectoryTableBase"); offset_cr3_to_eprocess = f_info->offset + f_info2->offset; memfrs_close_field(f_info2); memfrs_close_field(f_info); // Query ActiveProcessLinks in _EPROCESS f_info = memfrs_q_field(jeprocess, "ActiveProcessLinks"); // Query Blink in ActiveProcessLinks f_info2 = memfrs_q_field(f_info->jobject_type, "Blink"); // Calculate Entry List offset from eprocess offset_entry_list_to_eprocess = f_info->offset; // Calculate Blink offset from eprocess offset_blink_to_eprocess = f_info->offset + f_info2->offset; memfrs_close_field(f_info2); memfrs_close_field(f_info); // Query and Cal offset of ImageFileName in _EPROCESS struct f_info = memfrs_q_field(jeprocess, "ImageFileName"); offset_process_name_to_eprocess = f_info->offset; memfrs_close_field(f_info); // Start iteration process list eprocess_ptr_init = eprocess_ptr; do { //Read CR3 & Process name cpu_memory_rw_debug( cpu, eprocess_ptr + offset_cr3_to_eprocess, (uint8_t*)&cr3, sizeof(cr3), 0 ); cpu_memory_rw_debug( cpu, eprocess_ptr + offset_process_name_to_eprocess, (uint8_t*)buf, sizeof(buf), 0 ); printf( "eprocess: %lx CR3: %lx, Process Name: %s\n", eprocess_ptr, cr3, buf ); // read next entry cpu_memory_rw_debug( cpu, eprocess_ptr + offset_blink_to_eprocess, (uint8_t*)&eprocess_ptr, sizeof(eprocess_ptr), 0 ); // Substract entry_list offset to find base address of eprocess eprocess_ptr -= offset_entry_list_to_eprocess; } while( eprocess_ptr != eprocess_ptr_init ); return 0; }
static #endif uint32_t nand_dev_do_cmd(nand_dev_state *s, uint32_t cmd) { uint32_t size; uint64_t addr; nand_dev *dev; addr = s->addr_low | ((uint64_t)s->addr_high << 32); size = s->transfer_size; if(s->dev >= nand_dev_count) return 0; dev = nand_devs + s->dev; switch(cmd) { case NAND_CMD_GET_DEV_NAME: if(size > dev->devname_len) size = dev->devname_len; cpu_memory_rw_debug(cpu_single_env, s->data, dev->devname, size, 1); return size; case NAND_CMD_READ: if(addr >= dev->size) return 0; if(size + addr > dev->size) size = dev->size - addr; if(dev->fd >= 0) return nand_dev_read_file(dev, s->data, addr, size); cpu_memory_rw_debug(cpu_single_env,s->data, &dev->data[addr], size, 1); return size; case NAND_CMD_WRITE: if(dev->flags & NAND_DEV_FLAG_READ_ONLY) return 0; if(addr >= dev->size) return 0; if(size + addr > dev->size) size = dev->size - addr; if(dev->fd >= 0) return nand_dev_write_file(dev, s->data, addr, size); cpu_memory_rw_debug(cpu_single_env,s->data, &dev->data[addr], size, 0); return size; case NAND_CMD_ERASE: if(dev->flags & NAND_DEV_FLAG_READ_ONLY) return 0; if(addr >= dev->size) return 0; if(size + addr > dev->size) size = dev->size - addr; if(dev->fd >= 0) return nand_dev_erase_file(dev, addr, size); memset(&dev->data[addr], 0xff, size); return size; case NAND_CMD_BLOCK_BAD_GET: // no bad block support return 0; case NAND_CMD_BLOCK_BAD_SET: if(dev->flags & NAND_DEV_FLAG_READ_ONLY) return 0; return 0; default: cpu_abort(cpu_single_env, "nand_dev_do_cmd: Bad command %x\n", cmd); return 0; } }
int PEMU_read_mem(uint32_t vaddr, int len, void *buf) { return cpu_memory_rw_debug(first_cpu, vaddr, buf, len, 0); }
/* I/O write */ static void trace_dev_write(void *opaque, target_phys_addr_t offset, uint32_t value) { trace_dev_state *s = (trace_dev_state *)opaque; switch (offset >> 2) { case TRACE_DEV_REG_SWITCH: // context switch, switch to pid if (trace_filename != NULL) { trace_switch(value); #ifdef DEBUG printf("QEMU.trace: kernel, context switch %u\n", value); #endif } #ifdef CONFIG_MEMCHECK if (memcheck_enabled) { memcheck_switch(value); } #endif // CONFIG_MEMCHECK break; case TRACE_DEV_REG_TGID: // save the tgid for the following fork/clone tgid = value; #ifdef DEBUG if (trace_filename != NULL) { printf("QEMU.trace: kernel, tgid %u\n", value); } #endif break; case TRACE_DEV_REG_FORK: // fork, fork new pid if (trace_filename != NULL) { trace_fork(tgid, value); #ifdef DEBUG printf("QEMU.trace: kernel, fork %u\n", value); #endif } #ifdef CONFIG_MEMCHECK if (memcheck_enabled) { memcheck_fork(tgid, value); } #endif // CONFIG_MEMCHECK break; case TRACE_DEV_REG_CLONE: // fork, clone new pid (i.e. thread) if (trace_filename != NULL) { trace_clone(tgid, value); #ifdef DEBUG printf("QEMU.trace: kernel, clone %u\n", value); #endif } #ifdef CONFIG_MEMCHECK if (memcheck_enabled) { memcheck_clone(tgid, value); } #endif // CONFIG_MEMCHECK break; case TRACE_DEV_REG_EXECVE_VMSTART: // execve, vstart vstart = value; break; case TRACE_DEV_REG_EXECVE_VMEND: // execve, vend vend = value; break; case TRACE_DEV_REG_EXECVE_OFFSET: // execve, offset in EXE eoff = value; break; case TRACE_DEV_REG_EXECVE_EXEPATH: // init exec, path of EXE vstrcpy(value, path, CLIENT_PAGE_SIZE); if (trace_filename != NULL) { trace_init_exec(vstart, vend, eoff, path); #ifdef DEBUG printf("QEMU.trace: kernel, init exec [%lx,%lx]@%lx [%s]\n", vstart, vend, eoff, path); #endif } #ifdef CONFIG_MEMCHECK if (memcheck_enabled) { if (path[0] == '\0') { // vstrcpy may fail to copy path. In this case lets do it // differently. memcheck_get_guest_kernel_string(path, value, CLIENT_PAGE_SIZE); } memcheck_mmap_exepath(vstart, vend, eoff, path); } #endif // CONFIG_MEMCHECK path[0] = 0; break; case TRACE_DEV_REG_CMDLINE_LEN: // execve, process cmdline length cmdlen = value; break; case TRACE_DEV_REG_CMDLINE: // execve, process cmdline cpu_memory_rw_debug(cpu_single_env, value, arg, cmdlen, 0); if (trace_filename != NULL) { trace_execve(arg, cmdlen); } #ifdef CONFIG_MEMCHECK if (memcheck_enabled) { memcheck_set_cmd_line(arg, cmdlen); } #endif // CONFIG_MEMCHECK #ifdef DEBUG if (trace_filename != NULL) { int i; for (i = 0; i < cmdlen; i ++) if (i != cmdlen - 1 && arg[i] == 0) arg[i] = ' '; printf("QEMU.trace: kernel, execve %s[%d]\n", arg, cmdlen); arg[0] = 0; } #endif break; case TRACE_DEV_REG_EXIT: // exit, exit current process with exit code if (trace_filename != NULL) { trace_exit(value); #ifdef DEBUG printf("QEMU.trace: kernel, exit %x\n", value); #endif } #ifdef CONFIG_MEMCHECK if (memcheck_enabled) { memcheck_exit(value); } #endif // CONFIG_MEMCHECK break; case TRACE_DEV_REG_NAME: // record thread name vstrcpy(value, path, CLIENT_PAGE_SIZE); // Remove the trailing newline if it exists int len = strlen(path); if (path[len - 1] == '\n') { path[len - 1] = 0; } if (trace_filename != NULL) { trace_name(path); #ifdef DEBUG printf("QEMU.trace: kernel, name %s\n", path); #endif } break; case TRACE_DEV_REG_MMAP_EXEPATH: // mmap, path of EXE, the others are same as execve vstrcpy(value, path, CLIENT_PAGE_SIZE); if (trace_filename != NULL) { trace_mmap(vstart, vend, eoff, path); #ifdef DEBUG printf("QEMU.trace: kernel, mmap [%lx,%lx]@%lx [%s]\n", vstart, vend, eoff, path); #endif } #ifdef CONFIG_MEMCHECK if (memcheck_enabled) { if (path[0] == '\0') { // vstrcpy may fail to copy path. In this case lets do it // differently. memcheck_get_guest_kernel_string(path, value, CLIENT_PAGE_SIZE); } memcheck_mmap_exepath(vstart, vend, eoff, path); } #endif // CONFIG_MEMCHECK path[0] = 0; break; case TRACE_DEV_REG_INIT_PID: // init, name the pid that starts before device registered pid = value; #ifdef CONFIG_MEMCHECK if (memcheck_enabled) { memcheck_init_pid(value); } #endif // CONFIG_MEMCHECK break; case TRACE_DEV_REG_INIT_NAME: // init, the comm of the init pid vstrcpy(value, path, CLIENT_PAGE_SIZE); if (trace_filename != NULL) { trace_init_name(tgid, pid, path); #ifdef DEBUG printf("QEMU.trace: kernel, init name %u [%s]\n", pid, path); #endif } path[0] = 0; break; case TRACE_DEV_REG_DYN_SYM_ADDR: // dynamic symbol address dsaddr = value; break; case TRACE_DEV_REG_DYN_SYM: // add dynamic symbol vstrcpy(value, arg, CLIENT_PAGE_SIZE); if (trace_filename != NULL) { trace_dynamic_symbol_add(dsaddr, arg); #ifdef DEBUG printf("QEMU.trace: dynamic symbol %lx:%s\n", dsaddr, arg); #endif } arg[0] = 0; break; case TRACE_DEV_REG_REMOVE_ADDR: // remove dynamic symbol addr if (trace_filename != NULL) { trace_dynamic_symbol_remove(value); #ifdef DEBUG printf("QEMU.trace: dynamic symbol remove %lx\n", dsaddr); #endif } break; case TRACE_DEV_REG_PRINT_STR: // print string vstrcpy(value, arg, CLIENT_PAGE_SIZE); printf("%s", arg); arg[0] = 0; break; case TRACE_DEV_REG_PRINT_NUM_DEC: // print number in decimal printf("%d", value); break; case TRACE_DEV_REG_PRINT_NUM_HEX: // print number in hexical printf("%x", value); break; case TRACE_DEV_REG_STOP_EMU: // stop the VM execution if (trace_filename != NULL) { // To ensure that the number of instructions executed in this // block is correct, we pretend that there was an exception. trace_exception(0); } cpu_single_env->exception_index = EXCP_HLT; cpu_single_env->halted = 1; qemu_system_shutdown_request(); cpu_loop_exit(); break; case TRACE_DEV_REG_ENABLE: // tracing enable: 0 = stop, 1 = start if (value == 1) { if (trace_filename != NULL) { start_tracing(); } } else if (value == 0) { if (trace_filename != NULL) { stop_tracing(); // To ensure that the number of instructions executed in this // block is correct, we pretend that there was an exception. trace_exception(0); } } break; case TRACE_DEV_REG_UNMAP_START: unmap_start = value; break; case TRACE_DEV_REG_UNMAP_END: if (trace_filename != NULL) { trace_munmap(unmap_start, value); } #ifdef CONFIG_MEMCHECK if (memcheck_enabled) { memcheck_unmap(unmap_start, value); } #endif // CONFIG_MEMCHECK break; case TRACE_DEV_REG_METHOD_ENTRY: case TRACE_DEV_REG_METHOD_EXIT: case TRACE_DEV_REG_METHOD_EXCEPTION: case TRACE_DEV_REG_NATIVE_ENTRY: case TRACE_DEV_REG_NATIVE_EXIT: case TRACE_DEV_REG_NATIVE_EXCEPTION: if (trace_filename != NULL) { if (tracing) { int call_type = (offset - 4096) >> 2; trace_interpreted_method(value, call_type); } } break; #ifdef CONFIG_MEMCHECK case TRACE_DEV_REG_MALLOC: if (memcheck_enabled) { memcheck_guest_alloc(value); } break; case TRACE_DEV_REG_FREE_PTR: if (memcheck_enabled) { memcheck_guest_free(value); } break; case TRACE_DEV_REG_QUERY_MALLOC: if (memcheck_enabled) { memcheck_guest_query_malloc(value); } break; case TRACE_DEV_REG_LIBC_INIT: if (memcheck_enabled) { memcheck_guest_libc_initialized(value); } break; case TRACE_DEV_REG_PRINT_USER_STR: if (memcheck_enabled) { memcheck_guest_print_str(value); } break; #endif // CONFIG_MEMCHECK default: if (offset < 4096) { cpu_abort(cpu_single_env, "trace_dev_write: Bad offset %x\n", offset); } break; } }