EXTERN_C PVOID NTAPI RtlFindExportedRoutineByName( _In_ PVOID ImageBase, _In_ PCCH RoutineName);
PULONG W32pServiceTable
=
NULL;
typedef struct _LDR_DATA_TABLE_ENTRY {
LIST_ENTRY InLoadOrderModuleList;
LIST_ENTRY InMemoryOrderModuleList;
LIST_ENTRY InInitializationOrderLinks;
PVOID DllBase;
PVOID EntryPoint;
ULONG SizeOfImage;
UNICODE_STRING FullDllName;
UNICODE_STRING BaseDllName;
ULONG Flags;
USHORT LoadCount;
USHORT TlsIndex;
LIST_ENTRY HashLinks;
PVOID SectionPointer;
ULONG CheckSum;
ULONG TimeDateStamp;
} LDR_DATA_TABLE_ENTRY,
*
PLDR_DATA_TABLE_ENTRY;
PVOID GetSystemRoutineAddress(PCWSTR routine_name) {
UNICODE_STRING name;
RtlInitUnicodeString(&name, routine_name);
return
MmGetSystemRoutineAddress(&name);
}
PVOID GetSystemModuleBase(LPCWSTR module_name) {
PLIST_ENTRY module_list
=
reinterpret_cast<PLIST_ENTRY>(GetSystemRoutineAddress(L
"PsLoadedModuleList"
));
if
(!module_list) {
return
NULL;
}
for
(PLIST_ENTRY link
=
module_list; link !
=
module_list
-
>Blink; link
=
link
-
>Flink) {
LDR_DATA_TABLE_ENTRY
*
entry
=
CONTAINING_RECORD(link, LDR_DATA_TABLE_ENTRY, InLoadOrderModuleList);
UNICODE_STRING name;
RtlInitUnicodeString(&name, module_name);
if
(RtlEqualUnicodeString(&entry
-
>BaseDllName, &name, TRUE)) {
return
entry
-
>DllBase;
}
}
return
NULL;
}
ULONG64 GetShadowSSDTFuncCurAddr(ULONG
id
) {
LONG
dwtmp
=
0
;
PULONG ServiceTableBase
=
NULL;
ServiceTableBase
=
W32pServiceTable;
dwtmp
=
ServiceTableBase[
id
];
dwtmp
=
dwtmp >>
4
;
return
(LONGLONG)dwtmp
+
(ULONGLONG)ServiceTableBase;
}
NTSTATUS GetPEPPocess(const char
*
process_name, PEPROCESS
*
process) {
PEPROCESS sys_process
=
PsInitialSystemProcess;
PEPROCESS curr_entry
=
sys_process;
char image_name[
15
];
do {
RtlCopyMemory((PVOID)(&image_name), (PVOID)((uintptr_t)curr_entry
+
0x5a8
), sizeof(image_name));
if
(strstr(image_name, process_name)) {
ULONG active_threads;
RtlCopyMemory((PVOID)&active_threads, (PVOID)((uintptr_t)curr_entry
+
0x5F0
), sizeof(active_threads));
if
(active_threads) {
*
process
=
curr_entry;
return
STATUS_SUCCESS;
}
}
PLIST_ENTRY
list
=
(PLIST_ENTRY)((uintptr_t)(curr_entry)
+
0x448
);
curr_entry
=
(PEPROCESS)((uintptr_t)
list
-
>Flink
-
0x448
);
}
while
(curr_entry !
=
sys_process);
return
STATUS_NOT_FOUND;
}
VOID EnumShadowSSDT() {
PEPROCESS winlogon
=
NULL;
KAPC_STATE apc_state;
NTSTATUS status
=
STATUS_UNSUCCESSFUL;
status
=
GetPEPPocess((
"winlogon.exe"
), &winlogon);
KeStackAttachProcess(winlogon, &apc_state);
PVOID Win32KBase
=
GetSystemModuleBase(L
"win32k.sys"
);
W32pServiceTable
=
(PULONG)RtlFindExportedRoutineByName(Win32KBase,
"W32pServiceTable"
);
DbgPrintEx(
77
,
0
,
"[%s] Win32k.sys = 0x%llx\n"
, __FUNCTION__, Win32KBase);
DbgPrintEx(
77
,
0
,
"[%s] W32pServiceTable = 0x%llx\n"
, __FUNCTION__, W32pServiceTable);
PIMAGE_DOS_HEADER lpDosHeader
=
(PIMAGE_DOS_HEADER)Win32KBase;
PIMAGE_NT_HEADERS64 lpNtHeader
=
(PIMAGE_NT_HEADERS64)((ULONG64)Win32KBase
+
lpDosHeader
-
>e_lfanew);
if
(!lpNtHeader
-
>OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size) {
return
;
}
if
(!lpNtHeader
-
>OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress) {
return
;
}
PIMAGE_EXPORT_DIRECTORY lpExports
=
(PIMAGE_EXPORT_DIRECTORY)((ULONG64)Win32KBase
+
(ULONG64)lpNtHeader
-
>OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);
PULONG lpdwFunName
=
(PULONG)((ULONG64)Win32KBase
+
(ULONG64)lpExports
-
>AddressOfNames);
PUSHORT lpword
=
(PUSHORT)((ULONG64)Win32KBase
+
(ULONG64)lpExports
-
>AddressOfNameOrdinals);
PULONG lpdwFunAddr
=
(PULONG)((ULONG64)Win32KBase
+
(ULONG64)lpExports
-
>AddressOfFunctions);
for
(ULONG i
=
0
; i <
=
lpExports
-
>NumberOfNames
-
1
; i
+
+
) {
char
*
pFunName
=
(char
*
)(lpdwFunName[i]
+
(ULONG64)Win32KBase);
if
(strstr(pFunName,
"__win32kstub_"
))
{
PVOID _FunctionAddress
=
(PVOID)(lpdwFunAddr[lpword[i]]
+
(ULONG64)Win32KBase);
char
*
FunctionName
=
strstr(pFunName,
"Nt"
);
ULONG lFunctionIndex
=
*
(ULONG
*
)((PUCHAR)_FunctionAddress
+
1
);
ULONG64 FunctionAddress
=
GetShadowSSDTFuncCurAddr(lFunctionIndex);
DbgPrintEx(
77
,
0
,
"[%s] \nIndex: %d \nAddress: 0x%llx \n"
, FunctionName, lFunctionIndex, FunctionAddress);
}
}
KeUnstackDetachProcess(&apc_state);
}
VOID DriverUnload(PDRIVER_OBJECT drv_obj [[maybe_unused]] ) {
}
EXTERN_C NTSTATUS DriverEntry(PDRIVER_OBJECT drv_obj [[maybe_unused]], PUNICODE_STRING reg_path [[maybe_unused]] ) {
EnumShadowSSDT();
drv_obj
-
>DriverUnload
=
DriverUnload;
return
STATUS_SUCCESS;
}