From 7877105ba84a0b21d8ff75095cbdf425ddaf7626 Mon Sep 17 00:00:00 2001 From: Ben-Dumas Date: Wed, 13 Oct 2021 17:14:25 -0400 Subject: [PATCH 01/18] collapse wintrospection libraries into one --- panda/dependencies/ubuntu:18.04_build.txt | 5 + panda/dependencies/ubuntu:20.04_build.txt | 5 + .../callstack_instr/callstack_instr.cpp | 2 - panda/plugins/config.panda | 3 - panda/plugins/file_taint/file_taint.cpp | 7 +- panda/plugins/win2000x86intro/Makefile | 9 - panda/plugins/win2000x86intro/README.md | 30 - .../win2000x86intro/win2000x86intro.cpp | 156 ---- .../win2000x86intro/win2000x86intro_int.h | 6 - .../win2000x86intro/win2000x86intro_int_fns.h | 8 - panda/plugins/win7x86intro/Makefile | 9 - panda/plugins/win7x86intro/README.md | 33 - panda/plugins/win7x86intro/win7x86intro.cpp | 165 ---- panda/plugins/win7x86intro/win7x86intro_int.h | 6 - .../win7x86intro/win7x86intro_int_fns.h | 8 - panda/plugins/wintrospection/Makefile | 13 +- panda/plugins/wintrospection/pandamemory.cpp | 85 ++ panda/plugins/wintrospection/pandamemory.h | 21 + panda/plugins/wintrospection/wintrospection.c | 877 ------------------ .../plugins/wintrospection/wintrospection.cpp | 583 ++++++++++++ panda/plugins/wintrospection/wintrospection.h | 35 - .../wintrospection/wintrospection_int.h | 13 +- .../wintrospection/wintrospection_int_fns.h | 101 +- panda/plugins/winxpx86intro/Makefile | 9 - panda/plugins/winxpx86intro/README.md | 30 - panda/plugins/winxpx86intro/winxpx86intro.cpp | 179 ---- .../plugins/winxpx86intro/winxpx86intro_int.h | 6 - .../winxpx86intro/winxpx86intro_int_fns.h | 8 - panda/scripts/install_ubuntu.sh | 16 + panda/src/common.c | 5 +- 30 files changed, 735 insertions(+), 1698 deletions(-) delete mode 100644 panda/plugins/win2000x86intro/Makefile delete mode 100644 panda/plugins/win2000x86intro/README.md delete mode 100644 panda/plugins/win2000x86intro/win2000x86intro.cpp delete mode 100644 panda/plugins/win2000x86intro/win2000x86intro_int.h delete mode 100644 panda/plugins/win2000x86intro/win2000x86intro_int_fns.h delete mode 100644 panda/plugins/win7x86intro/Makefile delete mode 100644 panda/plugins/win7x86intro/README.md delete mode 100644 panda/plugins/win7x86intro/win7x86intro.cpp delete mode 100644 panda/plugins/win7x86intro/win7x86intro_int.h delete mode 100644 panda/plugins/win7x86intro/win7x86intro_int_fns.h create mode 100644 panda/plugins/wintrospection/pandamemory.cpp create mode 100644 panda/plugins/wintrospection/pandamemory.h delete mode 100644 panda/plugins/wintrospection/wintrospection.c create mode 100644 panda/plugins/wintrospection/wintrospection.cpp delete mode 100644 panda/plugins/wintrospection/wintrospection.h delete mode 100644 panda/plugins/winxpx86intro/Makefile delete mode 100644 panda/plugins/winxpx86intro/README.md delete mode 100644 panda/plugins/winxpx86intro/winxpx86intro.cpp delete mode 100644 panda/plugins/winxpx86intro/winxpx86intro_int.h delete mode 100644 panda/plugins/winxpx86intro/winxpx86intro_int_fns.h diff --git a/panda/dependencies/ubuntu:18.04_build.txt b/panda/dependencies/ubuntu:18.04_build.txt index b284ce0b4cc..b0695e00e85 100644 --- a/panda/dependencies/ubuntu:18.04_build.txt +++ b/panda/dependencies/ubuntu:18.04_build.txt @@ -71,3 +71,8 @@ texinfo uuid-dev xfslibs-dev zlib1g-dev + +# libosi install deps +cmake +ninja-build +rapidjson-dev diff --git a/panda/dependencies/ubuntu:20.04_build.txt b/panda/dependencies/ubuntu:20.04_build.txt index e9588bdab3f..7662ce454b5 100644 --- a/panda/dependencies/ubuntu:20.04_build.txt +++ b/panda/dependencies/ubuntu:20.04_build.txt @@ -83,3 +83,8 @@ libc6.1-dev-alpha-cross # rust install deps curl + +# libosi install deps +cmake +ninja-build +rapidjson-dev diff --git a/panda/plugins/callstack_instr/callstack_instr.cpp b/panda/plugins/callstack_instr/callstack_instr.cpp index 1b61b968d2c..32574a0aa6c 100644 --- a/panda/plugins/callstack_instr/callstack_instr.cpp +++ b/panda/plugins/callstack_instr/callstack_instr.cpp @@ -47,8 +47,6 @@ PANDAENDCOMMENT */ // needed for the threaded stack_type #include "osi/osi_types.h" #include "osi/osi_ext.h" -#include "wintrospection/wintrospection.h" -#include "wintrospection/wintrospection_ext.h" #include "osi_linux/osi_linux_ext.h" #include "callstack_instr.h" diff --git a/panda/plugins/config.panda b/panda/plugins/config.panda index 72db6034cd5..d3ec7d5d669 100644 --- a/panda/plugins/config.panda +++ b/panda/plugins/config.panda @@ -46,7 +46,4 @@ textprinter trace track_intexc unigrams -win2000x86intro -win7x86intro wintrospection -winxpx86intro diff --git a/panda/plugins/file_taint/file_taint.cpp b/panda/plugins/file_taint/file_taint.cpp index 61ecdbf1c1f..a418cb9015f 100644 --- a/panda/plugins/file_taint/file_taint.cpp +++ b/panda/plugins/file_taint/file_taint.cpp @@ -22,7 +22,6 @@ PANDAENDCOMMENT */ #include "osi/osi_types.h" #include "osi/osi_ext.h" -#include "wintrospection/wintrospection.h" #include "wintrospection/wintrospection_ext.h" #include "osi_linux/osi_linux_ext.h" @@ -207,11 +206,11 @@ void windows_read_enter(CPUState *cpu, target_ulong pc, uint32_t FileHandle, uint32_t ByteOffset, uint32_t Key) { // get_handle_name will assert if the filename is null - char *filename = get_handle_name(cpu, get_current_proc(cpu), FileHandle); + char *filename = get_handle_name(FileHandle); std::string ob_path = filename; // Check if the file handle is absolute, if not we need to make it absolute. if (filename[0] != '\\') { - char *cwd = get_cwd(cpu); + char *cwd = get_cwd(); ob_path = cwd; // If the cwd doesn't have a slash, add it. if (ob_path.back() != '\\') { @@ -221,7 +220,7 @@ void windows_read_enter(CPUState *cpu, target_ulong pc, uint32_t FileHandle, g_free(cwd); } verbose_printf("file_taint windows object path: %s\n", ob_path.c_str()); - int64_t pos = get_file_handle_pos(cpu, get_current_proc(cpu), FileHandle); + int64_t pos = get_file_handle_pos(FileHandle); read_enter(ob_path, FileHandle, pos); g_free(filename); } diff --git a/panda/plugins/win2000x86intro/Makefile b/panda/plugins/win2000x86intro/Makefile deleted file mode 100644 index f3982d849ad..00000000000 --- a/panda/plugins/win2000x86intro/Makefile +++ /dev/null @@ -1,9 +0,0 @@ -# Don't forget to add your plugin to config.panda! - -# If you need custom CFLAGS or LIBS, set them up here -# CFLAGS+= -# LIBS+= - -# The main rule for your plugin. List all object-file dependencies. -$(PLUGIN_TARGET_DIR)/panda_$(PLUGIN_NAME).so: \ - $(PLUGIN_OBJ_DIR)/$(PLUGIN_NAME).o diff --git a/panda/plugins/win2000x86intro/README.md b/panda/plugins/win2000x86intro/README.md deleted file mode 100644 index 842757402c6..00000000000 --- a/panda/plugins/win2000x86intro/README.md +++ /dev/null @@ -1,30 +0,0 @@ -Plugin: win2000x86intro -=========== - -Summary -------- - -`win2000x86intro` is an introspection provider for Windows 2000 guests, supplying information for the OSI API. Not much more to say about it; it should Just Work as long as the guest OS is Windows 2000. - -Arguments ---------- - -None. - -Dependencies ------------- - -`win2000x86intro` is an introspection provider for the `osi` plugin. - -APIs and Callbacks ------------------- - -None. - -Example -------- - -Running `osi_test` on an Windows 2000 32-bit replay: - - $PANDA_PATH/x86_64-softmmu/panda-system-x86_64 -replay foo \ - -panda osi -panda win2000x86intro -panda osi_test diff --git a/panda/plugins/win2000x86intro/win2000x86intro.cpp b/panda/plugins/win2000x86intro/win2000x86intro.cpp deleted file mode 100644 index 83631804555..00000000000 --- a/panda/plugins/win2000x86intro/win2000x86intro.cpp +++ /dev/null @@ -1,156 +0,0 @@ -/* PANDABEGINCOMMENT - * - * Authors: - * Tim Leek tleek@ll.mit.edu - * Ryan Whelan rwhelan@ll.mit.edu - * Joshua Hodosh josh.hodosh@ll.mit.edu - * Michael Zhivich mzhivich@ll.mit.edu - * Brendan Dolan-Gavitt brendandg@gatech.edu - * - * This work is licensed under the terms of the GNU GPL, version 2. - * See the COPYING file in the top-level directory. - * -PANDAENDCOMMENT */ -#define __STDC_FORMAT_MACROS - -#include -#include "panda/plugin.h" -#include "panda/plugin_plugin.h" - -extern "C" { - -#include "osi/osi_types.h" -#include "osi/os_intro.h" - -#include "qemu/rcu.h" -#include "qemu/rcu_queue.h" - -#include "exec/address-spaces.h" - -#include "wintrospection/wintrospection.h" -#include "wintrospection/wintrospection_ext.h" - -bool init_plugin(void *); -void uninit_plugin(void *); -void on_get_mappings(CPUState *cpu, OsiProc *p, GArray **out); -PTR get_win2000_kpcr(CPUState *cpu); -HandleObject *get_win2000_handle_object(CPUState *cpu, uint32_t eproc, uint32_t handle); -PTR get_win2000_kddebugger_data(CPUState *cpu); -} - -#include -#include - -#ifdef TARGET_I386 - -#define HANDLE_TABLE_L1_OFF 0x008 // _HANDLE_TABLE.Layer1 -#define KDDEBUGGER_DATA_SIZE 0x208 - -#define HANDLE_LOCK_FLAG 0x80000000 - -// Windows 2000 has a fixed location for the KPCR -PTR get_win2000_kpcr(CPUState *cpu) { - return 0xFFDFF000; -} - -// i.e. return pointer to the object represented by this handle -static uint32_t get_handle_table_entry(CPUState *cpu, uint32_t pHandleTable, uint32_t handle) { - uint32_t L1_index = (handle & HANDLE_MASK3) >> HANDLE_SHIFT3; - uint32_t L1_table_off = handle_table_L1_addr(cpu, pHandleTable, L1_index); - uint32_t L1_table; - if(panda_virtual_memory_rw(cpu, L1_table_off, (uint8_t *) &L1_table, 4, false) == -1) return 0; - - uint32_t L2_index = (handle & HANDLE_MASK2) >> HANDLE_SHIFT2; - uint32_t L2_table_off = handle_table_L2_addr(L1_table, L2_index); - uint32_t L2_table; - if(panda_virtual_memory_rw(cpu, L2_table_off, (uint8_t *) &L2_table, 4, false) == -1) return 0; - - uint32_t index = (handle & HANDLE_MASK1) >> HANDLE_SHIFT1; - uint32_t pEntry = handle_table_L3_entry(pHandleTable, L2_table, index); - uint32_t pObjectHeader; - if ((panda_virtual_memory_rw(cpu, pEntry, (uint8_t *) &pObjectHeader, 4, false)) == -1) return 0; - - // In Windows 2000 (and supposedly Windows NT 4), the three low-order and - // highest-order bit are flags. - // - // The remaining bits make up the pointer - sometimes. The lock flag must be - // set get a valid pointer to the object since these are kernel objects and - // they will always live in memory that is greater than 0x80000000. So to - // get the pointer you have to set the high bit if it is not already locked - // and mask off the lower three bits. - // - // Ref: Inside Microsoft Windows 2000, Third Edition, David A. Solomon, Mark - // E. Russinovich. - pObjectHeader |= HANDLE_LOCK_FLAG; - pObjectHeader &= TABLE_MASK; - - return pObjectHeader; -} - - -HandleObject *get_win2000_handle_object(CPUState *cpu, uint32_t eproc, uint32_t handle) { - uint32_t pObjectTable; - uint32_t handleTable; - if (-1 == panda_virtual_memory_rw(cpu, eproc+get_eproc_objtable_off(), (uint8_t *)&pObjectTable, 4, false)) { - return NULL; - } - if (-1 == panda_virtual_memory_read(cpu, pObjectTable + HANDLE_TABLE_L1_OFF, - (uint8_t *)&handleTable, - sizeof(handleTable))) { - return NULL; - } - uint32_t pObjHeader = get_handle_table_entry(cpu, handleTable, handle); - if (pObjHeader == 0) return NULL; - uint32_t pObj = pObjHeader + OBJECT_HEADER_BODY_OFFSET; - uint8_t objType = 0; - if (-1 == panda_virtual_memory_rw(cpu, pObjHeader+get_obj_type_offset(), (uint8_t *)&objType, 1, false)) { - return NULL; - } - HandleObject *ho = (HandleObject *)g_malloc(sizeof(HandleObject)); - ho->objType = objType; - ho->pObj = pObj; - return ho; -} - -// Returns the physical address of KDDEBUGGER_DATA64. -PTR get_win2000_kddebugger_data(CPUState *cpu) -{ - static PTR cached_kdbg = -1; - if (cached_kdbg != -1) { - return cached_kdbg; - } - - MemoryRegion *mr = memory_region_find(get_system_memory(), 0x2000000, 1).mr; - rcu_read_lock(); - uint8_t *host_ptr = (uint8_t *)qemu_map_ram_ptr(mr->ram_block, 0); - uint8_t signature[] = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 'K', 'D', 'B', 'G'}; - - for (int i = 0; i < int128_get64(mr->size) - KDDEBUGGER_DATA_SIZE; i++) { - if (0 == memcmp(signature, host_ptr + i, sizeof(signature))) { - // We subtract eight bytes from the current position because of the - // list entry field size. This gives us the start of the - // KDDEBUGGER_DATA structure. - cached_kdbg = i - 8; - break; - } - } - rcu_read_unlock(); - - return cached_kdbg; -} - -#endif - -bool init_plugin(void *self) { -#if defined(TARGET_I386) && !defined(TARGET_X86_64) - assert(init_wintrospection_api()); - return true; -#else - return false; -#endif - -} - -void uninit_plugin(void *self) { -} diff --git a/panda/plugins/win2000x86intro/win2000x86intro_int.h b/panda/plugins/win2000x86intro/win2000x86intro_int.h deleted file mode 100644 index 96600663733..00000000000 --- a/panda/plugins/win2000x86intro/win2000x86intro_int.h +++ /dev/null @@ -1,6 +0,0 @@ -typedef void PTR; -typedef void CPUState; -typedef void HandleObject; -typedef void uint32_t; - -#include "win2000x86intro_int_fns.h" diff --git a/panda/plugins/win2000x86intro/win2000x86intro_int_fns.h b/panda/plugins/win2000x86intro/win2000x86intro_int_fns.h deleted file mode 100644 index a710934b727..00000000000 --- a/panda/plugins/win2000x86intro/win2000x86intro_int_fns.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef __WIN2000X86INTRO_INT_FNS_H__ -#define __WIN2000X86INTRO_INT_FNS_H__ - -PTR get_win2000_kpcr(CPUState *cpu); -HandleObject *get_win2000_handle_object(CPUState *cpu, uint32_t eproc, uint32_t handle); -PTR get_win2000_kddebugger_data(CPUState *cpu); - -#endif diff --git a/panda/plugins/win7x86intro/Makefile b/panda/plugins/win7x86intro/Makefile deleted file mode 100644 index f3982d849ad..00000000000 --- a/panda/plugins/win7x86intro/Makefile +++ /dev/null @@ -1,9 +0,0 @@ -# Don't forget to add your plugin to config.panda! - -# If you need custom CFLAGS or LIBS, set them up here -# CFLAGS+= -# LIBS+= - -# The main rule for your plugin. List all object-file dependencies. -$(PLUGIN_TARGET_DIR)/panda_$(PLUGIN_NAME).so: \ - $(PLUGIN_OBJ_DIR)/$(PLUGIN_NAME).o diff --git a/panda/plugins/win7x86intro/README.md b/panda/plugins/win7x86intro/README.md deleted file mode 100644 index a8790aa5c25..00000000000 --- a/panda/plugins/win7x86intro/README.md +++ /dev/null @@ -1,33 +0,0 @@ -Plugin: win7x86intro -=========== - -Summary -------- - -`win7x86intro` is an introspection provider for Windows 7 guests, supplying information for the OSI API. Not much more to say about it; it should Just Work as long as the guest OS is Windows 7 32-bit. - -Arguments ---------- - -None. - -Dependencies ------------- - -`win7x86intro` is an introspection provider for the `osi` plugin. - -APIs and Callbacks ------------------- - -None. - -Example -------- - -Running `osi_test` on an Windows 7 32-bit replay: - - $PANDA_PATH/x86_64-softmmu/panda-system-x86_64 -replay foo \ - -panda osi -panda win7x86intro -panda osi_test - -Bugs ----- diff --git a/panda/plugins/win7x86intro/win7x86intro.cpp b/panda/plugins/win7x86intro/win7x86intro.cpp deleted file mode 100644 index d68d947abc7..00000000000 --- a/panda/plugins/win7x86intro/win7x86intro.cpp +++ /dev/null @@ -1,165 +0,0 @@ -/* PANDABEGINCOMMENT - * - * Authors: - * Tim Leek tleek@ll.mit.edu - * Ryan Whelan rwhelan@ll.mit.edu - * Joshua Hodosh josh.hodosh@ll.mit.edu - * Michael Zhivich mzhivich@ll.mit.edu - * Brendan Dolan-Gavitt brendandg@gatech.edu - * - * This work is licensed under the terms of the GNU GPL, version 2. - * See the COPYING file in the top-level directory. - * -PANDAENDCOMMENT */ -#define __STDC_FORMAT_MACROS - -#include "panda/plugin.h" -#include "panda/plugin_plugin.h" - -extern "C" { - -#include "osi/osi_types.h" -#include "osi/os_intro.h" - -#include "wintrospection/wintrospection.h" -#include "wintrospection/wintrospection_ext.h" - -bool init_plugin(void *); -void uninit_plugin(void *); -void on_get_mappings(CPUState *, OsiProc *p, GArray **out); -PTR get_win7_kpcr(CPUState *cpu); -HandleObject *get_win7_handle_object(CPUState *cpu, uint32_t eproc, uint32_t handle); -PTR get_win7_kdbg(CPUState *cpu); -} - -#include -#include - -#ifdef TARGET_I386 - -#define KMODE_FS 0x030 // Segment number of FS in kernel mode -#define KPCR_KDVERSION_OFF 0x034 // _KPCR.KdVersionBlock -#define KDVERSION_DDL_OFF 0x020 // _DBGKD_GET_VERSION64.DebuggerDataList - -// XXX: this will have to change for 64-bit -PTR get_win7_kpcr(CPUState *cpu) { - // Read the kernel-mode FS segment base - uint32_t e1, e2; - PTR fs_base; - - CPUArchState *env = (CPUArchState *)cpu->env_ptr; - // Read out the two 32-bit ints that make up a segment descriptor - panda_virtual_memory_rw(cpu, env->gdt.base + KMODE_FS, (uint8_t *)&e1, sizeof(PTR), false); - panda_virtual_memory_rw(cpu, env->gdt.base + KMODE_FS + 4, (uint8_t *)&e2, sizeof(PTR), false); - - // Turn wacky segment into base - fs_base = (e1 >> 16) | ((e2 & 0xff) << 16) | (e2 & 0xff000000); - - return fs_base; -} - -// i.e. return pointer to the object represented by this handle -static uint32_t get_handle_table_entry(CPUState *cpu, uint32_t pHandleTable, uint32_t handle) { - uint32_t tableCode, tableLevels; - // get tablecode - panda_virtual_memory_rw(cpu, pHandleTable, (uint8_t *)&tableCode, 4, false); - // extract levels - tableLevels = tableCode & LEVEL_MASK; - if (tableLevels > 2) { - return 0; - } - uint32_t pEntry=0; - if (tableLevels == 0) { - uint32_t index = (handle & HANDLE_MASK1) >> HANDLE_SHIFT1; - pEntry = handle_table_L1_entry(cpu, pHandleTable, index); - } - if (tableLevels == 1) { - uint32_t L1_index = (handle & HANDLE_MASK2) >> HANDLE_SHIFT2; - uint32_t L1_table_off = handle_table_L1_addr(cpu, pHandleTable, L1_index); - uint32_t L1_table; - panda_virtual_memory_rw(cpu, L1_table_off, (uint8_t *) &L1_table, 4, false); - uint32_t index = (handle & HANDLE_MASK1) >> HANDLE_SHIFT1; - pEntry = handle_table_L2_entry(pHandleTable, L1_table, index); - } - if (tableLevels == 2) { - uint32_t L1_index = (handle & HANDLE_MASK3) >> HANDLE_SHIFT3; - uint32_t L1_table_off = handle_table_L1_addr(cpu, pHandleTable, L1_index); - uint32_t L1_table; - panda_virtual_memory_rw(cpu, L1_table_off, (uint8_t *) &L1_table, 4, false); - uint32_t L2_index = (handle & HANDLE_MASK2) >> HANDLE_SHIFT2; - uint32_t L2_table_off = handle_table_L2_addr(L1_table, L2_index); - uint32_t L2_table; - panda_virtual_memory_rw(cpu, L2_table_off, (uint8_t *) &L2_table, 4, false); - uint32_t index = (handle & HANDLE_MASK1) >> HANDLE_SHIFT1; - pEntry = handle_table_L3_entry(pHandleTable, L2_table, index); - } - uint32_t pObjectHeader; - if ((panda_virtual_memory_rw(cpu, pEntry, (uint8_t *) &pObjectHeader, 4, false)) == -1) { - return 0; - } - - // Like in Windows 2000, the entry here needs to be masked off. However, it - // appears that starting in Windows XP, they've done away with the lock - // flag. The lower three bits mask should be consistent across Windows - // versions because of the object alignment. - // - // No obvious reference. - pObjectHeader &= TABLE_MASK; - - return pObjectHeader; -} - - -HandleObject *get_win7_handle_object(CPUState *cpu, uint32_t eproc, uint32_t handle) { - uint32_t pObjectTable; - if (-1 == panda_virtual_memory_rw(cpu, eproc+get_eproc_objtable_off(), (uint8_t *)&pObjectTable, 4, false)) { - return NULL; - } - uint32_t pObjHeader = get_handle_table_entry(cpu, pObjectTable, handle); - if (pObjHeader == 0) return NULL; - uint32_t pObj = pObjHeader + OBJECT_HEADER_BODY_OFFSET; - uint8_t objType = 0; - if (-1 == panda_virtual_memory_rw(cpu, pObjHeader+get_obj_type_offset(), &objType, 1, false)) { - return NULL; - } - HandleObject *ho = (HandleObject *) malloc(sizeof(HandleObject)); - ho->objType = objType; - ho->pObj = pObj; - return ho; -} - -PTR get_win7_kdbg(CPUState *cpu) -{ - PTR kpcr = get_win7_kpcr(cpu); - PTR kdversion, kddl, kddlp; - if (-1 == panda_virtual_memory_rw(cpu, kpcr + KPCR_KDVERSION_OFF, - (uint8_t *)&kdversion, sizeof(PTR), - false)) { - return 0; - } - // DebuggerDataList is a pointer to a pointer to the _KDDEBUGGER_DATA64 - // So we need to dereference it twice. - if (-1 == panda_virtual_memory_rw(cpu, kdversion + KDVERSION_DDL_OFF, - (uint8_t *)&kddlp, sizeof(PTR), false)) { - return 0; - } - if (-1 == panda_virtual_memory_rw(cpu, kddlp, (uint8_t *)&kddl, sizeof(PTR), - false)) { - return 0; - } - return panda_virt_to_phys(cpu, kddl); -} - -#endif - -bool init_plugin(void *self) { -#ifdef TARGET_I386 - init_wintrospection_api(); - return true; -#else - return false; -#endif - -} - -void uninit_plugin(void *self) { } diff --git a/panda/plugins/win7x86intro/win7x86intro_int.h b/panda/plugins/win7x86intro/win7x86intro_int.h deleted file mode 100644 index dc42d09f2fb..00000000000 --- a/panda/plugins/win7x86intro/win7x86intro_int.h +++ /dev/null @@ -1,6 +0,0 @@ -typedef void PTR; -typedef void CPUState; -typedef void HandleObject; -typedef void uint32_t; - -#include "win7x86intro_int_fns.h" diff --git a/panda/plugins/win7x86intro/win7x86intro_int_fns.h b/panda/plugins/win7x86intro/win7x86intro_int_fns.h deleted file mode 100644 index b7d7686e3ed..00000000000 --- a/panda/plugins/win7x86intro/win7x86intro_int_fns.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef __WIN7X86INTRO_INT_FNS_H__ -#define __WIN7X86INTRO_INT_FNS_H__ - -PTR get_win7_kpcr(CPUState *cpu); -HandleObject *get_win7_handle_object(CPUState *cpu, uint32_t eproc, uint32_t handle); -PTR get_win7_kdbg(CPUState *cpu); - -#endif diff --git a/panda/plugins/wintrospection/Makefile b/panda/plugins/wintrospection/Makefile index f3982d849ad..adea5382e7c 100644 --- a/panda/plugins/wintrospection/Makefile +++ b/panda/plugins/wintrospection/Makefile @@ -2,8 +2,17 @@ # If you need custom CFLAGS or LIBS, set them up here # CFLAGS+= -# LIBS+= +LIBS += -losi -liohal -loffset + +# Example: this plugin has runtime symbol dependencies on plugin_x: +# LIBS+=-L$(PLUGIN_TARGET_DIR) -l:panda_plugin_x.so +# Also create a plugin_plugin.d file in this directory to ensure plugin_x +# gets compiled before this plugin, example contents: +# plugin-this_plugins_name : plugin-plugin_x +# or if you're using the extra plugins dir: +# extra-plugin-this_plugins_name : extra-plugin-plugin_x # The main rule for your plugin. List all object-file dependencies. $(PLUGIN_TARGET_DIR)/panda_$(PLUGIN_NAME).so: \ - $(PLUGIN_OBJ_DIR)/$(PLUGIN_NAME).o + $(PLUGIN_OBJ_DIR)/$(PLUGIN_NAME).o \ + $(PLUGIN_OBJ_DIR)/pandamemory.o diff --git a/panda/plugins/wintrospection/pandamemory.cpp b/panda/plugins/wintrospection/pandamemory.cpp new file mode 100644 index 00000000000..c82bbca42b1 --- /dev/null +++ b/panda/plugins/wintrospection/pandamemory.cpp @@ -0,0 +1,85 @@ +#include "panda/plugin.h" +#include "panda/common.h" + +#include +#include + +#include +#include + +#include "pandamemory.h" + +class PandaPhysicalMemory { +private: + pm_addr_t m_max_address; + +public: + static const uint32_t PAPM_TAG = 0x5041504d; + + PandaPhysicalMemory() { m_max_address = ram_size; } + + pm_addr_t get_max_address() { return m_max_address; } + + uint8_t get_byte(pm_addr_t addr) { + uint8_t retval = 0; + if (addr < m_max_address) { + panda_physical_memory_rw(addr, &retval, 1, 0); + } + return retval; + } +}; + +pm_addr_t get_panda_physical_memory_upper_bound(struct PhysicalMemory *pmem) { + auto papm = (PandaPhysicalMemory *)pmem->opaque; + return papm->get_max_address(); +} + +bool read_panda_physical_memory(struct PhysicalMemory *pmem, pm_addr_t addr, + uint8_t *buffer, uint64_t size) { + auto papm = (PandaPhysicalMemory *)pmem->opaque; + auto max_addr = papm->get_max_address(); + + for (size_t ix = 0; ix < size; ++ix) { + auto current_addr = addr + ix; + if ((uintptr_t)current_addr > max_addr) { + return false; + } + buffer[ix] = papm->get_byte(current_addr); + } + return true; +} + +void free_panda_physical_memory(struct PhysicalMemory *pmem) { + auto papm = (PandaPhysicalMemory *)pmem->opaque; + delete papm; + // Memset here for a few reasons: + // - Ensure use-after-free bugs fail early (i.e. on a null pointer deref + // rather + // than on stale data) + // - The caller will still have an invalid pointer to pmem, so mistakes are + // more + // likely + std::memset(pmem, 0, sizeof(PhysicalMemory)); + std::free(pmem); +} + +struct PhysicalMemory *create_panda_physical_memory() { + // Allocate the backing physical memory object + PandaPhysicalMemory *papm = new PandaPhysicalMemory(); + + // Allocate the wrapper object + auto pmem = + (struct PhysicalMemory *)std::calloc(1, sizeof(struct PhysicalMemory)); + if (!pmem) { + delete papm; + return nullptr; + } + + pmem->tagvalue = PandaPhysicalMemory::PAPM_TAG; + pmem->opaque = papm; + pmem->upper_bound = get_panda_physical_memory_upper_bound; + pmem->read = read_panda_physical_memory; + pmem->free = free_panda_physical_memory; + + return pmem; +} diff --git a/panda/plugins/wintrospection/pandamemory.h b/panda/plugins/wintrospection/pandamemory.h new file mode 100644 index 00000000000..071113ae3bd --- /dev/null +++ b/panda/plugins/wintrospection/pandamemory.h @@ -0,0 +1,21 @@ +#ifndef __PANDA_PHYSICAL_MEMORY_H +#define __PANDA_PHYSICAL_MEMORY_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Use PANDA as a physical memory reader for the HAL + * + * \return struct PhysicalMemory* + */ +struct PhysicalMemory* create_panda_physical_memory(); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/panda/plugins/wintrospection/wintrospection.c b/panda/plugins/wintrospection/wintrospection.c deleted file mode 100644 index 5c2f516c891..00000000000 --- a/panda/plugins/wintrospection/wintrospection.c +++ /dev/null @@ -1,877 +0,0 @@ -/* PANDABEGINCOMMENT - * - * Authors: - * Tim Leek tleek@ll.mit.edu - * Ryan Whelan rwhelan@ll.mit.edu - * Joshua Hodosh josh.hodosh@ll.mit.edu - * Michael Zhivich mzhivich@ll.mit.edu - * Brendan Dolan-Gavitt brendandg@gatech.edu - * Tom Boning tboning@mit.edu - * - * This work is licensed under the terms of the GNU GPL, version 2. - * See the COPYING file in the top-level directory. - * -PANDAENDCOMMENT */ -#define __STDC_FORMAT_MACROS - -#include -#include -#include -#include - -#include - -#include "panda/rr/rr_log.h" -#include "panda/tcg-utils.h" - -#include "osi/osi_types.h" -#include "osi/os_intro.h" -#include "osi/osi_ext.h" - -#include "panda/plugin.h" -#include "panda/plugin_plugin.h" -#include "panda/plog.h" - -#include "syscalls2/syscalls_ext_typedefs.h" - -#include "wintrospection.h" -#include "wintrospection_int_fns.h" - -#include "win2000x86intro/win2000x86intro_ext.h" -#include "win7x86intro/win7x86intro_ext.h" -#include "winxpx86intro/winxpx86intro_ext.h" - -#include "glib.h" - -bool init_plugin(void *); -void uninit_plugin(void *); - -// this stuff only makes sense for win x86 32-bit -#ifdef TARGET_I386 - -// Constants that are the same in all supported versions of windows -// Supports: Windows 2000 SP4, XP SP3, and Windows 7 SP1. -#define KPCR_CURTHREAD_OFF 0x124 // _KPCR.PrcbData.CurrentThread -#define EPROC_DTB_OFF 0x018 // _EPROCESS.Pcb.DirectoryTableBase -#define EPROC_TYPE_OFF 0x000 // _EPROCESS.Pcb.Header.Type -#define EPROC_SIZE_OFF 0x002 // _EPROCESS.Pcb.Header.Size -#define EPROC_TYPE 0x003 // Value of Type -#define EPROC_DTB_OFF 0x018 // _EPROCESS.Pcb.DirectoryTableBase -#define PEB_PEB_LDR_DATA_OFF 0x00c // _PEB.Ldr -#define PEB_LDR_DATA_LOAD_LIST_OFF 0x00c // _PEB_LDR_DATA.InLoadOrderModuleList -#define LDR_LOAD_LINKS_OFF 0x000 // _LDR_DATA_TABLE_ENTRY.InLoadOrderLinks -#define LDR_BASE_OFF 0x018 // _LDR_DATA_TABLE_ENTRY.DllBase -#define LDR_SIZE_OFF 0x020 // _LDR_DATA_TABLE_ENTRY.SizeOfImage -#define LDR_BASENAME_OFF 0x02c // _LDR_DATA_TABLE_ENTRY.BaseDllName -#define LDR_FILENAME_OFF 0x024 // _LDR_DATA_TABLE_ENTRY.FullDllName -#define OBJNAME_OFF 0x008 -#define FILE_OBJECT_NAME_OFF 0x030 -#define FILE_OBJECT_POS_OFF 0x038 -#define PROCESS_PARAMETERS_OFF 0x010 // PEB.ProcessParameters -#define UNICODE_WORKDIR_OFF 0x24 // ProcessParameters.WorkingDirectory -// KDDEBUGGER_DATA64.PsActiveProcessHead -#define KDDBG64_LOADED_MOD_HEAD_OFF 0x048 -// KDDEBUGGER_DATA64.PsLoadedModuleList -#define KDDBG64_ACTIVE_PROCESS_HEAD_OFF 0x50 -// _CLIENT_ID.UniqueThread -#define CLIENT_ID_UNIQUE_THREAD 0x4 - -// "Constants" specific to the guest operating system. -// These are initialized in the init_plugin function. -static uint32_t task_change_hook_addr; // Address within nt!SwapContext call - // that is after control registers have - // been updated. -static uint32_t task_change_hook_offset; // Offset within ntoskrnl.exe that - // is used to compute an address in - // nt!SwapContext after the control - // registers have been updated. -static uint32_t kthread_kproc_off; // _KTHREAD.Process -static uint32_t kthread_cid_off; // _ETHREAD._KTHREAD.Cid -static uint32_t eproc_pid_off; // _EPROCESS.UniqueProcessId -static uint32_t eproc_ppid_off; // _EPROCESS.InheritedFromUniqueProcessId -static uint32_t eproc_name_off; // _EPROCESS.ImageFileName -static uint32_t eproc_objtable_off; // _EPROCESS.ObjectTable -static uint32_t - eproc_ppeb_off; // _EPROCESS.Peb (pointer to process environment block) -static uint32_t eproc_size; // Value of Size -static uint32_t eproc_links_off; // _EPROCESS.ActiveProcessLinks -static uint32_t obj_type_file; // FILE object type -static uint32_t obj_type_key; // KEY object type -static uint32_t obj_type_process; // PROCESS object type -static uint32_t obj_type_offset; // XXX_OBJECT.Type (offset from start of OBJECT_TYPE_HEADER) -static uint32_t ntreadfile_esp_off; // Number of bytes left on stack when NtReadFile returns - -// Function pointer, returns location of KPCR structure. OS-specific. -static PTR(*get_kpcr)(CPUState *cpu); - -// Function pointer, returns handle table entry. OS-specific. -static HandleObject *(*get_handle_object)(CPUState *cpu, PTR eproc, uint32_t handle); - -// Function pointer, returns location of KDDEBUGGER_DATA<32|64> data structure. -// OS-specific. -static PTR (*get_kddebugger_data)(CPUState *cpu); - -char *make_pagedstr(void) { - char *m = g_strdup("(paged)"); - assert(m); - return m; -} - -// Gets a unicode string. Does its own mem allocation. -// Output is a null-terminated UTF8 string -char *get_unicode_str(CPUState *cpu, PTR ustr) { - uint16_t size = 0; - PTR str_ptr = 0; - if (-1 == panda_virtual_memory_rw(cpu, ustr, (uint8_t *)&size, 2, false)) { - return make_pagedstr(); - } - - // Unicode Strings can be zero length. In this case, just return an empty - // string. - if (size == 0) { - return g_strdup(""); - } - - // Clamp size - if (size > 1024) size = 1024; - if (-1 == panda_virtual_memory_rw(cpu, ustr+4, (uint8_t *)&str_ptr, 4, false)) { - return make_pagedstr(); - } - - gchar *in_str = (gchar *)g_malloc0(size); - if (-1 == panda_virtual_memory_rw(cpu, str_ptr, (uint8_t *)in_str, size, false)) { - g_free(in_str); - return make_pagedstr(); - } - - gsize bytes_written = 0; - gchar *out_str = g_convert(in_str, size, - "UTF-8", "UTF-16LE", NULL, &bytes_written, NULL); - - // An abundance of caution: we copy it over to something allocated - // with our own malloc. In the future we need to provide a way for - // someone else to free the memory allocated in here... - char *ret = (char *)g_malloc(bytes_written+1); - memcpy(ret, out_str, bytes_written+1); - g_free(in_str); - g_free(out_str); - return ret; -} - -void add_mod(CPUState *cpu, GArray *ms, PTR mod, bool ignore_basename) { - OsiModule m; - memset(&m, 0, sizeof(OsiModule)); - fill_osimod(cpu, &m, mod, ignore_basename); - g_array_append_val(ms, m); -} - -void on_get_current_process(CPUState *cpu, OsiProc **out) { - PTR eproc = get_current_proc(cpu); - if(eproc) { - OsiProc *p = (OsiProc *)g_malloc(sizeof(OsiProc)); - fill_osiproc(cpu, p, eproc); - *out = p; - } else { - *out = NULL; - } -} - -void on_get_current_process_handle(CPUState *cpu, OsiProcHandle **out) { - PTR eproc = get_current_proc(cpu); - if(eproc) { - OsiProcHandle *h = (OsiProcHandle *)g_malloc(sizeof(OsiProcHandle)); - fill_osiprochandle(cpu, h, eproc); - *out = h; - } else { - *out = NULL; - } -} - -void on_get_mappings(CPUState *cpu, OsiProc *p, GArray **out) -{ - *out = NULL; - if (p == NULL) { - return; - } - - PTR eproc = p->taskd; - PTR ptr_peb; - // EPROCESS is allocated from the non-paged pool, so it should - // accessible at any time via its virtual address. - if (-1 == panda_virtual_memory_read(cpu, eproc + eproc_ppeb_off, - (uint8_t *)&ptr_peb, sizeof(ptr_peb))) { - fprintf(stderr, "Could not read PEB Pointer from _EPROCESS!\n"); - return; - } - - // Since we are getting the libraries for a specified process, we have to - // make sure that we are looking in the address space of the process that - // was passed in. We will temporarily override CR3 with the value specified - // in _EPROCESS.Pcb.DirectoryTableBase. Again, since EPROCESS is allocated - // from the non-paged pool this shouldn't fail. - uint32_t dtb = -1; - if (panda_virtual_memory_read(cpu, eproc + EPROC_DTB_OFF, (uint8_t *)&dtb, - sizeof(dtb))) { - fprintf(stderr, "Could not read DirectoryTableBase from _EPROCESS!\n"); - return; - } -#ifdef TARGET_I386 - CPUArchState *env = (CPUArchState *)cpu->env_ptr; - target_ulong cur_cr3 = env->cr[3]; - env->cr[3] = dtb; -#endif - - // Get the location of the _PEB_LDR_DATA structure which contains the head - // of the DLL listing. - PTR ptr_peb_ldr_data; - if (-1 == panda_virtual_memory_read(cpu, ptr_peb + PEB_PEB_LDR_DATA_OFF, - (uint8_t *)&ptr_peb_ldr_data, - sizeof(ptr_peb_ldr_data))) { - // We fail silently here - _PEB is part of the paged pool, so its - // possible that this is paged out and nothing is wrong. -#ifdef TARGET_I386 - env->cr[3] = cur_cr3; -#endif - return; - } - - bool reached_paged_entry = false; - PTR sentinel = ptr_peb_ldr_data + PEB_LDR_DATA_LOAD_LIST_OFF; - PTR cur_entry = sentinel; - do { - // Read the current list entry Flink pointer. - if (-1 == panda_virtual_memory_read(cpu, cur_entry, - (uint8_t *)&cur_entry, - sizeof(cur_entry))) { - fprintf(stderr, "Could not read next entry in module list.\n"); - break; - } - - // If we've reached the sentinel, we're done. - if (cur_entry == sentinel) { - break; - } - - // We're reasonbly sure we've found a library, add it to the list. - // Note, the library may be paged out and if so, we stop iterating. - PTR ptr_ldr_data_table_entry = cur_entry - LDR_LOAD_LINKS_OFF; - char *name = - get_unicode_str(cpu, ptr_ldr_data_table_entry + LDR_BASENAME_OFF); - char *filename = - get_unicode_str(cpu, ptr_ldr_data_table_entry + LDR_FILENAME_OFF); - PTR base = -1; - if (-1 == panda_virtual_memory_read( - cpu, ptr_ldr_data_table_entry + LDR_BASE_OFF, - (uint8_t *)&base, sizeof(base))) { - // If this fails, we assume that this LDR_DATA_TABLE_ENTRY is paged - reached_paged_entry = true; - } - PTR size = -1; - if (-1 == panda_virtual_memory_read( - cpu, ptr_ldr_data_table_entry + LDR_SIZE_OFF, - (uint8_t *)&size, sizeof(size))) { - // If this fails, we assume that this LDR_DATA_TABLE_ENTRY is paged - reached_paged_entry = true; - } - - OsiModule mod; - if (NULL == *out) { - *out = g_array_sized_new(false, false, sizeof(mod), 128); - g_array_set_clear_func(*out, - (GDestroyNotify)free_osimodule_contents); - } - mod.modd = ptr_ldr_data_table_entry; - mod.base = base; - mod.size = size; - mod.name = name; - mod.file = filename; - g_array_append_val(*out, mod); - } while (false == reached_paged_entry); - - // Now that we've gotten the libraries, we need to restore CR3. -#ifdef TARGET_I386 - env->cr[3] = cur_cr3; -#endif -} - -void on_get_modules(CPUState *cpu, GArray **out) -{ - PTR kdbg = get_kddebugger_data(cpu); - PTR PsLoadedModuleList = 0xFFFFFFFF; - PTR mod_current = 0x0; - - // Dbg.PsLoadedModuleList - if (-1 == panda_physical_memory_rw(kdbg + KDDBG64_LOADED_MOD_HEAD_OFF, - (uint8_t *)&PsLoadedModuleList, - sizeof(PTR), false)) - goto error; - - if (*out == NULL) { - // g_array_sized_new() args: zero_term, clear, element_sz, reserved_sz - *out = g_array_sized_new(false, false, sizeof(OsiModule), 128); - g_array_set_clear_func(*out, (GDestroyNotify)free_osimodule_contents); - } - - mod_current = get_next_mod(cpu, PsLoadedModuleList); - - // We want while loop here -- we are starting at the head, - // which is not a valid module - while (mod_current != 0x0 && mod_current != PsLoadedModuleList) { - add_mod(cpu, *out, mod_current, false); - mod_current = get_next_mod(cpu, mod_current); - } - return; - -error: - *out = NULL; - return; -} - -void on_get_processes(CPUState *cpu, GArray **out) { - // The process list in NT can be iterated by starting at the - // nt!PsActiveProcessHead symbol. The symbol points to an nt!_LIST_ENTRY - // that acts as a sentinel node for the process list, so we can use it as a - // reference point to start and stop iterating. - - // Assume failure until we reach the first process, so set the output to - // null. - *out = NULL; - - // Try to get the nt!PsActiveProcessHead from the KDDEBUGGER_DATA64 struct. - // Note that the result of kddebugger_data returns a physical address. - PTR kddebugger_data = get_kddebugger_data(cpu); - PTR sentinel = -1; - if (-1 == panda_physical_memory_rw( - kddebugger_data + KDDBG64_ACTIVE_PROCESS_HEAD_OFF, - (uint8_t *)&sentinel, sizeof(sentinel), 0)) { - fprintf(stderr, "Could not get PsActiveProcessHead!\n"); - return; - } - PTR cur_entry = sentinel; - do { - // Read the current list entry Flink pointer. - if (-1 == panda_virtual_memory_read(cpu, cur_entry, - (uint8_t *)&cur_entry, - sizeof(cur_entry))) { - fprintf(stderr, "Error reading process list entry!\n"); - break; - } - - - // If we've reached the sentinel, we're done. - if (cur_entry == sentinel) { - break; - } - - // We've found the procss, if this is the first one go ahead and create - // the array. - OsiProc cur_proc; - if (*out == NULL) { - *out = g_array_sized_new(false, false, sizeof(cur_proc), 128); - g_array_set_clear_func(*out, (GDestroyNotify)free_osiproc_contents); - } - PTR cur_eproc = cur_entry - eproc_links_off; - fill_osiproc(cpu, &cur_proc, cur_eproc); - g_array_append_val(*out, cur_proc); - } while (true); -} - -void on_get_current_thread(CPUState *cpu, OsiThread **out) { - // Get current process. - OsiProc *p = NULL; - on_get_current_process(cpu, &p); - if (NULL == p) { - goto error; - } - - OsiThread tmp; - tmp.pid = p->pid; - free_osiproc(p); - - PTR ethread; - if (-1 == panda_virtual_memory_read(cpu, get_kpcr(cpu) + KPCR_CURTHREAD_OFF, - (uint8_t *)ðread, sizeof(ethread))) { - goto error; - } - - // Cid contains thread ID - if (-1 == panda_virtual_memory_read( - cpu, ethread + kthread_cid_off + CLIENT_ID_UNIQUE_THREAD, - (uint8_t *)&tmp.tid, sizeof(tmp.tid))) { - goto error; - } - - if (NULL == *out) { - *out = (OsiThread *)g_malloc(sizeof(**out)); - } - - **out = tmp; -error: - return; -} - -/** - * @brief PPP callback to retrieve the process pid from a handle. - */ -void on_get_process_pid(CPUState *cpu, const OsiProcHandle *h, target_pid_t *pid) { - if (h->taskd == (intptr_t)(NULL) || h->taskd == (target_ptr_t)-1) { - *pid = (target_pid_t)-1; - } else { - *pid = get_pid(cpu, h->taskd); - } -} - -/** - * @brief PPP callback to retrieve the process parent pid from a handle. - */ -void on_get_process_ppid(CPUState *cpu, const OsiProcHandle *h, target_pid_t *ppid) { - if (h->taskd == (intptr_t)(NULL) || h->taskd == (target_ptr_t)-1) { - *ppid = (target_pid_t)-1; - } else { - *ppid = get_ppid(cpu, h->taskd); - } -} - -uint32_t get_ntreadfile_esp_off(void) { return ntreadfile_esp_off; } - -uint32_t get_kthread_kproc_off(void) { return kthread_kproc_off; } - -uint32_t get_eproc_pid_off(void) { return eproc_pid_off; } - -uint32_t get_eproc_name_off(void) { return eproc_name_off; } - -uint32_t get_eproc_objtable_off(void) { return eproc_objtable_off; } - -uint32_t get_obj_type_offset(void) { return obj_type_offset; } - -uint32_t get_pid(CPUState *cpu, PTR eproc) { - uint32_t pid; - if(-1 == panda_virtual_memory_rw(cpu, eproc+eproc_pid_off, (uint8_t *)&pid, 4, false)) return 0; - return pid; -} - -PTR get_ppid(CPUState *cpu, PTR eproc) { - PTR ppid; - if(-1 == panda_virtual_memory_rw(cpu, eproc+eproc_ppid_off, (uint8_t *)&ppid, sizeof(PTR), false)) return 0; - return ppid; -} - -PTR get_dtb(CPUState *cpu, PTR eproc) { - PTR dtb = 0; - assert(!panda_virtual_memory_rw(cpu, eproc+EPROC_DTB_OFF, (uint8_t *)&dtb, sizeof(PTR), false)); - assert(dtb); - return dtb; -} - - -void get_procname(CPUState *cpu, PTR eproc, char **name) { - assert(name); - *name = (char *)g_malloc(17); - assert(*name); - assert(!panda_virtual_memory_rw(cpu, eproc+eproc_name_off, (uint8_t *)*name, 16, false)); - (*name)[16] = '\0'; -} - -char *get_cwd(CPUState *cpu) -{ - PTR eproc = get_current_proc(cpu); - - // Get pointer to PEB - target_ulong ppeb = 0x0; - assert(!panda_virtual_memory_read(cpu, eproc + eproc_ppeb_off, - (uint8_t *)&ppeb, sizeof(ppeb))); - // Get pointer to PROCESS_PARAMETERS - target_ulong pprocess_params = 0x0; - assert(!panda_virtual_memory_read(cpu, ppeb + PROCESS_PARAMETERS_OFF, - (uint8_t *)&pprocess_params, - sizeof(pprocess_params))); - - // Get the work dir handle - uint32_t cwd_handle = 0x0; - assert(!panda_virtual_memory_read(cpu, pprocess_params + 0x2C, - (uint8_t *)&cwd_handle, - sizeof(cwd_handle))); - - char *cwd_handle_name = get_handle_name(cpu, eproc, cwd_handle); - - return cwd_handle_name; -} - -bool is_valid_process(CPUState *cpu, PTR eproc) { - uint8_t type; - uint8_t size; - - if(eproc == 0) return false; - - if(-1 == panda_virtual_memory_rw(cpu, eproc+EPROC_TYPE_OFF, (uint8_t *)&type, 1, false)) return false; - if(-1 == panda_virtual_memory_rw(cpu, eproc+EPROC_SIZE_OFF, (uint8_t *)&size, 1, false)) return false; - - return type == EPROC_TYPE && size == eproc_size && - get_next_proc(cpu, eproc); -} - - -uint32_t get_current_proc(CPUState *cpu) { - PTR thread, proc; - PTR kpcr = get_kpcr(cpu); - - // Read KPCR->CurrentThread->Process - if (-1 == panda_virtual_memory_rw(cpu, kpcr+KPCR_CURTHREAD_OFF, (uint8_t *)&thread, sizeof(PTR), false)) return 0; - if (-1 == panda_virtual_memory_rw(cpu, thread+get_kthread_kproc_off(), (uint8_t *)&proc, sizeof(PTR), false)) return 0; - - // Sometimes, proc == 0 here. Is there a better way to do this? - - return is_valid_process(cpu, proc) ? proc : 0; -} - -// Process introspection -PTR get_next_proc(CPUState *cpu, PTR eproc) { - PTR next; - if (-1 == panda_virtual_memory_rw(cpu, eproc+eproc_links_off, (uint8_t *)&next, sizeof(PTR), false)) - return 0; - next -= eproc_links_off; - return next; -} - - - -// Win7 Obj Type Indices -/* -typedef enum { - OBJ_TYPE_Type = 2, - OBJ_TYPE_Directory = 3, - OBJ_TYPE_SymbolicLink = 4, - OBJ_TYPE_Token = 5, - OBJ_TYPE_Job = 6, - OBJ_TYPE_Process = 7, - OBJ_TYPE_Thread = 8, - OBJ_TYPE_UserApcReserve = 9, - OBJ_TYPE_IoCompletionReserve = 10, - OBJ_TYPE_DebugObject = 11, - OBJ_TYPE_Event = 12, - OBJ_TYPE_EventPair = 13, - OBJ_TYPE_Mutant = 14, - OBJ_TYPE_Callback = 15, - OBJ_TYPE_Semaphore = 16, - OBJ_TYPE_Timer = 17, - OBJ_TYPE_Profile = 18, - OBJ_TYPE_KeyedEvent = 19, - OBJ_TYPE_WindowStation = 20, - OBJ_TYPE_Desktop = 21, - OBJ_TYPE_TpWorkerFactory = 22, - OBJ_TYPE_Adapter = 23, - OBJ_TYPE_Controller = 24, - OBJ_TYPE_Device = 25, - OBJ_TYPE_Driver = 26, - OBJ_TYPE_IoCompletion = 27, - OBJ_TYPE_File = 28, - OBJ_TYPE_TmTm = 29, - OBJ_TYPE_TmTx = 30, - OBJ_TYPE_TmRm = 31, - OBJ_TYPE_TmEn = 32, - OBJ_TYPE_Section = 33, - OBJ_TYPE_Session = 34, - OBJ_TYPE_Key = 35, - OBJ_TYPE_ALPCPort = 36, - OBJ_TYPE_PowerRequest = 37, - OBJ_TYPE_WmiGuid = 38, - OBJ_TYPE_EtwRegistration = 39, - OBJ_TYPE_EtwConsumer = 40, - OBJ_TYPE_FilterConnectionPort = 41, - OBJ_TYPE_FilterCommunicationPort = 42, - OBJ_TYPE_PcwObject = 43 -} OBJ_TYPES; -*/ - - -uint32_t handle_table_code(CPUState *cpu, uint32_t table_vaddr) { - uint32_t tableCode; - // HANDLE_TABLE.TableCode is offest 0 - assert(!panda_virtual_memory_rw(cpu, table_vaddr, (uint8_t *)&tableCode, 4, false)); - return (tableCode & TABLE_MASK); -} - - -uint32_t handle_table_L1_addr(CPUState *cpu, uint32_t table_vaddr, uint32_t entry_num) { - return table_vaddr + ADDR_SIZE * entry_num; -} - - -uint32_t handle_table_L2_addr(uint32_t L1_table, uint32_t L2) { - if (L1_table != 0x0) { - uint32_t L2_entry = L1_table + ADDR_SIZE * L2; - return L2_entry; - } - return 0; -} - - -uint32_t handle_table_L1_entry(CPUState *cpu, uint32_t table_vaddr, uint32_t entry_num) { - return (handle_table_code(cpu, table_vaddr) + - HANDLE_TABLE_ENTRY_SIZE * entry_num); -} - - -uint32_t handle_table_L2_entry(uint32_t table_vaddr, uint32_t L1_table, uint32_t L2) { - if (L1_table == 0) return 0; - return L1_table + HANDLE_TABLE_ENTRY_SIZE * L2; -} - - -uint32_t handle_table_L3_entry(uint32_t table_vaddr, uint32_t L2_table, uint32_t L3) { - if (L2_table == 0) return 0; - return L2_table + HANDLE_TABLE_ENTRY_SIZE * L3; -} - -uint32_t get_eproc_peb_off(void) { - return eproc_ppeb_off; -} - - - -// Module stuff -const char *get_mod_basename(CPUState *cpu, PTR mod) { - return get_unicode_str(cpu, mod+LDR_BASENAME_OFF); -} - -const char *get_mod_filename(CPUState *cpu, PTR mod) { - return get_unicode_str(cpu, mod+LDR_FILENAME_OFF); -} - -PTR get_mod_base(CPUState *cpu, PTR mod) { - PTR base; - assert(!panda_virtual_memory_rw(cpu, mod+LDR_BASE_OFF, (uint8_t *)&base, sizeof(PTR), false)); - return base; -} - -PTR get_mod_size(CPUState *cpu, PTR mod) { - uint32_t size; - assert(!panda_virtual_memory_rw(cpu, mod+LDR_SIZE_OFF, (uint8_t *)&size, sizeof(uint32_t), false)); - return size; -} - -PTR get_next_mod(CPUState *cpu, PTR mod) { - PTR next; - if (-1 == panda_virtual_memory_rw(cpu, mod+LDR_LOAD_LINKS_OFF, (uint8_t *)&next, sizeof(PTR), false)) - return 0; - next -= LDR_LOAD_LINKS_OFF; - return next; -} - -char *read_unicode_string(CPUState *cpu, uint32_t pUstr) -{ - return get_unicode_str(cpu, pUstr); -} - -char *get_objname(CPUState *cpu, uint32_t obj) { - uint32_t pObjectName; - assert(-1 != panda_virtual_memory_rw(cpu, obj+OBJNAME_OFF, (uint8_t *)&pObjectName, sizeof(pObjectName), false)); - return read_unicode_string(cpu, pObjectName); -} - -char *get_file_obj_name(CPUState *cpu, uint32_t fobj) { - return read_unicode_string(cpu, fobj + FILE_OBJECT_NAME_OFF); -} - -int64_t get_file_obj_pos(CPUState *cpu, uint32_t fobj) { - int64_t file_pos; - if (-1 == panda_virtual_memory_rw(cpu, fobj+FILE_OBJECT_POS_OFF, (uint8_t *)&file_pos, sizeof(file_pos), false)) { - return -1; - } else { - return file_pos; - } -} - -char *get_handle_object_name(CPUState *cpu, HandleObject *ho) { - char *name; - if (ho == NULL) { - name = g_strdup("unknown"); - } else if(ho->objType == obj_type_file) { - name = get_file_obj_name(cpu, ho->pObj); - } else if(ho->objType == obj_type_key) { - name = g_strdup_printf("_CM_KEY_BODY@%08x", ho->pObj); - } else if(ho->objType == obj_type_process) { - get_procname(cpu, ho->pObj, &name); - } else { - name=g_strdup_printf("unknown object type %d", ho->objType); - } - assert(name); - return name; -} - - -char *get_handle_name(CPUState *cpu, PTR eproc, uint32_t handle) { - HandleObject *ho = get_handle_object(cpu, eproc, handle); - return get_handle_object_name(cpu, ho); -} - -int64_t get_file_handle_pos(CPUState *cpu, PTR eproc, uint32_t handle) { - HandleObject *ho = get_handle_object(cpu, eproc, handle); - if (!ho) { - return -1; - } else { - return get_file_obj_pos(cpu, ho->pObj); - } -} - -void fill_osiproc(CPUState *cpu, OsiProc *p, PTR eproc) { - p->taskd = eproc; - get_procname(cpu, eproc, &p->name); - p->asid = get_dtb(cpu, eproc); - p->pages = NULL; - p->pid = get_pid(cpu, eproc); - p->ppid = get_ppid(cpu, eproc); -} - -void fill_osiprochandle(CPUState *cpu, OsiProcHandle *h, PTR eproc) { - h->taskd = eproc; - h->asid = get_dtb(cpu, eproc); -} - -void fill_osimod(CPUState *cpu, OsiModule *m, PTR mod, bool ignore_basename) { - m->modd = mod; - m->file = (char *)get_mod_filename(cpu, mod); - m->base = get_mod_base(cpu, mod); - m->size = get_mod_size(cpu, mod); - m->name = ignore_basename ? g_strdup("-") : (char *)get_mod_basename(cpu, mod); - assert(m->name); -} - -static void before_tcg_codegen(CPUState *cpu, TranslationBlock *tb) -{ - if (0x0 == task_change_hook_addr && 0 == strcmp(panda_os_variant, "7")) { - // On Windows 7, we have to compute the task change hook address - // relative to the ntoskrnl.exe base (because ASLR). - GArray *mods = get_modules(cpu); - for (int i = 0; i < mods->len; i++) { - OsiModule *mod = &g_array_index(mods, OsiModule, i); - if (0 == strcmp("ntoskrnl.exe", mod->name)) { - task_change_hook_addr = mod->base + task_change_hook_offset; - printf("task change hook address = %lX\n", (uint64_t)task_change_hook_addr); - } - } - if (NULL != mods) { - g_array_free(mods, true); - } - } - - if ((tb->pc <= task_change_hook_addr) && (task_change_hook_addr < tb->pc + tb->size)) { - TCGOp *op = find_guest_insn_by_addr(task_change_hook_addr); - if (op) { - insert_call_1p(&op, (void(*)(void*))notify_task_change, cpu); - } - } -} - -#endif - - -bool init_plugin(void *self) { -#ifdef TARGET_I386 - // this stuff only currently works for win7 or win2000, 32-bit - assert (panda_os_familyno == OS_WINDOWS); - assert (panda_os_bits == 32); - assert (panda_os_variant); - - if(0 == strcmp(panda_os_variant, "7")) { - task_change_hook_addr = 0x0; - task_change_hook_offset = 0x55209; - kthread_kproc_off=0x150; - kthread_cid_off = 0x22c; - eproc_pid_off=0x0b4; - eproc_ppid_off=0x140; - eproc_name_off=0x16c; - eproc_objtable_off=0xf4; - eproc_ppeb_off = 0x1a8; - obj_type_file = 28; - obj_type_key = 35; - obj_type_process = 7; - obj_type_offset = 0xc; - eproc_size = 0x26; - eproc_links_off = 0x0b8; - ntreadfile_esp_off = 0; - panda_require("win7x86intro"); - assert(init_win7x86intro_api()); - get_kpcr = get_win7_kpcr; - get_handle_object = get_win7_handle_object; - get_kddebugger_data = get_win7_kdbg; - } else if (0 == strcmp(panda_os_variant, "2000")) { - task_change_hook_addr = 0x804043E3; - task_change_hook_offset = 0x0; - kthread_kproc_off = 0x22c; - kthread_cid_off = 0x1e0; - eproc_pid_off=0x09c; - eproc_ppid_off=0x1c8; - eproc_name_off=0x1fc; - eproc_objtable_off=0x128; - eproc_ppeb_off = 0x1b0; - obj_type_file = 0x05; - obj_type_key = 0x32; - obj_type_process = 0x03; - obj_type_offset = 0x18; - eproc_size = 0x1b; - eproc_links_off = 0x0a0; - ntreadfile_esp_off = 0x24; - panda_require("win2000x86intro"); - assert(init_win2000x86intro_api()); - get_kpcr = get_win2000_kpcr; - get_handle_object = get_win2000_handle_object; - get_kddebugger_data = get_win2000_kddebugger_data; - } else if (0 == strcmp(panda_os_variant, "xpsp3")) { - task_change_hook_addr = 0x804DB9D7; - task_change_hook_offset = 0x0; - kthread_kproc_off = 0x044; - kthread_cid_off = 0x1ec; - eproc_pid_off = 0x084; - eproc_ppid_off = 0x14c; - eproc_name_off = 0x174; - eproc_objtable_off = 0x0c4; - eproc_ppeb_off = 0x1b0; - obj_type_file = 28; - obj_type_key = 20; - obj_type_process = 5; - obj_type_offset = 0x8; - eproc_size = 0x1b; // why??? - eproc_links_off = 0x088; - ntreadfile_esp_off = 0; - panda_require("winxpx86intro"); - assert(init_winxpx86intro_api()); - get_kpcr = get_winxp_kpcr; - get_handle_object = get_winxp_handle_object; - get_kddebugger_data = get_winxp_kdbg; - } else { - fprintf(stderr, "Plugin is not supported for this windows " - "version (%s).\n", panda_os_variant); - } - - PPP_REG_CB("osi", on_get_current_process, on_get_current_process); - PPP_REG_CB("osi", on_get_current_process_handle, on_get_current_process_handle); - PPP_REG_CB("osi", on_get_processes, on_get_processes); - PPP_REG_CB("osi", on_get_current_thread, on_get_current_thread); - PPP_REG_CB("osi", on_get_process_pid, on_get_process_pid); - PPP_REG_CB("osi", on_get_process_ppid, on_get_process_ppid); - PPP_REG_CB("osi", on_get_mappings, on_get_mappings); - PPP_REG_CB("osi", on_get_modules, on_get_modules); - - assert(init_osi_api()); - - panda_cb pcb; - pcb.before_tcg_codegen = &before_tcg_codegen; - panda_register_callback(self, PANDA_CB_BEFORE_TCG_CODEGEN, pcb); - - return true; -#else - fprintf(stderr, "Plugin is not supported on this platform.\n"); - return false; -#endif - -} - -void uninit_plugin(void *self) { - printf("Unloading wintrospection plugin\n"); - // if we don't clear tb's when this exits we have TBs which can call - // into our exited plugin. - panda_do_flush_tb(); -} - -/* vim: set tabstop=4 softtabstop=4 expandtab: */ diff --git a/panda/plugins/wintrospection/wintrospection.cpp b/panda/plugins/wintrospection/wintrospection.cpp new file mode 100644 index 00000000000..7fbcecac854 --- /dev/null +++ b/panda/plugins/wintrospection/wintrospection.cpp @@ -0,0 +1,583 @@ +/* PANDABEGINCOMMENT + * + * Authors: + * Tim Leek tleek@ll.mit.edu + * Ryan Whelan rwhelan@ll.mit.edu + * Joshua Hodosh josh.hodosh@ll.mit.edu + * Michael Zhivich mzhivich@ll.mit.edu + * Brendan Dolan-Gavitt brendandg@gatech.edu + * + * This work is licensed under the terms of the GNU GPL, version 2. + * See the COPYING file in the top-level directory. + * +PANDAENDCOMMENT */ +// This needs to be defined before anything is included in order to get +// the PRIx64 macro +#define __STDC_FORMAT_MACROS + +#include +#include +#include + +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "glib.h" + +#include "panda/plugin.h" +#include "panda/plugin_plugin.h" + +#include "../osi/osi_types.h" +#include "../osi/osi_ext.h" +#include "../osi/os_intro.h" + +#include "pandamemory.h" + +// These need to be extern "C" so that the ABI is compatible with +// QEMU/PANDA, which is written in C +extern "C" { +bool init_plugin(void *); +void uninit_plugin(void *); +} + +void on_get_current_thread(CPUState *cpu, OsiThread *out); +void on_get_process_pid(CPUState *cpu, const OsiProcHandle *h, + target_pid_t *pid); +void on_get_current_process_handle(CPUState *cpu, OsiProcHandle **out); +void on_get_process_handles(CPUState *cpu, GArray **out); +void on_get_process_ppid(CPUState *cpu, const OsiProcHandle *h, + target_pid_t *ppid); +void on_get_current_process(CPUState *cpu, OsiProc **out); +void on_get_process(CPUState *cpu, const OsiProcHandle *h, OsiProc **out); +void on_get_processes(CPUState *cpu, GArray **out); +void on_get_modules(CPUState *cpu, GArray **out); +void on_get_mappings(CPUState *cpu, OsiProc *p, GArray **out); + +std::unique_ptr g_kernel_manager; +std::unique_ptr g_process_manager; +bool g_update_task; + +static std::map system_asid_lookup = { + {"windows-32-7sp1", 0x185000}, + {"windows-64-7sp1", 0x187000}, +}; + +/* ****************************************************************** + Helpers +****************************************************************** */ +void fill_process(OsiProc *p, WindowsProcess *win_proc) { + p->taskd = process_get_eprocess(win_proc); + p->asid = process_get_asid(win_proc); + p->pid = process_get_pid(win_proc); + p->ppid = process_get_ppid(win_proc); + p->pages = NULL; + + p->name = (char *)g_malloc(17); + strncpy(p->name, process_get_shortname(win_proc), 17); +} + +void fill_module(OsiModule *m, struct WindowsModuleEntry *win_mod) { + m->modd = module_entry_get_module_entry(win_mod); + m->size = module_entry_get_modulesize(win_mod); + m->base = module_entry_get_base_address(win_mod); + m->file = strdup(module_entry_get_dllpath(win_mod)); + m->name = strdup(module_entry_get_dllname(win_mod)); +} + +std::string get_key_name(uint64_t ptr) { + auto object = g_process_manager->get_type(ptr, "_CM_KEY_BODY"); + + osi::i_t nameblock; + uint8_t compressed; + uint16_t size; + + std::vector keyname; + + auto kcb = object("KeyControlBlock"); + while (kcb.get_address()) { + nameblock = kcb("NameBlock"); + compressed = nameblock["Compressed"].get8(); + size = nameblock["NameLength"].get16(); + + if (compressed) { + char *temp = new char[size + 1]{'\0'}; + nameblock["Name"].getx(*temp, size); + + size_t total = strnlen(temp, size); + if (total == size) { + temp[size] = '\0'; + } + + for (size_t idx = 0; idx < total; idx++) { + if (!isprint(temp[idx])) { + temp[idx] = '?'; + } + } + + keyname.push_back(std::string(temp, total)); + delete temp; + } else { + auto raw_name = + osi::ustring(nameblock["Name"].set_type("_UNICODE_STRING")); + keyname.push_back(raw_name.as_utf8()); + } + kcb = kcb("ParentKcb"); + } + + std::string full_key; + for (auto it = keyname.rbegin(); it != keyname.rend(); it++) { + full_key += "\\" + *it; + } + + return full_key; +} + +std::string extract_handle_name(struct WindowsHandleObject *handle) { + auto ptr = handle_get_pointer(handle); + if (!ptr) { + return "unknown"; + } + + std::stringstream ss; + + const char *type_name = handle_get_typename(handle); + if (strcmp(type_name, "Key") == 0) { + ss << get_key_name(ptr); + } else if (strcmp(type_name, "File") == 0) { + auto file = g_process_manager->get_type(ptr, "_FILE_OBJECT"); + osi::ustring uname(file["FileName"]); + ss << uname.as_utf8(); + } else if (strcmp(type_name, "Process") == 0) { + struct WindowsProcess *p = + create_process(g_kernel_manager->get_kernel_object(), ptr); + ss << process_get_shortname(p); + free_process(p); + } else { + ss << "unknown object type " << handle_get_type(handle); + } + + return ss.str(); +} + +/* ****************************************************************** + Our Callbacks +****************************************************************** */ + +int64_t get_file_handle_pos(uint64_t handle) { + auto kernel = g_kernel_manager->get_kernel_object(); + WindowsHandleObject *h = resolve_handle(kernel, handle); + + auto ptr = handle_get_pointer(h); + if (!ptr) { + return -1; + } + + int64_t file_pos = -1; + try { + auto file = g_process_manager->get_type(ptr, "_FILE_OBJECT"); + file_pos = file["CurrentByteOffset"].get64(); + } catch (std::runtime_error const &) { + // runtime_error is raised when a virtual memory read fails + // it's the equiv of (-1 == panda_virtual_memory_rw(...)) + } + + return file_pos; +} + +char *get_cwd(void) { + osi::i_t eproc = g_process_manager->get_process(); + + bool wow = false; + if (panda_os_bits == 64 && eproc["Wow64Process"].getu()) + wow = true; + + osi::i_t peb; + if (wow) { + peb = eproc("Wow64Process").set_type("_PEB32"); + } else { + peb = eproc("Peb"); + } + + osi::i_t params; + if (wow) { + params = g_process_manager->get_type(peb["ProcessParameters"].get32(), + "_RTL_USER_PROCESS_PARAMETERS"); + } else { + params = peb("ProcessParameters"); + } + + auto dir = osi::ustring(params["CurrentDirectory"]); + std::string path = dir.as_utf8(); + return strdup(path.c_str()); +} + +char *get_handle_name(uint64_t handle) { + auto kernel = g_kernel_manager->get_kernel_object(); + WindowsHandleObject *h = resolve_handle(kernel, handle); + + auto name = extract_handle_name(h); + return strdup(name.c_str()); +} + +/* ****************************************************************** + PPP Callbacks +****************************************************************** */ + +void on_get_current_thread(CPUState *cpu, OsiThread **out) { + OsiThread *t = (OsiThread *)g_malloc(sizeof(OsiThread)); + + auto proc = g_process_manager->get_process_object(); + auto kernel = g_kernel_manager->get_kernel_object(); + + t->pid = proc->pid; + t->tid = kosi_get_current_tid(kernel); + + *out = t; +} + +void on_get_process_pid(CPUState *cpu, const OsiProcHandle *h, + target_pid_t *pid) { + if (h->taskd == (intptr_t)(NULL) || h->taskd == (target_ptr_t)-1) { + *pid = (target_pid_t)-1; + } else { + *pid = g_process_manager->get_process_object()->pid; + } +} + +void on_get_current_process_handle(CPUState *cpu, OsiProcHandle **out) { + OsiProcHandle *p = (OsiProcHandle *)g_malloc(sizeof(OsiProcHandle)); + + auto process = g_process_manager->get_process_object(); + p->taskd = process->eprocess_address; + p->asid = process->vmem->get_asid(); + + *out = p; +} + +void on_get_process_handles(CPUState *cpu, GArray **out) { + if (*out == NULL) { + *out = g_array_sized_new(false, false, sizeof(OsiProcHandle), 128); + g_array_set_clear_func(*out, (GDestroyNotify)free_osiprochandle_contents); + } + + auto kernel = g_kernel_manager->get_kernel_object(); + + struct WindowsProcessList *plist = get_process_list(kernel); + struct WindowsProcess *process; + while ((process = process_list_next(plist)) != nullptr) { + OsiProcHandle cur_handle; + cur_handle.taskd = process_get_eprocess(process); + cur_handle.asid = process_get_asid(process); + g_array_append_val(*out, cur_handle); + + free_process(process); + } + free_process_list(plist); +} + +void on_get_process_ppid(CPUState *cpu, const OsiProcHandle *h, + target_pid_t *ppid) { + if (h->taskd == (intptr_t)(NULL) || h->taskd == (target_ptr_t)-1) { + *ppid = (target_pid_t)-1; + } else { + auto kernel = g_kernel_manager->get_kernel_object(); + auto process = kosi_get_current_process(kernel); + *ppid = process_get_ppid(process); + free_process(process); + } +} + +void on_get_current_process(CPUState *cpu, OsiProc **out) { + OsiProc *p = (OsiProc *)g_malloc(sizeof(OsiProc)); + + auto proc = g_process_manager->get_process_object(); + auto kernel = g_kernel_manager->get_kernel_object(); + + WindowsProcess *process = create_process(kernel, proc->eprocess_address); + fill_process(p, process); + free_process(process); + + *out = p; +} + +void on_get_process(CPUState *cpu, const OsiProcHandle *h, OsiProc **out) { + OsiProc *p = NULL; + if (h != NULL && h->taskd != (target_ptr_t)NULL) { + p = (OsiProc *)g_malloc(sizeof(OsiProc)); + + auto kernel = g_kernel_manager->get_kernel_object(); + auto proc = create_process(kernel, h->taskd); + fill_process(p, proc); + free_process(proc); + } + *out = p; +} + +void on_get_processes(CPUState *cpu, GArray **out) { + if (*out == NULL) { + *out = g_array_sized_new(false, false, sizeof(OsiProc), 128); + g_array_set_clear_func(*out, (GDestroyNotify)free_osiproc_contents); + } + + auto kernel = g_kernel_manager->get_kernel_object(); + + struct WindowsProcessList *plist = get_process_list(kernel); + struct WindowsProcess *process; + while ((process = process_list_next(plist)) != nullptr) { + OsiProc cur_proc; + fill_process(&cur_proc, process); + g_array_append_val(*out, cur_proc); + + free_process(process); + } + free_process_list(plist); +} + +void on_get_modules(CPUState *cpu, GArray **out) { + if (*out == NULL) { + // g_array_sized_new() args: zero_term, clear, element_sz, reserved_sz + *out = g_array_sized_new(false, false, sizeof(OsiModule), 128); + g_array_set_clear_func(*out, (GDestroyNotify)free_osimodule_contents); + } + + auto kernel = g_kernel_manager->get_kernel_object(); + + auto ldr_table = g_kernel_manager->get_type( + kernel->details.PsLoadedModuleList, "_LDR_DATA_TABLE_ENTRY"); + osi::iterator pitr(ldr_table, "InLoadOrderLinks"); + pitr++; // skip head_sentinel + do { + auto entry = *pitr; + + OsiModule m; + memset(&m, 0, sizeof(OsiModule)); + + m.modd = entry.get_address(); + m.size = entry["SizeOfImage"].get32(); + m.base = entry["DllBase"].getu(); + + try { + osi::ustring dllname(entry["BaseDllName"]); + std::string dllname_utf8 = dllname.as_utf8().c_str(); + m.name = strdup(dllname_utf8.c_str()); + + osi::ustring dllpath(entry["FullDllName"]); + std::string dllpath_utf8 = dllpath.as_utf8(); + m.file = strdup(dllpath_utf8.c_str()); + } catch (std::runtime_error const &) { + // runtime_error is thrown when virtual memory + // cannot read the struct attribute + m.name = strdup("-"); + m.file = strdup("-"); + } + + g_array_append_val(*out, m); + + pitr++; + } while (*pitr != ldr_table); +} + +void on_get_mappings(CPUState *cpu, OsiProc *p, GArray **out) { + if (p == NULL) { + return; + } + + if (*out == NULL) { + // g_array_sized_new() args: zero_term, clear, element_sz, reserved_sz + *out = g_array_sized_new(false, false, sizeof(OsiModule), 128); + g_array_set_clear_func(*out, (GDestroyNotify)free_osimodule_contents); + } + + auto kernel = g_kernel_manager->get_kernel_object(); + + auto proc = create_process(kernel, p->taskd); + struct WindowsModuleList *mlist = + get_module_list(kernel, p->taskd, process_is_wow64(proc)); + free_process(proc); + + if (mlist) { + struct WindowsModuleEntry *mentry; + while ((mentry = module_list_next(mlist)) != nullptr) { + OsiModule m; + memset(&m, 0, sizeof(OsiModule)); + fill_module(&m, mentry); + g_array_append_val(*out, m); + + free_module_entry(mentry); + } + } + + // this is guarded from nullptr, so safe here + free_module_list(mlist); +} + +/* ****************************************************************** + Initialization logic +****************************************************************** */ + +void update_process_manager() { + auto kernel = g_kernel_manager->get_kernel_object(); + g_process_manager->initialize(kernel, + kosi_get_current_process_address(kernel)); +} + +void before_block_exec(CPUState *cpu, TranslationBlock *tb) { + if (!g_update_task) + return; + + notify_task_change(cpu); + + g_process_manager.reset(new WindowsProcessManager()); + update_process_manager(); + + g_update_task = false; +} + +bool asid_changed(CPUState *cpu, target_ulong old_pgd, target_ulong new_pgd) { + if (old_pgd != new_pgd) + g_update_task = true; + + return false; +} + +/** + * Get the Kernel Processor Control Region (KPCR) on a 32-bit system + * + * The KPCR should be accessible from FS. FS is stored at selector 0x30 + * in the Global Descriptor Table (GDT), so we look here to load it. + * The base of this segment contains the KPCR. + * + */ +uint64_t get_kpcr_i386(CPUState *cpu) { +#if defined(TARGET_I386) + CPUArchState *env = (CPUArchState *)cpu->env_ptr; + + // read the FS segment descriptor from the GDT + uint32_t e1 = 0, e2 = 0; + panda_virtual_memory_rw(cpu, env->gdt.base + 0x30, (uint8_t *)&e1, 4, false); + panda_virtual_memory_rw(cpu, env->gdt.base + 0x30 + 4, (uint8_t *)&e2, 4, + false); + + // get base address from wacky segment + // see https://wiki.osdev.org/Global_Descriptor_Table + // for a layout -- we need the upper 16 bits of the first word, and + // the lowest and highest byte of the second word all together + uint32_t addr = ((e1 >> 16) | ((e2 & 0xff) << 16) | (e2 & 0xff000000)); + + return addr; +#endif + return 0; +} + +/** + * Get the Kernel Processor Control Region (KPCR) on a 64-bit system + * + * The KPCR should be stored in the Model Specific Register, KernelGSBase. If + * it is not there, then it has already been swapped into GS (with swapgs). We + * know if a KPCR has been found, because a KPCR struct has a pointer to itself + * at offset 0x18. + */ +uint64_t get_kpcr_amd64(CPUState *cpu) { +#if defined(TARGET_X86_64) + CPUArchState *env = (CPUArchState *)cpu->env_ptr; + + uint64_t kpcr = env->kernelgsbase; + + auto tlib = load_type_library(panda_os_name); + auto mr = offset_of(tlib, translate(tlib, "_KPCR"), "Self"); + + // check if the SelfPcr member is a pointer to itself. if so, we found the + // KPCR. + uint64_t base_self; + panda_virtual_memory_rw(cpu, kpcr + mr->offset, (uint8_t *)&base_self, 8, + false); + if (kpcr != base_self) { + // it has been swapped into GS + kpcr = env->segs[R_GS].base; + } + return kpcr; +#endif + return 0; +} + +void initialize_introspection(CPUState *cpu) { + auto pmem = create_panda_physical_memory(); + if (!pmem) { + fprintf(stderr, "Error creating physical memory interface\n"); + exit(1); + } + + auto asid_entry = system_asid_lookup.find(std::string(panda_os_name)); + if (asid_entry == system_asid_lookup.end()) { + fprintf(stderr, "%s is an unsupported profile\n", panda_os_name); + exit(2); + } + + auto kpcr = (panda_os_bits == 64) ? get_kpcr_amd64(cpu) : get_kpcr_i386(cpu); + auto width = (panda_os_bits == 64) ? 8 : 4; + + // BDD : last argument should be panda_pae_enabled + auto success = g_kernel_manager->initialize(pmem, width, asid_entry->second, + kpcr, false); + if (!success) { + fprintf(stderr, "Error initializing kernel manager\n"); + exit(3); + } + + g_process_manager = + std::unique_ptr(new WindowsProcessManager()); + update_process_manager(); +} + +bool init_plugin(void *self) { +#if defined(TARGET_I386) // only supports i386 and x86_64 + panda_require("osi"); + assert(init_osi_api()); + + panda_cb pcb; + + pcb.before_block_exec = before_block_exec; + panda_register_callback(self, PANDA_CB_BEFORE_BLOCK_EXEC, pcb); + pcb.asid_changed = asid_changed; + panda_register_callback(self, PANDA_CB_ASID_CHANGED, pcb); + pcb.after_loadvm = initialize_introspection; + panda_register_callback(self, PANDA_CB_AFTER_LOADVM, pcb); + + PPP_REG_CB("osi", on_get_current_thread, on_get_current_thread); + PPP_REG_CB("osi", on_get_process_pid, on_get_process_pid); + PPP_REG_CB("osi", on_get_current_process_handle, + on_get_current_process_handle); + PPP_REG_CB("osi", on_get_process_handles, on_get_process_handles); + PPP_REG_CB("osi", on_get_process_ppid, on_get_process_ppid); + PPP_REG_CB("osi", on_get_current_process, on_get_current_process); + PPP_REG_CB("osi", on_get_process, on_get_process); + PPP_REG_CB("osi", on_get_processes, on_get_processes); + PPP_REG_CB("osi", on_get_modules, on_get_modules); + PPP_REG_CB("osi", on_get_mappings, on_get_mappings); + + g_kernel_manager = std::unique_ptr( + new WindowsKernelManager(std::string(panda_os_name))); + g_update_task = false; + return true; +#endif + return false; +} + +void uninit_plugin(void *self) { + printf("Unloading wintrospection plugin\n"); + + // if we don't clear tb's when this exits we have TBs which can call + // into our exited plugin. + panda_do_flush_tb(); +} diff --git a/panda/plugins/wintrospection/wintrospection.h b/panda/plugins/wintrospection/wintrospection.h deleted file mode 100644 index 71c23229d90..00000000000 --- a/panda/plugins/wintrospection/wintrospection.h +++ /dev/null @@ -1,35 +0,0 @@ -#pragma once - -typedef struct handle_object_struct { - uint8_t objType; - uint32_t pObj; -} HandleObject; - - -// See: https://msdn.microsoft.com/en-us/library/windows/desktop/aa380518(v=vs.85).aspx -typedef struct { - uint16_t Length; // length excluding terminator in bytes - uint16_t MaximumLength; // allocated memory for buffer - target_ulong Buffer; // pointer to allocated memory -} win_unicode_string_t; - -// Size of guest pointer. -// Note that this can't just be target_ulong since -// a 32-bit OS will run on x86_64-softmmu -// To add support for a 64-bit OS, consider creating a wintrospection64 plugin. -#define PTR uint32_t - -#define HANDLE_MASK1 0x000007fc -#define HANDLE_SHIFT1 2 -#define HANDLE_MASK2 0x001ff800 -#define HANDLE_SHIFT2 11 -#define HANDLE_MASK3 0x7fe00000 -#define HANDLE_SHIFT3 21 -#define LEVEL_MASK 0x00000007 -#define TABLE_MASK ~LEVEL_MASK -#define ADDR_SIZE 4 -#define HANDLE_TABLE_ENTRY_SIZE 8 - -// Given an object header, we can find the body of the object at this offset. -// This seems stable across versions of Windows (at least Win 2k SP4 - 7 SP1). -#define OBJECT_HEADER_BODY_OFFSET 0x18 diff --git a/panda/plugins/wintrospection/wintrospection_int.h b/panda/plugins/wintrospection/wintrospection_int.h index c572e6d9907..d0e764e99da 100644 --- a/panda/plugins/wintrospection/wintrospection_int.h +++ b/panda/plugins/wintrospection/wintrospection_int.h @@ -1,15 +1,4 @@ -typedef void HandleObject; -typedef void CPUState; -typedef void uint32_t; +typedef void uint64_t; typedef void int64_t; -typedef void bool; -typedef void PTR; -typedef void OsiProc; -typedef void OsiProcHandle; -typedef void OsiModule; -typedef void OsiThread; -typedef void GArray; -typedef void target_pid_t; #include "wintrospection_int_fns.h" - diff --git a/panda/plugins/wintrospection/wintrospection_int_fns.h b/panda/plugins/wintrospection/wintrospection_int_fns.h index 34e5dab1adb..6647283c557 100644 --- a/panda/plugins/wintrospection/wintrospection_int_fns.h +++ b/panda/plugins/wintrospection/wintrospection_int_fns.h @@ -1,102 +1,7 @@ #pragma once -char *make_pagedstr(void); +char *get_handle_name(uint64_t handle); -char *get_unicode_str(CPUState *cpu, PTR ustr); +char *get_cwd(void); -// returns virtual address of EPROCESS data structure of currently running process -PTR get_current_proc(CPUState *cpu); - -// returns next process in process list -PTR get_next_proc(CPUState *cpu, PTR eproc); - -// returns true if eproc points to an EPROCESS structure -bool is_valid_process(CPUState *cpu, PTR eproc); - -// returns pid,given virtual address of EPROCESS data structure -uint32_t get_pid(CPUState *cpu, PTR eproc); - -// returns parent pid,given virtual address of EPROCESS data structure -uint32_t get_ppid(CPUState *cpu, PTR eproc); - -PTR get_dtb(CPUState *cpu, PTR eproc); - -// fills name (assumed alloced) for process given virtual address of EPROCESS data structure -void get_procname(CPUState *cpu, PTR eproc, char **name); - -char *get_cwd(CPUState *cpu); - -char *get_handle_object_name(CPUState *cpu, HandleObject *ho); - -int64_t get_file_handle_pos(CPUState *cpu, PTR eproc, uint32_t handle); - -char *get_handle_name(CPUState *cpu, PTR eproc, uint32_t handle); - -char * get_objname(CPUState *cpu, uint32_t obj); - -char *get_file_obj_name(CPUState *cpu, uint32_t fobj); - -int64_t get_file_obj_pos(CPUState *cpu, uint32_t fobj); - -char *read_unicode_string(CPUState *cpu, uint32_t pUstr); - -const char *get_mod_basename(CPUState *cpu, PTR mod); - -const char *get_mod_filename(CPUState *cpu, PTR mod); - -PTR get_mod_base(CPUState *cpu, PTR mod); - -PTR get_mod_size(CPUState *cpu, PTR mod); - -PTR get_next_mod(CPUState *cpu, PTR mod); - -void fill_osiproc(CPUState *cpu, OsiProc *p, PTR eproc); - -void fill_osiprochandle(CPUState *cpu, OsiProcHandle *h, PTR eproc); - -void fill_osimod(CPUState *cpu, OsiModule *m, PTR mod, bool ignore_basename); - -void add_mod(CPUState *cpu, GArray *ms, PTR mod, bool ignore_basename); - -void on_get_current_process(CPUState *cpu, OsiProc **out); - -void on_get_current_process_handle(CPUState *cpu, OsiProcHandle **out); - -void on_get_modules(CPUState *cpu, GArray **out); - -void on_get_mappings(CPUState *cpu, OsiProc *p, GArray **out); - -void on_get_processes(CPUState *cpu, GArray **out); - -void on_get_current_thread(CPUState *cpu, OsiThread **t); - -void on_get_process_pid(CPUState *cpu, const OsiProcHandle *h, target_pid_t *pid); - -void on_get_process_ppid(CPUState *cpu, const OsiProcHandle *h, target_pid_t *ppid); - -// Getters for os-specific constants -uint32_t get_ntreadfile_esp_off(void); - -uint32_t get_eproc_pid_off(void); - -uint32_t get_eproc_name_off(void); - -uint32_t get_kthread_kproc_off(void); - -uint32_t get_eproc_objtable_off(void); - -uint32_t get_obj_type_offset(void); - -uint32_t handle_table_code(CPUState *cpu, uint32_t table_vaddr); - -uint32_t handle_table_L1_addr(CPUState *cpu, uint32_t table_vaddr, uint32_t entry_num); - -uint32_t handle_table_L2_addr(uint32_t L1_table, uint32_t L2); - -uint32_t handle_table_L1_entry(CPUState *cpu, uint32_t table_vaddr, uint32_t entry_num); - -uint32_t handle_table_L2_entry(uint32_t table_vaddr, uint32_t L1_table, uint32_t L2); - -uint32_t handle_table_L3_entry(uint32_t table_vaddr, uint32_t L2_table, uint32_t L3); - -uint32_t get_eproc_peb_off(void); +int64_t get_file_handle_pos(uint64_t handle); diff --git a/panda/plugins/winxpx86intro/Makefile b/panda/plugins/winxpx86intro/Makefile deleted file mode 100644 index f3982d849ad..00000000000 --- a/panda/plugins/winxpx86intro/Makefile +++ /dev/null @@ -1,9 +0,0 @@ -# Don't forget to add your plugin to config.panda! - -# If you need custom CFLAGS or LIBS, set them up here -# CFLAGS+= -# LIBS+= - -# The main rule for your plugin. List all object-file dependencies. -$(PLUGIN_TARGET_DIR)/panda_$(PLUGIN_NAME).so: \ - $(PLUGIN_OBJ_DIR)/$(PLUGIN_NAME).o diff --git a/panda/plugins/winxpx86intro/README.md b/panda/plugins/winxpx86intro/README.md deleted file mode 100644 index 126092342f8..00000000000 --- a/panda/plugins/winxpx86intro/README.md +++ /dev/null @@ -1,30 +0,0 @@ -Plugin: winxpx86intro -=========== - -Summary -------- - -`winxpx86intro` is an introspection provider for Windows XP guests, supplying information for the OSI API. Not much more to say about it; it should just work as long as the guest OS is Windows XP SP3. - -Arguments ---------- - -None. - -Dependencies ------------- - -`winxpx86intro` is an introspection provider for the `osi` plugin. - -APIs and Callbacks ------------------- - -None. - -Example -------- - -Running `osi_test` on an Windows XP 32-bit replay: - - $PANDA_PATH/i386-softmmu/panda-system-i386 -replay foo \ - -panda osi -panda win7x86intro -panda osi_test diff --git a/panda/plugins/winxpx86intro/winxpx86intro.cpp b/panda/plugins/winxpx86intro/winxpx86intro.cpp deleted file mode 100644 index 8d8940f2e8b..00000000000 --- a/panda/plugins/winxpx86intro/winxpx86intro.cpp +++ /dev/null @@ -1,179 +0,0 @@ -/* PANDABEGINCOMMENT - * - * Authors: - * Tim Leek tleek@ll.mit.edu - * Ryan Whelan rwhelan@ll.mit.edu - * Joshua Hodosh josh.hodosh@ll.mit.edu - * Michael Zhivich mzhivich@ll.mit.edu - * Brendan Dolan-Gavitt brendandg@gatech.edu - * - * This work is licensed under the terms of the GNU GPL, version 2. - * See the COPYING file in the top-level directory. - * -PANDAENDCOMMENT */ -#define __STDC_FORMAT_MACROS - -#include "panda/plugin.h" -#include "panda/plugin_plugin.h" - -extern "C" { - -#include "osi/osi_types.h" -#include "osi/os_intro.h" - -#include "wintrospection/wintrospection.h" -#include "wintrospection/wintrospection_ext.h" - -bool init_plugin(void *); -void uninit_plugin(void *); -void on_get_mappings(CPUState *, OsiProc *p, GArray **out); -PTR get_winxp_kpcr(CPUState *cpu); -HandleObject *get_winxp_handle_object(CPUState *cpu, uint32_t eproc, - uint32_t handle); -PTR get_winxp_kdbg(CPUState *cpu); -} - -#include -#include - -#ifdef TARGET_I386 - -#define KPCR_KDVERSION_OFF 0x034 // _KPCR.KdVersionBlock -#define KDVERSION_DDL_OFF 0x020 // _DBGKD_GET_VERSION64.DebuggerDataList -#define OBJ_TYPE_INDEX_OFF 0x04c // _OBJECT_TYPE.Index - -// XXX: this will have to change for 64-bit -PTR get_winxp_kpcr(CPUState *cpu) -{ - return 0xFFDFF000; -} - -// i.e. return pointer to the object represented by this handle -static uint32_t get_handle_table_entry(CPUState *cpu, uint32_t pHandleTable, uint32_t handle) { - uint32_t tableCode, tableLevels; - // get tablecode - panda_virtual_memory_rw(cpu, pHandleTable, (uint8_t *)&tableCode, 4, false); - // extract levels - tableLevels = tableCode & LEVEL_MASK; - if (tableLevels > 2) { - return 0; - } - uint32_t pEntry=0; - if (tableLevels == 0) { - uint32_t index = (handle & HANDLE_MASK1) >> HANDLE_SHIFT1; - pEntry = handle_table_L1_entry(cpu, pHandleTable, index); - } - if (tableLevels == 1) { - uint32_t L1_index = (handle & HANDLE_MASK2) >> HANDLE_SHIFT2; - uint32_t L1_table_off = handle_table_L1_addr(cpu, pHandleTable, L1_index); - uint32_t L1_table; - panda_virtual_memory_rw(cpu, L1_table_off, (uint8_t *) &L1_table, 4, false); - uint32_t index = (handle & HANDLE_MASK1) >> HANDLE_SHIFT1; - pEntry = handle_table_L2_entry(pHandleTable, L1_table, index); - } - if (tableLevels == 2) { - uint32_t L1_index = (handle & HANDLE_MASK3) >> HANDLE_SHIFT3; - uint32_t L1_table_off = handle_table_L1_addr(cpu, pHandleTable, L1_index); - uint32_t L1_table; - panda_virtual_memory_rw(cpu, L1_table_off, (uint8_t *) &L1_table, 4, false); - uint32_t L2_index = (handle & HANDLE_MASK2) >> HANDLE_SHIFT2; - uint32_t L2_table_off = handle_table_L2_addr(L1_table, L2_index); - uint32_t L2_table; - panda_virtual_memory_rw(cpu, L2_table_off, (uint8_t *) &L2_table, 4, false); - uint32_t index = (handle & HANDLE_MASK1) >> HANDLE_SHIFT1; - pEntry = handle_table_L3_entry(pHandleTable, L2_table, index); - } - uint32_t pObjectHeader; - if ((panda_virtual_memory_rw(cpu, pEntry, (uint8_t *) &pObjectHeader, 4, false)) == -1) { - return 0; - } - - // Like in Windows 2000, the entry here needs to be masked off. However, the - // lock flag was moved to the low-order bit. So we only need to mask off the - // lower three bits of the entry. - // - // Russinovich, Mark E., and David A. Solomon. Microsoft Windows - // Internals, Fourth Edition: Microsoft Windows Server 2003, Windows XP, - // and Windows 2000. Microsoft Press, 2005, pp. 139. - pObjectHeader &= TABLE_MASK; - - return pObjectHeader; -} - -HandleObject *get_winxp_handle_object(CPUState *cpu, uint32_t eproc, - uint32_t handle) -{ - // Obtain the handle table (also called the object table). - uint32_t pObjectTable; - if (-1 == panda_virtual_memory_rw(cpu, eproc+get_eproc_objtable_off(), (uint8_t *)&pObjectTable, 4, false)) { - return NULL; - } - - // Given the handle, lookup the object's header in the table. - uint32_t pObjHeader = get_handle_table_entry(cpu, pObjectTable, handle); - if (pObjHeader == 0) { - return NULL; - } - - // Once we have the header, we can get the object's body. - uint32_t pObj = pObjHeader + OBJECT_HEADER_BODY_OFFSET; - - // In Windows XP, we need to look at the _OBJECT_TYPE struct to get the type - // index. - uint32_t pObjType; - if (-1 == panda_virtual_memory_read(cpu, pObjHeader + get_obj_type_offset(), - (uint8_t *)&pObjType, - sizeof(pObjType))) { - return NULL; - } - uint8_t objType = 0; - if (-1 == panda_virtual_memory_read(cpu, pObjType + OBJ_TYPE_INDEX_OFF, - (uint8_t *)&objType, sizeof(objType))) { - return NULL; - } - - // Construct our handle object and return. - HandleObject *ho = (HandleObject *) malloc(sizeof(HandleObject)); - ho->objType = objType; - ho->pObj = pObj; - return ho; -} - -PTR get_winxp_kdbg(CPUState *cpu) -{ - PTR kpcr = get_winxp_kpcr(cpu); - PTR kdversion, kddl, kddlp; - if (-1 == panda_virtual_memory_rw(cpu, kpcr + KPCR_KDVERSION_OFF, - (uint8_t *)&kdversion, sizeof(PTR), - false)) { - return 0; - } - // DebuggerDataList is a pointer to a pointer to the _KDDEBUGGER_DATA64 - // So we need to dereference it twice. - if (-1 == panda_virtual_memory_rw(cpu, kdversion + KDVERSION_DDL_OFF, - (uint8_t *)&kddlp, sizeof(PTR), false)) { - return 0; - } - if (-1 == panda_virtual_memory_rw(cpu, kddlp, (uint8_t *)&kddl, sizeof(PTR), - false)) { - return 0; - } - - kddl = panda_virt_to_phys(cpu, kddl); - - return kddl; -} - -#endif - -bool init_plugin(void *self) { -#ifdef TARGET_I386 - init_wintrospection_api(); - return true; -#else - return false; -#endif - -} - -void uninit_plugin(void *self) { } diff --git a/panda/plugins/winxpx86intro/winxpx86intro_int.h b/panda/plugins/winxpx86intro/winxpx86intro_int.h deleted file mode 100644 index 1ba861e3c26..00000000000 --- a/panda/plugins/winxpx86intro/winxpx86intro_int.h +++ /dev/null @@ -1,6 +0,0 @@ -typedef void PTR; -typedef void CPUState; -typedef void HandleObject; -typedef void uint32_t; - -#include "winxpx86intro_int_fns.h" diff --git a/panda/plugins/winxpx86intro/winxpx86intro_int_fns.h b/panda/plugins/winxpx86intro/winxpx86intro_int_fns.h deleted file mode 100644 index d1b9e439e72..00000000000 --- a/panda/plugins/winxpx86intro/winxpx86intro_int_fns.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef __WIN7X86INTRO_INT_FNS_H__ -#define __WIN7X86INTRO_INT_FNS_H__ - -PTR get_winxp_kpcr(CPUState *cpu); -HandleObject *get_winxp_handle_object(CPUState *cpu, uint32_t eproc, uint32_t handle); -PTR get_winxp_kdbg(CPUState *cpu); - -#endif diff --git a/panda/scripts/install_ubuntu.sh b/panda/scripts/install_ubuntu.sh index d4b53cf2db6..e7e38b04ee3 100755 --- a/panda/scripts/install_ubuntu.sh +++ b/panda/scripts/install_ubuntu.sh @@ -112,6 +112,22 @@ if [[ !$(ldconfig -p | grep -q libcapstone.so.4) ]]; then popd fi +# if the windows introspection library is not installed, clone and install +if [[ !$(dpkg -l | grep -q libosi) ]]; then + libosi_name=libosi-$(date +"%Y%m%d") + libosi_branch=dev + libosi_repo=https://github.com/panda-re/wintrospection + + echo "Installing libosi" + pushd . + git clone -b $libosi_branch $libosi_repo $libosi_name && cd $_ + mkdir build && cd $_ + cmake -GNinja .. && \ + ninja && ninja package && \ + $SUDO dpkg -i libosi*.deb + popd && rm -rf $libosi_name +fi + # PyPANDA needs CFFI from pip (the version in apt is too old) # Install system-wide since PyPANDA install will also be system-wide $SUDO python3 -m pip install pip diff --git a/panda/src/common.c b/panda/src/common.c index 560f3b87887..764b812cc98 100644 --- a/panda/src/common.c +++ b/panda/src/common.c @@ -162,9 +162,8 @@ void panda_disas(FILE *out, void *code, unsigned long size) { // regular expressions used to validate the -os option const char * valid_os_re[] = { - "windows[-_]32[-_]xpsp[23]", - "windows[-_]32[-_]7", - "windows[-_]32[-_]2000", + "windows[-_]32[-_]7sp[01]", + "windows[-_]64[-_]7sp[01]", "linux[-_]32[-_].+", "linux[-_]64[-_].+", "freebsd[-_]32[-_].+", From d2ac2eb4f0ba1e0478e6fbdea80cc0224954929e Mon Sep 17 00:00:00 2001 From: Ben-Dumas Date: Mon, 18 Oct 2021 18:32:45 -0400 Subject: [PATCH 02/18] testing file_taint --- panda/plugins/syscalls2/syscalls2.cpp | 2 +- .../plugins/wintrospection/wintrospection.cpp | 38 +++++++++++-------- 2 files changed, 24 insertions(+), 16 deletions(-) diff --git a/panda/plugins/syscalls2/syscalls2.cpp b/panda/plugins/syscalls2/syscalls2.cpp index 2554a3c81e0..507bcd6c7b0 100644 --- a/panda/plugins/syscalls2/syscalls2.cpp +++ b/panda/plugins/syscalls2/syscalls2.cpp @@ -1059,7 +1059,7 @@ bool init_plugin(void *self) { std::cerr << PANDA_MSG "using profile for windows sp3 x86 32-bit" << std::endl; syscalls_profile = &profiles[PROFILE_WINDOWS_XPSP3_X86]; } - if (0 == strcmp(panda_os_variant, "7")) { + if (0 == strncmp(panda_os_variant, "7", 1)) { std::cerr << PANDA_MSG "using profile for windows 7 x86 32-bit" << std::endl; syscalls_profile = &profiles[PROFILE_WINDOWS_7_X86]; } diff --git a/panda/plugins/wintrospection/wintrospection.cpp b/panda/plugins/wintrospection/wintrospection.cpp index 7fbcecac854..90fd71bef83 100644 --- a/panda/plugins/wintrospection/wintrospection.cpp +++ b/panda/plugins/wintrospection/wintrospection.cpp @@ -49,6 +49,10 @@ PANDAENDCOMMENT */ extern "C" { bool init_plugin(void *); void uninit_plugin(void *); + +int64_t get_file_handle_pos(uint64_t handle); +char *get_cwd(void); +char *get_handle_name(uint64_t handle); } void on_get_current_thread(CPUState *cpu, OsiThread *out); @@ -178,20 +182,19 @@ int64_t get_file_handle_pos(uint64_t handle) { auto kernel = g_kernel_manager->get_kernel_object(); WindowsHandleObject *h = resolve_handle(kernel, handle); - auto ptr = handle_get_pointer(h); - if (!ptr) { - return -1; - } - + uint64_t ptr; int64_t file_pos = -1; - try { - auto file = g_process_manager->get_type(ptr, "_FILE_OBJECT"); - file_pos = file["CurrentByteOffset"].get64(); - } catch (std::runtime_error const &) { - // runtime_error is raised when a virtual memory read fails - // it's the equiv of (-1 == panda_virtual_memory_rw(...)) + if (h != nullptr && (ptr = handle_get_pointer(h))) { + try { + auto file = g_process_manager->get_type(ptr, "_FILE_OBJECT"); + file_pos = file["CurrentByteOffset"].get64(); + } catch (std::runtime_error const &) { + // runtime_error is raised when a virtual memory read fails + // it's the equiv of (-1 == panda_virtual_memory_rw(...)) + } } + free_handle(h); return file_pos; } @@ -217,17 +220,22 @@ char *get_cwd(void) { params = peb("ProcessParameters"); } - auto dir = osi::ustring(params["CurrentDirectory"]); - std::string path = dir.as_utf8(); + auto dospath = osi::ustring(params["CurrentDirectory"]["DosPath"]); + std::string path = dospath.as_utf8(); return strdup(path.c_str()); } char *get_handle_name(uint64_t handle) { auto kernel = g_kernel_manager->get_kernel_object(); WindowsHandleObject *h = resolve_handle(kernel, handle); + if (!h) + return strdup("unknown"); + + auto tmp = extract_handle_name(h); + char *name = strdup(tmp.c_str()); - auto name = extract_handle_name(h); - return strdup(name.c_str()); + free_handle(h); + return name; } /* ****************************************************************** From a79f36ebde7791a94a865b4480c9ba5d8bf6866e Mon Sep 17 00:00:00 2001 From: Ben-Dumas Date: Tue, 19 Oct 2021 19:47:40 -0400 Subject: [PATCH 03/18] add missing system asids --- panda/plugins/wintrospection/wintrospection.cpp | 9 +++++++-- panda/src/common.c | 2 ++ 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/panda/plugins/wintrospection/wintrospection.cpp b/panda/plugins/wintrospection/wintrospection.cpp index 90fd71bef83..a050e0630c9 100644 --- a/panda/plugins/wintrospection/wintrospection.cpp +++ b/panda/plugins/wintrospection/wintrospection.cpp @@ -73,8 +73,13 @@ std::unique_ptr g_process_manager; bool g_update_task; static std::map system_asid_lookup = { - {"windows-32-7sp1", 0x185000}, - {"windows-64-7sp1", 0x187000}, + {"windows-32-2000", 0x0}, // TO-DO + {"windows-32-xpsp2", 0x39000}, + {"windows-32-xpsp3", 0x39000}, + {"windows-32-7sp0", 0x185000}, + {"windows-64-7sp0", 0x187000}, + {"windows-32-7sp1", 0x185000}, + {"windows-64-7sp1", 0x187000}, }; /* ****************************************************************** diff --git a/panda/src/common.c b/panda/src/common.c index 764b812cc98..2ed30f6f70f 100644 --- a/panda/src/common.c +++ b/panda/src/common.c @@ -162,6 +162,8 @@ void panda_disas(FILE *out, void *code, unsigned long size) { // regular expressions used to validate the -os option const char * valid_os_re[] = { + "windows[-_]32[-_]xpsp[23]", + "windows[-_]32[-_]2000", "windows[-_]32[-_]7sp[01]", "windows[-_]64[-_]7sp[01]", "linux[-_]32[-_].+", From ec510bc6f9bd8a2e5c2dd587e50072d90a01f627 Mon Sep 17 00:00:00 2001 From: Ben-Dumas Date: Fri, 22 Oct 2021 16:02:07 -0400 Subject: [PATCH 04/18] memory leak, null process bug --- panda/plugins/wintrospection/wintrospection.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/panda/plugins/wintrospection/wintrospection.cpp b/panda/plugins/wintrospection/wintrospection.cpp index a050e0630c9..2af5cedf50d 100644 --- a/panda/plugins/wintrospection/wintrospection.cpp +++ b/panda/plugins/wintrospection/wintrospection.cpp @@ -315,8 +315,12 @@ void on_get_current_process(CPUState *cpu, OsiProc **out) { OsiProc *p = (OsiProc *)g_malloc(sizeof(OsiProc)); auto proc = g_process_manager->get_process_object(); - auto kernel = g_kernel_manager->get_kernel_object(); + if (proc->eprocess_address == 0) { + *out = NULL; + return; + } + auto kernel = g_kernel_manager->get_kernel_object(); WindowsProcess *process = create_process(kernel, proc->eprocess_address); fill_process(p, process); free_process(process); @@ -519,6 +523,8 @@ uint64_t get_kpcr_amd64(CPUState *cpu) { // it has been swapped into GS kpcr = env->segs[R_GS].base; } + + free_member_result(mr); return kpcr; #endif return 0; From 3500dd56ce6036076818dff3ffed5f38d0fa8f24 Mon Sep 17 00:00:00 2001 From: Ben-Dumas Date: Fri, 29 Oct 2021 16:47:56 -0400 Subject: [PATCH 05/18] support windows2k --- panda/plugins/wintrospection/wintrospection.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/panda/plugins/wintrospection/wintrospection.cpp b/panda/plugins/wintrospection/wintrospection.cpp index 2af5cedf50d..b821f3a9e60 100644 --- a/panda/plugins/wintrospection/wintrospection.cpp +++ b/panda/plugins/wintrospection/wintrospection.cpp @@ -73,7 +73,7 @@ std::unique_ptr g_process_manager; bool g_update_task; static std::map system_asid_lookup = { - {"windows-32-2000", 0x0}, // TO-DO + {"windows-32-2000", 0x30000}, {"windows-32-xpsp2", 0x39000}, {"windows-32-xpsp3", 0x39000}, {"windows-32-7sp0", 0x185000}, @@ -105,6 +105,12 @@ void fill_module(OsiModule *m, struct WindowsModuleEntry *win_mod) { } std::string get_key_name(uint64_t ptr) { + if (strncmp(panda_os_name, "windows-32-2000", 15) == 0) { + // just keep previous functionality for windows 2k, + // as we couldn't verify the fancy functionality works + return std::string("_CM_KEY_BODY@0x") + std::to_string(ptr); + } + auto object = g_process_manager->get_type(ptr, "_CM_KEY_BODY"); osi::i_t nameblock; From 93fd998c7dff53eb83af55c431c372f450708205 Mon Sep 17 00:00:00 2001 From: Ben-Dumas Date: Thu, 2 Dec 2021 11:27:52 -0500 Subject: [PATCH 06/18] update Dockerfile --- Dockerfile | 7 +++++++ panda/scripts/install_ubuntu.sh | 4 ++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index 926babd76c1..a0e4774de7a 100644 --- a/Dockerfile +++ b/Dockerfile @@ -39,6 +39,13 @@ ENV PATH="/root/.cargo/bin:${PATH}" # Sanity check to ensure cargo is installed RUN cargo --help +# install libosi +RUN cd /tmp && \ + git clone https://github.com/panda-re/libosi && \ + mkdir libosi/build && cd $_ && \ + cmake -GNinja .. && ninja && ninja package && dpkg -i libosi*.deb && \ + cd /tmp && rm -rf libosi/ + # Build and install panda # Copy repo root directory to /panda, note we explicitly copy in .git directory # Note .dockerignore file keeps us from copying things we don't need diff --git a/panda/scripts/install_ubuntu.sh b/panda/scripts/install_ubuntu.sh index e7e38b04ee3..2a143a3e13c 100755 --- a/panda/scripts/install_ubuntu.sh +++ b/panda/scripts/install_ubuntu.sh @@ -115,8 +115,8 @@ fi # if the windows introspection library is not installed, clone and install if [[ !$(dpkg -l | grep -q libosi) ]]; then libosi_name=libosi-$(date +"%Y%m%d") - libosi_branch=dev - libosi_repo=https://github.com/panda-re/wintrospection + libosi_branch=master + libosi_repo=https://github.com/panda-re/libosi echo "Installing libosi" pushd . From 3cbeaee399cf8eb4cd1e8515e96717adacf0e82e Mon Sep 17 00:00:00 2001 From: Ben-Dumas Date: Mon, 6 Dec 2021 13:43:22 -0500 Subject: [PATCH 07/18] fix Dockerfile --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index a0e4774de7a..f6f8b0eb9f8 100644 --- a/Dockerfile +++ b/Dockerfile @@ -42,7 +42,7 @@ RUN cargo --help # install libosi RUN cd /tmp && \ git clone https://github.com/panda-re/libosi && \ - mkdir libosi/build && cd $_ && \ + mkdir /tmp/libosi/build && cd /tmp/libosi/build && \ cmake -GNinja .. && ninja && ninja package && dpkg -i libosi*.deb && \ cd /tmp && rm -rf libosi/ From a6554cbf38f1599b91a7f32df890ce89f5ad134b Mon Sep 17 00:00:00 2001 From: Ben-Dumas Date: Mon, 13 Dec 2021 11:15:53 -0500 Subject: [PATCH 08/18] max memory address can be larger than ram_size --- panda/plugins/wintrospection/pandamemory.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/panda/plugins/wintrospection/pandamemory.cpp b/panda/plugins/wintrospection/pandamemory.cpp index c82bbca42b1..4c2312b0d20 100644 --- a/panda/plugins/wintrospection/pandamemory.cpp +++ b/panda/plugins/wintrospection/pandamemory.cpp @@ -16,7 +16,12 @@ class PandaPhysicalMemory { public: static const uint32_t PAPM_TAG = 0x5041504d; - PandaPhysicalMemory() { m_max_address = ram_size; } + PandaPhysicalMemory() { + rcu_read_lock(); + MemoryRegion *region = panda_find_ram(); + m_max_address = region->size + region->addr; + rcu_read_unlock(); + } pm_addr_t get_max_address() { return m_max_address; } From 9b31e80e9f0be66f6b07fcd2d55a8c5185821409 Mon Sep 17 00:00:00 2001 From: Ben-Dumas Date: Mon, 13 Dec 2021 13:00:40 -0500 Subject: [PATCH 09/18] check for pae --- .../plugins/wintrospection/wintrospection.cpp | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/panda/plugins/wintrospection/wintrospection.cpp b/panda/plugins/wintrospection/wintrospection.cpp index b821f3a9e60..1442c3106a9 100644 --- a/panda/plugins/wintrospection/wintrospection.cpp +++ b/panda/plugins/wintrospection/wintrospection.cpp @@ -536,6 +536,21 @@ uint64_t get_kpcr_amd64(CPUState *cpu) { return 0; } +bool is_windows_pae_enabled(CPUState* cpu) { +#if defined(TARGET_I386) + // windows only uses PAE on 32-bit systems for x86 + if (panda_os_bits == 32) { + CPUArchState *env = (CPUArchState *)cpu->env_ptr; + + bool cr0_paging_enabled = env->cr[0] & 0x80000000; + bool cr4_pae_enabled = env->cr[4] & 0x20; + + return cr0_paging_enabled && cr4_pae_enabled; + } +#endif + return false; +} + void initialize_introspection(CPUState *cpu) { auto pmem = create_panda_physical_memory(); if (!pmem) { @@ -552,9 +567,8 @@ void initialize_introspection(CPUState *cpu) { auto kpcr = (panda_os_bits == 64) ? get_kpcr_amd64(cpu) : get_kpcr_i386(cpu); auto width = (panda_os_bits == 64) ? 8 : 4; - // BDD : last argument should be panda_pae_enabled auto success = g_kernel_manager->initialize(pmem, width, asid_entry->second, - kpcr, false); + kpcr, is_windows_pae_enabled(cpu)); if (!success) { fprintf(stderr, "Error initializing kernel manager\n"); exit(3); From fcd26ede117337fe68610391d4451a508f41201f Mon Sep 17 00:00:00 2001 From: Luke Craig Date: Thu, 16 Dec 2021 21:21:49 -0500 Subject: [PATCH 10/18] add pypanda example for library --- panda/python/examples/example_win.py | 36 ++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100755 panda/python/examples/example_win.py diff --git a/panda/python/examples/example_win.py b/panda/python/examples/example_win.py new file mode 100755 index 00000000000..bd153dab8d1 --- /dev/null +++ b/panda/python/examples/example_win.py @@ -0,0 +1,36 @@ +#!/usr/bin/env python3 +''' +example_win.py + +This is an example for taking a recording of windows and then replaying it and +using it to do analysis. +''' +from pandare import Panda + +rec = False + +if rec: + panda = Panda(qcow="win7pro_x86.qcow2",mem="4G", extra_args=["-vnc", "127.0.0.1:5900", "-monitor","telnet:127.0.0.1:55555,server,nowait"]) +else: + panda = Panda(qcow="win7pro_x86.qcow2",mem="4G", extra_args=["-nographic"],os_version="windows-32-7") + +first = True + +@panda.cb_asid_changed +def asidchange(cpu, old_asid, new_asid): + if old_asid != new_asid: + global first + if first: + print("processes:") + for proc in panda.get_processes(cpu): + print(f"{panda.ffi.string(proc.name)} {proc.pid} {proc.ppid}") + first = False + else: + print(f"process: {panda.get_process_name(cpu)}") + return 0 + +if rec: + panda.run() +else: + panda.run_replay("rec_name") + From ce6ce7aed8efae1d553d6ef583adca8a10b1dcb3 Mon Sep 17 00:00:00 2001 From: Ben-Dumas Date: Fri, 17 Dec 2021 10:54:06 -0500 Subject: [PATCH 11/18] change before_block to start_block --- .../plugins/wintrospection/wintrospection.cpp | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/panda/plugins/wintrospection/wintrospection.cpp b/panda/plugins/wintrospection/wintrospection.cpp index 1442c3106a9..12428d416e6 100644 --- a/panda/plugins/wintrospection/wintrospection.cpp +++ b/panda/plugins/wintrospection/wintrospection.cpp @@ -1,11 +1,9 @@ /* PANDABEGINCOMMENT * * Authors: - * Tim Leek tleek@ll.mit.edu - * Ryan Whelan rwhelan@ll.mit.edu - * Joshua Hodosh josh.hodosh@ll.mit.edu - * Michael Zhivich mzhivich@ll.mit.edu - * Brendan Dolan-Gavitt brendandg@gatech.edu + * Ben Dumas benjamin.dumas@ll.mit.edu + * Nick Gillum nicholas.gillum@ll.mit.edu + * Lisa Baer lisa.baer@ll.mit.edu * * This work is licensed under the terms of the GNU GPL, version 2. * See the COPYING file in the top-level directory. @@ -455,7 +453,7 @@ void update_process_manager() { kosi_get_current_process_address(kernel)); } -void before_block_exec(CPUState *cpu, TranslationBlock *tb) { +void start_block_exec(CPUState *cpu, TranslationBlock *tb) { if (!g_update_task) return; @@ -586,8 +584,8 @@ bool init_plugin(void *self) { panda_cb pcb; - pcb.before_block_exec = before_block_exec; - panda_register_callback(self, PANDA_CB_BEFORE_BLOCK_EXEC, pcb); + pcb.start_block_exec = start_block_exec; + panda_register_callback(self, PANDA_CB_START_BLOCK_EXEC, pcb); pcb.asid_changed = asid_changed; panda_register_callback(self, PANDA_CB_ASID_CHANGED, pcb); pcb.after_loadvm = initialize_introspection; @@ -615,8 +613,4 @@ bool init_plugin(void *self) { void uninit_plugin(void *self) { printf("Unloading wintrospection plugin\n"); - - // if we don't clear tb's when this exits we have TBs which can call - // into our exited plugin. - panda_do_flush_tb(); } From 1e1d8f9ae4a25621fd5d8e325f161e51189ebf57 Mon Sep 17 00:00:00 2001 From: Ben-Dumas Date: Fri, 17 Dec 2021 14:30:50 -0500 Subject: [PATCH 12/18] read the entire pmem request at once --- panda/plugins/wintrospection/pandamemory.cpp | 18 +++--------------- 1 file changed, 3 insertions(+), 15 deletions(-) diff --git a/panda/plugins/wintrospection/pandamemory.cpp b/panda/plugins/wintrospection/pandamemory.cpp index 4c2312b0d20..47a82703768 100644 --- a/panda/plugins/wintrospection/pandamemory.cpp +++ b/panda/plugins/wintrospection/pandamemory.cpp @@ -24,14 +24,6 @@ class PandaPhysicalMemory { } pm_addr_t get_max_address() { return m_max_address; } - - uint8_t get_byte(pm_addr_t addr) { - uint8_t retval = 0; - if (addr < m_max_address) { - panda_physical_memory_rw(addr, &retval, 1, 0); - } - return retval; - } }; pm_addr_t get_panda_physical_memory_upper_bound(struct PhysicalMemory *pmem) { @@ -44,14 +36,10 @@ bool read_panda_physical_memory(struct PhysicalMemory *pmem, pm_addr_t addr, auto papm = (PandaPhysicalMemory *)pmem->opaque; auto max_addr = papm->get_max_address(); - for (size_t ix = 0; ix < size; ++ix) { - auto current_addr = addr + ix; - if ((uintptr_t)current_addr > max_addr) { - return false; - } - buffer[ix] = papm->get_byte(current_addr); + if ((addr + size) > max_addr) { + return false; } - return true; + return 0 == panda_physical_memory_rw(addr, buffer, size, 0); } void free_panda_physical_memory(struct PhysicalMemory *pmem) { From 183eb63d12f7e1b45d9e5a73dd66c9d3643436a7 Mon Sep 17 00:00:00 2001 From: Ben-Dumas Date: Fri, 17 Dec 2021 14:52:04 -0500 Subject: [PATCH 13/18] use helper read fn --- panda/plugins/wintrospection/pandamemory.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/panda/plugins/wintrospection/pandamemory.cpp b/panda/plugins/wintrospection/pandamemory.cpp index 47a82703768..ca00b36c268 100644 --- a/panda/plugins/wintrospection/pandamemory.cpp +++ b/panda/plugins/wintrospection/pandamemory.cpp @@ -39,7 +39,7 @@ bool read_panda_physical_memory(struct PhysicalMemory *pmem, pm_addr_t addr, if ((addr + size) > max_addr) { return false; } - return 0 == panda_physical_memory_rw(addr, buffer, size, 0); + return 0 == panda_physical_memory_read(addr, buffer, size); } void free_panda_physical_memory(struct PhysicalMemory *pmem) { From 5a0c2e589a7b0d52868608d34802adce7426758a Mon Sep 17 00:00:00 2001 From: Ben-Dumas Date: Tue, 4 Jan 2022 11:02:06 -0500 Subject: [PATCH 14/18] add method for getting the max ram address --- panda/include/panda/common.h | 5 ++++ panda/plugins/wintrospection/pandamemory.cpp | 3 +-- panda/src/common.c | 27 ++++++++++++++++++++ 3 files changed, 33 insertions(+), 2 deletions(-) diff --git a/panda/include/panda/common.h b/panda/include/panda/common.h index 2950668e18b..e5b14a5a84f 100644 --- a/panda/include/panda/common.h +++ b/panda/include/panda/common.h @@ -70,6 +70,11 @@ target_ulong panda_current_pc(CPUState *cpu); // END_PYPANDA_NEEDS_THIS -- do not delete this comment! +/** + * @brief Return the max address of system memory that maps to RAM. + */ +Int128 panda_find_max_ram_address(void); + /** * @brief Reads/writes data into/from \p buf from/to guest physical address \p addr. */ diff --git a/panda/plugins/wintrospection/pandamemory.cpp b/panda/plugins/wintrospection/pandamemory.cpp index ca00b36c268..2805ab73773 100644 --- a/panda/plugins/wintrospection/pandamemory.cpp +++ b/panda/plugins/wintrospection/pandamemory.cpp @@ -18,8 +18,7 @@ class PandaPhysicalMemory { PandaPhysicalMemory() { rcu_read_lock(); - MemoryRegion *region = panda_find_ram(); - m_max_address = region->size + region->addr; + m_max_address = panda_find_max_ram_address(); rcu_read_unlock(); } diff --git a/panda/src/common.c b/panda/src/common.c index 2ed30f6f70f..d29be2e2b0d 100644 --- a/panda/src/common.c +++ b/panda/src/common.c @@ -257,6 +257,33 @@ MemoryRegion* panda_find_ram(void) { return ram; } +/* Return the max address of system memory that maps to RAM. */ +Int128 panda_find_max_ram_address(void) { + Int128 curr_max = 0; + Int128 mr_check_max; + + MemoryRegion *sys_mem = get_system_memory(); + MemoryRegion *mr_check; + MemoryRegion *mr_iter; + + QTAILQ_FOREACH(mr_iter, &(sys_mem->subregions), subregions_link) { + mr_check = mr_iter; + + // if this region is a RAM region OR is aliased to a RAM region, check the max address + if ((mr_iter->alias && memory_region_is_ram(mr_iter->alias)) || memory_region_is_ram(mr_check)) { + mr_check_max = mr_check->addr + memory_region_size(mr_check); + } else { + mr_check_max = 0; + } + + if (mr_check_max > curr_max) { + curr_max = mr_check_max; + } + } + + return curr_max; +} + #ifdef TARGET_ARM #define CPSR_M (0x1fU) #define ARM_CPU_MODE_SVC 0x13 From a88a22bebc4570351eaa12e4732560dca74746f1 Mon Sep 17 00:00:00 2001 From: Ben-Dumas Date: Tue, 4 Jan 2022 14:12:30 -0500 Subject: [PATCH 15/18] support exact task swaps when possible --- .../plugins/wintrospection/wintrospection.cpp | 69 ++++++++++++++++--- 1 file changed, 61 insertions(+), 8 deletions(-) diff --git a/panda/plugins/wintrospection/wintrospection.cpp b/panda/plugins/wintrospection/wintrospection.cpp index 12428d416e6..6e3b4232c64 100644 --- a/panda/plugins/wintrospection/wintrospection.cpp +++ b/panda/plugins/wintrospection/wintrospection.cpp @@ -35,6 +35,7 @@ PANDAENDCOMMENT */ #include "panda/plugin.h" #include "panda/plugin_plugin.h" +#include "panda/tcg-utils.h" #include "../osi/osi_types.h" #include "../osi/osi_ext.h" @@ -69,6 +70,13 @@ void on_get_mappings(CPUState *cpu, OsiProc *p, GArray **out); std::unique_ptr g_kernel_manager; std::unique_ptr g_process_manager; bool g_update_task; +uint64_t swapcontext_address = 0; + +// globals for toggling callbacks +void* self = NULL; +panda_cb pcb_asid; +panda_cb pcb_startblock; +panda_cb pcb_tcgcodegen; static std::map system_asid_lookup = { {"windows-32-2000", 0x30000}, @@ -377,7 +385,6 @@ void on_get_modules(CPUState *cpu, GArray **out) { auto ldr_table = g_kernel_manager->get_type( kernel->details.PsLoadedModuleList, "_LDR_DATA_TABLE_ENTRY"); osi::iterator pitr(ldr_table, "InLoadOrderLinks"); - pitr++; // skip head_sentinel do { auto entry = *pitr; @@ -472,6 +479,16 @@ bool asid_changed(CPUState *cpu, target_ulong old_pgd, target_ulong new_pgd) { return false; } +void before_tcg_codegen(CPUState *cpu, TranslationBlock *tb) +{ + if ((tb->pc <= swapcontext_address) && (swapcontext_address < tb->pc + tb->size)) { + TCGOp *op = find_guest_insn_by_addr(swapcontext_address); + if (op) { + insert_call_1p(&op, (void(*)(void*))notify_task_change, cpu); + } + } +} + /** * Get the Kernel Processor Control Region (KPCR) on a 32-bit system * @@ -575,19 +592,52 @@ void initialize_introspection(CPUState *cpu) { g_process_manager = std::unique_ptr(new WindowsProcessManager()); update_process_manager(); + + uint64_t swapcontext_offset = g_kernel_manager->get_swapcontext_offset(); + + // we do not know exactly when a nt!SwapContext executes, and we must use the + // ASID change heuristic. + if (swapcontext_offset == 0x0) { + panda_disable_callback(self, PANDA_CB_BEFORE_TCG_CODEGEN, pcb_tcgcodegen); + return; + } + + GArray *mods = get_modules(cpu); + for (int i = 0; i < mods->len; i++) { + OsiModule *mod = &g_array_index(mods, OsiModule, i); + if (0 == strcmp("ntoskrnl.exe", mod->name)) { + swapcontext_address = mod->base + swapcontext_offset; + } + } + if (NULL != mods) { + g_array_free(mods, true); + } + + if (swapcontext_address == 0x0) { + fprintf(stderr, "Error finding ntoskrnl! Defaulting to ASID change heuristic.\n"); + panda_disable_callback(self, PANDA_CB_BEFORE_TCG_CODEGEN, pcb_tcgcodegen); + } else { + panda_disable_callback(self, PANDA_CB_START_BLOCK_EXEC, pcb_startblock); + panda_disable_callback(self, PANDA_CB_ASID_CHANGED, pcb_asid); + } } -bool init_plugin(void *self) { +bool init_plugin(void *_self) { #if defined(TARGET_I386) // only supports i386 and x86_64 panda_require("osi"); assert(init_osi_api()); + self = _self; - panda_cb pcb; + pcb_startblock.start_block_exec = start_block_exec; + panda_register_callback(self, PANDA_CB_START_BLOCK_EXEC, pcb_startblock); + + pcb_asid.asid_changed = asid_changed; + panda_register_callback(self, PANDA_CB_ASID_CHANGED, pcb_asid); - pcb.start_block_exec = start_block_exec; - panda_register_callback(self, PANDA_CB_START_BLOCK_EXEC, pcb); - pcb.asid_changed = asid_changed; - panda_register_callback(self, PANDA_CB_ASID_CHANGED, pcb); + pcb_tcgcodegen.before_tcg_codegen = before_tcg_codegen; + panda_register_callback(self, PANDA_CB_BEFORE_TCG_CODEGEN, pcb_tcgcodegen); + + panda_cb pcb; pcb.after_loadvm = initialize_introspection; panda_register_callback(self, PANDA_CB_AFTER_LOADVM, pcb); @@ -611,6 +661,9 @@ bool init_plugin(void *self) { return false; } -void uninit_plugin(void *self) { +void uninit_plugin(void *_self) { printf("Unloading wintrospection plugin\n"); + // if we don't clear tb's when this exits we have TBs which can call + // into our exited plugin. + panda_do_flush_tb(); } From 271e5358c8d357f992698296833739a2b6426f3c Mon Sep 17 00:00:00 2001 From: Luke Craig Date: Tue, 4 Jan 2022 15:50:21 -0500 Subject: [PATCH 16/18] use hooks --- .../plugins/wintrospection/wintrospection.cpp | 36 ++++++++++++------- 1 file changed, 23 insertions(+), 13 deletions(-) diff --git a/panda/plugins/wintrospection/wintrospection.cpp b/panda/plugins/wintrospection/wintrospection.cpp index 6e3b4232c64..da6abb18899 100644 --- a/panda/plugins/wintrospection/wintrospection.cpp +++ b/panda/plugins/wintrospection/wintrospection.cpp @@ -40,11 +40,13 @@ PANDAENDCOMMENT */ #include "../osi/osi_types.h" #include "../osi/osi_ext.h" #include "../osi/os_intro.h" +#include #include "pandamemory.h" // These need to be extern "C" so that the ABI is compatible with // QEMU/PANDA, which is written in C +void (*hooks_add_hook)(struct hook*); extern "C" { bool init_plugin(void *); void uninit_plugin(void *); @@ -479,14 +481,8 @@ bool asid_changed(CPUState *cpu, target_ulong old_pgd, target_ulong new_pgd) { return false; } -void before_tcg_codegen(CPUState *cpu, TranslationBlock *tb) -{ - if ((tb->pc <= swapcontext_address) && (swapcontext_address < tb->pc + tb->size)) { - TCGOp *op = find_guest_insn_by_addr(swapcontext_address); - if (op) { - insert_call_1p(&op, (void(*)(void*))notify_task_change, cpu); - } - } +void task_change_hook(CPUState *cpu, TranslationBlock *tb, struct hook* h){ + notify_task_change(cpu); } /** @@ -598,7 +594,6 @@ void initialize_introspection(CPUState *cpu) { // we do not know exactly when a nt!SwapContext executes, and we must use the // ASID change heuristic. if (swapcontext_offset == 0x0) { - panda_disable_callback(self, PANDA_CB_BEFORE_TCG_CODEGEN, pcb_tcgcodegen); return; } @@ -615,10 +610,28 @@ void initialize_introspection(CPUState *cpu) { if (swapcontext_address == 0x0) { fprintf(stderr, "Error finding ntoskrnl! Defaulting to ASID change heuristic.\n"); - panda_disable_callback(self, PANDA_CB_BEFORE_TCG_CODEGEN, pcb_tcgcodegen); } else { + // disable ASID change heuristic panda_disable_callback(self, PANDA_CB_START_BLOCK_EXEC, pcb_startblock); panda_disable_callback(self, PANDA_CB_ASID_CHANGED, pcb_asid); + + // add hook for swapcontext_address + void *hooks = panda_get_plugin_by_name("hooks"); + if (hooks == NULL){ + panda_require("hooks"); + hooks = panda_get_plugin_by_name("hooks"); + } + hooks_add_hook = (void(*)(struct hook*)) dlsym(hooks, "add_hook"); + + // create hook for swapcontext_address + struct hook h; + h.addr = swapcontext_address; + h.asid = 0; // match any asid + h.cb.start_block_exec = task_change_hook; + h.type = PANDA_CB_START_BLOCK_EXEC; + h.enabled = true; + h.km = MODE_ANY; + hooks_add_hook(&h); } } @@ -634,9 +647,6 @@ bool init_plugin(void *_self) { pcb_asid.asid_changed = asid_changed; panda_register_callback(self, PANDA_CB_ASID_CHANGED, pcb_asid); - pcb_tcgcodegen.before_tcg_codegen = before_tcg_codegen; - panda_register_callback(self, PANDA_CB_BEFORE_TCG_CODEGEN, pcb_tcgcodegen); - panda_cb pcb; pcb.after_loadvm = initialize_introspection; panda_register_callback(self, PANDA_CB_AFTER_LOADVM, pcb); From aa0b90e676c85a8f1d8c02a2ae6f00b179647b21 Mon Sep 17 00:00:00 2001 From: Luke Craig Date: Tue, 4 Jan 2022 16:10:41 -0500 Subject: [PATCH 17/18] change to tabs (really just to kick the CI again) --- Dockerfile | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Dockerfile b/Dockerfile index 94096778c27..074eba55502 100644 --- a/Dockerfile +++ b/Dockerfile @@ -42,10 +42,10 @@ RUN cargo --help # install libosi RUN cd /tmp && \ - git clone https://github.com/panda-re/libosi && \ - mkdir /tmp/libosi/build && cd /tmp/libosi/build && \ - cmake -GNinja .. && ninja && ninja package && dpkg -i libosi*.deb && \ - cd /tmp && rm -rf libosi/ + git clone https://github.com/panda-re/libosi && \ + mkdir /tmp/libosi/build && cd /tmp/libosi/build && \ + cmake -GNinja .. && ninja && ninja package && dpkg -i libosi*.deb && \ + cd /tmp && rm -rf libosi/ # Build and install panda # Copy repo root directory to /panda, note we explicitly copy in .git directory From deee942ed2237201e7bb90428813e6b99fc7afc2 Mon Sep 17 00:00:00 2001 From: Ben-Dumas Date: Wed, 5 Jan 2022 13:10:36 -0500 Subject: [PATCH 18/18] initialize might happen mid-replay --- panda/plugins/file_taint/file_taint.cpp | 6 +- .../plugins/wintrospection/wintrospection.cpp | 105 +++++++++++++----- .../wintrospection/wintrospection_int.h | 1 + .../wintrospection/wintrospection_int_fns.h | 6 +- 4 files changed, 87 insertions(+), 31 deletions(-) diff --git a/panda/plugins/file_taint/file_taint.cpp b/panda/plugins/file_taint/file_taint.cpp index a418cb9015f..bd55f1b25ff 100644 --- a/panda/plugins/file_taint/file_taint.cpp +++ b/panda/plugins/file_taint/file_taint.cpp @@ -206,11 +206,11 @@ void windows_read_enter(CPUState *cpu, target_ulong pc, uint32_t FileHandle, uint32_t ByteOffset, uint32_t Key) { // get_handle_name will assert if the filename is null - char *filename = get_handle_name(FileHandle); + char *filename = get_handle_name(cpu, FileHandle); std::string ob_path = filename; // Check if the file handle is absolute, if not we need to make it absolute. if (filename[0] != '\\') { - char *cwd = get_cwd(); + char *cwd = get_cwd(cpu); ob_path = cwd; // If the cwd doesn't have a slash, add it. if (ob_path.back() != '\\') { @@ -220,7 +220,7 @@ void windows_read_enter(CPUState *cpu, target_ulong pc, uint32_t FileHandle, g_free(cwd); } verbose_printf("file_taint windows object path: %s\n", ob_path.c_str()); - int64_t pos = get_file_handle_pos(FileHandle); + int64_t pos = get_file_handle_pos(cpu, FileHandle); read_enter(ob_path, FileHandle, pos); g_free(filename); } diff --git a/panda/plugins/wintrospection/wintrospection.cpp b/panda/plugins/wintrospection/wintrospection.cpp index da6abb18899..2a575750828 100644 --- a/panda/plugins/wintrospection/wintrospection.cpp +++ b/panda/plugins/wintrospection/wintrospection.cpp @@ -69,16 +69,18 @@ void on_get_processes(CPUState *cpu, GArray **out); void on_get_modules(CPUState *cpu, GArray **out); void on_get_mappings(CPUState *cpu, OsiProc *p, GArray **out); +void initialize_introspection(CPUState *cpu); + std::unique_ptr g_kernel_manager; std::unique_ptr g_process_manager; -bool g_update_task; -uint64_t swapcontext_address = 0; + +bool g_initialized_kernel; +uint64_t swapcontext_address; // globals for toggling callbacks void* self = NULL; panda_cb pcb_asid; panda_cb pcb_startblock; -panda_cb pcb_tcgcodegen; static std::map system_asid_lookup = { {"windows-32-2000", 0x30000}, @@ -197,7 +199,11 @@ std::string extract_handle_name(struct WindowsHandleObject *handle) { Our Callbacks ****************************************************************** */ -int64_t get_file_handle_pos(uint64_t handle) { +int64_t get_file_handle_pos(CPUState *cpu, uint64_t handle) { + if (!g_initialized_kernel) { + initialize_introspection(cpu); + } + auto kernel = g_kernel_manager->get_kernel_object(); WindowsHandleObject *h = resolve_handle(kernel, handle); @@ -217,7 +223,11 @@ int64_t get_file_handle_pos(uint64_t handle) { return file_pos; } -char *get_cwd(void) { +char *get_cwd(CPUState *cpu) { + if (!g_initialized_kernel) { + initialize_introspection(cpu); + } + osi::i_t eproc = g_process_manager->get_process(); bool wow = false; @@ -244,7 +254,11 @@ char *get_cwd(void) { return strdup(path.c_str()); } -char *get_handle_name(uint64_t handle) { +char *get_handle_name(CPUState *cpu, uint64_t handle) { + if (!g_initialized_kernel) { + initialize_introspection(cpu); + } + auto kernel = g_kernel_manager->get_kernel_object(); WindowsHandleObject *h = resolve_handle(kernel, handle); if (!h) @@ -262,6 +276,10 @@ char *get_handle_name(uint64_t handle) { ****************************************************************** */ void on_get_current_thread(CPUState *cpu, OsiThread **out) { + if (!g_initialized_kernel) { + initialize_introspection(cpu); + } + OsiThread *t = (OsiThread *)g_malloc(sizeof(OsiThread)); auto proc = g_process_manager->get_process_object(); @@ -275,6 +293,10 @@ void on_get_current_thread(CPUState *cpu, OsiThread **out) { void on_get_process_pid(CPUState *cpu, const OsiProcHandle *h, target_pid_t *pid) { + if (!g_initialized_kernel) { + initialize_introspection(cpu); + } + if (h->taskd == (intptr_t)(NULL) || h->taskd == (target_ptr_t)-1) { *pid = (target_pid_t)-1; } else { @@ -283,6 +305,10 @@ void on_get_process_pid(CPUState *cpu, const OsiProcHandle *h, } void on_get_current_process_handle(CPUState *cpu, OsiProcHandle **out) { + if (!g_initialized_kernel) { + initialize_introspection(cpu); + } + OsiProcHandle *p = (OsiProcHandle *)g_malloc(sizeof(OsiProcHandle)); auto process = g_process_manager->get_process_object(); @@ -293,6 +319,10 @@ void on_get_current_process_handle(CPUState *cpu, OsiProcHandle **out) { } void on_get_process_handles(CPUState *cpu, GArray **out) { + if (!g_initialized_kernel) { + initialize_introspection(cpu); + } + if (*out == NULL) { *out = g_array_sized_new(false, false, sizeof(OsiProcHandle), 128); g_array_set_clear_func(*out, (GDestroyNotify)free_osiprochandle_contents); @@ -315,6 +345,10 @@ void on_get_process_handles(CPUState *cpu, GArray **out) { void on_get_process_ppid(CPUState *cpu, const OsiProcHandle *h, target_pid_t *ppid) { + if (!g_initialized_kernel) { + initialize_introspection(cpu); + } + if (h->taskd == (intptr_t)(NULL) || h->taskd == (target_ptr_t)-1) { *ppid = (target_pid_t)-1; } else { @@ -326,6 +360,10 @@ void on_get_process_ppid(CPUState *cpu, const OsiProcHandle *h, } void on_get_current_process(CPUState *cpu, OsiProc **out) { + if (!g_initialized_kernel) { + initialize_introspection(cpu); + } + OsiProc *p = (OsiProc *)g_malloc(sizeof(OsiProc)); auto proc = g_process_manager->get_process_object(); @@ -343,6 +381,10 @@ void on_get_current_process(CPUState *cpu, OsiProc **out) { } void on_get_process(CPUState *cpu, const OsiProcHandle *h, OsiProc **out) { + if (!g_initialized_kernel) { + initialize_introspection(cpu); + } + OsiProc *p = NULL; if (h != NULL && h->taskd != (target_ptr_t)NULL) { p = (OsiProc *)g_malloc(sizeof(OsiProc)); @@ -356,6 +398,10 @@ void on_get_process(CPUState *cpu, const OsiProcHandle *h, OsiProc **out) { } void on_get_processes(CPUState *cpu, GArray **out) { + if (!g_initialized_kernel) { + initialize_introspection(cpu); + } + if (*out == NULL) { *out = g_array_sized_new(false, false, sizeof(OsiProc), 128); g_array_set_clear_func(*out, (GDestroyNotify)free_osiproc_contents); @@ -376,6 +422,10 @@ void on_get_processes(CPUState *cpu, GArray **out) { } void on_get_modules(CPUState *cpu, GArray **out) { + if (!g_initialized_kernel) { + initialize_introspection(cpu); + } + if (*out == NULL) { // g_array_sized_new() args: zero_term, clear, element_sz, reserved_sz *out = g_array_sized_new(false, false, sizeof(OsiModule), 128); @@ -419,6 +469,10 @@ void on_get_modules(CPUState *cpu, GArray **out) { } void on_get_mappings(CPUState *cpu, OsiProc *p, GArray **out) { + if (!g_initialized_kernel) { + initialize_introspection(cpu); + } + if (p == NULL) { return; } @@ -456,33 +510,34 @@ void on_get_mappings(CPUState *cpu, OsiProc *p, GArray **out) { Initialization logic ****************************************************************** */ -void update_process_manager() { +void task_change(CPUState *cpu) { + g_process_manager.reset(new WindowsProcessManager()); + auto kernel = g_kernel_manager->get_kernel_object(); g_process_manager->initialize(kernel, kosi_get_current_process_address(kernel)); -} - -void start_block_exec(CPUState *cpu, TranslationBlock *tb) { - if (!g_update_task) - return; notify_task_change(cpu); +} - g_process_manager.reset(new WindowsProcessManager()); - update_process_manager(); - - g_update_task = false; +void start_block_exec(CPUState *cpu, TranslationBlock *tb) { + task_change(cpu); + panda_disable_callback(self, PANDA_CB_START_BLOCK_EXEC, pcb_startblock); } bool asid_changed(CPUState *cpu, target_ulong old_pgd, target_ulong new_pgd) { + if (!g_initialized_kernel) { + initialize_introspection(cpu); + } + if (old_pgd != new_pgd) - g_update_task = true; + panda_enable_callback(self, PANDA_CB_START_BLOCK_EXEC, pcb_startblock); return false; } void task_change_hook(CPUState *cpu, TranslationBlock *tb, struct hook* h){ - notify_task_change(cpu); + task_change(cpu); } /** @@ -584,10 +639,11 @@ void initialize_introspection(CPUState *cpu) { fprintf(stderr, "Error initializing kernel manager\n"); exit(3); } + g_initialized_kernel = true; g_process_manager = std::unique_ptr(new WindowsProcessManager()); - update_process_manager(); + task_change(cpu); uint64_t swapcontext_offset = g_kernel_manager->get_swapcontext_offset(); @@ -612,7 +668,6 @@ void initialize_introspection(CPUState *cpu) { fprintf(stderr, "Error finding ntoskrnl! Defaulting to ASID change heuristic.\n"); } else { // disable ASID change heuristic - panda_disable_callback(self, PANDA_CB_START_BLOCK_EXEC, pcb_startblock); panda_disable_callback(self, PANDA_CB_ASID_CHANGED, pcb_asid); // add hook for swapcontext_address @@ -643,14 +698,11 @@ bool init_plugin(void *_self) { pcb_startblock.start_block_exec = start_block_exec; panda_register_callback(self, PANDA_CB_START_BLOCK_EXEC, pcb_startblock); + panda_disable_callback(self, PANDA_CB_START_BLOCK_EXEC, pcb_startblock); pcb_asid.asid_changed = asid_changed; panda_register_callback(self, PANDA_CB_ASID_CHANGED, pcb_asid); - panda_cb pcb; - pcb.after_loadvm = initialize_introspection; - panda_register_callback(self, PANDA_CB_AFTER_LOADVM, pcb); - PPP_REG_CB("osi", on_get_current_thread, on_get_current_thread); PPP_REG_CB("osi", on_get_process_pid, on_get_process_pid); PPP_REG_CB("osi", on_get_current_process_handle, @@ -663,9 +715,12 @@ bool init_plugin(void *_self) { PPP_REG_CB("osi", on_get_modules, on_get_modules); PPP_REG_CB("osi", on_get_mappings, on_get_mappings); + // globals g_kernel_manager = std::unique_ptr( new WindowsKernelManager(std::string(panda_os_name))); - g_update_task = false; + swapcontext_address = 0; + g_initialized_kernel = false; + return true; #endif return false; diff --git a/panda/plugins/wintrospection/wintrospection_int.h b/panda/plugins/wintrospection/wintrospection_int.h index d0e764e99da..ae70a800dd0 100644 --- a/panda/plugins/wintrospection/wintrospection_int.h +++ b/panda/plugins/wintrospection/wintrospection_int.h @@ -1,4 +1,5 @@ typedef void uint64_t; typedef void int64_t; +typedef void CPUState; #include "wintrospection_int_fns.h" diff --git a/panda/plugins/wintrospection/wintrospection_int_fns.h b/panda/plugins/wintrospection/wintrospection_int_fns.h index 6647283c557..bbedc475d09 100644 --- a/panda/plugins/wintrospection/wintrospection_int_fns.h +++ b/panda/plugins/wintrospection/wintrospection_int_fns.h @@ -1,7 +1,7 @@ #pragma once -char *get_handle_name(uint64_t handle); +char *get_handle_name(CPUState *cpu, uint64_t handle); -char *get_cwd(void); +char *get_cwd(CPUState *cpu); -int64_t get_file_handle_pos(uint64_t handle); +int64_t get_file_handle_pos(CPUState *cpu, uint64_t handle);