mirror of
https://github.com/donnaskiez/ac.git
synced 2024-11-21 22:24:08 +01:00
e
This commit is contained in:
parent
cfb3640a88
commit
5f90ddc085
2 changed files with 71 additions and 26 deletions
|
@ -46,6 +46,53 @@ end:
|
||||||
return debugger_data;
|
return debugger_data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VOID ScanPageForProcessAllocations(
|
||||||
|
_In_ UINT64 PageBase,
|
||||||
|
_In_ ULONG PageSize
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if ( !PageBase || !PageSize )
|
||||||
|
return;
|
||||||
|
|
||||||
|
CHAR process[ 4 ] = { 'Proc' };
|
||||||
|
|
||||||
|
DEBUG_LOG( "1: %hhx, 2: %hhx, 3: %hhx, 5: %hhx", process[ 0 ], process[ 1 ], process[ 2 ], process[ 3 ] );
|
||||||
|
|
||||||
|
__debugbreak();
|
||||||
|
|
||||||
|
for ( INT offset = 0; offset < PageSize; offset++ )
|
||||||
|
{
|
||||||
|
if ( !MmIsAddressValid( PageBase + offset ) )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
CHAR current_char = *( PCHAR )( PageBase + offset );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This is your basic page table walk function. On intel systems, paging has 4 levels,
|
||||||
|
* each table holds 512 entries with a total size of 0x1000 (512 * sizeof(QWORD)). Each entry
|
||||||
|
* in each table contains a value with a subset bitfield containing the physical address
|
||||||
|
* of the base of the next table in the structure. So for example, a PML4 entry contains
|
||||||
|
* a physical address that points to the base of the PDPT table, it is the same for a PDPT
|
||||||
|
* entry -> PD base and so on.
|
||||||
|
*
|
||||||
|
* However, as with all good things Windows has implemented security features meaning
|
||||||
|
* we cannot use functions such as MmCopyMemory or MmMapIoSpace on paging structures,
|
||||||
|
* so we must find another way to walk the pages. Luckily for us, there exists
|
||||||
|
* MmGetVirtualForPhysical. This function is self explanatory and returns the corresponding
|
||||||
|
* virtual address given a physical address. What this means is that we can extract a page
|
||||||
|
* entry physical address, pass it to MmGetVirtualForPhysical which returns us the virtual
|
||||||
|
* address of the base of the next page structure. This is because page tables are still
|
||||||
|
* mapped by the kernel and exist in virtual memory just like everything else and hence
|
||||||
|
* reading the value at all 512 entries from the virtual base will give us the equivalent
|
||||||
|
* value as directly reading the physical address.
|
||||||
|
*
|
||||||
|
* Using this, we essentially walk the page tables as any regular translation would
|
||||||
|
* except instead of simply reading the physical we translate it to a virtual address
|
||||||
|
* and extract the physical address from the value at each virtual address page entry.
|
||||||
|
*/
|
||||||
|
|
||||||
VOID WalkKernelPageTables()
|
VOID WalkKernelPageTables()
|
||||||
{
|
{
|
||||||
CR3 cr3;
|
CR3 cr3;
|
||||||
|
@ -60,41 +107,33 @@ VOID WalkKernelPageTables()
|
||||||
PTE pt_base;
|
PTE pt_base;
|
||||||
PTE pt_entry;
|
PTE pt_entry;
|
||||||
UINT64 base_physical_page;
|
UINT64 base_physical_page;
|
||||||
|
UINT64 base_virtual_page;
|
||||||
PHYSICAL_ADDRESS physical;
|
PHYSICAL_ADDRESS physical;
|
||||||
|
|
||||||
cr3.BitAddress = __readcr3();
|
cr3.BitAddress = __readcr3();
|
||||||
|
|
||||||
DEBUG_LOG( "cr3: %llx", cr3.BitAddress );
|
physical.QuadPart = cr3.Bits.PhysicalAddress << PAGE_4KB_SHIFT;
|
||||||
|
|
||||||
physical.QuadPart = cr3.Bits.PhysicalAddress << 12;
|
|
||||||
|
|
||||||
/* Get our PML4 base address */
|
|
||||||
pml4_base.BitAddress = MmGetVirtualForPhysical( physical );
|
pml4_base.BitAddress = MmGetVirtualForPhysical( physical );
|
||||||
|
|
||||||
if ( !MmIsAddressValid(pml4_base.BitAddress) || !pml4_base.BitAddress )
|
if ( !MmIsAddressValid( pml4_base.BitAddress ) || !pml4_base.BitAddress )
|
||||||
{
|
|
||||||
DEBUG_ERROR( "Pml4 base is null or invalid" );
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
for ( INT pml4_index = 0; pml4_index < 512; pml4_index++ )
|
for ( INT pml4_index = 0; pml4_index < PML4_ENTRY_COUNT; pml4_index++ )
|
||||||
{
|
{
|
||||||
/* get our PML4 entry*/
|
|
||||||
pml4_entry.BitAddress = *(UINT64*)( pml4_base.BitAddress + pml4_index * sizeof( UINT64 ) );
|
pml4_entry.BitAddress = *(UINT64*)( pml4_base.BitAddress + pml4_index * sizeof( UINT64 ) );
|
||||||
|
|
||||||
/* check the present bit */
|
|
||||||
if ( pml4_entry.Bits.Present == NULL )
|
if ( pml4_entry.Bits.Present == NULL )
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* read our pml4 entry */
|
physical.QuadPart = pml4_entry.Bits.PhysicalAddress << PAGE_4KB_SHIFT;
|
||||||
physical.QuadPart = pml4_entry.Bits.PhysicalAddress << 12;
|
|
||||||
|
|
||||||
pdpt_base.BitAddress = MmGetVirtualForPhysical( physical );
|
pdpt_base.BitAddress = MmGetVirtualForPhysical( physical );
|
||||||
|
|
||||||
if ( !pdpt_base.BitAddress || !MmIsAddressValid( pdpt_base.BitAddress ) )
|
if ( !pdpt_base.BitAddress || !MmIsAddressValid( pdpt_base.BitAddress ) )
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
for ( INT pdpt_index = 0; pdpt_index < 512; pdpt_index++ )
|
for ( INT pdpt_index = 0; pdpt_index < PDPT_ENTRY_COUNT; pdpt_index++ )
|
||||||
{
|
{
|
||||||
pdpt_entry.BitAddress = *( UINT64* )( pdpt_base.BitAddress + pdpt_index * sizeof( UINT64 ) );
|
pdpt_entry.BitAddress = *( UINT64* )( pdpt_base.BitAddress + pdpt_index * sizeof( UINT64 ) );
|
||||||
|
|
||||||
|
@ -103,21 +142,19 @@ VOID WalkKernelPageTables()
|
||||||
|
|
||||||
if ( IS_LARGE_PAGE( pdpt_entry.BitAddress ) )
|
if ( IS_LARGE_PAGE( pdpt_entry.BitAddress ) )
|
||||||
{
|
{
|
||||||
|
/* 2GB size page */
|
||||||
pdpt_large_entry.BitAddress = pdpt_entry.BitAddress;
|
pdpt_large_entry.BitAddress = pdpt_entry.BitAddress;
|
||||||
|
|
||||||
//scan large page bla bla
|
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
physical.QuadPart = pdpt_entry.Bits.PhysicalAddress << 12;
|
physical.QuadPart = pdpt_entry.Bits.PhysicalAddress << PAGE_4KB_SHIFT;
|
||||||
|
|
||||||
pd_base.BitAddress = MmGetVirtualForPhysical( physical );
|
pd_base.BitAddress = MmGetVirtualForPhysical( physical );
|
||||||
|
|
||||||
if ( !pd_base.BitAddress || !MmIsAddressValid( pd_base.BitAddress ) )
|
if ( !pd_base.BitAddress || !MmIsAddressValid( pd_base.BitAddress ) )
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
for ( INT pd_index = 0; pd_index < 512; pd_index++ )
|
for ( INT pd_index = 0; pd_index < PD_ENTRY_COUNT; pd_index++ )
|
||||||
{
|
{
|
||||||
pd_entry.BitAddress = *( UINT64* )( pd_base.BitAddress + pd_index * sizeof( UINT64 ) );
|
pd_entry.BitAddress = *( UINT64* )( pd_base.BitAddress + pd_index * sizeof( UINT64 ) );
|
||||||
|
|
||||||
|
@ -128,34 +165,35 @@ VOID WalkKernelPageTables()
|
||||||
{
|
{
|
||||||
/* 2MB size page */
|
/* 2MB size page */
|
||||||
pd_large_entry.BitAddress = pd_entry.BitAddress;
|
pd_large_entry.BitAddress = pd_entry.BitAddress;
|
||||||
|
|
||||||
//scan etc.
|
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
physical.QuadPart = pd_entry.Bits.PhysicalAddress << 12;
|
physical.QuadPart = pd_entry.Bits.PhysicalAddress << PAGE_4KB_SHIFT;
|
||||||
|
|
||||||
pt_base.BitAddress = MmGetVirtualForPhysical( physical );
|
pt_base.BitAddress = MmGetVirtualForPhysical( physical );
|
||||||
|
|
||||||
if ( !pt_base.BitAddress || !MmIsAddressValid( pt_base.BitAddress ) )
|
if ( !pt_base.BitAddress || !MmIsAddressValid( pt_base.BitAddress ) )
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
for ( INT pt_index = 0; pt_index < 512; pt_index++ )
|
for ( INT pt_index = 0; pt_index < PT_ENTRY_COUNT; pt_index++ )
|
||||||
{
|
{
|
||||||
pt_entry.BitAddress = *( UINT64* )( pt_base.BitAddress + pt_index * sizeof( UINT64 ) );
|
pt_entry.BitAddress = *( UINT64* )( pt_base.BitAddress + pt_index * sizeof( UINT64 ) );
|
||||||
|
|
||||||
if ( pt_entry.Bits.Present == NULL )
|
if ( pt_entry.Bits.Present == NULL )
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
base_physical_page = pt_entry.Bits.PhysicalAddress << 12;
|
physical.QuadPart = pt_entry.Bits.PhysicalAddress << PAGE_4KB_SHIFT;
|
||||||
|
|
||||||
|
base_virtual_page = MmGetVirtualForPhysical( physical );
|
||||||
|
|
||||||
|
ScanPageForProcessAllocations( base_virtual_page, PAGE_BASE_SIZE );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DEBUG_LOG( "Finished scanning memory" );
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
VOID ScanNonPagedPoolForProcessTags()
|
VOID ScanNonPagedPoolForProcessTags()
|
||||||
|
|
|
@ -6,6 +6,13 @@
|
||||||
#define POOL_DUMP_BLOCK_TAG 'dump'
|
#define POOL_DUMP_BLOCK_TAG 'dump'
|
||||||
#define POOL_DEBUGGER_DATA_TAG 'data'
|
#define POOL_DEBUGGER_DATA_TAG 'data'
|
||||||
|
|
||||||
|
#define PML4_ENTRY_COUNT 512
|
||||||
|
#define PDPT_ENTRY_COUNT 512
|
||||||
|
#define PD_ENTRY_COUNT 512
|
||||||
|
#define PT_ENTRY_COUNT 512
|
||||||
|
|
||||||
|
#define PAGE_BASE_SIZE 0x1000
|
||||||
|
|
||||||
/* creds: https://www.unknowncheats.me/forum/2602838-post2.html */
|
/* creds: https://www.unknowncheats.me/forum/2602838-post2.html */
|
||||||
|
|
||||||
typedef struct _DBGKD_DEBUG_DATA_HEADER64
|
typedef struct _DBGKD_DEBUG_DATA_HEADER64
|
||||||
|
|
Loading…
Reference in a new issue