Skip to content

Commit

Permalink
Updating loaded for 64-bit systems
Browse files Browse the repository at this point in the history
  • Loading branch information
AndrewQuijano committed Dec 14, 2024
1 parent ffde8fe commit b9e901d
Show file tree
Hide file tree
Showing 2 changed files with 138 additions and 61 deletions.
134 changes: 109 additions & 25 deletions panda/plugins/loaded/loaded.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ PANDAENDCOMMENT */
#include <cstdio>
#include <map>
#include <memory>
#include <sys/mman.h>

#include "panda/plugin.h"
#include "panda/plugin_plugin.h"
Expand Down Expand Up @@ -52,14 +53,13 @@ PPP_PROT_REG_CB(on_library_load);
// This creates the global for this call back fn (on_library_load)
PPP_CB_BOILERPLATE(on_library_load)

bool debug = true;
bool debug = false;

#define MAX_FILENAME 256
std::map <target_ulong, OsiProc> running_procs;

void die(const char* fmt, ...) {
va_list args;

va_start(args, fmt);
vfprintf(stderr, fmt, args);
va_end(args);
Expand Down Expand Up @@ -94,39 +94,99 @@ void linux_old_mmap_return(CPUState *cpu, target_ulong pc, uint32_t arg_ptr) {
}
}

