Skip to content

Commit

Permalink
Ssdtmon invalid assumption that physical memory is contiguous (#1337)
Browse files Browse the repository at this point in the history
* initial

* initial
  • Loading branch information
archercreat committed Nov 11, 2021
1 parent 810e9e0 commit fc757e9
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 43 deletions.
80 changes: 41 additions & 39 deletions src/plugins/ssdtmon/ssdtmon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -186,13 +186,17 @@ event_response_t write_cb(drakvuf_t drakvuf, drakvuf_trap_info_t* info)
keyval("Table", fmt::Qstr("SSDT"))
);
}
else if (info->trap_pa > s->w32pservicetable - 8 && info->trap_pa <= s->w32pservicetable + sizeof(uint32_t) * s->w32pservicelimit + sizeof(uint32_t) - 1 )
for (size_t i = 0; i < s->w32p_ssdt.size(); i++)
{
int64_t table_index = (info->trap_pa - s->w32pservicetable) / sizeof(uint32_t);
fmt::print(s->format, "ssdtmon", drakvuf, info,
keyval("TableIndex", fmt::Nval(table_index)),
keyval("Table", fmt::Qstr("SSDTShadow"))
);
const auto& [base, size] = s->w32p_ssdt[i];
if (info->trap_pa >= base && info->trap_pa < base + size)
{
int64_t table_index = (info->trap_pa - base + i * VMI_PS_4KB) / sizeof(uint32_t);
fmt::print(s->format, "ssdtmon", drakvuf, info,
keyval("TableIndex", fmt::Nval(table_index)),
keyval("Table", fmt::Qstr("SSDTShadow"))
);
}
}
return 0;
}
Expand Down Expand Up @@ -305,42 +309,51 @@ ssdtmon::ssdtmon(drakvuf_t drakvuf, const ssdtmon_config* config, output_format_
throw -1;
}
// Read ssdt shadow size
if (VMI_SUCCESS != vmi_read_32_va(vmi, w32k_base + w32psl_rva, gui_pid, &this->w32pservicelimit))
uint32_t w32pservicelimit;
if (VMI_SUCCESS != vmi_read_32_va(vmi, w32k_base + w32psl_rva, gui_pid, &w32pservicelimit))
{
PRINT_DEBUG("[SSDTMON] Failed to read W32pServiceLimit\n");
throw -1;
}
// NOTE: We use vmi_translate_uv2p instead of vmi_translate_kv2p because Win32k.sys mapping is not present
// in system process, only in process with GUI dependencies, hence we use explorer.exe as a pid.
if (VMI_SUCCESS != vmi_translate_uv2p(vmi, w32k_base + w32pst_rva, gui_pid, &this->w32pservicetable))
addr_t w32pservicetable;
if (VMI_SUCCESS != vmi_translate_uv2p(vmi, w32k_base + w32pst_rva, gui_pid, &w32pservicetable))
{
PRINT_DEBUG("[SSDTMON] Failed to translate win32k!W32pServiceTable to physical address\n");
throw -1;
}
}

PRINT_DEBUG("[SSDTMON] SSDT shadow is at 0x%lx. Number of syscalls: %u. Size: %lu\n",
this->w32pservicetable,
this->w32pservicelimit,
sizeof(uint32_t)*this->w32pservicelimit);

this->ssdt_trap[0].memaccess.gfn = this->w32pservicetable >> 12;
this->ssdt_trap[0].cb = write_cb;

if (!drakvuf_add_trap(drakvuf, &this->ssdt_trap[0]))
throw -1;

addr_t ssdt_shadow_write_end = (this->w32pservicetable + sizeof(uint32_t) * this->w32pservicelimit) >> 12;
this->ssdt_trap[0].memaccess.gfn = w32pservicetable >> 12;
this->ssdt_trap[0].cb = write_cb;
if (!drakvuf_add_trap(drakvuf, &this->ssdt_trap[0]))
throw -1;

