Quantcast
Channel: CodeSection,代码区,网络安全 - CodeSec
Viewing all articles
Browse latest Browse all 12749

Petya变种勒索蠕虫启动代码分析

$
0
0
背景

继5月的WannaCry勒索蠕虫事件以后,2017年6月又出现了Petya变种勒索蠕虫,除了利用永恒之蓝漏洞和加密勒索以后,Petya变种与WannaCry有比较大的差别。WannaCry会加密机器上的文件,导致数据损毁,而Petya更为激进,它会加密系统的MBR直接导致机器无法启动,本文对其执行的MBR及文件系统的加密机制做详细的分析。

恶意代码分析

由于执行恶意操作的指令并不是以文件形式存在,我们使用WinHex工具提取受攻击机器的磁盘前23个扇区的数据进行分析,对应代码数据的Hash为841e12729f200a5620859f2958e2d484 。

相关数据结构

计算机启动时执行完BIOS的启动代码,检查各硬件设备正常后,JMP到MBR的引导代码进行执行;然后由MBR引导至活动分区的DBR,再由DBR引导操作系统。如:DBR调用NTLDR,再由NTLDR调用系统内核。

Petya病毒修改了系统的MBR,病毒在Bios加载后获得执行机会,病毒将加载存储在0×1扇区后的大小为0×20大小的病毒代码加载执行,这些代码会还原出真实的MBR,通过对还原出来的MBR解析,得到系统的DBR,通过DBR解析到系统的MFT结构,遍历所有的MFT,根据MFT找到文件内容所在的扇区后,读取该扇区加密内容后再写回到扇区中,从而实现对文件的加密。要完整的了解整个的加密过程,首先就是熟悉系统的MBR、DBR、MFT等结构的含义与功能。

MBR

Petya病毒修改了系统的MBR,病毒在Bios加载后获得执行机会,病毒将加载存储在0×1扇区后的大小为0×20大小的病毒代码加载执行,这些代码会还原出真实的MBR。在加密文件的过程中,Petya病毒会使用到MBR中

MBR扇区由以下四部分组成:

引导代码:引导代码占MBR分区的前440字节,负责整个系统启动。如果引导代码被破坏,系统将无法启动。

windows磁盘签名:占引导代码后面的4字节,是Windows初始化磁盘写入的磁盘标签,如果此标签被破坏,则系统会提示“初始化磁盘”。

MBR分区表:占Windows磁盘标签后面的64个字节,是整个硬盘的分区表。

MBR结束标志:占MBR扇区最后2个字节,一直为“55AA”。

MBR结构如下:

