mirror of
https://dev.lirent.ru/Vatrog/vm-introspection-engine.git
synced 2026-06-18 04:16:39 +03:00
112 lines
3.3 KiB
C
112 lines
3.3 KiB
C
|
|
#include <stdint.h>
|
||
|
|
#include <stddef.h>
|
||
|
|
#include <string.h>
|
||
|
|
#include "include/memory.h"
|
||
|
|
#include "../include/include.h"
|
||
|
|
|
||
|
|
#define pr_(ctx) (ctx->prof)
|
||
|
|
|
||
|
|
#define RING_GUARD 100000u
|
||
|
|
#define MOD_GUARD 4096u
|
||
|
|
|
||
|
|
static void grab_ustr(gva_ctx* ctx, uintptr_t cr3, uint64_t va, gtext* out) {
|
||
|
|
uint16_t len = 0;
|
||
|
|
uint64_t buf = 0;
|
||
|
|
out->va = 0;
|
||
|
|
out->len = 0;
|
||
|
|
if (gva_read(ctx, cr3, va, &len, 2) || gva_read(ctx, cr3, va + 8, &buf, 8)) {
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
out->va = buf;
|
||
|
|
out->len = len;
|
||
|
|
}
|
||
|
|
|
||
|
|
int proc_list(gva_ctx* ctx, int skip_system, process* dst, size_t nmax) {
|
||
|
|
const profile* p = &pr_(ctx);
|
||
|
|
const uint64_t kcr3 = ctx->kcr3;
|
||
|
|
if (!kcr3 || !ctx->sysproc) {
|
||
|
|
return -1;
|
||
|
|
}
|
||
|
|
|
||
|
|
size_t n = 0;
|
||
|
|
unsigned guard = 0;
|
||
|
|
uint64_t ep = ctx->sysproc, node;
|
||
|
|
|
||
|
|
do {
|
||
|
|
uint64_t pid = 0, ppid = 0, dtb = 0, peb = 0;
|
||
|
|
gva_read(ctx, kcr3, ep + p->ep_pid, &pid, 8);
|
||
|
|
gva_read(ctx, kcr3, ep + p->ep_dtb, &dtb, 8);
|
||
|
|
if (p->ep_peb) { gva_read(ctx, kcr3, ep + p->ep_peb, &peb, 8); }
|
||
|
|
if (p->ep_ppid) { gva_read(ctx, kcr3, ep + p->ep_ppid, &ppid, 8); }
|
||
|
|
|
||
|
|
if (!skip_system || peb) {
|
||
|
|
if (n >= nmax) {
|
||
|
|
return (int)n;
|
||
|
|
}
|
||
|
|
process* q = &dst[n++];
|
||
|
|
q->eprocess = ep;
|
||
|
|
q->cr3 = dtb & PFN_MASK;
|
||
|
|
q->peb = peb;
|
||
|
|
q->pid = (uint32_t)pid;
|
||
|
|
q->ppid = p->ep_ppid ? (uint32_t)ppid : (uint32_t)-1;
|
||
|
|
q->create_time = 0;
|
||
|
|
if (p->ep_createtime) {
|
||
|
|
gva_read(ctx, kcr3, ep + p->ep_createtime, &q->create_time, 8);
|
||
|
|
}
|
||
|
|
memset(q->name, 0, sizeof q->name);
|
||
|
|
gva_read(ctx, kcr3, ep + p->ep_name, q->name, sizeof q->name - 1);
|
||
|
|
q->path.va = 0;
|
||
|
|
q->path.len = 0;
|
||
|
|
if (p->ep_imgpath) {
|
||
|
|
grab_ustr(ctx, kcr3, ep + p->ep_imgpath, &q->path); /* read text under kcr3 */
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
if (gva_read(ctx, kcr3, ep + p->ep_links, &node, 8)) {
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
ep = node - p->ep_links;
|
||
|
|
} while (ep != ctx->sysproc && ++guard < RING_GUARD);
|
||
|
|
|
||
|
|
return (int)n;
|
||
|
|
}
|
||
|
|
|
||
|
|
int proc_modules(gva_ctx* ctx, const process* pr, pmodule* dst, size_t nmax) {
|
||
|
|
const profile* p = &pr_(ctx);
|
||
|
|
const uint64_t cr3 = pr->cr3;
|
||
|
|
if (!pr->peb || !cr3) {
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
uint64_t ldr = 0, head, link;
|
||
|
|
if (gva_read(ctx, cr3, pr->peb + p->peb_ldr, &ldr, 8) || !ldr) {
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
head = ldr + p->ldr_loadlist;
|
||
|
|
if (gva_read(ctx, cr3, head, &link, 8)) {
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
size_t n = 0;
|
||
|
|
unsigned guard = 0;
|
||
|
|
while (link != head && n < nmax && ++guard < MOD_GUARD) {
|
||
|
|
const uint64_t entry = link; /* InLoadOrderLinks at offset 0 of the entry */
|
||
|
|
uint64_t base = 0;
|
||
|
|
uint32_t size = 0;
|
||
|
|
gva_read(ctx, cr3, entry + p->lde_base, &base, 8);
|
||
|
|
gva_read(ctx, cr3, entry + p->lde_size, &size, 4);
|
||
|
|
|
||
|
|
pmodule* m = &dst[n++];
|
||
|
|
m->pr = pr;
|
||
|
|
m->entry = entry;
|
||
|
|
m->base = base;
|
||
|
|
m->size = size;
|
||
|
|
grab_ustr(ctx, cr3, entry + p->lde_name, &m->name);
|
||
|
|
grab_ustr(ctx, cr3, entry + p->lde_fullname, &m->path);
|
||
|
|
|
||
|
|
if (gva_read(ctx, cr3, link, &link, 8)) {
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return (int)n;
|
||
|
|
}
|