跳转到帖子

游客您好,欢迎来到黑客世界论坛!您可以在这里进行注册。

赤队小组-代号1949(原CHT攻防小组)在这个瞬息万变的网络时代,我们保持初心,创造最好的社区来共同交流网络技术。您可以在论坛获取黑客攻防技巧与知识,您也可以加入我们的Telegram交流群 共同实时探讨交流。论坛禁止各种广告,请注册用户查看我们的使用与隐私策略,谢谢您的配合。小组成员可以获取论坛隐藏内容!

TheHackerWorld官方

Windows XML Event Log(EVTX)Single Log Clearing(IV)——通过注入获得日志文件的句柄 删除当前系统的单个日志记录

精选回复

发布于

0x00 前言

Windows Eventlog (EVTX)单条日志清理系列之四介绍了当前系统中删除单条日志记录的第二种方法:在日志服务事件日志的对应进程中获取指定日志文件的句柄,通过Dll注入获取句柄的操作权限,使用句柄修改日志文件。

0x01 简介

本文将介绍以下内容:

利用理念

程序实现

枚举日志服务Eventlog对应进程的所有句柄,获取指定日志文件的句柄。

通过Dll注入获得句柄的操作权限。

进程间消息传输的方法

0x02 利用思路

系统启动日志服务Eventlog后,会以独占模式打开日志文件,这将阻止其他进程打开日志文件并对其进行修改。

那么,如果我们通过Dll将内存注入进程,然后获取指定日志文件的句柄,是否可以获得日志文件的操作权限呢?

0x03 枚举日志服务Eventlog对应进程的所有句柄,获得指定日志文件的句柄

1、利用工具processhacker获得指定日志文件的句柄

下载地址:

https://processhacker.sourceforge.io/

(1)获得日志服务Eventlog对应进程的pid

执行以下powershell代码:

get-wmio object-Class win32 _ service-Filter ' name=' event log ' ' | select-exp ProcessId

(2)运行processhacker

根据pid找到进程,并检查属性-句柄。

获取当前进程的所有句柄信息。

如下图

2-1.png

可以看到c:\ windows \ system32 \ wine vt \ logs \ security . evtx对应的句柄值是0x1c8。

2、通过c++程序实现获得指定日志文件的句柄

查看processhacker的源代码,找到实现方法。

代码位置:

https://github . com/process hacker/process hacker/blob/e2d 793289 dede 80 f 6 E3 BDA 26d 6478 DC 58 b 20 b 7 f 8/process hacker/hndlprv . c # L307

获取参考资料:

在Windows 8和更高版本上,使用带有ProcessHandleInformation的NtQueryInformationProcess是最有效的方法。

在Windows XP和更高版本上,使用SystemExtendedHandleInformation的NtQuerySystemInformation。

否则,可以使用带有SystemHandleInformation的NtQuerySystemInformation。

所以,选择第三种方法尝试实现。

注:

经过测试,第三种方法适用于Win7及更新的操作系统。

使用NtQuerySystemInformation查询SystemHandleInformation可以得到所有进程的句柄信息。

挑选出日志进程中的所有句柄。

然后通过NtDuplicateObject获取句柄的名称和具体数值信息。

最后过滤出你要找的句柄,输出句柄值。

完整的实现代码已经开源,下载地址如下:

https://github . com/3g student/home-of-C-Language/blob/master/GetPIDandHandle(evtx)。卡片打印处理机(Card Print Processor的缩写)

代码实现根据输入的关键字进行搜索,获得对应的句柄名称和句柄值。

测试下图

2-2.png

成功获取日志服务Eventlog对应的进程的pid,security.evtx对应的句柄值为0x1c8

0x04 通过Dll注入获得该句柄的操作权限

通过NtCreateThreadEx LdrLoadDll进行Dll注入的代码可以引用:

https://github . com/3g student/home-of-C-Language/blob/master/NtCreateThreadEx+ldrloaddll . CPP

注:

成功注入后需要FreeDll。

成功注入后,使用获得的句柄值作为函数CreateFileMapping()的第一个参数,创建一个文件映射内核对象。

然后调用函数MapViewOfFile()将文件数据映射到进程的地址空间。

接下来,修改内存中的数据并删除单个日志记录。

最后,调用函数FlushViewOfFile()将内存数据写入磁盘。

0x05 进程间消息传递的方法

在实际使用中,删除日志记录的全部代码都应该放在Dll中,但是参数无法通过CreateRemoteThread传入Dll,导致无法删除指定EventlogRecordId的日志。

您可以在这里使用进程间的消息传递。

实现的方式有很多种,信号、流水线、消息队列、共享内存,甚至读写文件。

因为函数CreateFileMapping()用于创建0x04部分中的文件映射内核对象,所以进程间消息传输也使用内存映射。

创建共享内存,代码可以参考:

https://github . com/3g student/home-of-C-Language/blob/master/openfile mapping . CPP

代码中创建了两个内存映射对象,并指定了函数CreateFileMapping()的访问权限,允许任何人访问这个对象,也就是函数CreateFileMapping()的第二个参数。

