Windows XML Event Log (EVTX)單條日誌清除(二)——程序實現刪除evtx文件的單條日誌記錄

0x00 前言

Windows XML Event Log (EVTX)單條日誌清除系列文章的第二篇,介紹對指定evtx文件的單條日誌刪除方法,解決在程序設計上需要考慮的多個問題,開源實現代碼。

 

0x01 簡介

本文將要介紹以下內容:

  • 對指定evtx文件單條日誌的刪除思路

  • 程序實現細節

  • 開源代碼

 

0x02 對指定evtx文件單條日誌的刪除思路

在上篇文章《Windows XML Event Log (EVTX)單條日誌清除(一)——刪除思路與實例》介紹了evtx日誌文件中刪除單條日誌的原理和一個實例,採用修改日誌長度的方法實現日誌刪除

實現思路如圖

2-1.png

注:

圖片來自https://blog.fox-it.com/2017/12/08/detection-and-recovery-of-nsas-covered-up-tracks/

這種方法在實現上相對簡單,但是需要考慮多種不同的情況:

刪除中間日誌

刪除最後一條日誌

刪除第一條日誌

 

0x03 刪除中間日誌

方法如下:

  1. File header中的Next record identifier值減1

  2. 重新計算File header中的Checksum

  3. 重新計算前一日誌長度,共2個位置(偏移4和當前日誌的最後4字節)

  4. 後續日誌的Event record identifier依次減1

  5. ElfChuk中的Last event record number減1

  6. ElfChuk中的Last event record identifier減1

  7. 重新計算ElfChuk中Event records checksum

  8. 重新計算ElfChuk中Checksum

 

1、File header中的Next record identifier值減1

讀取日誌文件內容

定義日誌文件格式結構體,對日誌文件格式進行解析

Next record identifier值減1:

FileHeader->NextRecordIdentifier = FileHeader->NextRecordIdentifier-1

 

2、重新計算File header中的Checksum

計算CRC校驗和的c代碼如下:

unsigned int CRC32[256];
static void init_table()
{
   int i, j;
   unsigned int crc;
   for (i = 0; i < 256; i++)
   {
       crc = i;
       for (j = 0; j < 8; j++)
       {
           if (crc & 1)
               crc = (crc >> 1) ^ 0xEDB88320;
           else
               crc = crc >> 1;
       }
       CRC32[i] = crc;
   }
}
unsigned int GetCRC32(unsigned char *buf, int len)
{
   unsigned int ret = 0xFFFFFFFF;
   int i;
   static char init = 0;
   if (!init)
   {
       init_table();
       init = 1;
   }
   for (i = 0; i < len; i++)
   {
       ret = CRC32[((ret & 0xFF) ^ buf[i])] ^ (ret >> 8);
   }
   ret = ~ret;
   return ret;
}

 

計算File header前120字節的Checksum

代碼如下:

unsigned char *ChecksumBuf = new unsigned char[120];
memcpy(ChecksumBuf, (PBYTE)elfFilePtr, 120);
crc32 = GetCRC32(ChecksumBuf, 120);

 

3、重新計算前一日誌長度,共2個位置(偏移4和當前日誌的最後4字節)

NewSize = CurrentRecord->Size + PrevRecord->Size

更新長度:

PrevRecord->Size = NewSize

 

(3) 定位後一日誌NextRecord

使用NewSize替換NextRecord起始點前的4字節:

*(PULONG)((PBYTE)NextRecord-4) = NewSize

 

4、後續日誌的Event record identifier依次減1

遍歷後續日誌,Event record identifier依次減1

需要修改兩個位置:

CurrentRecord->EventRecordIdentifier = CurrentRecord->EventRecordIdentifier-1
CurrentRecord->Template->EventRecordIdentifier = CurrentRecord->Template->EventRecordIdentifier-1

 

5、ElfChuk中的Last event record number減1

 

ElfChuk->LastEventRecordNumber = ElfChuk->LastEventRecordNumber-1

 

 

6、 ElfChuk中的Last event record identifier減1

 

ElfChuk->LastEventRecordIdentifier = ElfChuk->LastEventRecordIdentifier-1

 

7、重新計算ElfChuk中Event records checksum

 

unsigned char *ChecksumBuf = new unsigned char[currentChunk->FreeSpaceOffset - 512];        
memcpy(ChecksumBuf, (PBYTE)currentChunk+512, currentChunk->FreeSpaceOffset - 512);
crc32 = GetCRC32(ChecksumBuf, currentChunk->FreeSpaceOffset - 512);

 

 

8、 重新計算ElfChuk中Checksum

 

unsigned char *ChecksumBuf = new unsigned char[504];
memcpy(ChecksumBuf, (PBYTE)currentChunk, 120);
memcpy(ChecksumBuf+120, (PBYTE)currentChunk+128, 384);
crc32 = GetCRC32(ChecksumBuf, 504);

0x04 刪除最後一條日誌

刪除最後一條日誌在上篇文章《Windows XML Event Log (EVTX)單條日誌清除(一)——刪除思路與實例》做過實例演示,與刪除中間日誌的方法基本相同

區別如下:

  1. 後續日誌的Event record identifier不需要減1,因爲沒有後續日誌

  2. 需要重新計算ElfChuk中的Last event record data offset

程序細節如下:

  1. 重新計算ElfChuk中的Last event record data offset

ElfChuk->LastEventRecordDataOffset = ElfChuk->LastEventRecordDataOffset-LastRecord->Size

 

0x05 刪除第一條日誌

修改日誌長度的方法不適用於刪除第一條日誌,因爲沒有前一個日誌覆蓋當前日誌

如果想要依舊使用覆蓋長度的方法實現,需要對日誌的文件格式做進一步分析

我們知道,Event Record的內容以Binary XML格式保存

Binary XML格式可參考:

https://github.com/libyal/libevtx/blob/master/documentation/Windows%20XML%20Event%20Log%20(EVTX).asciidoc#4-binary-xml

 

通過修改Binary XML格式的內容實現合併日誌,需要修改以下內容:

  • Written date and time

  • Template definition Data size

  • Next template definition offset

 

注:

該方法同樣適用於修改中間日誌和最後一條日誌,所以說,只要理解了日誌格式,刪除的方法不唯一

 

其他實現的細節見開源代碼,地址如下:

https://github.com/3gstudent/Eventlogedit-evtx--Evolution/blob/master/DeleteRecordofFile.cpp

 

代碼實現了讀取指定日誌文件c:\\test\\Setup.evtx,刪除單條日誌(EventRecordID=14),並保存爲新的日誌文件c:\\test\\SetupNew.evtx

 

注:在代碼的實現細節上我參考了看雪上的Demo代碼

地址如下:

https://bbs.pediy.com/thread-219313.htm

 

0x06 小結

本文介紹了刪除evtx文件單條日誌記錄的思路和程序實現細節,開源代碼。刪除單條日誌記錄的方法不唯一。接下來將會介紹刪除當前系統單條日誌記錄的多個方法。

發佈了26 篇原創文章 · 獲贊 175 · 訪問量 189萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章