关于通用日志文件系统
使用通用日志文件系统
• 创建日志文件
• 使用日志文件
BLF格式
typedef struct _CLFS_LOG_BLOCK_HEADER
{
UCHAR MajorVersion;
UCHAR MinorVersion;
UCHAR Usn;
CLFS_CLIENT_ID ClientId;
USHORT TotalSectorCount;
USHORT ValidSectorCount;
ULONG Padding;
ULONG Checksum; // 日志块数据的校验和(Crc32校验)
ULONG Flags;
CLFS_LSN CurrentLsn;
CLFS_LSN NextLsn;
ULONG RecordOffsets[16]; // 每个记录的偏移值
ULONG SignaturesOffset; // 一块内存的偏移值
} CLFS_LOG_BLOCK_HEADER, *PCLFS_LOG_BLOCK_HEADER;
typedef struct _CLFS_CONTROL_RECORD
{
CLFS_METADATA_RECORD_HEADER hdrControlRecord;
ULONGLONG ullMagicValue;
UCHAR Version;
CLFS_EXTEND_STATE eExtendState;
USHORT iExtendBlock;
USHORT iFlushBlock;
ULONG cNewBlockSectors;
ULONG cExtendStartSectors;
ULONG cExtendSectors;
CLFS_TRUNCATE_CONTEXT cxTruncate;
USHORT cBlocks;
ULONG cReserved;
CLFS_METADATA_BLOCK rgBlocks[ANYSIZE_ARRAY];
} CLFS_CONTROL_RECORD, *PCLFS_CONTROL_RECORD;
typedef struct _CLFS_METADATA_BLOCK
{
union
{
PUCHAR pbImage; // 指向内存中数据的指针,
ULONGLONG ullAlignment;
};
ULONG cbImage; // 日志块的大小
ULONG cbOffset; // 偏移
CLFS_METADATA_BLOCK_TYPE eBlockType;
} CLFS_METADATA_BLOCK, *PCLFS_METADATA_BLOCK;
包含了有关布局,扩展区域以及截断区域的信息,其中cBlocks表示整个文件中包含的日志块的数量。
typedef struct _CLFS_BASE_RECORD_HEADER
{
CLFS_METADATA_RECORD_HEADER hdrBaseRecord;
CLFS_LOG_ID cidLog;
ULONGLONG rgClientSymTbl[CLIENT_SYMTBL_SIZE];
ULONGLONG rgContainerSymTbl[CONTAINER_SYMTBL_SIZE];
ULONGLONG rgSecuritySymTbl[SHARED_SECURITY_SYMTBL_SIZE];
ULONG cNextContainer;
CLFS_CLIENT_ID cNextClient;
ULONG cFreeContainers;
ULONG cActiveContainers; // 当前活跃的容器数
ULONG cbFreeContainers;
ULONG cbBusyContainers;
ULONG rgClients[MAX_CLIENTS_DEFAULT];
ULONG rgContainers[MAX_CONTAINERS_DEFAULT]; // 保存容器上下文的偏移值
ULONG cbSymbolZone;
ULONG cbSector;
USHORT bUnused;
CLFS_LOG_STATE eLogState;
UCHAR cUsn;
UCHAR cClients;
} CLFS_BASE_RECORD_HEADER, *PCLFS_BASE_RECORD_HEADER;
typedef struct _CLFS_CONTAINER_CONTEXT
{
CLFS_NODE_ID cidNode;
ULONGLONG cbContainer;
CLFS_CONTAINER_ID cidContainer;
CLFS_CONTAINER_ID cidQueue;
union
{
CClfsContainer* pContainer; // 指向内核对象的指针,内核对象的首部有虚函数表
ULONGLONG ullAlignment;
};
CLFS_USN usnCurrent;
CLFS_CONTAINER_STATE eState;
ULONG cbPrevOffset;
ULONG cbNextOffset;
} CLFS_CONTAINER_CONTEXT, *PCLFS_CONTAINER_CONTEXT;
包含了因为截断操作而需要对扇区进行更改的客户端信息,以及具体更改的扇区字节。
Fuzz CLFS
漏洞分析
这里可以通过NtAlpcCreateResourceReserve函数来创建一个Reserve Blob,会调用AlpcAddHandleTableEntry函数把刚创建好的Reserve Blob的地址写入到_ALPC_HANDLE_TABLE结构的Handles数组中。
当调用NtAlpcSendWaitReceivePort函数发送消息时,它会将用户传入的数据写入到_KALPC_MESSAGE结构中ExtensionBuffer所指向的地址,我们可以用它来实现任意地址写入。
当调用NtAlpcSendWaitReceivePort函数接收消息时,它会读取_KALPC_MESSAGE结构中ExtensionBuffer所指向的地址处的数据,我们可以用它来实现任意地址读取。
首先通过溢出占用Handles结构的_KALPC_REVERSE指针,我们可以构造一个虚假的Reserve Blob,然后继续构造一个虚假的_KALPC_MESSAGE结构,那么我们就可以通过_KALPC_MESSAGE结构中的ExtensionBuffer字段和ExtensionBufferSize字段来实现任意地址读写。
原文始发于微信公众号(山石网科安全技术研究院):Windows 通用日志文件系统(CLFS)解析