正常情况下,该值设置为NULL,表示默认的访问权限,但必须设置为允许任何人访问注入的Dll中的对象,否则会提示拒绝访问。

原因如下:

将Dll注入svchost.exe后,权限是System。默认访问权限无法访问用户创建的内存映射文件对象,必须指定该权限以允许任何人访问该对象。

当然,如果消息由具有两个用户权限的进程传递,CreateFileMapping()函数的第二个参数为NULL。

读取指定的共享内存,代码可以参考:

https://github . com/3g student/home-of-C-Language/blob/master/openfile mapping . CPP

代码读取这两个内存映射对象,并添加数据类型转换(string到int)的函数。

0x06 程序实现流程

1、自己解析格式,实现日志删除

删除的键码如下:

https://github.com/3gstudent/Eventlogedit-evtx-进化/blob/master/deleterecordoffile . CPP

代码实现了删除文件c:\test\Setup.evtx中的一个日志(EventRecordID=14),新文件保存为C: \ test \ setupnew.evtx。

整个实施过程分为两部分:

发起人

注入的Dll

1.启动程序(Loader-rewriting.cpp)

代码地址:

https://github.com/3gstudent/Eventlogedit-evtx-进化/blob/master/Loader-rewriting . CPP

流程如下:

获取日志服务Eventlog对应的进程的pid。

枚举日志服务Eventlog对应进程的所有句柄,获取指定日志文件的句柄。

创建两个内存映射,用于将日志文件的句柄传递给dll和需要删除日志的EventRecordID。

将Dll注入到日志服务Eventlog对应的进程中

释放Dll

关闭内存映射

2.注入的Dll(Dll-rewriting.cpp)

代码地址:

https://github.com/3gstudent/Eventlogedit-evtx-进化/blob/master/Dll-重写. cpp

流程如下:

分别从两个内存映射中读取消息,将读取的内容从string转换为int类型,获取日志文件的句柄和需要删除日志的EventRecordID。

调用CreateFileMapping()函数,传入日志文件的句柄,并创建一个文件映射内核对象。

调用MapViewOfFile()函数将文件数据映射到进程的地址空间。

修改内存数据并删除指定的日志。

调用函数FlushViewOfFile()将内存数据写入磁盘。

关闭日志文件的内存映射。

测试下图

3-1.png

2、使用WinAPI EvtExportLog,过滤出想要删除的内容

可供参考的代码:

https://github . com/360-A-Team/event cleaner/blob/master/event cleaner/event cleaner . CPP # L528

我按照这个思路写了代码:

https://github.com/3gstudent/Eventlogedit-evtx-Evolution/blob/master/deleterecordoffilex . CPP

该代码调用Windows API EvtExportLog来过滤日志文件,在删除指定的日志后,剩余的日志内容将保存为一个新文件temp.evtx

整个实施过程分为三个部分:

删除日志程序

发起人

注入的Dll

1.日志删除程序(DeleteRecord-EvtExportLog.cpp)

代码地址:

https://github.com/3gstudent/Eventlogedit-evtx-Evolution/blob/master/DeleteRecord-evtexportlog . CPP

流程如下:

指定日志文件和EventRecordID以删除日志。

生成新的日志文件temp.evtx

2.启动程序(Loader-EvtExportLog.cpp)

代码地址:

https://github.com/3gstudent/Eventlogedit-evtx-Evolution/blob/master/Loader-evtexportlog . CPP

流程如下:

获取日志服务Eventlog对应的进程的pid。

枚举日志服务Eventlog对应进程的所有句柄,获取指定日志文件的句柄。

创建三个内存映射,将日志文件的句柄、新日志文件的长度和新日志文件的内容传递给dll。

将Dll注入到日志服务Eventlog对应的进程中

释放Dll

关闭内存映射

3.注入的Dll(Dll-EvtExportLog.cpp)

代码地址:

https://github.com/3gstudent/Eventlogedit-evtx-Evolution/blob/master/Dll-evtexportlog . CPP

流程如下:

从第一个内存映射中获取日志文件的句柄,将读取的内容从string转换为int类型。

从第二个内存映射中获取新日志文件的长度。

根据新日志文件的长度,从第三内存映射表中获取新日志文件的内容。

调用CreateFileMapping()函数,传入日志文件的句柄,并创建一个文件映射内核对象。

调用MapViewOfFile()函数将文件数据映射到进程的地址空间。

修改内存数据并用新日志文件的内容覆盖它。

调用函数FlushViewOfFile()将内存数据写入磁盘。

关闭日志文件的内存映射。

测试下图

3-2.png

注:

以上两种方法,删除setup.evtx没有问题,删除system.evtx和security.evtx会因为竞争条件导致删除失败。

0x07 小结

介绍了当前系统中删除单个日志记录的第二种方法:在日志服务Eventlog的相应进程中获取指定日志文件的句柄,通过Dll注入获取权限,并使用该句柄修改日志文件。

在某些情况下,dll注入会失败,那么有什么办法可以删除当前系统的单条日志记录呢?下一篇文章将介绍

留下回复

创建帐户或登录后发表意见

最近浏览 0

  • 没有会员查看此页面。