void linux_mmap_pgoff_return(CPUState *cpu,target_ulong pc,uint32_t addr,uint32_t len,uint32_t prot,uint32_t flags,uint32_t fd,uint32_t pgoff) {
void linux_mmap_pgoff_return(CPUState *cpu, target_ulong pc,
uint32_t addr, uint32_t len,
uint32_t prot,uint32_t flags,
uint32_t fd,uint32_t pgoff) {
CPUArchState *env = (CPUArchState*)cpu->env_ptr;
target_ulong asid = panda_current_asid(cpu);
if (running_procs.count(asid) == 0) {
//printf ("linux_mmap_pgoff_enter for asid=0x%x fd=%d -- dont know about that asid. discarding \n", (unsigned int) asid, (int) fd);
// printf ("linux_mmap_pgoff_enter for asid=0x%x fd=%d -- dont know about that asid. discarding \n", (unsigned int) asid, (int) fd);
return;
}
if ((int32_t) fd == -1){
//printf ("linux_mmap_pgoff_enter for asid=0x%x fd=%d flags=%x -- not valid fd . . . \n", (unsigned int) asid, (int) fd, flags);
if ((int32_t) fd == -1) {
// printf ("linux_mmap_pgoff_enter for asid=0x%x fd=%d flags=%x -- not valid fd . . . \n", (unsigned int) asid, (int) fd, flags);
return;
}
OsiProc proc = running_procs[asid];
char *filename = osi_linux_fd_to_filename(cpu, &proc, fd);
// gets us offset into the file. could be useful
//uint64_t pos = osi_linux_fd_to_pos(env, &proc, fd);
// uint64_t pos = osi_linux_fd_to_pos(env, &proc, fd);
// if a filename exists and permission is executable
// TODO: fix this magic constant of 0x04 for PROT_EXEC
if (filename != NULL && ((prot & 0x04) == 0x04)) {
if (filename != NULL && ((prot & PROT_EXEC) == PROT_EXEC)) {
if (debug) {
printf ("[loaded] linux_mmap_pgoff(fd=%d filename=[%s] "
"len=%d prot=%x flags=%x "
"pgoff=%d)=" TARGET_FMT_lx "\n", (int) fd,
filename, len, prot, flags, pgoff, env->regs[R_EAX]);
}
PPP_RUN_CB(on_library_load, cpu, pc, filename, env->regs[R_EAX], len)
} else if ((prot & 0x04) == 0x04) {
PPP_RUN_CB(on_library_load, cpu, pc, filename, env->regs[R_EAX], len);
}
else if ((prot & PROT_EXEC) == PROT_EXEC) {
printf("[loaded] mapped executable section without a filename!\n");
printf ("[loaded] linux_mmap_pgoff(fd=%d "
"len=%d prot=%x flags=%x "
"pgoff=%d)=" TARGET_FMT_lx "\n", (int) fd,
len, prot, flags, pgoff, env->regs[R_EAX]);
}
}

#elif defined(TARGET_I386) && defined(TARGET_X86_64)
void linux_mprotect_return(CPUState* cpu, target_ulong pc,
uint64_t start, uint32_t len,
uint64_t prot) {
if (debug) {
printf("[loaded] mprotect() on x86-64\n");
}
}

void linux_mmap_return(CPUState *cpu, target_ulong pc,
uint64_t addr, uint64_t len, uint64_t prot,
uint64_t flags, uint64_t fd, uint64_t offset) {

if (debug) {
printf("[loaded] linux_mmap_return 64-bit is called\n");
}
CPUArchState *env = (CPUArchState*)cpu->env_ptr;
target_ulong asid = panda_current_asid(cpu);
if (running_procs.count(asid) == 0) {
return;
}
if ((int32_t) fd == -1) {
return;
}
if (debug) {
printf("[loaded] linux_mmap_return 64-bit is called, with OK fd and non-zero running proc\n");
}

OsiProc proc = running_procs[asid];
char * filename = osi_linux_fd_to_filename(cpu, &proc, fd);
// gets us offset into the file. could be useful
// uint64_t pos = osi_linux_fd_to_pos(cpu, &proc, fd);
// if a filename exists and permission is executable
if (filename != NULL && ((prot & PROT_EXEC) == PROT_EXEC)) {
if (debug) {
printf("[loaded] linux_mmap(fd=%lu filename=[%s] len=%lu prot=%lx flags=%lx pgoff=%lu)=%lx\n",
fd, filename, len, prot, flags, offset, (unsigned long) env->regs[R_EAX]);
}
PPP_RUN_CB(on_library_load, cpu, pc, filename, env->regs[R_EAX], len);
}
else if ((prot & PROT_EXEC) == PROT_EXEC) {
printf("[loaded] mapped executable section without a filename!\n");
printf("[loaded] linux_mmap(fd=%lu len=%lu prot=%lx flags=%lx pgoff=%lu)=%lx\n",
fd, len, prot, flags, offset, (unsigned long) env->regs[R_EAX]);
}
else {
if (debug) {
if (filename == NULL) {
printf("[loaded] I got a null file name\n");
}
else {
printf("[loaded] It seems like filename %s was null, OR PROT_EXEC was not there\n", filename);
}
}
}
}
#endif

// get current process before each bb execs
Expand All @@ -137,42 +197,54 @@ void osi_foo(CPUState *cpu, TranslationBlock *tb) {

std::unique_ptr<OsiProc, decltype(free_osiproc)*> p { get_current_process(cpu), free_osiproc };

//some sanity checks on what we think the current process is
// some sanity checks on what we think the current process is
// we couldn't find the current task
if (!p) return;
if (!p) {
return;
}
// this means we didnt find current task
if (p->taskd == 0) return;
if (p->taskd == 0){
return;
}
// or the name
if (p->name == 0) return;
if (p->name == 0) {
return;
}
// this is just not ok
if (((int) p->pid) == -1) return;
if (((int) p->pid) == -1) {
return;
}
uint32_t n = strnlen(p->name, 32);
// name is one char?
if (n<2) return;
if (n < 2) {
return;
}
uint32_t np = 0;
for (uint32_t i=0; i<n; i++) {
np += (isprint(p->name[i]) != 0);
}
// name doesnt consist of solely printable characters
// printf ("np=%d n=%d\n", np, n);
if (np != n) return;
if (np != n) {
return;
}
target_ulong asid = panda_current_asid(cpu);
if (running_procs.count(asid) == 0) {
printf ("adding asid=0x%x to running procs. cmd=[%s] task=0x%x\n", (unsigned int) asid, p->name, (unsigned int) p->taskd);
printf ("[loaded] adding asid=0x%x to running procs. cmd=[%s] task=0x%x\n", (unsigned int) asid, p->name, (unsigned int) p->taskd);
}
running_procs[asid] = *p;
}

return;
}
bool init_plugin(void *self) {
//panda_arg_list *args = panda_get_args("loaded");

bool init_plugin(void *self) {
panda_require("osi");
assert(init_osi_api());
panda_require("osi_linux");
assert(init_osi_linux_api());
panda_require("syscalls2");
panda_arg_list *args = panda_get_args("loaded");
debug = panda_parse_bool_opt(args, "debug", "enable debug output");

#if defined(TARGET_I386) && !defined(TARGET_X86_64)
{
Expand All @@ -183,10 +255,22 @@ bool init_plugin(void *self) {

PPP_REG_CB("syscalls2", on_sys_mmap_pgoff_return, linux_mmap_pgoff_return);
// don't use these at them moment
//PPP_REG_CB("syscalls2", on_sys_old_mmap_return, linux_old_mmap_return);
//PPP_REG_CB("syscalls2", on_sys_mprotect_return, linux_mprotect_return);
// PPP_REG_CB("syscalls2", on_sys_old_mmap_return, linux_old_mmap_return);
// PPP_REG_CB("syscalls2", on_sys_mprotect_return, linux_mprotect_return);
printf("[loaded] The plugin is supported on i386\n");
#elif defined(TARGET_I386) && defined(TARGET_X86_64)
{
panda_cb pcb;
pcb.before_block_exec = osi_foo;
panda_register_callback(self, PANDA_CB_BEFORE_BLOCK_EXEC, pcb);
}
// Tell Plugin 'syscall2', that if a systemcall 'mmap' occurs, then run the code in 'linux_mmap_return'
// https://www.linuxquestions.org/questions/linux-general-1/difference-between-mmap2-syscall-and-mmap_pgoff-syscall-for-32-bit-linux-4175622986/
PPP_REG_CB("syscalls2", on_sys_mmap_return, linux_mmap_return);
PPP_REG_CB("syscalls2", on_sys_mprotect_return, linux_mprotect_return);
printf("[loaded] The plugin is supported on x86-64\n");
#else
fprintf(stderr, "The loaded plugin is not currently supported on this platform.\n");
fprintf(stderr, "[loaded] The plugin is not currently supported on this platform.\n");
return false;
#endif
return true;
Expand Down
65 changes: 29 additions & 36 deletions panda/plugins/loaded_libs/loaded_libs.cpp
Original file line number Diff line number Diff line change
@@ -1,23 +1,20 @@
#define __STDC_FORMAT_MACROS

#include <cstdio>

#include "panda/plugin.h"

#include "syscalls2/syscalls_ext_typedefs.h"
#include "syscalls2/syscalls2_info.h"
#include "syscalls2/syscalls2_ext.h"

extern "C" {

bool init_plugin(void *);
void uninit_plugin(void *);
bool init_plugin(void *);
void uninit_plugin(void *);

#include "osi/osi_types.h"
#include "osi/osi_ext.h"
}


#include<map>
#include<vector>
#include<set>
Expand All @@ -40,24 +37,31 @@ uint64_t get_libs_failed_count = 0;
void get_libs(CPUState *env) {

get_libs_count ++;

bool fail = false;
OsiProc *current = get_current_process(env);
if (current == NULL) fail=true;
if (program_name && strcmp(current->name, program_name)) fail=true;
if (current->pid == 0) fail=true;
if (current == NULL) {
fail = true;
}
if (program_name && strcmp(current->name, program_name)) {
fail = true;
}
if (current->pid == 0) {
fail = true;
}
GArray *ms = get_mappings(env, current);
if (ms == NULL) fail=true;
if (ms == NULL) {
fail = true;
}
OsiThread *thread = get_current_thread(env);
if (thread == NULL) fail=true;

if (thread == NULL) {
fail = true;
}
assert (pandalog);

if (fail) {
get_libs_failed_count ++;
}
else {

Panda__LogEntry ple = PANDA__LOG_ENTRY__INIT;
Panda__LoadedLibs ll = PANDA__LOADED_LIBS__INIT;
Panda__Module** m = (Panda__Module **) malloc (sizeof (Panda__Module *) * ms->len);
Expand Down Expand Up @@ -90,7 +94,6 @@ void get_libs(CPUState *env) {
ll.tid = thread->tid;

Asid asid = panda_current_asid(env);

ple.has_asid = true;
ple.asid = asid;
ple.asid_libraries = &ll;
Expand All @@ -106,54 +109,44 @@ void get_libs(CPUState *env) {
cleanup_osi(current, thread, ms);
}



// 9 long sys_mmap(

void mmap_return(CPUState *cpu, target_ulong pc, unsigned long addr, unsigned long length, unsigned long prot, unsigned long flags, unsigned long fd, unsigned long offset) {
get_libs(cpu);
}


uint64_t bb_count = 0;

void before_block(CPUState *env, TranslationBlock *tb) {

// check up on module list every 50 bb
bb_count ++;
if ((bb_count % 100) == 0) {
get_libs(env);
}

}


bool init_plugin(void *self) {
panda_require("osi");
assert(init_osi_api());
panda_require("syscalls2");

#ifdef TARGET_X86_64
PPP_REG_CB("syscalls2", on_sys_mmap_return, mmap_return);
PPP_REG_CB("syscalls2", on_sys_mmap_return, mmap_return);
panda_cb pcb;
pcb.before_block_exec = before_block;
panda_register_callback(self, PANDA_CB_BEFORE_BLOCK_EXEC, pcb);

panda_arg_list *args;
args = panda_get_args("loaded_libs");
program_name = panda_parse_string_opt(args, "program_name", NULL, "program name to collect libraries for");
return true;
#else
/* #error "No on_sys_mmap_return for target" */
/* #error "No on_sys_mmap_return for target" */
printf("loaded_libs plugin is not available for this architecture");
return false;
#endif

panda_cb pcb;
pcb.before_block_exec = before_block;
panda_register_callback(self, PANDA_CB_BEFORE_BLOCK_EXEC, pcb);

panda_arg_list *args;
args = panda_get_args("loaded_libs");
program_name = panda_parse_string_opt(args, "program_name", NULL, "program name to collect libraries for");

return true;
}

void uninit_plugin(void *self) {

cout << "get_libs_count = " << get_libs_count << "\n";
cout << "get_libs_failed_count = " << get_libs_failed_count << "\n";
cout << "frac = " << ((float) get_libs_failed_count) / get_libs_count << "\n";

}

0 comments on commit b9e901d

Please sign in to comment.