Technical Analysis : NotPetya\Petya MBR


This post will cover technical details of custom boot loader of NotPetya\Petya.

It starts with copying disk sectors (overwritten by malware) 1 to 32 at address 0x8000. Below is the set of instruction performing above operation.


To read sectors from disk it use INT13 BIOS interrupt call.Below is an example of INT 13 interrupt.
DAP













AH 42h = function number for extended read
DL 80h  = drive index (e.g. 1st HDD = 80h)
DS:SI 7BDCh = segment:offset pointer to the DAP, see below

DAP : Disk Address Packet
offset range size value description
00h 1 byte      10h size of DAP (set this to 10h)
01h 1 byte      00h unused, should be zero
02h..03h 2 bytes    01h number of sectors to be read
04h..07h 4 bytes    0x8000h segment:offset pointer to the memory buffer to which sectors will be transferred
08h..0Fh 8 bytes 01h     absolute number of the start of the sectors to be read (1st sector of drive has number 0)

memory buffer 0x8000 where 1st sector is read and next stage execution begins.











Next step is to get information of drives having status code set between 0x80-0x8F. Below information about a drive is collected and stored in array where each entry is of 8-byte.
1.Status Code - 1byte
2.Drive Sector 0 contain overwritten MBR - 1byte
3.Drive Present - 1byte
4.Total Number of Sectors - 4bytes

Read Drive Parameters, if Drive exist this call will be successful and Drive Present Flag will be set to 1 else set to 0.












Get total number of sectors in a drive by reading partition table entries and update value Total Number of Sectors.













Check sector 0 of drive contain bytes overwritten by NotPetya\Petya and set Drive Sector 0 contain overwritten MBR flag to 1 else set to 0.























Once information about all drives are read.It is stored into drive info array where each drive entry is eight bytes.Below drive info array containing two entries.
Drive info array





1.Status Code - 0x80
2.Drive Sector 0 contain overwritten MBR - 0x1
3.Drive Present - 0x1
4.Total Number of Sectors - 0x77FE098

Next it check whether drive is already encrypted by reading sector 32 (contains salsa20 key) of drive for which Drive Sector 0 contain overwritten MBR value is set to 1.If first byte of sector 32 is set to 1 it means already encrypted else not encrypted.




If disk is not encrypted.It proceeds with disk encryption and display below message on screen.


















Read sector 32(contains sals20 key) and move 1 to first byte of sector 32 and destroy next 0x20 bytes (which is salsa20 key) by overwriting with 0's and write back to sector 32 of Hard Disk Drive.

Read sector 32.









move 1 to first byte of sector 32.



Destroy next 0x20 bytes (which is salsa20 key).











Buffer containing sector 32 overwritten bytes.






Write above buffer byte to sector 32 of Hard Drive Disk.
Read sector 33 and encrypt using salsa20 key.






















Next step is to iterate over drive info array entries mentioned above and if Drive Present value of an entry is set perform below task.
1.Read Sector 34 (holds encrypted System MBR).
2.Decrypt System MBR.
3.Read Partition Table entries from decrypted System MBR.
4.Read first absolute sector and Number of sectors for each partition table entry.
5.For each partition table entry calculate address of NTFS_BOOT_SECTOR structure.
6.From NTFS_BOOT_SECTOR structure read field n64MFTLogicalClustNum and calculate address of NTFS_MFT_FILE_ENTRY_HEADER.
7.From NTFS_MFT_FILE_ENTRY_HEADER read field wAttribOffset and jump to Master File Table Attributes represented by NTFS_ATTRIBUTE structure.
8.Continue to next Master File Table Attribute until Master File Table Attribute of type Data is not found.
9.Read Data run lists entry of Master File Table Data Attribute.
10.For each Data run list calculate number of clusters in it and offset of first cluster.
11.Start encrypting bytes of Data run list clusters using salsa20 algorithm.

Read sector 34(holds encrypted system MBR).









Decrypt System MBR.







Read Partition Table entries from decrypted System MBR






























Read first absolute sector and Number of sectors for each partition table entry.



First Partition Entry
1.First Absolute Sector - 0x3F
2.Number of Sectors - 0x04FF9725
Second Partition Entry
1.First Absolute Sector - 0x04FF9764
2.Number of Sectors - 0x02804934

