rewire/example/main.cpp

103 lines
3.0 KiB
C++

#include <iostream>
#include <sys/syscall.h>
#include <unordered_set>
#include <string>
#include <linux/limits.h> // For PATH_MAX
#include "wirekit.hpp"
/*
To show the paradigms implemented in rewire, this simple wirekit compiles a list
of all files a program opens and prints it after the program exits!
*/
std::unordered_set<std::string> opened_files;
char BUF[PATH_MAX + 1] = { 0 };
void open_entry() {
user_regs_struct regs;
if (rewire_subject_get_regs(&regs) != REWIRE_SUCCESS) {
std::cout << "Rewire failed to get tracee registers!" << std::endl;
return;
}
uint32_t read;
if (rewire_subject_load_cstr((const char*)regs.rdi, BUF, &read, sizeof(BUF) - 1) != REWIRE_SUCCESS) {
std::cout << "Rewire failed to extract pathname handed to open()!" << std::endl;
return;
}
// Log opened file
opened_files.emplace(BUF);
}
void openat_entry() {
user_regs_struct regs;
if (rewire_subject_get_regs(&regs) != REWIRE_SUCCESS) {
std::cout << "Rewire failed to get tracee registers!" << std::endl;
return;
}
uint32_t read;
if (rewire_subject_load_cstr((const char*)regs.rsi, BUF, &read, sizeof(BUF) - 1) != REWIRE_SUCCESS) {
std::cout << "Rewire failed to extract pathname handed to open()!" << std::endl;
return;
}
// Log opened file
opened_files.emplace(BUF);
}
err_t wirekit_prepare() {
/*
wirekit_prepare is called once after the wirekit is loaded.
Use it to initialize any local data here!
*/
std::cout << "There is nothing to prepare in this wirekit :)" << std::endl;
return REWIRE_SUCCESS;
}
err_t wirekit_command_start(int argc, const char* const* argv) {
/*
wirekit_command_start is called for every command, before the first thread is spawned.
In shell mode, rewire calls this function multiple times.
Use it to register system call hooks!
*/
std::cout << "Executing \"" << argv[0] << "\" with arguments [ ";
for (int i = 1; i < argc; i++)
std::cout << "\"" << argv[i] << "\"" << (i < argc - 1 ? ", " : "");
std::cout << " ]" << std::endl;
if (rewire_syscall_hook(SYS_open, open_entry, nullptr) != REWIRE_SUCCESS ||
rewire_syscall_hook(SYS_openat, openat_entry, nullptr) != REWIRE_SUCCESS) {
std::cout << "Failed to register entry hooks for open and openat system calls!" << std::endl;
return REWIRE_FAILURE;
}
return REWIRE_SUCCESS;
}
void wirekit_command_exit() {
/*
wirekit_command_exit is called after each command exits.
In shell mode, rewire calls this function multiple times.
Use it to wrap up and reset wirekit data before the next command is started!
*/
std::cout << "The command opened the following files:" << std::endl;
for (const std::string& f : opened_files)
std::cout << " \"" << f << "\"" << std::endl;
opened_files.clear(); // Next commands starts on empty set (could also be done in beginning of wirekit_command_start)
}
/*
void wirekit_subject_start() {
// wirekit_subject_start is called whenever a new thread (subject), under the current command, first performs a system call
}
void wirekit_subject_exit() {
// wirekit_subject_exit is called whenever a thread exits under the current command
}
*/