#include <boost/algorithm/string.hpp>
#include <boost/program_options.hpp>
#include <csignal>
#include <functional>
#include <iostream>
#include <mutex>
#include <string>
namespace po = boost::program_options;
using std::placeholders::_1;
po::variables_map& vm);
std::unique_ptr<Domain>
domain;
}
public:
std::cout << "Received event " << event.type() << std::endl;
}
};
const Vcpu& vcpu =
event.vcpu();
std::cout <<
"Vcpu " << vcpu.
id() <<
": [" <<
event.task().pid() <<
":" <<
event.task().tid()
<< "] " << event.task().process_name() << '\n';
std::cout << '\t' << "RIP 0x" << std::hex << regs.rip() << std::dec << '\n';
std::cout << '\t';
std::cout << "R";
std::cout << "w";
std::cout << "X";
std::cout << '\n';
std::cout.flush();
}
int main(
int argc,
char** argv) {
po::options_description desc("Options");
std::string domain_name;
std::string process_name;
std::string address_str;
uint32_t length = 0;
uint64_t pid = 0;
desc.add_options()
("domain,D", po::value<std::string>(&domain_name)->required(), "The domain name or ID attach to")
("procname", po::value<std::string>(&process_name), "A process name to watch")
("pid", po::value<uint64_t>(&pid), "A process identifier to watch")
("address,a", po::value<std::string>(&address_str)->required(), "An address of a buffer to watch. Requires procname or pid.")
("length,l", po::value<uint32_t>(&length)->default_value(1), "The length of the buffer to watch")
("read,r", "Watch read accesses")
("write,w", "Watch writes accesses")
("execute,x", "Watch instruction fetch accesses")
("help", "Display program help");
std::cout.sync_with_stdio(false);
po::variables_map vm;
const bool read = vm.count("read");
const bool write = vm.count("write");
const bool exec = vm.count("execute");
char* endptr = nullptr;
uint64_t address = strtoull(address_str.c_str(), &endptr, 0);
if (*endptr != '\0') {
std::cerr << "Invalid input address: " << address_str << '\n';
return 1;
}
if (process_name.empty() && vm.count("pid") == 0) {
std::cerr << "Virtual addresses require a process name or PID\n";
return 1;
}
if (!length) {
std::cerr << "A minimum length of 1 is required\n";
return 1;
}
if (!read && !write && !exec) {
std::cerr << "At least one of read, write, or execute must be specified\n";
return 1;
}
if (vm.count("pid") && !process_name.empty()) {
std::cerr << "Specifiy either pid or procname, not both.\n";
return 1;
}
boost::to_lower(process_name);
auto hypervisor = Hypervisor::instance();
domain = hypervisor->attach_domain(domain_name);
std::unique_ptr<Watchpoint> watchpoint;
if (!
domain->detect_guest()) {
std::cerr << "Failed to detect guest OS\n";
return 1;
}
switch (
domain->guest()->os()) {
case OS::Windows: {
const auto& kernel = guest->
kernel();
std::shared_ptr<nt::PROCESS> process;
for (const auto& entry : cidtable->open_handles()) {
auto object_header = entry->ObjectHeader();
if (object_header->type() == nt::ObjectType::Process) {
auto test_process = kernel.process(object_header->Body());
if (vm.count("pid") == 0) {
auto name = boost::to_lower_copy(test_process->ImageFileName());
if (boost::starts_with(name, process_name)) {
process = std::move(test_process);
break;
}
} else {
if (pid == test_process->UniqueProcessId()) {
process = std::move(test_process);
break;
}
}
}
}
if (!process) {
std::cerr << "Failed to find a matching process\n";
return 1;
}
watchpoint =
break;
}
default:
std::cerr << "Unsupported OS\n";
return 1;
}
std::cout << "Running!" << std::endl;
return 0;
}
po::variables_map& vm) {
try {
po::store(po::parse_command_line(argc, argv, desc), vm);
if (vm.count("help")) {
std::cout << "ivmemwatch - Watch guest memory accesses" << '\n';
std::cout << desc << '\n';
exit(0);
}
po::notify(vm);
} catch (po::error& e) {
std::cerr << "ERROR: " << e.what() << std::endl << std::endl;
std::cerr << desc << std::endl;
exit(1);
}
}
Definition vmcall_interface.cc:71
void process_event(Event &event) override
Definition vmcall_interface.cc:80
Interface for an event poller callback.
Definition EventCallback.hh:29
Interface class for hypervisor events.
Definition Event.hh:43
virtual MemAccessEvent & mem_access()=0
Get memory access event information.
virtual bool write_violation() const =0
Returns true if the event was caused by a write attempt.
virtual bool read_violation() const =0
Returns true if the event was caused by a read attempt.
virtual bool execute_violation() const =0
Returns true if the event was caused by am execute attempt.
A class representing a single virtual processor.
Definition Vcpu.hh:33
virtual Registers & registers()=0
Get the processor's registers.
virtual uint32_t id() const =0
Get the number of this Vcpu.
Definition guest_ptr.hh:88
A representation of a Windows Guest OS.
Definition WindowsGuest.hh:33
virtual nt::NtKernel & kernel()=0
Get the Nt kernel.
virtual std::unique_ptr< HANDLE_TABLE > CidTable()=0
Get the PspCidTable from the kernel.
bool interrupted
Definition ivcallmon.cc:43
void mem_callback(Event &event)
Definition ivmemwatch.cc:61
int main(int argc, char **argv)
Definition main.c:35
Classes related to Microsoft Windows guests.
Definition LanguageId.hh:21
Core IntroVirt classes.
Definition Cr0.hh:20
void sig_handler(int signum)
Definition vmcall_interface.cc:571
void parse_program_options(int argc, char **argv, po::options_description &desc, po::variables_map &vm)
Definition vmcall_interface.cc:581
unique_ptr< Domain > domain
Definition vmcall_interface.cc:48