Lists Windows guest processes and optional token/process details. Demonstrates walking the process list (PsActiveProcessHead), reading EPROCESS, and optional filtering by name or PID.
#include <boost/algorithm/string.hpp>
#include <boost/program_options.hpp>
#include <iostream>
#include <set>
#include <string>
#include <vector>
using namespace std;
namespace po = boost::program_options;
po::variables_map& vm);
std::cout <<
" EPROCESS: " << process.
ptr() <<
'\n';
std::cout << " WoW64Process\n";
std::cout << " Session ID: ";
else
std::cout << "None\n";
}
std::cout << " TOKEN:\n";
cout << " User: ";
if (sid) {
cout << *sid << '\n';
} else {
cout << "Unreadable\n";
}
} else {
cout << " Unreadable\n";
}
cout << " Primary Group: ";
if (sid) {
cout << *sid << '\n';
} else {
cout << "Unreadable\n";
}
}
cout << " Groups:\n";
size_t groupIdx = 0;
for (const auto& sidAndAttributes : token.Groups()) {
const auto sid = sidAndAttributes->Sid();
cout << " [" << groupIdx++ << "] ";
if (sid) {
cout << *sid << '\n';
} else {
cout << "Unreadable\n";
}
cout << " Attributes: " << sidAndAttributes->Attributes() << '\n';
}
}
result.clear();
if (resourceDir) {
if (!versionEntry) {
return;
}
const auto* versionDir = versionEntry->
Directory();
if (!versionDir) {
return;
}
const auto* versionInfoEntry = versionDir->
entry(1);
if (!versionInfoEntry) {
return;
}
const auto* versionInfoDir = versionInfoEntry->
Directory();
if (!versionInfoDir) {
return;
}
const auto* englishVersionInfoEntry =
versionInfoDir->
entry(LanguageId::English_United_States);
if (!englishVersionInfoEntry) {
return;
}
const auto* englishVersionInfoData = englishVersionInfoEntry->
Data();
if (!englishVersionInfoData) {
return;
}
auto versionInfo = VS_VERSIONINFO::make_unique(englishVersionInfoData->data_address());
if (sfi) {
if (st) {
}
}
}
}
if (!WoW64Process)
std::cout << " PEB:\n";
else
std::cout << " WoW64Process PEB:\n";
try {
if (!peb) {
std::cout << " NULL\n";
return;
}
std::cout << " Paged out\n";
return;
}
cout << std::hex;
cout << std::dec;
cout << " Module List: \n";
if (!ldr) {
std::cout << " Unreadable\n";
return;
}
for (const auto& entry : moduleList) {
if (!entry->FullDllName().empty()) {
cout << " " << entry->FullDllName() << '\n';
} else if (!entry->BaseDllName().empty()) {
cout << " " << entry->BaseDllName() << '\n';
} else {
cout << " < Name not readable >\n";
}
cout << std::hex;
cout << " Base: 0x" << entry->DllBase() << '\n';
cout << " Entry Point: 0x" << entry->EntryPoint() << '\n';
cout << std::dec;
cout << " Size: " << entry->SizeOfImage() << " bytes\n";
try {
auto pe = PE::make_unique(entry->ptr().clone(entry->DllBase()));
std::map<std::string, std::string> versionData;
try {
if (!versionData.empty()) {
cout << " Version Information:\n";
for (auto iter : versionData) {
auto&& key = iter.first;
auto&& value = iter.second;
cout << " " << key;
cout << ": ";
cout << value;
cout << '\n';
}
}
cout << " Failed to get version data\n";
}
cout << " Failed to parse PE Header\n";
}
}
}
cout << " VAD:\n";
if (!vad) {
std::cout << " Null\n";
return;
}
for (auto mmvad : vad->VadTreeInOrder()) {
cout << " Range: " << mmvad->StartingAddress();
cout << " - " << mmvad->EndingAddress() << '\n';
cout << " Commit Charge: " << mmvad->CommitCharge() << '\n';
cout << " Size: " << mmvad->RegionSize() << " bytes\n";
cout << " Type: " << mmvad->Type() << '\n';
cout << " Allocation: " << mmvad->Allocation() << "[0x" << hex
<< mmvad->Allocation().value() << dec << "]\n";
cout << " Protection: " << mmvad->Protection() << "[0x" << hex
<< mmvad->Protection().value() << dec << "]\n";
try {
if (fileObj) {
cout << " File: ";
if (dev) {
}
cout << '\n';
}
cout << " File: [Unreadable Filename]\n";
cout << ex << '\n';
}
}
}
cout << " Environment:\n";
try {
std::cout << " Paged out\n";
return;
}
if (peb) {
if (params) {
for (auto iter : envMap) {
auto& key = iter.first;
auto& value = iter.second;
cout << " " << key << "\n";
cout << " " << value << "\n";
}
} else {
cout << " RTL_USER_PROCESS_PARAMETERS Unavailable\n";
}
} else {
cout << " Null\n";
}
}
std::cout << " Handles:\n";
if (!table) {
std::cout << "Null HANDLE_TABLE\n";
return;
}
std::cout << " Handle Count: " << table->HandleCount() << '\n';
try {
for (const auto& entry : table->open_handles()) {
std::cout << " 0x" << std::hex << entry->Handle() << std::dec << ": ";
try {
auto object = OBJECT::make_shared(kernel, entry->ObjectHeader());
std::cout << object->header().type();
std::cout << " [" << object->ptr() << "]";
std::cout << "Unable to read OBJECT_HEADER";
}
std::cout << '\n';
}
std::cout << '\n';
}
}
cout << " Threads: ";
try {
cout << "(" << threadList.size() << ")\n";
for (const auto& thread : threadList) {
cout << " TID: " << thread->Cid().UniqueThread() << '\n';
cout << hex;
cout << " State: " << thread->State() << '\n';
cout << " CrossThreadFlags: 0x" << thread->CrossThreadFlags() << '\n';
cout << " Affinity: 0x" << thread->Affinity() << '\n';
cout << " TEB: ";
const TEB* teb = thread->Teb();
if (teb) {
cout << teb->
ptr() <<
'\n';
cout << " TIB:\n";
cout <<
" Stack Base: " << tib.
StackBase() <<
'\n';
cout <<
" Stack Limit: " << tib.
StackLimit() <<
'\n';
} else {
cout << "<unreadable>\n";
}
if (thread->State() != KTHREAD_STATE::Terminated) {
cout << " ETHREAD Object: " << thread->header().Body() << '\n';
cout << " Win32StartAddress: " << thread->Win32StartAddress();
const uint64_t pWin32StartAddress = thread->Win32StartAddress().address();
auto mmvad = thread->Process().VadRoot();
if (mmvad) {
auto entry = mmvad->search(pWin32StartAddress);
if (entry) {
if (fObj) {
const uint64_t offset = pWin32StartAddress - entry->StartingAddress();
cout <<
" (" << fObj->
FileName() <<
"+0x" << offset <<
")";
}
}
}
std::cout << '\n';
}
cout << std::dec;
}
cout << "\n Unable to read thread list\n";
}
}
int main(
int argc,
char** argv) {
po::options_description desc("Options");
std::string domain_name;
std::vector<std::string> names;
std::vector<uint64_t> pids;
bool display_full = false;
desc.add_options()
("domain,D", po::value<std::string>(&domain_name)->required(), "The domain name or ID attach to")
("name", po::value<std::vector<std::string>>(&names), "Only show processes beginning with the provided value. Can be called multiple times.")
("pid", po::value<std::vector<uint64_t>>(&pids), "Only show processes matching the given PID. Can be called multiple times.")
("env", "Display environmental variables")
("handles", "Display handle table information")
("peb", "Display the PEB (Process Environment Block)")
("thread", "Display the THREAD object in each process")
("token", "Display token information")
("vad", "Display the VAD (Virtual Address Descriptor)")
("full", po::bool_switch(&display_full), "Display all process information")
("help", "Display program help");
po::variables_map vm;
std::set<std::string> name_filter;
std::transform(names.begin(), names.end(), std::inserter(name_filter, name_filter.end()),
[](const std::string& s) -> std::string { return boost::to_lower_copy(s); });
std::set<uint64_t> pid_filter;
std::copy(pids.begin(), pids.end(), std::inserter(pid_filter, pid_filter.end()));
auto hypervisor = Hypervisor::instance();
auto domain = hypervisor->attach_domain(domain_name);
if (!
domain->detect_guest()) {
std::cerr << "Failed to detect guest operating system\n";
return 1;
}
auto* guest =
domain->guest();
if (guest->os() != OS::Windows) {
std::cerr << "Unsupported OS: " << guest->os() << '\n';
return 2;
}
for (auto& entry : CidTable->open_handles()) {
std::unique_ptr<OBJECT_HEADER> header(entry->ObjectHeader());
if (header->type() == ObjectType::Process) {
auto process = kernel.
process(header->Body());
continue;
if (!name_filter.empty()) {
const std::string ImageFileName = boost::to_lower_copy(process->
ImageFileName());
bool match = false;
for (const std::string& name : name_filter) {
if (boost::starts_with(ImageFileName, name)) {
match = true;
break;
}
}
if (!match)
continue;
}
try {
if (display_full || vm.count("token"))
if (display_full || vm.count("peb")) {
}
if (display_full || vm.count("vad"))
if (display_full || vm.count("env"))
if (display_full || vm.count("handles"))
if (display_full || vm.count("thread"))
std::cout << ex;
throw;
}
}
}
return 0;
}
po::variables_map& vm) {
try {
po::store(po::parse_command_line(argc, argv, desc), vm);
if (vm.count("help")) {
std::cout << "ivprocinfo - Display process information" << '\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);
}
}
static const uint16_t VERSION
Definition ResourceDirType.hh:33
Base class for exceptions with stack unwinding.
Definition TraceableException.hh:31
Thrown when translating a guest virtual address is marked as not present.
Definition VirtualAddressNotPresentException.hh:31
A representation of a Windows Guest OS.
Definition WindowsGuest.hh:33
Class for the Windows NT DEVICE_OBJECT structure.
Definition DEVICE_OBJECT.hh:38
virtual std::string DeviceName() const =0
Definition FILE_OBJECT.hh:66
virtual const DEVICE_OBJECT * DeviceObject() const =0
virtual std::string FileName() const =0
virtual uint32_t SessionID() const =0
virtual guest_ptr< void > StackLimit() const =0
virtual guest_ptr< void > StackBase() const =0
Abstraction for the Windows NT kernel.
Definition NtKernel.hh:37
virtual std::unique_ptr< HANDLE_TABLE > CidTable()=0
Get the PspCidTable from the kernel.
virtual std::shared_ptr< PROCESS > process(const guest_ptr< void > &ptr) const =0
Get the PROCESS at the given address.
virtual guest_ptr< void > ptr() const =0
Definition PEB_LDR_DATA.hh:32
virtual const std::vector< std::shared_ptr< const LDR_DATA_TABLE_ENTRY > > & InLoadOrderList() const =0
virtual const PEB_LDR_DATA * Ldr() const =0
virtual const RTL_USER_PROCESS_PARAMETERS * ProcessParameters() const =0
virtual guest_ptr< void > ImageBaseAddress() const =0
virtual std::unique_ptr< HANDLE_TABLE > ObjectTable()=0
Get the handle table for this process, used for looking up objects by handle number.
virtual bool isWow64Process() const =0
virtual const std::string & ImageFileName() const =0
virtual const PEB * Peb() const =0
virtual const MM_SESSION_SPACE * Session() const =0
virtual TOKEN & Token()=0
virtual uint64_t UniqueProcessId() const =0
virtual uint64_t InheritedFromUniqueProcessId() const =0
virtual std::shared_ptr< const MMVAD > VadRoot() const =0
virtual const PEB * WoW64Process() const =0
virtual std::vector< std::shared_ptr< THREAD > > ThreadList()=0
Definition RTL_USER_PROCESS_PARAMETERS.hh:33
virtual std::map< std::string, std::string > EnvironmentMap() const =0
Get the environment as a string map, for quick lookups.
virtual const NT_TIB & NtTib() const =0
virtual WinError LastErrorValue() const =0
virtual guest_ptr< void > ptr() const =0
virtual const SID * PrimaryGroup() const =0
virtual const SID * User() const =0
virtual const IMAGE_RESOURCE_DIRECTORY * Directory() const =0
Get the IMAGE_RESOURCE_DIRECTORY if it exists.
virtual const IMAGE_RESOURCE_DATA_ENTRY * Data() const =0
Get the IMAGE_RESOURCE_DATA_ENTRY if it exists.
virtual const IMAGE_RESOURCE_DIRECTORY_ENTRY * entry(uint16_t Id) const =0
Parser for Windows Portable Executable (PE) headers.
Definition PE.hh:30
virtual const IMAGE_OPTIONAL_HEADER & optional_header() const =0
Definition StringFileInfo.hh:25
virtual const pe::StringTable * StringTable() const =0
Definition StringTable.hh:34
virtual const std::map< std::string, std::string > & entries() const =0
void print_process(const PROCESS &process)
Definition ivprocinfo.cc:49
void getPEVersionData(const PE &pe, std::map< std::string, std::string > &result)
Definition ivprocinfo.cc:108
void print_token(const PROCESS &process)
Definition ivprocinfo.cc:65
void print_threads(const PROCESS &process)
Definition ivprocinfo.cc:322
void print_peb(const PROCESS &process, bool WoW64Process)
Definition ivprocinfo.cc:156
void print_environment(const PROCESS &process)
Definition ivprocinfo.cc:267
void print_vad(const PROCESS &process)
Definition ivprocinfo.cc:228
void print_handles(const nt::NtKernel &kernel, const PROCESS &process)
Definition ivprocinfo.cc:296
int main(int argc, char **argv)
Definition main.c:35
Classes related to the Windows NT kernel.
Definition APPHELPCACHESERVICECLASS.hh:23
Classes related to parsing the PE file format in memory.
Definition FileFlags.hh:22
Classes related to Microsoft Windows guests.
Definition LanguageId.hh:21
Core IntroVirt classes.
Definition Cr0.hh:20
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