;====================================================================
; 主引导记录(MBR)结构
;====================================================================
; typedef struct _MASTER_BOOT_RECORD
; {
; UCHAR BootCode[446];
; PARTITION_ENTRY Partition[4];
; USHORT Signature;
; }MASTER_BOOT_RECORD,*PMASTER_BOOT_RECORD;
;
;====================================================================
;====================================================================
; 分区表项结构(16字节)
;====================================================================
;
; typedef struct _PARTITION_ENTRY
; {
; UCHAR BootIndicator; // 能否启动标志
; UCHAR StartHead; // 该分区起始磁头号
; UCHAR StartSector; // 起始柱面号高2位:6位起始扇区号
; UCHAR StartCylinder; // 起始柱面号低8位
; UCHAR PartitionType; // 分区类型
; UCHAR EndHead; // 该分区终止磁头号
; UCHAR EndSector; // 终止柱面号高2位:6位终止扇区号
; UCHAR EndCylinder; // 终止柱面号低8位
; ULONG StartLBA; // 起始扇区号
; ULONG TotalSector; // 分区尺寸(总扇区数); }PARTITION_ENTRY,*PPARTITION_ENTRY;

对于其中的PartitionType 字段,Windows下可识别的分区类型主要有:

0×07表示普通分区(Windows分区、数据分区。默认分区类型 )。

0xEE表示该分区表是PMBR,紧随其后的应该是GPT分区表头和GPT分区表,因此这是一块GPT硬盘。

0xEF表示EFI系统分区

Petya在解密出原始的MBR后,解析MBR结构,得到起始扇区号,并根据起始扇区定位到DBR。

病毒解析MBR时,会对分区类型做判断,如果PMBR和EFI类型的系统分区,默认会不做处理。

在010edit工具中查看


Petya变种勒索蠕虫启动代码分析

判断分区类型,取了这两个字段:开始扇区与扇区大小:


Petya变种勒索蠕虫启动代码分析

在启动扇区(也就是63扇区)处,读一个扇区的内容,就是DBR结构

从MBR中可以定位到MBR分区表,根据分区表的属性就可以得到活动分区的扇区地址,也就得到了DBR结构地址。

DBR

DBR中存放着关于文件系统的重要参数信息以及系统引导代码。病毒解析到DBR后,只是为了取的DBR结构中的 MftStartLcn 字段(这个字段表明了MFT结构所在的扇区地址),以便能进一步定位文件系统。

DBR的结构如下:

////////////////////////////////////////////////////////////////////////////
//
// NTFS 的DBR 数据结构
//
////////////////////////////////////////////////////////////////////////////
typedef struct _BIOS_PARAMETER_BLOCK {
/*+0x0B*/ uint16 BytesPerSector; // 字节/扇区一般为0x0200 即512
/*+0x0D*/ uchar SectorsPerCluster; // 扇区/簇
/*+0x0E*/ uint16 ReservedSectors; // 保留扇区
/*+0x0F*/ uchar Fats; //
/*+0x11*/ uint16 RootEntries; //
/*+0x13*/ uint16 Sectors; //
/*+0x15*/ uchar Media; // 媒介描述
/*+0x16*/ uint16 SectorsPerFat; //
/*+0x18*/ uint16 SectorsPerTrack; // 扇区/磁轨
/*+0x1A*/ uint16 Heads; // 头
/*+0x1C*/ uint32 HiddenSectors; // 隐藏扇区
/*+0x20*/ uint32 LargeSectors; // checked when volume is mounted
}BIOS_PARAMETER_BLOCK, *pBIOS_PARAMETER_BLOCK;
typedef struct _NTFS_Boot_Sector{
/*+0x00*/ uchar JmpCode[3]; // 跳转指令
/*+0x03*/ char OemID[8]; // 文件系统ID
/*+0x0B*/ BIOS_PARAMETER_BLOCK PackedBpb; // BPB
/*+0x24*/ uchar Unused[4]; // 未使用,总是为
/*+0x28*/ uint64 NumberSectors; // 扇区总数
/*+0x30*/ lcn MftStartLcn; // 开始C# $MFT (簇) 乘以 BIOS_PARAMETER_BLOCK.SectorsPerCluster 值得到扇区号
/*+0x38*/ lcn Mft2StartLcn; // 开始C# $MFTMirr (簇)
/*+0x40*/ uchar ClustersPerFileRecordSegment; // 文件记录大小指示器
/*+0x41*/ uchar Reserved0[3]; // 未使用
/*+0x44*/ uchar DefaultClustersPerIndexAllocationBuffer; // 簇/索引块
/*+0x45*/ uchar Reserved1[3]; // 未使用
/*+0x48*/ uint64 SerialNumber; // 64位序列号
/*+0x50*/ uint32 Checksum; // 校验和
/*+0x54*/ uchar BootStrap[426]; // 启动代码
/*+0x1FE*/ uint16 RecordEndSign; // 0xAA55 结束标记
}NTFS_Boot_Sector, *pNTFS_Boot_Sector;

其中,定位MFT时,最重要的结构为MftStartLcn表示起始簇号,乘以 BIOS_PARAMETER_BLOCK.SectorsPerCluster (在我的机器上这个值为8,表示一个簇由8个扇区组成)后就得到起始扇区号。

MFT

简介

MFT,即主文件表(MasterFileTable)的简称,它是NTFS文件系统的核心。MFT由一个个MFT项(也称为文件记录)组成。每个MFT项的前部 为0×10字节的 头结构,用来描述本MFT项的相关信息。后面节存放着属性。每个文件和目录的信息都包含在MFT中,每个文件和目录至少有一个MFT项。除了引导扇区外,访问其他任何一个文件前都需要先访问MFT,在MFT中找到该文件的MFT项,根据MFT项中记录的信息找到文件内容并对其进行访问。

MFT结构分为两种:元文件与普通文件。

元文件对于用户是不能直接访问的,MFT将开头的16个文件记录块保留用于这些元数据文件,除此之外的文件记录块才用于普通的用户文件和目录。

16个元文件

#define MFT_IDX_MFT 0
#define MFT_IDX_MFT_MIRR 1
#define MFT_IDX_LOG_FILE 2
#define MFT_IDX_VOLUME 3
#define MFT_IDX_ATTR_DEF 4
#define MFT_IDX_ROOT 5
#define MFT_IDX_BITMAP 6
#define MFT_IDX_BOOT 7
#define MFT_IDX_BAD_CLUSTER 8
#define MFT_IDX_SECURE 9
#define MFT_IDX_UPCASE 10
#define MFT_IDX_EXTEND 11
#define MFT_IDX_RESERVED12 12
#define MFT_IDX_RESERVED13 13
#define MFT_IDX_RESERVED14 14
#define MFT_IDX_RESERVED15 15
#define MFT_IDX_USER 16

这16个原文件本身也是MFT结构的模式,可以理解为记录了MFT信息的MFT结构。

怎么解析这16个原文件的MFT结构呢?

换句话说,通过MBR定位到DBR,通过DBR定位到MFT,此时的MFT就对应着索引为MFT_IDX_MFT 的MFT,向后偏移文件记录大小的地方,就存放着索引为MFT_IDX_MFT_MIRR 的MFT。再向后偏移文件记录大小的地方,就存放着索引为 MFT_IDX_LOG_FILE 的MFT

解析这16个原文件的MFT结构有什么用?

如对于MFT_IDX_VOLUME这个MFT结构,解析这个MFT结构中的ATTR_TYPE_VOLUME_INFORMATION (对应着0×70)就可以得到NTFS卷的版本信息,解析这个MFT结构中的 ATTR_TYPE_VOLUME_NAME 属性(对应着0×60)就可以得到NTFS卷名信息。

再如,对于MFT_IDX_MFT这个MFT结构,解析这个MFT结构中的ATTR_TYPE_DATA (对应0×80)的属性 RealSize,就表示整个卷所有的文件记录的大小信息。利用这个大小信息是以字节表示的,用这个大小信息除以每个文件记录所占用的字节就得到了卷占有的文件记录数量。计算出来的文件记录数量是将元文件也计算在内的。

依次遍历每个文件记录数量,读取这个文件记录的内容就是MFT结构,解析这个MFT的对应属性就可以解析出文件名、文件属性、文件内容等。

普通MFT

遍历文件时,从第16个文件记录开始向后遍历,才会得到普通的用户文件和目录信息及内容。

数据结构

MFT的直观结构如下,

// 文件记录体
// 属性1
// 属性2
// …………
Petya变种勒索蠕虫启动代码分析

每个MFT的结构如下:

// 文件记录头
typedef struct _FILE_RECORD_HEADER
{
/*+0x00*/ uint32 Type; // 固定值'FILE'
/*+0x04*/ uint16 UsaOffset; // 更新序列号偏移, 与操作系统有关
/*+0x06*/ uint16 UsaCount; // 固定列表大小Size in words of Update Sequence Number & Array (S)
/*+0x08*/ uint64 Lsn; // 日志文件序列号(LSN)
} FILE_RECORD_HEADER, *PFILE_RECORD_HEADER;
// 文件记录体
typedef struct _FILE_RECORD{
/*+0x00*/ FILE_RECORD_HEADER Ntfs; // MFT表头
/*+0x10*/ uint16 SequenceNumber; // 序列号(用于记录文件被反复使用的次数)
/*+0x12*/ uint16 LinkCount; // 硬连接数
/*+0x14*/ uint16 AttributeOffset; // 第一个属性偏移
/*+0x16*/ uint16 Flags; // falgs, 00表示删除文件,01表示正常文件,02表示删除目录,03表示正常目录
/*+0x18*/ uint32 BytesInUse; // 文件记录实时大小(字节) 当前MFT表项长度,到FFFFFF的长度+4
/*+0x1C*/ uint32 BytesAllocated; // 文件记录分配大小(字节)
/*+0x20*/ uint64 BaseFileRecord; // = 0 基础文件记录 File reference to the base FILE record
/*+0x28*/ uint16 NextAttributeNumber; // 下一个自由ID号
/*+0x2A*/ uint16 Pading; // 边界
/*+0x2C*/ uint32 MFTRecordNu

Viewing all articles
Browse latest Browse all 12749

Latest Images

Trending Articles





Latest Images