DMP: Fix ETHREAD address on triage dump

* Gets `ETHREAD` address from `KPRCB`
This commit is contained in:
GustavoLCR 2022-01-04 05:44:44 -03:00 committed by Anton Kochkov
parent 7c6810e2ee
commit 11c366583e
2 changed files with 47 additions and 37 deletions

View file

@ -128,51 +128,61 @@ static bool rz_debug_dmp_init(RzDebug *dbg, void **user) {
if (!ctx->windctx.profile) {
winkd_build_profile(&ctx->windctx, dbg->analysis->typedb);
}
} else {
eprintf("Failed to download ntoskrnl.pdb, many things won't work.\n");
}
}
if (ctx->type == DMP_DUMPTYPE_TRIAGE) {
// Map EPROCESS into address space
RzIOMap *map = rz_io_map_new(core->io, desc->fd, RZ_PERM_R, ProcessOffset, 0, ThreadOffset - ProcessOffset);
map->name = strdup("kernel.target.eprocess");
WindProc *target = winkd_get_process_at(&ctx->windctx, 0);
RzList *l = winkd_list_process(&ctx->windctx);
RzListIter *it;
WindProc *p;
rz_list_foreach (l, it, p) {
if (p->uniqueid == target->uniqueid) {
rz_io_map_remap(core->io, map->id, p->eprocess);
rz_io_map_depriorize(core->io, map->id);
ctx->windctx.target = *p;
memcpy(ctx->windctx.target.name, target->name, sizeof(ctx->windctx.target.name));
break;
}
}
free(target);
rz_list_free(l);
if (!ctx->windctx.profile) {
eprintf("Could not find a profile for this Windows: %s %" PFMT32d "-bit %" PFMT32u " SP %" PFMT32u "\n",
ctx->windctx.is_arm ? "ARM" : "x86", dbg->bits * 8, MinorVersion, ServicePackBuild);
return false;
}
ctx->kthread_process_offset = rz_type_db_struct_member_offset(dbg->analysis->typedb, "_KTHREAD", "Process");
ctx->kprcb_context_offset = rz_type_db_struct_member_offset(dbg->analysis->typedb, "_KPRCB", "Context");
if (ctx->windctx.is_arm) {
const ut64 switch_frame_offset = rz_type_db_struct_member_offset(dbg->analysis->typedb, "_KTHREAD", "SwitchFrame");
ctx->kthread_switch_frame_offset = switch_frame_offset + rz_type_db_struct_member_offset(dbg->analysis->typedb, "_KSWITCH_FRAME", "Fp");
}
const ut64 KiProcessorBlock = dbg->corebind.numGet(dbg->corebind.core, "pdb.KiProcessorBlock");
ut64 i;
for (i = 0; i < NumberProcessors; i++) {
ut64 address = KiProcessorBlock + i * (ctx->windctx.is_64bit ? 8 : 4);
ut64 kprcb = winkd_read_ptr_at(&ctx->windctx, ctx->windctx.read_at_kernel_virtual, address);
rz_vector_push(&ctx->KiProcessorBlock, &kprcb);
}
if (ctx->type == DMP_DUMPTYPE_TRIAGE) {
// Map ETHREAD into address space
const ut64 address = 0x1000;
map = rz_io_map_new(core->io, desc->fd, RZ_PERM_R, ThreadOffset, address, CallStackOffset - ThreadOffset);
rz_io_map_depriorize(core->io, map->id);
map->name = strdup("kernel.target.ethread");
WindThread *target_thread = winkd_get_thread_at(&ctx->windctx, address);
ctx->windctx.target_thread = *target_thread;
ctx->windctx.target_thread.ethread = address;
const ut64 current_thread_offset = ctx->windctx.is_64bit ? 8 : 4;
ut64 *kprcb;
rz_vector_foreach(&ctx->KiProcessorBlock, kprcb) {
const ut64 current_thread = winkd_read_ptr_at(&ctx->windctx, ctx->windctx.read_at_kernel_virtual, *kprcb + current_thread_offset);
WindThread *thread = winkd_get_thread_at(&ctx->windctx, current_thread);
if (thread && thread->uniqueid == target_thread->uniqueid) {
// Map EPROCESS into address space
const ut64 current_process = winkd_read_ptr_at(&ctx->windctx, ctx->windctx.read_at_kernel_virtual, thread->ethread + ctx->kthread_process_offset);
RzIOMap *map = rz_io_map_new(core->io, desc->fd, RZ_PERM_R, ProcessOffset, current_process, ThreadOffset - ProcessOffset);
map->name = strdup("kernel.target.eprocess");
WindProc *process = winkd_get_process_at(&ctx->windctx, current_process);
ctx->windctx.target = *process;
ctx->windctx.target_thread = *thread;
free(process);
free(thread);
break;
}
free(thread);
}
rz_io_map_remap(core->io, map->id, ctx->windctx.target_thread.ethread);
free(target_thread);
} else {
ctx->kprcb_context_offset = rz_type_db_struct_member_offset(dbg->analysis->typedb, "_KPRCB", "Context");
if (ctx->windctx.is_arm) {
const ut64 switch_frame_offset = rz_type_db_struct_member_offset(dbg->analysis->typedb, "_KTHREAD", "SwitchFrame");
ctx->kthread_switch_frame_offset = switch_frame_offset + rz_type_db_struct_member_offset(dbg->analysis->typedb, "_KSWITCH_FRAME", "Fp");
}
const ut64 KiProcessorBlock = dbg->corebind.numGet(dbg->corebind.core, "pdb.KiProcessorBlock");
int i;
for (i = 0; i < NumberProcessors; i++) {
ut64 address = KiProcessorBlock + i * (ctx->windctx.is_64bit ? 8 : 4);
ut64 kprcb = winkd_read_ptr_at(&ctx->windctx, ctx->windctx.read_at_kernel_virtual, address);
rz_vector_push(&ctx->KiProcessorBlock, &kprcb);
}
}
return true;
@ -186,7 +196,6 @@ static int rz_debug_dmp_attach(RzDebug *dbg, int pid) {
return dbg->pid;
}
const ut64 current_thread_offset = ctx->windctx.is_64bit ? 8 : 4;
const int process_offset = rz_type_db_struct_member_offset(dbg->analysis->typedb, "_KTHREAD", "Process");
ut64 *kprcb;
rz_vector_foreach_prev(&ctx->KiProcessorBlock, kprcb) {
const ut64 current_thread = winkd_read_ptr_at(&ctx->windctx, ctx->windctx.read_at_kernel_virtual, *kprcb + current_thread_offset);
@ -194,7 +203,7 @@ static int rz_debug_dmp_attach(RzDebug *dbg, int pid) {
if (!thread) {
continue;
}
const ut64 current_process = winkd_read_ptr_at(&ctx->windctx, ctx->windctx.read_at_kernel_virtual, thread->ethread + process_offset);
const ut64 current_process = winkd_read_ptr_at(&ctx->windctx, ctx->windctx.read_at_kernel_virtual, thread->ethread + ctx->kthread_process_offset);
WindProc *process = winkd_get_process_at(&ctx->windctx, current_process);
if (!process || (!process->uniqueid && !strncmp(process->name, "Idle", sizeof(process->name)))) {
free(thread);
@ -250,7 +259,7 @@ static int rz_debug_dmp_select(RzDebug *dbg, int pid, int tid) {
dbg->tid = ctx->windctx.target_thread.uniqueid;
return ctx->windctx.target_thread.uniqueid;
}
if (winkd_set_target(&ctx->windctx, pid, tid)) {
ctx->target = TARGET_VIRTUAL;
}

View file

@ -110,6 +110,7 @@ typedef struct _DmpCtx {
RzVector /*<ut64>*/ KiProcessorBlock;
ut32 kprcb_context_offset; // nt!_KPRCB ProcessorState.ContextFrame
ut32 kthread_switch_frame_offset; // nt!_KTHREAD SwitchFrame.Fp
ut32 kthread_process_offset; // nt!_KTHREAD Process
ut8 *context;
size_t context_sz;
} DmpCtx;