Hook SSDT表中的NtOpenProcess函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
#include <ntifs.h>
#include "C:\D\test\CC++\cc++lib\driver\def.h"

VOID GetSSDT0(PVOID* addr);
BOOLEAN HookSSDT_On(PVOID newfunc, PVOID hkfunc, PVOID* oldbase, PULONG oldoffset);
VOID HookSSDT_Off(PVOID oldbase, ULONG oldoffset);
NTSTATUS NTAPI MyNtOpenProcess(_Out_ PHANDLE ProcessHandle, _In_ ACCESS_MASK DesiredAccess,
_In_ POBJECT_ATTRIBUTES ObjectAttributes, _In_opt_ PCLIENT_ID ClientId);
VOID TestProtectProcessSSDT();

NTSTATUS DriverUnload(PDRIVER_OBJECT pdriver)
{
DbgPrint("unload...\n");
return STATUS_SUCCESS;
}
static PDRIVER_OBJECT g_pdriver = NULL;
NTSTATUS DriverEntry(PDRIVER_OBJECT pdriver, PUNICODE_STRING path)
{
pdriver->DriverUnload = DriverUnload;
DbgPrint("loading...\n");
g_pdriver = pdriver;
TestProtectProcessSSDT();;
return STATUS_SUCCESS;
}
VOID GetSSDT0(PVOID* addr)
{
PLDR_DATA_TABLE_ENTRY entry = (PLDR_DATA_TABLE_ENTRY)g_pdriver->DriverSection;
PLDR_DATA_TABLE_ENTRY head = entry;
UNICODE_STRING temp = { 0 };
RtlInitUnicodeString(&temp, L"ntoskrnl.exe");
PCHAR start = NULL;
ULONG size = 0;
do
{
if (RtlCompareUnicodeString(&temp, &entry->BaseDllName, TRUE) == 0)
{
DbgPrint("wZ\n", &entry->BaseDllName);
start = (PCHAR)entry->DllBase;
size = entry->SizeOfImage;
break;
}
entry = entry->InLoadOrderLinks.Flink;
} while (entry != head);
//4c8d15
//4c8d1d
for (size_t i = 0; i < size; i++)
{
if (MmIsAddressValid(start))
{
if (*start == (CHAR)0x4c && *(start + 1) == (CHAR)0x8d && *(start + 2) == (CHAR)0x15)
{
start += 7;
if (MmIsAddressValid(start))
{
if (*start == (CHAR)0x4c && *(start + 1) == (CHAR)0x8d && *(start + 2) == (CHAR)0x1d)
{
start += 7;
if (MmIsAddressValid(start))
{
*addr = (ULONG64)start + *(PULONG)(start - 4);
return;
}
}
}
start++;
}
}
}
}

BOOLEAN HookSSDT_On(PVOID newfunc, PVOID hkfunc, PVOID* oldbase, PULONG oldoffset)
{
PVOID ssdt = NULL;
GetSSDT0(&ssdt);
if (!ssdt)return;
ULONG index = *(PULONG)((ULONG64)ssdt + 0x10);
ULONG offset = 0;
PVOID pfunc = NULL;
for (size_t i = 0; i < index; i++)
{
offset = ((PULONG) * (PULONG64)ssdt)[i];
(ULONG64)pfunc = *(PULONG64)ssdt + (offset >> 4);
if (hkfunc == pfunc)
{
*oldbase = *(PULONG64)ssdt + sizeof(ULONG) + 1;
*oldoffset = offset;
offset = (ULONG64)newfunc - *(PULONG64)ssdt;
PHYSICAL_ADDRESS physical = MmGetPhysicalAddress(*oldbase);
PVOID map = MmMapIoSpace(physical, 0x10, MmCached);
*(PULONG)map = offset << 4;
DebugMessage("挂钩完成\n");
MmUnmapIoSpace(map, 0x10);
return TRUE;
}
}
return FALSE;
}
VOID HookSSDT_Off(PVOID oldbase, ULONG oldoffset)
{
PHYSICAL_ADDRESS physical = MmGetPhysicalAddress(oldbase);
PVOID map = MmMapIoSpace(physical, 0x10, MmCached);
*(PULONG)map = oldbase;
DebugMessage("卸载完成\n");
MmUnmapIoSpace(map, 0x10);
}

NTSTATUS NTAPI MyNtOpenProcess(_Out_ PHANDLE ProcessHandle, _In_ ACCESS_MASK DesiredAccess,
_In_ POBJECT_ATTRIBUTES ObjectAttributes, _In_opt_ PCLIENT_ID ClientId)
{
DebugMessage("%d,%d\n", ClientId->UniqueProcess, ClientId->UniqueThread);
return NtOpenProcess(ProcessHandle, DesiredAccess, ObjectAttributes, ClientId);
}
PVOID hkbase = NULL;
ULONG hkoffset = 0;

VOID TestProtectProcessSSDT()
{
HookSSDT_On(MyNtOpenProcess, NtOpenProcess, &hkbase, &hkoffset);
}

保护进程,通过Hook SSDT表中的NtOpenProcess函数来保护进程不被读写

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
#include <ntifs.h>
#include "C:\D\test\CC++\cc++lib\driver\def.h"

