Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix tracer plugins #1

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
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
119 changes: 78 additions & 41 deletions plugins/apicall_tracer/apicall_tracer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,8 @@ const size_t MAX_FUNCTION_PROTOTYPE_SIZE = 512;

std::shared_ptr<Windows7IntrospectionManager> g_os_manager;
static struct WindowsKernelOSI* g_kernel_osi = nullptr;
static char* g_database_path;
bool g_initialized = false;

int call_total = 0;
int call_instrumented = 0;
Expand Down Expand Up @@ -289,10 +291,64 @@ struct call_id get_call_unique_id(CPUState* env, target_ulong func, uint64_t tid
return identifier;
}

bool initialize_globals(CPUState* env)
{
const char* profile = panda_os_name;
const char* database_path = (const char*)g_database_path;

std::shared_ptr<IntroPANDAManager> os_manager;
if (!init_ipanda(env, os_manager)) {
fprintf(stderr, "Could not initialize the introspection library.\n");
return false;
}

// TODO: temporary -- forcing to be windows specific so i don't have to edit any more
// code in this plugin
g_os_manager = std::dynamic_pointer_cast<Windows7IntrospectionManager>(os_manager);
g_kernel_osi = g_os_manager->get_kosi();

g_current_process = std::make_shared<Process>();
g_previous_asid = 0;

g_syscalls_osi.reset(new OsiSyscallInterface(profile, g_os_manager, "calls.db"));
if (!g_syscalls_osi) {
fprintf(stderr, "[%s] Failed to find a syscall profile for %s\n", __FILE__,
profile);
return false;
}

g_reporter = create_reporter_ctx(database_path, g_syscalls_osi.get());
if (!g_reporter || !g_reporter->is_valid()) {
fprintf(stderr, "[%s] Failed to create a recording context\n", __FILE__);
return false;
}

if (!init_trace_engine(profile, g_syscalls_osi, add_syscall_manager, g_reporter,
g_kernel_osi)) {
fprintf(stderr, "[%s] Failed to initialize trace engine!\n", __FILE__);
return false;
}

if (g_current_osi == nullptr) {
fprintf(stderr, "[%s] The trace engine did not update introspection structure\n",
__FILE__);
return false;
}

g_initialized = true;
fprintf(stdout, "apicall_tracer initialized\n");
set_callstack_osi(g_current_osi);
return g_initialized;
}