For each partition table entry calculate address of NTFS_BOOT_SECTOR structure.
NTFS_BOOT_SECTOR is located at first physical address of partition entry which can be calculated as -Address of NTFS_BOOT_SECTOR = First Absolute Sector  of partition entry* Size of Sector = 0x3F * 0x200 = 0x7E00.
















NTFS_BOOT_SECTOR
















From NTFS_BOOT_SECTOR structure read field n64MFTLogicalClustNum and calculate address of NTFS_MFT_FILE_ENTRY_HEADER.

n64MFTLogicalClustNum - 0x0C0000
wBytesPerSector - 0x200
uchSectorPerClust - 0x08

Address of NTFS_MFT_FILE_ENTRY_HEADER = ((n64MFTLogicalClustNum*uchSectorPerClust) * wBytesPerSector + (First Absolute Sector * wBytesPerSector)) = (0xC0000*8)*0x200 + (0x3F*0x200) = 0xC0007E00









NTFS_MFT_FILE_ENTRY_HEADER






From NTFS_MFT_FILE_ENTRY_HEADER read field wAttribOffset and jump to Master File Table Attributes represented by NTFS_ATTRIBUTE structure.
wAttribOffset = 0x38

Continue to next Master File Table Attribute until Master File Table Attribute of type Data is not found.




























Read Data run lists entry of Master File Table Data Attribute.
MFT Data Attributes








NTFS_ATTRIBUTE .dwType = 0x80
NTFS_ATTRIBUTE.dwFullLength = 0x48
NTFS_ATTRIBUTE.uchNonResFlag = 0x01

NTFS_ATTRIBUTE.NONRESIDENT.wDatarunOffset = 0x40

Portion highlighted in orange is Data run list entry.
First byte is 0x32.
Lower nibble of first byte (0x32) which is 2 means read next two bytes (highlighted in blue) adjacent to first byte 0x32. This value denotes number of cluster 0x1848.
Higher nibble of first byte (0x32) which is 3 means read three bytes (highlighted in green) after the number of clusters value .This value denotes Absolute value of start of clusters for Data run list (0xC0000).
Adding higher and lower nibble of first bytes i.e. 3 + 2 = 5, which denotes size(in bytes) of a Data run list entry after first byte and after that second Data run list entry begin. In above image it is 0x00 which mean no more Data run list entry.

For each Data run list calculate number of sectors in it and offset of first cluster.















Physical Address of Cluster =  (Absolute Value of Start of Cluster Data run list entry* No of Sectors Per Cluster * BytesPerSector) + (First Absolute Sector * Size of Sector) = (0xC0000*8*0x200) + (0x3F*0x200) = C0007E00

In above code we can see it skips first 0x20 sectors i.e. 0x20 * 0x200 =  0x4000 bytes.
Therefore physical address of first cluster on disk from where encryption starts C0007E00 + 0x4000 = 0xC000BE00.

Number of sectors to encrypt = (Number of Cluster in Data run list entry * No of Sectors Per Cluster) = 0x1848 * 8  = 0xC240

It skips first 0x20 sectors therefore Number of  sectors to encrypt = 0xC240 - 20 = 0xC220 (49696).

Before start with encryption of 0xC220(49696) sectors from physical address 0xC000BE00 it display fake CHKDSK message.


















Read two sectors (0x400 bytes) from physical address 0xC000BE00 and encrypt using salsa20 algorithm.










Disk Address packet for reading disk.



Number of Sectors to read - 0x02
absolute number of the start of the sectors to be read - 0x60005F = 0x60005F * 0x200 = 0xC000BE00































Comments

Popular posts from this blog

VIrtual Machine Detection Techniques

DoublePulsar Backdoor

Google CTF 2017 : Android RE Challenge

Debugging MBR : IDA Pro and Bochs Emulator

Analyzing ATM Malwares

PaloAlto CTF 2017 : Binary Challenge 2

FireEye FLARE CTF 2017 : APK Challenge 8

NotPetya\Petya : Overwriting System MBR

WannaCry Encryption Flow

Samsung CTF : Chicken or Egg Reversing Challenge