Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion plugins/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -70,4 +70,4 @@ add_subdirectory(callstack)
add_subdirectory(apicall_tracer)
add_subdirectory(memory_regions)
add_subdirectory(pmemdump)
#add_subdirectory(volatility)
add_subdirectory(volatility)
22 changes: 11 additions & 11 deletions plugins/volatility/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ set(PANDA_PLUGIN_NAME "volatility")
set(PLUGIN_TARGET "panda_${PANDA_PLUGIN_NAME}")

# The volatility plugin requires linking against python
find_package(PythonLibs 2.7 REQUIRED)
find_package(PythonLibs 3.8 REQUIRED)
if (NOT PYTHONLIBS_FOUND)
message(FATAL_ERROR "Could not find python libraries. Is python-dev installed?")
endif()
Expand All @@ -20,20 +20,20 @@ set(LINK_LIBS_X86_64 ${LINK_LIBS} panda_ipanda-x86_64)
set(TARGET_DEPS_I386 panda_ipanda-i386)
set(TARGET_DEPS_X86_64 panda_ipanda-x86_64)

add_custom_command(OUTPUT ${PANDA_PLUGIN_DIR_I386}/volglue.py
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_CURRENT_SOURCE_DIR}/volglue.py ${PANDA_PLUGIN_DIR_I386}/volglue.py
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/volglue.py)
add_custom_command(OUTPUT ${PANDA_PLUGIN_DIR_X86_64}/volglue.py
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_CURRENT_SOURCE_DIR}/volglue.py ${PANDA_PLUGIN_DIR_X86_64}/volglue.py
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/volglue.py)
add_custom_target(volglue-script ALL
DEPENDS ${PANDA_PLUGIN_DIR_I386}/volglue.py ${PANDA_PLUGIN_DIR_X86_64}/volglue.py)
add_custom_command(OUTPUT ${PANDA_PLUGIN_DIR_I386}/volglue3.py
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_CURRENT_SOURCE_DIR}/volglue3.py ${PANDA_PLUGIN_DIR_I386}/volglue3.py
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/volglue3.py)
add_custom_command(OUTPUT ${PANDA_PLUGIN_DIR_X86_64}/volglue3.py
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_CURRENT_SOURCE_DIR}/volglue3.py ${PANDA_PLUGIN_DIR_X86_64}/volglue3.py
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/volglue3.py)
add_custom_target(volglue3-script ALL
DEPENDS ${PANDA_PLUGIN_DIR_I386}/volglue3.py ${PANDA_PLUGIN_DIR_X86_64}/volglue3.py)


add_i386_plugin(${PLUGIN_TARGET} SRC_FILES LINK_LIBS_I386)
add_x86_64_plugin(${PLUGIN_TARGET} SRC_FILES LINK_LIBS_X86_64)
add_dependencies(${PLUGIN_TARGET}-i386 ${TARGET_DEPS_I386})
add_dependencies(${PLUGIN_TARGET}-x86_64 ${TARGET_DEPS_X86_64})