void return_insn_callback(CPUState* env, target_ulong func)
{
ret_total++;

if (!g_initialized) {
return;
}

// we aren't interested if this call has been in the kernel
if (panda_in_kernel(env)) {
return;
Expand All @@ -306,8 +362,10 @@ void return_insn_callback(CPUState* env, target_ulong func)
if (windows_interesting_call_check(env, func, tid)) {
ret_instrumented++;

int i = 0;
for (auto& manager : *g_syscall_managers) {
manager->handle_potential_syscall_exit(env, func);
manager->handle_potential_syscall_exit(env, func);
i++;
}
}
}
Expand All @@ -316,6 +374,10 @@ void call_insn_callback(CPUState* env, target_ulong func)
{
call_total++;

if (!g_initialized) {
return;
}

// we don't care about calls happening within the kernel
if (panda_in_kernel(env)) {
return;
Expand All @@ -338,6 +400,12 @@ void call_insn_callback(CPUState* env, target_ulong func)

bool update_symbols(CPUState* env, target_ulong oldval, target_ulong newval)
{
if (!g_initialized) {
if (!initialize_globals(env)) {
return 0;
}
}

// create a list of modules using the current process
auto process = kosi_get_current_process(g_kernel_osi);
auto module_list = get_module_list(g_kernel_osi, process_get_eprocess(process),
Expand Down Expand Up @@ -436,52 +504,17 @@ bool init_plugin(void* self)
strdup(panda_parse_string(tracer_args, "output", "results"));
fprintf(stdout, "Writing analysis results to %s\n", database_path);

panda_free_args(tracer_args);

std::shared_ptr<IntroPANDAManager> os_manager;
g_database_path = (char*)database_path;

if (!init_ipanda(self, os_manager)) {
fprintf(stderr, "Could not initialize the introspection library.\n");
return false;
}

// temporary -- forcing to be windows specific so i don't have to edit any more code
// in this plugin
g_os_manager = std::dynamic_pointer_cast<Windows7IntrospectionManager>(os_manager);
g_kernel_osi = g_os_manager->get_kosi();

g_current_process = std::make_shared<Process>();
g_previous_asid = 0;

g_syscalls_osi.reset(new OsiSyscallInterface(profile, g_os_manager, "calls.db"));
if (!g_syscalls_osi) {
fprintf(stderr, "[%s] Failed to find a syscall profile for %s\n", __FILE__,
profile);
return false;
}

g_reporter = create_reporter_ctx(database_path, g_syscalls_osi.get());
if (!g_reporter || !g_reporter->is_valid()) {
fprintf(stderr, "[%s] Failed to create a recording context\n", __FILE__);
return false;
}

if (!init_trace_engine(profile, g_syscalls_osi, add_syscall_manager, g_reporter,
g_kernel_osi)) {
fprintf(stderr, "[%s] Failed to initialize trace engine!\n", __FILE__);
return false;
}
panda_free_args(tracer_args);

if (g_current_osi == nullptr) {
fprintf(stderr, "[%s] The trace engine did not update introspection structure\n",
__FILE__);
return false;
}

// Call Backs
panda_cb pcb;
pcb.asid_changed = update_symbols;
panda_register_callback(self, PANDA_CB_ASID_CHANGED, pcb);
pcb.after_loadvm = (reinterpret_cast<void (*)(CPUState*)>(initialize_globals));
panda_register_callback(self, PANDA_CB_AFTER_LOADVM, pcb);

init_callstack_plugin(self, g_current_osi);
register_callstack_callback("on_call", call_insn_callback);
Expand All @@ -490,7 +523,6 @@ bool init_plugin(void* self)
fprintf(stderr, "[%s] This platform is not supported\n", __FILE__);
return false;
#endif
fprintf(stdout, "apicall_tracer initialized\n");
return true;
}

Expand All @@ -509,4 +541,9 @@ void uninit_plugin(void* self)
fprintf(stdout, "\tCall Targets: %d Hits and %d Misses\n", target_hits,
target_misses);
fprintf(stdout, "\tCallers: %d Hits and %d Misses\n", caller_hits, caller_misses);
if (!g_initialized) {
// create output file
throw std::runtime_error(
"panda introspection never initialized. Corrupted recording?");
}
}
6 changes: 6 additions & 0 deletions plugins/callstack/callstack.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -472,6 +472,12 @@ bool context_switch(CPUState* env, target_ulong oldval, target_ulong newval)
return 0;
}

void set_callstack_osi(CurrentProcessOSI* call_tracer_current_process_osi)
{
g_current_osi = call_tracer_current_process_osi;
g_needs_update = true;
}

bool init_callstack_plugin(void* self, CurrentProcessOSI* call_tracer_current_process_osi)
{
fprintf(stdout, "Initializing plugin callstack_instr\n");
Expand Down
1 change: 1 addition & 0 deletions plugins/callstack/callstack.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ int register_callstack_callback(const std::string callback_type,
callback_function_pointer new_pointer);
bool init_callstack_plugin(void* self,
CurrentProcessOSI* call_tracer_current_process_osi);
void set_callstack_osi(CurrentProcessOSI* call_tracer_current_process_osi);

#ifdef __cplusplus
extern "C" {
Expand Down
80 changes: 56 additions & 24 deletions plugins/syscall_tracer/syscall_tracer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,40 @@ static bool is_syscall_insn(CPUState* env, target_ptr_t pc)
return false;
}

bool initialize_syscall_tracer(CPUState* env)
{
const char* profile = panda_os_name;
const char* log_path = (const char*)g_log_path;

if (!init_ipanda(env, g_os_manager)) {
fprintf(stderr, "Could not initialize the introspection library.\n");
return false;
}

g_syscalls_osi.reset(new OsiSyscallInterface(profile, g_os_manager, "syscalls.db"));
if (!g_syscalls_osi) {
fprintf(stderr, "[%s] Failed to find a syscall profile for %s\n", __FILE__,
profile);
return false;
}

g_reporter = create_reporter_ctx(log_path);

if (!g_reporter || !g_reporter->is_valid()) {
fprintf(stderr, "[%s] Failed to create a recording context\n", __FILE__);
return false;
}

if (!init_trace_engine(profile, g_syscalls_osi, add_syscall_manager, g_reporter)) {
fprintf(stderr, "[%s] Failed to initialize trace engine!\n", __FILE__);
return false;
}

g_initialized = true;
fprintf(stdout, "Success initializing syscall_tracer!\n");
return g_initialized;
}

/**
* Callback to before_block_exec for invoking syscall return
* handlers. Each syscall manager maintains a list of return
Expand Down Expand Up @@ -114,15 +148,29 @@ static int syscall_insn_callback(CPUState* env, target_ptr_t pc)
return 0;
}

bool context_switch_callback(CPUState* env, target_ulong old_asid, target_ulong new_asid)
{
if (!g_initialized) {
initialize_syscall_tracer(env);
}

return false;
}

void register_panda_callbacks(void* self)
{
panda_cb pcb;
pcb.asid_changed = context_switch_callback;
panda_register_callback(self, PANDA_CB_ASID_CHANGED, pcb);
pcb.insn_translate = is_syscall_insn;
panda_register_callback(self, PANDA_CB_INSN_TRANSLATE, pcb);
pcb.insn_exec = syscall_insn_callback;
panda_register_callback(self, PANDA_CB_INSN_EXEC, pcb);
pcb.before_block_exec = before_block_exec;
panda_register_callback(self, PANDA_CB_BEFORE_BLOCK_EXEC, pcb);
pcb.after_loadvm =
(reinterpret_cast<void (*)(CPUState*)>(initialize_syscall_tracer));
panda_register_callback(self, PANDA_CB_AFTER_LOADVM, pcb);
}

bool init_plugin(void* self)
Expand All @@ -131,11 +179,6 @@ bool init_plugin(void* self)
#if defined(TARGET_I386)
register_panda_callbacks(self);

if (!init_ipanda(self, g_os_manager)) {
fprintf(stderr, "Could not initialize the introspection library.\n");
return false;
}

const char* profile = panda_os_name;
if (!profile) {
fprintf(stderr,
Expand All @@ -150,29 +193,18 @@ bool init_plugin(void* self)
g_log_path = (char*)log_path;
panda_free_args(args);

g_syscalls_osi.reset(new OsiSyscallInterface(profile, g_os_manager, "syscalls.db"));
if (!g_syscalls_osi) {
fprintf(stderr, "[%s] Failed to find a syscall profile for %s\n", __FILE__,
profile);
return false;
}

g_reporter = create_reporter_ctx(log_path);
if (!g_reporter || !g_reporter->is_valid()) {
fprintf(stderr, "[%s] Failed to create a recording context\n", __FILE__);
return false;
}

if (!init_trace_engine(profile, g_syscalls_osi, add_syscall_manager, g_reporter)) {
fprintf(stderr, "[%s] Failed to initialize trace engine!\n", __FILE__);
return false;
}

#else
fprintf(stderr, "[%s] This platform is not currently supported.\n", __FILE__);
return false;
#endif
return true;
}

void uninit_plugin(void* self) { uninit_trace_engine(); }
void uninit_plugin(void* self) {
if (g_initialized) {
uninit_trace_engine();
} else {
throw std::runtime_error(
"panda introspection never initialized. Corrupted recording?\n");
}
}