cnhackteam7 发布于2022年11月8日 分享 发布于2022年11月8日 0x00 前言 清除Windows事件查看器日志(evt)单日志系列文章之三介绍了在指定时间段内删除当前系统中EVT日志记录的方法和详细的测试过程,并说明了日志数量无法修改的原因。最后,查询日志内容和修改日志内容的实现代码是开源的。 0x01 简介 本文将介绍以下内容: XP系统中枚举所有句柄的方法 过滤日志文件句柄的标准 XP下Dll注入的示例代码 实际测试过程 无法修改日志数量的原因 日志查询的程序实现细节 修改日志的程序实现细节 0x02 XP系统下枚举系统所有句柄 上一篇文章《Windows单条日志清除(五)——通过DuplicateHandle获取日志文件句柄删除当前系统单条日志记录》介绍了Win8及以上系统的实现方法: 使用NtQuerySystemInformation查询SystemHandleInformation可以得到所有进程的句柄信息。 通过NtDuplicateObject获取句柄的名称和具体数值信息。 过滤掉你要找的句柄。 通过DuplicateHandle复制句柄。 获取修改日志文件的权限。 在XP系统下,不能用NtQuerySystemInformation查询SystemHandleInformation来获取进程的句柄信息。 参考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。 尝试第二种方法,使用NtQuerySystemInformation查询systemextendedhandleinformation。 注: 第二种方法支持WinXP及更高版本的系统。 0x03 筛选出指定日志文件的句柄 1、筛选出类型为文件的句柄 ObjectTypeNumber=0x1c 注: Win8和更高版本的系统,ObjectTypeNumber=0x1e Xp和WinXP系统,ObjectTypeNumber=0x1c 2、过滤出有可能导致挂起的句柄 通过API WaitForSingleObject进行判断。 否则,该进程将被挂起。 3、缩小范围,指定文件属性 日志的属性是固定的,handle-grantaccess=0x0012019f。 完整的实现代码已经开源,下载地址如下: https://github . com/3g student/home-of-C-Language/blob/master/GetPIDandHandle(evt)。卡片打印处理机(Card Print Processor的缩写) 代码实现根据输入的关键字进行搜索,获得对应的句柄名称和句柄值。 0x04 日志删除的实现方法1:通过Dll注入获得句柄操作权限 在系统进程中注入dll,dll文件可以获得日志文件的句柄。 接下来的操作是: 调用CreateFileMapping()函数创建一个文件映射内核对象。 调用MapViewOfFile()函数将文件数据映射到进程的地址空间。 修改内存中的数据并删除指定的日志记录。 调用函数FlushViewOfFile()将内存数据写入磁盘。 清除内存映射对象 完整的实现过程请参考之前的文章《Windows XML Event Log (EVTX)单条日志清除(四)——通过注入获取日志文件句柄删除当前系统单条日志记录》关于删除evtx文件的单条日志。 在xp系统下,不能使用NtCreateThreadEx LdrLoadDll注入Dll,但是可以直接调用CreateRemoteThread。 实现代码可以参考: https://github . com/3g student/home-of-C-Language/blob/master/createremotethread . CPP 0x05 日志删除的实现方法2:通过DuplicateHandle获得句柄操作权限 参考之前的文章《Windows XML Event Log (EVTX)单条日志清除(五)——通过DuplicateHandle获取日志文件句柄删除当前系统单条日志记录》 过滤掉句柄后,再次调用NtDuplicateObject获取真正的句柄并删除日志文件。 同样,需要采取以下行动: 调用CreateFileMapping()函数创建一个文件映射内核对象。 调用MapViewOfFile()函数将文件数据映射到进程的地址空间。 修改内存中的数据并删除指定的日志记录。 调用函数FlushViewOfFile()将内存数据写入磁盘。 清除内存映射对象 删除日志请参考之前的文章《Windows Event Viewer Log (EVT)单条日志清除(二)——程序实现删除evt文件指定时间段的日志记录》。 下面是完整的实现代码: https://github.com/3gstudent/Eventlogedit-evt-General/blob/master/evtdeleterecordbygethandle . CPP 代码实现了在指定的evt文件中删除一定时间内的多个日志,并生成调试文件sys2.evt和sys3.evt。 Sys2.evt在删除日志后保存数组的内容。 Sys3.evt保存映射到内存中的内容。 程序执行后,sys2.evt和sys3.evt成功删除了指定的日志,但是当前系统的日志文件产生了错误。 为了进行比较测试,我将删除时间段调整为不同于当前日志的值,即不会删除任何日志。程序执行后,当前系统的日志文件正常。 再者,只要不改变日志的数量,修改日志的内容,当前系统的日志文件还是正常的。 这里有个结论:无法通过获得日志文件句柄修改内存数据的方式改变日志的数目 同样,通过ProcessHacker直接修改内存文件的文件头,也改变不了日志的数量。 程序验证,通过API GetNumberOfEventLogRecords查询日志号 c代码如下: #包括 #pragma注释(lib,' Advapi32.lib ') int main(int argc,char *argv[]) { HANDLE hEventLog=NULL hEventLog=OpenEventLog(NULL,argv[1]); if (NULL==hEventLog) { printf('OpenEventLog失败,返回0x%x,\n ',GetLastError()); 转到清理; } DWORD number of records=0; BOOL flag=GetNumberOfEventLogRecords(hEventLog,number of records); if (NULL==flag) { printf(' GetNumberOfEventLogRecords失败,返回0x%x,\n ',GetLastError()); 转到清理; } printf('%d\n ',number of records); 清理: if (hEventLog) CloseEventLog(hEventLog); } cmd: GetNumberOfEventLogRecords.exe系统 获取日志的数量 内存文件文件头的最后(最新)记录号和文件记录尾的最后(最新)记录号由ProcessHacker直接修改。 再次执行程序获取日志数,发现获取的日志数不变。 验证结论:修改内存中的日志内容并不能改变实际的日志数量。 0x06 日志查询和日志修改的程序实现细节 该查询的代码如下: https://github.com/3gstudent/Eventlogedit-evt-General/blob/master/evtqueryrecordbygethandle . CPP 该代码实现了日志的遍历,并显示每个日志的信息。 日志修改后的代码如下: https://github.com/3gstudent/Eventlogedit-evt-General/blob/master/evtmodifyrecordbygethandle . CPP 该代码实现了对指定日志信息的修改。 0x07 小结 介绍了在当前系统的指定时间段内删除evt日志记录的两种方法:Dll注入和DuplicateHandle分别获取句柄操作权限,并使用该句柄修改日志文件。 删除方式不是简单的覆盖,而是完全删除某段时间的日志。删除evtx文件的日志也可以参考这个方法,但是实现比较复杂,后面会更新evtx的实现代码。 留下回复 链接帖子 意见的链接 分享到其他网站 更多分享选项…
推荐的帖子