install(FILES ${PANDA_PLUGIN_DIR_I386}/volglue.py DESTINATION lib/panda/i386)
install(FILES ${PANDA_PLUGIN_DIR_X86_64}/volglue.py DESTINATION lib/panda/x86_64)
install(FILES ${PANDA_PLUGIN_DIR_I386}/volglue3.py DESTINATION lib/panda/i386)
install(FILES ${PANDA_PLUGIN_DIR_X86_64}/volglue3.py DESTINATION lib/panda/x86_64)
22 changes: 22 additions & 0 deletions plugins/volatility/memory-server.cc
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,19 @@ extern "C" {
#define SUCCESS_CODE 0x79
#define FAILURE_CODE 0x77

#include <stdio.h>

int file_exists_access(const char *filename) {
// F_OK tests for existence of the file
if (access(filename, F_OK) == 0) {
return 1; // File exists
} else {
fprintf(stderr, "Error checking file existence: %s (errno: %d)\n", filename, errno);
return 0; // File does not exist or an error occurred
}
}


struct __attribute__((__packed__)) request {
uint64_t type; // {QUIT, READ, QUERY_SIZE}_MESSAGE, ... rest reserved
uint64_t address; // address to read from
Expand Down Expand Up @@ -299,6 +312,15 @@ static int setup_socket(char* path, struct sockaddr_un* address,
fprintf(stderr, "[%s] QemuMemoryAccess: bind failed\n", __FILE__);
return -2;
}
if (!file_exists_access(path)) {
fprintf(stdout, "%s not exists\n", path);
exit(1);
}
if (chmod(path, 0777) != 0) {
fprintf(stderr, "Failed to set permissions for %s\n", path);
exit(1);
}

if (listen(socket_fd, 0) != 0) {
fprintf(stderr, "[%s] QemuMemoryAccess: listen failed\n", __FILE__);
return -3;
Expand Down
198 changes: 96 additions & 102 deletions plugins/volatility/volatility.cc
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,9 @@ char g_profile[512] = {0};

// Constants
#define SOCKET_PATH_FMT "/tmp/panda%d.sock"
char g_location[512] = "file://\0";
char g_location[512] = "file:\0";
char g_filter_path[512] = {0};
const char g_script_name[] = "/volglue.py";
const char g_script_name[] = "/volglue3.py";

// Globals
std::shared_ptr<IntroPANDAManager> os_manager;
Expand All @@ -50,6 +50,7 @@ bool g_check_for_process = true;
bool g_targeted = true;

static PyObject* g_pfunc = NULL;
PyConfig config;

#define CHECK_OR_DIE(_obj, _emsg, _elabel) \
do { \
Expand All @@ -71,6 +72,56 @@ void uninit_plugin(void*);
int run_volatility_analysis(CPUState* env);
bool log_analysis_results(CPUState* env, const char* data);

static const uint8_t _zero_block[1024] = {0};
static void actually_dump_physical_memory(FILE* out, size_t len)
{
hwaddr addr = 0;
uint8_t block[sizeof(_zero_block)];

if (!out)
return;

while (len != 0)
{
size_t l = sizeof(block);
if (l > len)
l = len;
if (panda_physical_memory_read(addr, block, l) == MEMTX_OK)
fwrite(block, 1, l, out);
else
fwrite(_zero_block, 1, l, out);
addr += l;
len -= l;
}
}

static void dump_memory(char* filename, char* register_filename, uint64_t pmem_len){
FILE* out = fopen(filename, "wb");

if (pmem_len == 0){
// dump all memory if not specified as arg
pmem_len = ram_size;
}

actually_dump_physical_memory(out, pmem_len);
fclose(out);
if (register_filename)
{
if ((out = fopen(register_filename, "w")) != NULL)
{
CPUState* cpu;
CPU_FOREACH(cpu)
{
fprintf(out, "CPU#%d\n", cpu->cpu_index);
cpu_dump_state(cpu, out, fprintf, CPU_DUMP_FPU);
}
fclose(out);
}
}

panda_replay_end();
}

/**
* Run the volatility analysis, passing the desired profile and args
* as python strings. Stores the results in the panda log or writes them
Expand All @@ -79,32 +130,34 @@ bool log_analysis_results(CPUState* env, const char* data);
int run_volatility_analysis(CPUState* env)
{
// Convert global strings to python strings
PyObject* pprofile_str = PyString_FromString(g_profile);
PyObject* plocation_str = PyString_FromString(g_location);
PyObject* pfilter_str = PyString_FromString(g_filter_path);
// PyObject* pprofile_str = PyUnicode_FromString(g_profile);
dump_memory("mem.ram", "mem.regs.txt", 100);
PyObject* plocation_str = PyUnicode_FromString(g_location);
fprintf(stdout, "Location: %s\n", g_location);
PyObject* pfilter_str = PyUnicode_FromString(g_filter_path);

PyObject* pargs = PyTuple_New(3);
PyObject* pargs = PyTuple_New(2);

// Mildly concerned about death-by-oom
if (!pprofile_str || !plocation_str || !pfilter_str || !pargs) {
if (!plocation_str) {
fprintf(stderr, "[%s] Failed to allocate args\n", __FILE__);
Py_XDECREF(pprofile_str);
// Py_XDECREF(pprofile_str);
Py_XDECREF(plocation_str);
Py_XDECREF(pfilter_str);
Py_XDECREF(pargs);
}

// Add these strings to an argument object
PyTuple_SetItem(pargs, 0, pprofile_str);
PyTuple_SetItem(pargs, 1, plocation_str);
PyTuple_SetItem(pargs, 2, pfilter_str);
PyTuple_SetItem(pargs, 0, plocation_str);
PyTuple_SetItem(pargs, 1, pfilter_str);

// Call run(profile, location)
// Call run(location)
PyObject* pvalue = PyObject_CallObject(g_pfunc, pargs);
if (pvalue) {
// The function returned a value successfully
if (PyString_Check(pvalue)) {
const char* json_str = PyString_AsString(pvalue);
if (PyUnicode_Check(pvalue)) {
const char* json_str = PyUnicode_AsUTF8(pvalue);
fprintf(stdout, "%s\n", json_str);
if (log_analysis_results(env, json_str)) {
fprintf(stderr, "[%s] Failed to record result!\n", __FILE__);
}
Expand Down Expand Up @@ -302,97 +355,23 @@ bool init_plugin(void* self)

// Read arguments
const char* profile_arg = panda_os_name;
const char* profile = nullptr; // volatility profile
// const char* profile = nullptr; // volatility profile
if (!profile_arg) {
fprintf(stderr, "[%s] The -os <profile> flag is required\n", __FILE__);
return false;
} else if (strcasecmp(profile_arg, "windows-64-vistasp0") == 0) {
profile = "VistaSP0x64";
} else if (strcasecmp(profile_arg, "windows-32-vistasp0") == 0) {
profile = "VistaSP0x86";
} else if (strcasecmp(profile_arg, "windows-64-vistasp1") == 0) {
profile = "VistaSP1x64";
} else if (strcasecmp(profile_arg, "windows-32-vistasp1") == 0) {
profile = "VistaSP1x86";
} else if (strcasecmp(profile_arg, "windows-64-vistasp2") == 0) {
profile = "VistaSP2x64";
} else if (strcasecmp(profile_arg, "windows-32-vistasp2") == 0) {
profile = "VistaSP2x86";
} else if (strcasecmp(profile_arg, "windows-64-10x64sp0") == 0) {
profile = "Win10x64";
} else if (strcasecmp(profile_arg, "windows-32-10x86sp0") == 0) {
profile = "Win10x86";
} else if (strcasecmp(profile_arg, "windows-32-2003sp0") == 0) {
profile = "Win2003SP0x86";
} else if (strcasecmp(profile_arg, "windows-64-2003sp1") == 0) {
profile = "Win2003SP1x64";
} else if (strcasecmp(profile_arg, "windows-32-2003sp1") == 0) {
profile = "Win2003SP1x86";
} else if (strcasecmp(profile_arg, "windows-64-2003sp2") == 0) {
profile = "Win2003SP2x64";
} else if (strcasecmp(profile_arg, "windows-32-2003sp2") == 0) {
profile = "Win2003SP2x86";
} else if (strcasecmp(profile_arg, "windows-64-2008r2sp0") == 0) {
profile = "Win2008R2SP0x64";
} else if (strcasecmp(profile_arg, "windows-64-2008r2sp1") == 0) {
profile = "Win2008R2SP1x64";
} else if (strcasecmp(profile_arg, "windows-64-2008sp1") == 0) {
profile = "Win2008SP1x64";
} else if (strcasecmp(profile_arg, "windows-32-2008sp1") == 0) {
profile = "Win2008SP1x86";
} else if (strcasecmp(profile_arg, "windows-64-2008sp2") == 0) {
profile = "Win2008SP2x64";
} else if (strcasecmp(profile_arg, "windows-32-2008sp2") == 0) {
profile = "Win2008SP2x86";
} else if (strcasecmp(profile_arg, "windows-64-2012r2sp0") == 0) {
profile = "Win2012R2x64";
} else if (strcasecmp(profile_arg, "windows-64-2012sp0") == 0) {
profile = "Win2012x64";
} else if (strcasecmp(profile_arg, "windows-64-7sp0") == 0) {
profile = "Win7SP0x64";
} else if (strcasecmp(profile_arg, "windows-32-7sp0") == 0) {
profile = "Win7SP0x86";
} else if (strcasecmp(profile_arg, "windows-64-7sp1") == 0) {
profile = "Win7SP1x64";
} else if (strcasecmp(profile_arg, "windows-32-7sp1") == 0) {
profile = "Win7SP1x86";
} else if (strcasecmp(profile_arg, "windows-64-81sp0") == 0) {
profile = "Win81U1x64";
} else if (strcasecmp(profile_arg, "windows-32-81sp0") == 0) {
profile = "Win81U1x86";
} else if (strcasecmp(profile_arg, "windows-64-8sp0") == 0) {
profile = "Win8SP0x64";
} else if (strcasecmp(profile_arg, "windows-32-8sp0") == 0) {
profile = "Win8SP0x86";
} else if (strcasecmp(profile_arg, "windows-64-8sp1") == 0) {
profile = "Win8SP1x64";
} else if (strcasecmp(profile_arg, "windows-32-8sp1") == 0) {
profile = "Win8SP1x86";
} else if (strcasecmp(profile_arg, "windows-64-xpsp1") == 0) {
profile = "WinXPSP1x64";
} else if (strcasecmp(profile_arg, "windows-64-xpsp2") == 0) {
profile = "WinXPSP2x64";
} else if (strcasecmp(profile_arg, "windows-32-xpsp2") == 0) {
profile = "WinXPSP2x86";
} else if (strcasecmp(profile_arg, "windows-32-xpsp3") == 0) {
profile = "WinXPSP3x86";
}
if (!profile) {
fprintf(stderr, "[%s] Unrecognized profile\n", __FILE__);
return false;
}

char* socket_path = (char*)calloc(512, 1);
if (!socket_path) {
fprintf(stderr, "[%s] Failed to allocate memory for socket path\n", __FILE__);
return false;
}
sprintf(socket_path, SOCKET_PATH_FMT, getpid());
strncat(g_location, socket_path, sizeof(g_location) - 1);
// sprintf(socket_path, SOCKET_PATH_FMT, getpid());
strncat(g_location, "mem.ram", sizeof(g_location) - 1);

const char* python_script = panda_parse_string(vol_args, "script", g_script_path);

strncpy(g_profile, profile, sizeof(g_profile) - 1);
// strncpy(g_profile, profile, sizeof(g_profile) - 1);
panda_free_args(vol_args);

panda_cb pcb;
Expand All @@ -403,23 +382,32 @@ bool init_plugin(void* self)

// This hack can be avoided by working with PANDA
// to expose the python shared library
dlopen("libpython2.7.so", RTLD_LAZY | RTLD_GLOBAL);
dlopen("libpython3.8.so", RTLD_LAZY | RTLD_GLOBAL);

char* script_contents = read_script(python_script);
if (!script_contents) {
fprintf(stderr, "[%s] Failed to open python script!\n", __FILE__);
return false;
}

Py_SetProgramName(g_program_name);
Py_Initialize();
const char* venv_path_cstr = std::getenv("VIRTUAL_ENV");
std::string venv_path(venv_path_cstr);
std::string exec_path = venv_path + "/bin/python";
std::wstring w_venv_path(venv_path.begin(), venv_path.end());
std::wstring w_exec(exec_path.begin(), exec_path.end());

Py_SetProgramName((wchar_t*) g_program_name);
PyConfig_InitPythonConfig(&config);
PyConfig_SetString(&config, &config.executable, w_exec.c_str());
Py_InitializeFromConfig(&config);

// Load the program as a code object
pcode = Py_CompileString((char*)script_contents, "volglue.py", Py_file_input);
pcode = Py_CompileString(script_contents, "volglue3.py", Py_file_input);
CHECK_OR_DIE(pcode, "Failed to compile python program!\n", cleanup);

// Load the code object into a module
pmodule = PyImport_ExecCodeModule(g_module_name, pcode);
// fprintf(stdout, "Module name: %s\n", g_module_name);
pmodule = PyImport_ExecCodeModule("gluemod", pcode);
CHECK_OR_DIE(pmodule, "Failed to load as module!\n", cleanup);

// Extract the entry point of our new module
Expand All @@ -433,10 +421,10 @@ bool init_plugin(void* self)

fprintf(stdout, "Successfully initialized python routines.\n");

if (!start_memory_server(socket_path)) {
fprintf(stderr, "[%s] Failed to start memory server!\n", __FILE__);
goto cleanup;
}
// if (!start_memory_server(socket_path)) {
// fprintf(stderr, "[%s] Failed to start memory server!\n", __FILE__);
// goto cleanup;
// }

if (script_contents) {
free(script_contents);
Expand Down Expand Up @@ -468,14 +456,20 @@ bool init_plugin(void* self)
pmodule = NULL;
Py_XDECREF(g_pfunc);
g_pfunc = NULL;
PyConfig_Clear(&config);
unlink("mem.ram");
unlink("mem.regs.txt");
return false;
}

void uninit_plugin(void* self)
{
stop_memory_server();
// stop_memory_server();
Py_XDECREF(g_pfunc);
g_pfunc = NULL;
PyConfig_Clear(&config);
Py_Finalize();
teardown_avro();
unlink("mem.ram");
unlink("mem.regs.txt");
}
Loading