VOID GetSSDT0(PVOID* addr);
BOOLEAN HookSSDT_On(PVOID newfunc, PVOID hkfunc, PVOID* oldbase, PULONG oldoffset);
VOID HookSSDT_Off(PVOID oldbase, ULONG oldoffset);
NTSTATUS NTAPI MyNtOpenProcess(_Out_ PHANDLE ProcessHandle, _In_ ACCESS_MASK DesiredAccess,
_In_ POBJECT_ATTRIBUTES ObjectAttributes, _In_opt_ PCLIENT_ID ClientId);
VOID TestProtectProcessSSDT();

NTSTATUS DriverUnload(PDRIVER_OBJECT pdriver)
{
DbgPrint("unload...\n");
return STATUS_SUCCESS;
}
static PDRIVER_OBJECT g_pdriver = NULL;
NTSTATUS DriverEntry(PDRIVER_OBJECT pdriver, PUNICODE_STRING path)
{
pdriver->DriverUnload = DriverUnload;
DbgPrint("loading...\n");
g_pdriver = pdriver;
TestProtectProcessSSDT();;
return STATUS_SUCCESS;
}
VOID GetSSDT0(PVOID* addr)
{
PLDR_DATA_TABLE_ENTRY entry = (PLDR_DATA_TABLE_ENTRY)g_pdriver->DriverSection;
PLDR_DATA_TABLE_ENTRY head = entry;
UNICODE_STRING temp = { 0 };
RtlInitUnicodeString(&temp, L"ntoskrnl.exe");
PCHAR start = NULL;
ULONG size = 0;
do
{
if (RtlCompareUnicodeString(&temp, &entry->BaseDllName, TRUE) == 0)
{
DbgPrint("wZ\n", &entry->BaseDllName);
start = (PCHAR)entry->DllBase;
size = entry->SizeOfImage;
break;
}
entry = entry->InLoadOrderLinks.Flink;
} while (entry != head);
//4c8d15
//4c8d1d
for (size_t i = 0; i < size; i++)
{
if (MmIsAddressValid(start))
{
if (*start == (CHAR)0x4c && *(start + 1) == (CHAR)0x8d && *(start + 2) == (CHAR)0x15)
{
start += 7;
if (MmIsAddressValid(start))
{
if (*start == (CHAR)0x4c && *(start + 1) == (CHAR)0x8d && *(start + 2) == (CHAR)0x1d)
{
start += 7;
if (MmIsAddressValid(start))
{
*addr = (ULONG64)start + *(PULONG)(start - 4);
return;
}
}
}
start++;
}
}
}
}

BOOLEAN HookSSDT_On(PVOID newfunc, PVOID hkfunc, PVOID* oldbase, PULONG oldoffset)
{
PVOID ssdt = NULL;
GetSSDT0(&ssdt);
if (!ssdt)return;
ULONG index = *(PULONG)((ULONG64)ssdt + 0x10);
ULONG offset = 0;
PVOID pfunc = NULL;
for (size_t i = 0; i < index; i++)
{
offset = ((PULONG) * (PULONG64)ssdt)[i];
(ULONG64)pfunc = *(PULONG64)ssdt + (offset >> 4);
if (hkfunc == pfunc)
{
*oldbase = *(PULONG64)ssdt + sizeof(ULONG) + 1;
*oldoffset = offset;
offset = (ULONG64)newfunc - *(PULONG64)ssdt;
PHYSICAL_ADDRESS physical = MmGetPhysicalAddress(*oldbase);
PVOID map = MmMapIoSpace(physical, 0x10, MmCached);
*(PULONG)map = offset << 4;
DebugMessage("挂钩完成\n");
MmUnmapIoSpace(map, 0x10);
return TRUE;
}
}
return FALSE;
}
VOID HookSSDT_Off(PVOID oldbase, ULONG oldoffset)
{
PHYSICAL_ADDRESS physical = MmGetPhysicalAddress(oldbase);
PVOID map = MmMapIoSpace(physical, 0x10, MmCached);
*(PULONG)map = oldbase;
DebugMessage("卸载完成\n");
MmUnmapIoSpace(map, 0x10);
}

NTSTATUS NTAPI MyNtOpenProcess(
_Out_ PHANDLE ProcessHandle,
_In_ ACCESS_MASK DesiredAccess,
_In_ POBJECT_ATTRIBUTES ObjectAttributes,
_In_opt_ PCLIENT_ID ClientId
)
{
PEPROCESS caller = PsGetCurrentProcess(); // 当前进程
PEPROCESS target = NULL;
const char* callerName = PsGetProcessImageFileName(caller);

if (ClientId && ClientId->UniqueProcess) {
if (NT_SUCCESS(PsLookupProcessByProcessId(ClientId->UniqueProcess, &target))) {
const char* targetName = PsGetProcessImageFileName(target);

if (_stricmp(callerName, "ce.exe") == 0 && _stricmp(targetName, "notepad.exe") == 0) {
if (DesiredAccess & (PROCESS_VM_READ | PROCESS_VM_WRITE | PROCESS_VM_OPERATION)) {
DebugMessage("[Hook] 阻止 c.exe 对 notepad.exe 的读/写内存访问\n");
ObDereferenceObject(target);
return STATUS_ACCESS_DENIED;
}
}

ObDereferenceObject(target);
}
}

return NtOpenProcess(ProcessHandle, DesiredAccess, ObjectAttributes, ClientId);
}

PVOID hkbase = NULL;
ULONG hkoffset = 0;

VOID TestProtectProcessSSDT()
{
HookSSDT_On(MyNtOpenProcess, NtOpenProcess, &hkbase, &hkoffset);
}