if ( ssdt_shadow_write_end != this->ssdt_trap[0].memaccess.gfn )
{
this->ssdt_trap[1].cb = write_cb;
this->ssdt_trap[1].memaccess.gfn = ssdt_shadow_write_end;
// On Win10 1803 x64 SSDT Shadow is 1226 elements long
if (sizeof(uint32_t) * w32pservicelimit > VMI_PS_4KB)
{
addr_t w32pservicetable_p2;
if (VMI_SUCCESS != vmi_translate_uv2p(vmi, w32k_base + w32pst_rva + sizeof(uint32_t) * w32pservicelimit, gui_pid, &w32pservicetable_p2))
{
PRINT_DEBUG("[SSDTMON] Failed to translate second page of win32k!W32pServiceTable to physical address\n");
throw -1;
}
this->ssdt_trap[1].memaccess.gfn = w32pservicetable_p2 >> 12;
this->ssdt_trap[1].cb = write_cb;
if (!drakvuf_add_trap(drakvuf, &this->ssdt_trap[1]))
throw -1;

this->w32p_ssdt.emplace_back(w32pservicetable, VMI_PS_4KB);
this->w32p_ssdt.emplace_back(w32pservicetable_p2, w32pservicelimit * sizeof(uint32_t) - VMI_PS_4KB);
}
else
{
this->w32p_ssdt.emplace_back(w32pservicetable, w32pservicelimit * sizeof(uint32_t));
}

if (!drakvuf_add_trap(drakvuf, &this->ssdt_trap[1]))
throw -1;
PRINT_DEBUG("[SSDTMON] SSDT shadow is at 0x%lx. Number of syscalls: %u. Size: %lu\n",
w32pservicetable, w32pservicelimit, sizeof(uint32_t) * w32pservicelimit);
}

json_object_put(profile_json);
}

Expand Down Expand Up @@ -387,23 +400,12 @@ ssdtmon::ssdtmon(drakvuf_t drakvuf, const ssdtmon_config* config, output_format_
this->ssdt_trap[2].cb = write_cb;
this->ssdt_trap[2].memaccess.gfn = this->kiservicetable >> 12;

addr_t ssdtwrite_end = (this->kiservicetable + sizeof(uint32_t) * this->kiservicelimit) >> 12;

if ( !drakvuf_add_trap(drakvuf, &this->ssdt_trap[2]) )
{
PRINT_DEBUG("SSDT plugin failed to trap on \n");
throw -1;
}

if ( ssdtwrite_end != this->ssdt_trap[2].memaccess.gfn )
{
this->ssdt_trap[3].cb = write_cb;
this->ssdt_trap[3].memaccess.gfn = ssdtwrite_end;

if ( !drakvuf_add_trap(drakvuf, &this->ssdt_trap[3]) )
throw -1;
}

addr_t sdt_rva, sdt_shadow_rva;

if (!drakvuf_get_kernel_symbol_rva(drakvuf, "KeServiceDescriptorTable", &sdt_rva) ||
Expand Down
7 changes: 3 additions & 4 deletions src/plugins/ssdtmon/ssdtmon.h
Original file line number Diff line number Diff line change
Expand Up @@ -123,15 +123,14 @@ class ssdtmon: public pluginex
addr_t kiservicetable;
uint32_t kiservicelimit;

addr_t w32pservicetable;
uint32_t w32pservicelimit;
std::vector<std::pair<addr_t, addr_t>> w32p_ssdt;

addr_t sdt_va, sdt_shadow_va;
std::array<uint8_t, 32> sdt_crc, sdt_shadow_crc;

drakvuf_trap_t ssdt_trap[4] =
drakvuf_trap_t ssdt_trap[3] =
{
[0 ... 3] = {
[0 ... 2] = {
.cb = nullptr,
.data = (void*)this,
.name = nullptr,
Expand Down

0 comments on commit fc757e9

Please sign in to comment.