Last active
October 23, 2020 15:05
-
-
Save Little-Ki/c7ba4ef573281c472f0d1575853509a8 to your computer and use it in GitHub Desktop.
[Code] [Kernel] SSDT proxy class
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* SSDT proxy class */ | |
/* | |
#pragma pack(1) | |
struct SYSTEM_SERVICE_TABLE { | |
// This pointer points to an array of int | |
// In 32 bits mode, this array saves <function's address>. | |
// In 64 bits mode, this array saves <(function's address - table's address) << 4>. | |
// So we calculate the function's address by this way: | |
// In 32 bits mode : function's address = [table's address + 4 * index] | |
// In 64 bits mode : function's address = [table's address + 4 * index] >> 4 + table's address | |
PVOID ServiceTableBase; | |
PVOID ServiceCounterTableBase; | |
#if defined(_X86_) | |
ULONG NumberOfServices; | |
#elif defined(_AMD64_) | |
ULONG64 NumberOfServices; | |
#endif | |
PVOID ParamTableBase; | |
} | |
#pragma pack() | |
*/ | |
class SSDT_proxy { | |
public: | |
SSDT_proxy(); | |
ULONG64 getFunction( ULONG index ); | |
private: | |
PSYSTEM_SERVICE_TABLE pTable = nullptr; | |
ULONG64 getTableX64(); | |
ULONG64 searchTableX64( ULONG64 begin, ULONG64 end ); | |
} | |
SSDT_proxy::SSDT_proxy() | |
{ | |
pTable = (PSYSTEM_SERVICE_TABLE) getTableX64(); | |
} | |
/* | |
In 32 bits mode, we just use: | |
__decltype(dllimport) ServiceDescriptorTableEntry_t KeServiceDescriptorTable | |
to get the address of table. | |
But in 64 bits mode, this symbol does not exported, but function KiSystemCall64 references KeServiceDescriptorTable, so we can use AOB scan to find its address. | |
Disassembly code looks like: | |
// Win7 x64 | |
nt!KiSystemServiceRepeat: | |
fffff800`03e8d772 4c8d15c7202300 lea r10,[nt!KeServiceDescriptorTable (fffff800`040bf840)] | |
fffff800`03e8d779 4c8d1d00212300 lea r11,[nt!KeServiceDescriptorTableShadow (fffff800`040bf880)] | |
… … | |
// Win8.1 x64 | |
nt!KiSystemServiceRepeat: | |
fffff800`11b6c752 4c8d1567531f00 lea r10,[nt!KeServiceDescriptorTable (fffff800`11d61ac0)] | |
fffff800`11b6c759 4c8d1da0531f00 lea r11,[nt!KeServiceDescriptorTableShadow (fffff800`11d61b00)] | |
… … | |
Just search { 0x4C, 0x8D, 0x15 } then we can get the address of KeServiceDescriptorTable | |
/* | |
ULONG64 SSDT_proxy::getTableX64() | |
{ | |
ULONG64 beginAddr = (ULONG64) __readmsr( 0xc0000082 ); | |
ULONG64 endAddr = beginAddr + 0x500; | |
ULONGLONG pServiceTable = 0; | |
pServiceTable = searchTableX64( beginAddr, endAddr ); | |
if ( pServiceTable ) | |
return(pServiceTable); | |
ULONGLONG serviceUser = 0; | |
ULONGLONG templong = 0xffffffffffffffff; | |
for ( PUCHAR i = (PUCHAR) beginAddr; i < (PUCHAR) endAddr + 0xff; i++ ) | |
{ | |
if ( MmIsAddressValid( i ) && MmIsAddressValid( i + 5 ) ) | |
{ | |
if ( *(PUCHAR) i == 0xe9 && *(PUCHAR) (i + 5) == 0xc3 ) | |
{ | |
memcpy( &templong, (PUCHAR) (i + 1), 4 ); | |
serviceUser = (ULONG64) (templong + 5 + i); | |
endAddr = serviceUser + 0x500; | |
pServiceTable = searchTableX64( serviceUser, endAddr ); | |
return(pServiceTable); | |
} | |
} | |
} | |
return 0 ; | |
} | |
ULONG64 SSDT_proxy::searchTableX64( ULONG64 begin, ULONG64 end ) | |
{ | |
if ( MmIsAddressValid( (PVOID64) begin ) == FALSE ) | |
return 0; | |
if ( MmIsAddressValid( (PVOID64) end ) == FALSE ) | |
return 0; | |
PUCHAR i = (PUCHAR) begin; | |
ULONG64 rel = 0; | |
for ( i = begin; i < (PUCHAR) end; i++ ) | |
{ | |
if ( MmIsAddressValid( i ) && MmIsAddressValid( i + 1 ) && MmIsAddressValid( i + 2 ) ) | |
{ | |
if ( *(i) == 0x4c && *(i + 1) == 0x8d && *(i + 2) == 0x15 ) | |
{ | |
memcpy( &rel, i + 3, 4 ); | |
return (ULONG64) rel + (ULONG64) i + 7; | |
} | |
} | |
} | |
return 0; | |
} | |
/* | |
Get function's address by function's index. | |
To get the function's index, just parse ntdll.dll pe struct. | |
The function's index is same between SSDT table and dll export table. | |
*/ | |
ULONG64 SSDT_proxy::getFunction( ULONG index ) | |
{ | |
LONG dwtmp = 0; | |
ULONG64 addr = 0; | |
PULONG pTableBase = NULL; | |
if ( pTable != NULL ) | |
{ | |
pTableBase = (PULONG) pTable->ServiceTableBase; | |
dwtmp = pTableBase[index]; | |
dwtmp = dwtmp >> 4; | |
addr = ( (LONG64) dwtmp + (ULONG64) pTableBase); /* &0xFFFFFFF0; */ | |
} | |
return addr; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment