Code routine comments are here, but no detailed code or structure comments. The symbolic names used here may or may not be helpful. Feel free to ask for more details ;)
seg000:0000 seg000 segment byte public 'CODE' use16
seg000:0000 assume cs:seg000
seg000:0000 assume es:nothing, ss:nothing, ds:nothing, fs:nothing, gs:nothing
seg000:0000
seg000:0000 start:
seg000:0000 jmp short near ptr BootSectorMain
seg000:0002 ; ---------------------------------------------------------------------------
seg000:0002 nop
seg000:0002 ; ---------------------------------------------------------------------------
seg000:0003 NtfsBpbEbpb db 'N', 'T', 'F', 'S' ; OemId
seg000:0003 db ' ', ' ', ' ', ' ' ; OemId
seg000:0003 dw 200h ; BytesPerSector
seg000:0003 db 8 ; SectorsPerCluster
seg000:0003 dw 0 ; NoOfSectorsToRead
seg000:0003 dd 0 ; LsnToRead
seg000:0003 db 0 ; ExtDiskAccessAvl
seg000:0003 db 0F8h ; MediaDescriptor
seg000:0003 db 2 dup(0)
seg000:0003 dw 3Fh ; SectorsPerTrack
seg000:0003 dw 0FFh ; NumberOfHeads
seg000:0003 dd 3Fh ; PartitionBase
seg000:0003 dd 0 ; ChsLimit
seg000:0003 db 80h ; DiskNumber
seg000:0003 db 0, 80h, 0
seg000:0003 dq 1DFF7E6h ; TotalSectors
seg000:0003 dq 0C0000h ; LcnOfMftBfrs
seg000:0003 dq 1DFF7Eh ; LcnOfMftMirrorBfrs
seg000:0003 dd 0F6h ; ClustersPerFrs
seg000:0003 dd 1 ; ClustersPerIndexBlock
seg000:0003 db 0D7h, 4, 72h, 54h ; VolumeSerialNumber
seg000:0003 db 2Eh, 72h, 54h, 62h ; VolumeSerialNumber
seg000:0003 dd 0 ; Checksum
seg000:0054
seg000:0054 ; ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ S U B R O U T I N E ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦
seg000:0054
seg000:0054 ; Description:
seg000:0054 ;
seg000:0054 ; Main boot sector routine. The boot sector was loaded
seg000:0054 ; by the MBR at segmented address 0000:7C00. Reads the
seg000:0054 ; entire NTFS bootstrap (16 sectors) from the disk and
seg000:0054 ; passes control to the bootstrap's main routine.
seg000:0054 ;
seg000:0054 ; Arguments:
seg000:0054 ;
seg000:0054 ; (None)
seg000:0054 ;
seg000:0054 ; Returns:
seg000:0054 ;
seg000:0054 ; (Does not return. Control is passed to the main
seg000:0054 ; bootstrap routine.)
seg000:0054
seg000:0054 BootSectorMain proc far
seg000:0054 cli
seg000:0055 xor ax, ax
seg000:0057 mov ss, ax
seg000:0059 mov sp, 7C00h
seg000:005C sti
seg000:005D mov ax, 7C0h
seg000:0060 mov ds, ax
seg000:0062 assume ds:nothing
seg000:0062 call ComputeChsLimit
seg000:0065 mov ax, 0D00h
seg000:0068 mov es, ax
seg000:006A assume es:nothing
seg000:006A xor bx, bx
seg000:006C mov byte ptr ds:NtfsBpbEbpb.NoOfSectorsToRead, 16
seg000:0071 call ReadDiskSectors
seg000:0074 push 0D00h
seg000:0077 push offset BootStrapMain
seg000:007A retf
seg000:007A BootSectorMain endp
seg000:007A
seg000:007B
seg000:007B ; ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ S U B R O U T I N E ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦
seg000:007B
seg000:007B ; Description:
seg000:007B ;
seg000:007B ; Computes the disk's total sector count according to
seg000:007B ; the C/H/S values returned by the legacy INT 13 -
seg000:007B ; DISK - GET DRIVE PARAMETERS bios function. Saves
seg000:007B ; computed value in the ChsLimit variable. Sectors
seg000:007B ; at or above this value will require the extended
seg000:007B ; disk access functions.
seg000:007B ;
seg000:007B ; Arguments:
seg000:007B ;
seg000:007B ; (None)
seg000:007B ;
seg000:007B ; Returns:
seg000:007B ;
seg000:007B ; (No return value)
seg000:007B ;
seg000:007B ; Preserves/modifies:
seg000:007B ;
seg000:007B ; (No explicit preservations)
seg000:007B
seg000:007B ComputeChsLimit proc near
seg000:007B mov dl, ds:NtfsBpbEbpb.DiskNumber
seg000:007F mov ah, 8
seg000:0081 int 13h
seg000:0083 jnb short succeeded
seg000:0085 mov cx, 0FFFFh
seg000:0088 mov dh, cl
seg000:008A
seg000:008A succeeded:
seg000:008A movzx eax, dh
seg000:008E inc ax
seg000:008F movzx edx, cl
seg000:0093 and dl, 3Fh
seg000:0096 mul dx
seg000:0098 xchg cl, ch
seg000:009A shr ch, 6
seg000:009D inc cx
seg000:009E movzx ecx, cx
seg000:00A2 mul ecx
seg000:00A5 mov ds:NtfsBpbEbpb.ChsLimit, eax
seg000:00A9 retn
seg000:00A9 ComputeChsLimit endp
seg000:00A9
seg000:00AA
seg000:00AA ; ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ S U B R O U T I N E ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦
seg000:00AA
seg000:00AA ; Description:
seg000:00AA ;
seg000:00AA ; Performs a check for the extended disk access bios
seg000:00AA ; functions. Sets the ExtDiskAccessAvl boolean
seg000:00AA ; variable to 1 if they are available.
seg000:00AA ;
seg000:00AA ; Arguments:
seg000:00AA ;
seg000:00AA ; (None)
seg000:00AA ;
seg000:00AA ; Returns:
seg000:00AA ;
seg000:00AA ; (No return value)
seg000:00AA ;
seg000:00AA ; Preserves/modifies:
seg000:00AA ;
seg000:00AA ; (No explicit preservations)
seg000:00AA
seg000:00AA CheckExtDiskAccessAvl proc near
seg000:00AA mov ah, 41h
seg000:00AC mov bx, 55AAh
seg000:00AF mov dl, ds:NtfsBpbEbpb.DiskNumber
seg000:00B3 int 13h
seg000:00B5 jb short failed
seg000:00B7 cmp bx, 0AA55h
seg000:00BB jnz short failed
seg000:00BD test cl, 1
seg000:00C0 jz short failed
seg000:00C2 inc ds:NtfsBpbEbpb.ExtDiskAccessAvl
seg000:00C6
seg000:00C6 failed:
seg000:00C6 retn
seg000:00C6 CheckExtDiskAccessAvl endp
seg000:00C6
seg000:00C7
seg000:00C7 ; ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ S U B R O U T I N E ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦
seg000:00C7
seg000:00C7 ; Description:
seg000:00C7 ;
seg000:00C7 ; Reads the specified number of sectors from the
seg000:00C7 ; specified logical sector number.
seg000:00C7 ;
seg000:00C7 ; Arguments:
seg000:00C7 ;
seg000:00C7 ; LsnToRead - Logical sector number to read from.
seg000:00C7 ;
seg000:00C7 ; NoOfSectorsToRead - Number of sectors to read.
seg000:00C7 ;
seg000:00C7 ; ES:BX - Memory buffer for the sectors to be read.
seg000:00C7 ;
seg000:00C7 ; Returns:
seg000:00C7 ;
seg000:00C7 ; (No return value. Errors produce a fatal error
seg000:00C7 ; display message.)
seg000:00C7 ;
seg000:00C7 ; Preserves/modifies:
seg000:00C7 ;
seg000:00C7 ; Preserves 32-bit GP registers, DS, ES.
seg000:00C7
seg000:00C7 ReadDiskSectors proc near
seg000:00C7 pushad
seg000:00C9 push ds
seg000:00CA push es
seg000:00CB
seg000:00CB read_next_sector:
seg000:00CB mov eax, ds:NtfsBpbEbpb.LsnToRead
seg000:00CF add eax, ds:NtfsBpbEbpb.PartitionBase
seg000:00D4 cmp eax, ds:NtfsBpbEbpb.ChsLimit
seg000:00D9 jb do_chs_disk_read
seg000:00DD push ds
seg000:00DE push large 0
seg000:00E1 push eax
seg000:00E3 push es
seg000:00E4 push bx
seg000:00E5 push large 10010h
seg000:00EB cmp ds:NtfsBpbEbpb.ExtDiskAccessAvl, 0
seg000:00F0 jnz do_extended_disk_read
seg000:00F4 call CheckExtDiskAccessAvl
seg000:00F7 cmp ds:NtfsBpbEbpb.ExtDiskAccessAvl, 0
seg000:00FC jz disk_read_error
seg000:0100
seg000:0100 do_extended_disk_read:
seg000:0100 mov ah, 42h
seg000:0102 mov dl, ds:NtfsBpbEbpb.DiskNumber
seg000:0106 push ss
seg000:0107 pop ds
seg000:0108 assume ds:nothing
seg000:0108 mov si, sp
seg000:010A int 13h
seg000:010C pop eax
seg000:010E pop bx
seg000:010F pop es
seg000:0110 assume es:nothing
seg000:0110 pop eax
seg000:0112 pop eax
seg000:0114 pop ds
seg000:0115 jmp short check_for_error
seg000:0117 ; ---------------------------------------------------------------------------
seg000:0117
seg000:0117 do_chs_disk_read:
seg000:0117 xor edx, edx
seg000:011A movzx ecx, ds:NtfsBpbEbpb.SectorsPerTrack
seg000:0120 div ecx
seg000:0123 inc dl
seg000:0125 mov cl, dl
seg000:0127 mov edx, eax
seg000:012A shr edx, 10h
seg000:012E div ds:NtfsBpbEbpb.NumberOfHeads
seg000:0132 xchg dl, dh
seg000:0134 mov dl, ds:NtfsBpbEbpb.DiskNumber
seg000:0138 mov ch, al
seg000:013A shl ah, 6
seg000:013D or cl, ah
seg000:013F mov ax, 201h
seg000:0142 int 13h
seg000:0144
seg000:0144 check_for_error:
seg000:0144 jb disk_read_error
seg000:0148 mov ax, es
seg000:014A add ax, 20h
seg000:014D mov es, ax
seg000:014F assume es:nothing
seg000:014F inc ds:NtfsBpbEbpb.LsnToRead
seg000:0154 dec ds:NtfsBpbEbpb.NoOfSectorsToRead
seg000:0158 jnz read_next_sector
seg000:015C pop es
seg000:015D assume es:nothing
seg000:015D pop ds
seg000:015E popad
seg000:0160 retn
seg000:0160 ReadDiskSectors endp
seg000:0160
seg000:0161 ; ---------------------------------------------------------------------------
seg000:0161
seg000:0161 disk_read_error:
seg000:0161 mov al, ds:diskReadErrorMsg
seg000:0164
seg000:0164 display_error_message:
seg000:0164 call DisplayMsg
seg000:0167 mov al, ds:restartMsg
seg000:016A call DisplayMsg
seg000:016D sti
seg000:016E
seg000:016E error_loop:
seg000:016E jmp short error_loop
seg000:0170
seg000:0170 ; ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ S U B R O U T I N E ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦
seg000:0170
seg000:0170 ; Description:
seg000:0170 ;
seg000:0170 ; Displays the given zero-terminated message string.
seg000:0170 ;
seg000:0170 ; Arguments:
seg000:0170 ;
seg000:0170 ; AL - Offset (relative to DS:0100) of the
seg000:0170 ; zero-terminated string to be displayed.
seg000:0170 ;
seg000:0170 ; Returns:
seg000:0170 ;
seg000:0170 ; (No return value)
seg000:0170 ;
seg000:0170 ; Preserves/modifies:
seg000:0170 ;
seg000:0170 ; (No explicit preservations)
seg000:0170
seg000:0170 DisplayMsg proc near
seg000:0170 mov ah, 1
seg000:0172 mov si, ax
seg000:0174
seg000:0174 loop:
seg000:0174 lodsb
seg000:0175 cmp al, 0
seg000:0177 jz short return
seg000:0179 mov ah, 0Eh
seg000:017B mov bx, 7
seg000:017E int 10h
seg000:0180 jmp short loop
seg000:0182 ; ---------------------------------------------------------------------------
seg000:0182
seg000:0182 return:
seg000:0182 retn
seg000:0182 DisplayMsg endp
seg000:0182
seg000:0182 ; ---------------------------------------------------------------------------
seg000:0183 aADiskReadErrorOccurred db 0Dh,0Ah
seg000:0183 db 'A disk read error occurred',0
seg000:01A0 aNtldrIsMissing db 0Dh,0Ah
seg000:01A0 db 'NTLDR is missing',0
seg000:01B3 aNtldrIsCompressed db 0Dh,0Ah
seg000:01B3 db 'NTLDR is compressed',0
seg000:01C9 aPressCtrlAltDelToRestart db 0Dh,0Ah
seg000:01C9 db 'Press Ctrl+Alt+Del to restart',0Dh,0Ah,0
seg000:01EB db 0
seg000:01EC db 0
seg000:01ED db 0
seg000:01EE db 0
seg000:01EF db 0
seg000:01F0 db 0
seg000:01F1 db 0
seg000:01F2 db 0
seg000:01F3 db 0
seg000:01F4 db 0
seg000:01F5 db 0
seg000:01F6 db 0
seg000:01F7 db 0
seg000:01F8 diskReadErrorMsg db 83h
seg000:01F9 ntldrIsMissingMsg db 0A0h
seg000:01FA ntldrIsCompressedMsg db 0B3h
seg000:01FB restartMsg db 0C9h
seg000:01FC db 0
seg000:01FD db 0
seg000:01FE dw 0AA55h
seg000:0200 aNtldr_length dw 5
seg000:0202 aNtldr:
seg000:0202 unicode 0,
seg000:020C aI30_length dw 4
seg000:020E aI30:
seg000:020E unicode 0, <$I30>
seg000:0216 pAttribListData dd 0E000h
seg000:021A pMftBfrs dd 3000h
seg000:021E MftFrsCount dd 0
seg000:0222 pRootdIndexRoot dd 0
seg000:0226 pRootdIndexAlloc dd 0
seg000:022A pRootdBitmap dd 0
seg000:022E pRootdIndexRootHdr dd 0
seg000:0232 pIndexAllocHdr dd 0
seg000:0236 pBitmapHdr dd 0
seg000:023A pNtldrRecord dd 0
seg000:023E dd 0
seg000:0242 pIndexAllocEntry dd 0
seg000:0246 pBitmapData dd 0
seg000:024A pMftFrInfoEnd dd 0
seg000:024E BytesPerCluster dd 0
seg000:0252 BytesPerFrs dd 0
seg000:0256 SectorsPerFrs dd 909012EBh
seg000:025A pMftFrInfo dd 0
seg000:025E SizeOfIaEntry dd 0
seg000:0262 ClustersPerIndxRecd dd 0
seg000:0266 SectorsPerIaEntry dd 0
seg000:026A
seg000:026A ; ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ S U B R O U T I N E ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦
seg000:026A
seg000:026A ; Description:
seg000:026A ;
seg000:026A ; Main bootstrap routine. Control is passed from the
seg000:026A ; boot sector's main routine. Locates and loads NTLDR
seg000:026A ; from the root directory of the boot partition, and
seg000:026A ; then passes control to NTLDR.
seg000:026A ;
seg000:026A ; Arguments:
seg000:026A ;
seg000:026A ; (None)
seg000:026A ;
seg000:026A ; Returns:
seg000:026A ;
seg000:026A ; (Does not return. Control is passed to NTLDR. Errors
seg000:026A ; produce a fatal error display message.)
seg000:026A
seg000:026A BootStrapMain proc far
seg000:026A mov ax, cs
seg000:026C mov ds, ax
seg000:026E shl ax, 4
seg000:0271 cli
seg000:0272 mov sp, ax
seg000:0274 sti
seg000:0275 call ComputeChsLimit
seg000:0278 movzx eax, ds:NtfsBpbEbpb.BytesPerSector
seg000:027E movzx ebx, ds:NtfsBpbEbpb.SectorsPerCluster
seg000:0284 mul ebx
seg000:0287 mov ds:BytesPerCluster, eax
seg000:028B mov ecx, ds:NtfsBpbEbpb.ClustersPerFrs
seg000:0290 cmp cl, 0
seg000:0293 jg @@1
seg000:0297 neg cl
seg000:0299 mov eax, 1
seg000:029F shl eax, cl
seg000:02A2 jmp short @@2
seg000:02A4 ; ---------------------------------------------------------------------------
seg000:02A4 nop
seg000:02A5
seg000:02A5 @@1:
seg000:02A5 mov eax, ds:BytesPerCluster
seg000:02A9 mul ecx
seg000:02AC
seg000:02AC @@2:
seg000:02AC mov ds:BytesPerFrs, eax
seg000:02B0 movzx ebx, ds:NtfsBpbEbpb.BytesPerSector
seg000:02B6 xor edx, edx
seg000:02B9 div ebx
seg000:02BC mov ds:SectorsPerFrs, eax
seg000:02C0 call MftFrInitialize
seg000:02C3 mov ecx, ds:pMftFrInfoEnd
seg000:02C8 mov ds:pRootdIndexRoot, ecx
seg000:02CD add ecx, ds:BytesPerFrs
seg000:02D2 mov ds:pRootdIndexAlloc, ecx
seg000:02D7 add ecx, ds:BytesPerFrs
seg000:02DC mov ds:pRootdBitmap, ecx
seg000:02E1 add ecx, ds:BytesPerFrs
seg000:02E6 mov ds:pNtldrRecord, ecx
seg000:02EB add ecx, ds:BytesPerFrs
seg000:02F0 mov ds:pIndexAllocEntry, ecx
seg000:02F5 mov eax, $INDEX_ROOT
seg000:02FB mov ecx, ds:pRootdIndexRoot
seg000:0300 call GetRootdAttribHdr
seg000:0303 or eax, eax
seg000:0306 jz disk_read_error
seg000:030A mov ds:pRootdIndexRootHdr, eax
seg000:030E mov eax, $INDEX_ALLOCATION
seg000:0314 mov ecx, ds:pRootdIndexAlloc
seg000:0319 call GetRootdAttribHdr
seg000:031C mov ds:pIndexAllocHdr, eax
seg000:0320 mov eax, $BITMAP
seg000:0326 mov ecx, ds:pRootdBitmap
seg000:032B call GetRootdAttribHdr
seg000:032E mov ds:pBitmapHdr, eax
seg000:0332 mov eax, ds:pRootdIndexRootHdr
seg000:0336 or eax, eax
seg000:0339 jz disk_read_error
seg000:033D cmp [eax+STD_ATTRIB_HDR.NonresidentFlag], 0
seg000:0342 jnz disk_read_error
seg000:0346 lea edx, [eax+(size STD_ATTRIB_HDR)]
seg000:034B add ax, [edx+ATTRIB_HDR_RESIDENT.AttributeOffset]
seg000:034F movzx ecx, [eax+INDEX_ROOT_ATTRIB.ClustersPerIndxRecd]
seg000:0355 mov ds:ClustersPerIndxRecd, ecx
seg000:035A mov ecx, [eax+INDEX_ROOT_ATTRIB.SizeOfIaEntry]
seg000:035F mov ds:SizeOfIaEntry, ecx
seg000:0364 mov eax, ds:SizeOfIaEntry
seg000:0368 movzx ecx, ds:NtfsBpbEbpb.BytesPerSector
seg000:036E xor edx, edx
seg000:0371 div ecx
seg000:0374 mov ds:SectorsPerIaEntry, eax
seg000:0378 mov eax, ds:pIndexAllocEntry
seg000:037C add eax, ds:SizeOfIaEntry
seg000:0381 mov ds:pBitmapData, eax
seg000:0385 cmp ds:pIndexAllocHdr, 0
seg000:038B jz no_index_allocation
seg000:038F cmp ds:pBitmapHdr, 0
seg000:0395 jz disk_read_error
seg000:0399 mov ebx, ds:pBitmapHdr
seg000:039E push ds
seg000:039F pop es
seg000:03A0 mov edi, ds:pBitmapData
seg000:03A5 call GetAttributeData
seg000:03A8
seg000:03A8 no_index_allocation:
seg000:03A8 movzx ecx, ds:aNtldr_length
seg000:03AE mov eax, offset aNtldr ; "NTLDR"
seg000:03B4 call FindFileInRootdIndex
seg000:03B7 or eax, eax
seg000:03BA jz error_ntldr_missing
seg000:03BE mov eax, dword ptr [eax+INDEX_ENTRY.FileReference]
seg000:03C2 push ds
seg000:03C3 pop es
seg000:03C4 mov edi, ds:pNtldrRecord
seg000:03C9 call GetFileRecord
seg000:03CC mov eax, ds:pNtldrRecord
seg000:03D0 mov ebx, $DATA
seg000:03D6 mov ecx, 0
seg000:03DC mov edx, 0
seg000:03E2 call FindAttribute
seg000:03E5 or eax, eax
seg000:03E8 jnz found_attribute
seg000:03EC mov ecx, $DATA
seg000:03F2 mov eax, ds:pNtldrRecord
seg000:03F6 call GetFrsWithAttribType
seg000:03F9 or eax, eax
seg000:03FC jz error_ntldr_missing
seg000:0400 push ds
seg000:0401 pop es
seg000:0402 mov edi, ds:pNtldrRecord
seg000:0407 call GetFileRecord
seg000:040A mov eax, ds:pNtldrRecord
seg000:040E mov ebx, $DATA
seg000:0414 mov ecx, 0
seg000:041A mov edx, 0
seg000:0420 call FindAttribute
seg000:0423 or eax, eax
seg000:0426 jz error_ntldr_missing
seg000:042A
seg000:042A found_attribute:
seg000:042A movzx ebx, [eax+STD_ATTRIB_HDR.Flags]
seg000:0430 and ebx, 0FFh
seg000:0437 jnz error_ntldr_compressed
seg000:043B mov ebx, eax
seg000:043E push 2000h
seg000:0441 pop es
seg000:0442 assume es:nothing
seg000:0442 sub edi, edi
seg000:0445 call GetAttributeData
seg000:0448 mov dl, ds:NtfsBpbEbpb.DiskNumber
seg000:044C mov ax, 3E8h
seg000:044F mov es, ax
seg000:0451 assume es:nothing
seg000:0451 lea si, NtfsBpbEbpb.BytesPerSector
seg000:0455 sub ax, ax
seg000:0457 push 2000h
seg000:045A push ax
seg000:045B retf
seg000:045B BootStrapMain endp
seg000:045B
seg000:045C
seg000:045C ; ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ S U B R O U T I N E ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦
seg000:045C
seg000:045C ; Description:
seg000:045C ;
seg000:045C ; Reads the specified number of clusters from the
seg000:045C ; specified logical cluster number.
seg000:045C ;
seg000:045C ; Arguments:
seg000:045C ;
seg000:045C ; EAX - Logical cluster number to read from.
seg000:045C ;
seg000:045C ; EDX - Number of clusters to read.
seg000:045C ;
seg000:045C ; ES:DI - Memory buffer for the clusters to be read.
seg000:045C ;
seg000:045C ; Returns:
seg000:045C ;
seg000:045C ; (No return value)
seg000:045C ;
seg000:045C ; Preserves/modifies:
seg000:045C ;
seg000:045C ; Preserves 32-bit GP registers, DS, ES.
seg000:045C
seg000:045C ReadDiskClusters proc near
seg000:045C push es
seg000:045D push ds
seg000:045E pushad
seg000:0460 mov ebx, edx
seg000:0463 movzx ecx, ds:NtfsBpbEbpb.SectorsPerCluster
seg000:0469 mul ecx
seg000:046C mov ds:NtfsBpbEbpb.LsnToRead, eax
seg000:0470 mov eax, ebx
seg000:0473 mul ecx
seg000:0476 mov ds:NtfsBpbEbpb.NoOfSectorsToRead, ax
seg000:0479 mov bx, di
seg000:047B and bx, 0Fh
seg000:047E mov ax, es
seg000:0480 shr edi, 4
seg000:0484 add ax, di
seg000:0486 push ax
seg000:0487 pop es
seg000:0488 assume es:nothing
seg000:0488 call ReadDiskSectors
seg000:048B popad
seg000:048D nop
seg000:048E pop ds
seg000:048F pop es
seg000:0490 retn
seg000:0490 ReadDiskClusters endp
seg000:0490
seg000:0491
seg000:0491 ; ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ S U B R O U T I N E ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦
seg000:0491
seg000:0491 ; Description:
seg000:0491 ;
seg000:0491 ; Finds the specified attribute in the given file
seg000:0491 ; record segment.
seg000:0491 ;
seg000:0491 ; Arguments:
seg000:0491 ;
seg000:0491 ; DS:EAX - Pointer to the file record segment.
seg000:0491 ;
seg000:0491 ; EBX - Attribute type.
seg000:0491 ;
seg000:0491 ; ECX - Attribute name length. (Zero for unnamed)
seg000:0491 ;
seg000:0491 ; DS:EDX - Pointer to the attribute name.
seg000:0491 ; (Not required for unnamed)
seg000:0491 ;
seg000:0491 ; Returns:
seg000:0491 ;
seg000:0491 ; DS:EAX - Pointer to the attribute's standard
seg000:0491 ; attribute header. If the attribute was not
seg000:0491 ; found, EAX is zero.
seg000:0491 ;
seg000:0491 ; Preserves/modifies:
seg000:0491 ;
seg000:0491 ; (No explicit preservations)
seg000:0491
seg000:0491 FindAttribute proc near
seg000:0491 add ax, [eax+NTFS_FILE_RECORD.FirstAttribOffset]
seg000:0495
seg000:0495 search_next:
seg000:0495 cmp [eaxSTD_ATTRIB_HDR.Type], -1
seg000:049A jz not_found
seg000:049E cmp [eax+STD_ATTRIB_HDR.Type], ebx
seg000:04A2 jnz next_attribute
seg000:04A6 or ecx, ecx
seg000:04A9 jnz find_named
seg000:04AD cmp [eax+STD_ATTRIB_HDR.NameLength], 0
seg000:04B2 jnz next_attribute
seg000:04B6 retn
seg000:04B7 ; ---------------------------------------------------------------------------
seg000:04B7
seg000:04B7 find_named:
seg000:04B7 cmp cl, [eax+STD_ATTRIB_HDR.NameLength]
seg000:04BB jnz next_attribute
seg000:04BF mov esi, eax
seg000:04C2 add si, [eax+STD_ATTRIB_HDR.NameOffset]
seg000:04C6 call UnicodeStringLwr
seg000:04C9 push ecx
seg000:04CB push ds
seg000:04CC pop es
seg000:04CD mov edi, edx
seg000:04D0 repe cmpsw
seg000:04D2 pop ecx
seg000:04D4 jnz next_attribute
seg000:04D8 retn
seg000:04D9 ; ---------------------------------------------------------------------------
seg000:04D9
seg000:04D9 next_attribute:
seg000:04D9 cmp [eax+STD_ATTRIB_HDR.Length], 0
seg000:04DF jz not_found
seg000:04E3 add eax, [eax+STD_ATTRIB_HDR.Length]
seg000:04E8 jmp short search_next
seg000:04EA ; ---------------------------------------------------------------------------
seg000:04EA
seg000:04EA not_found:
seg000:04EA sub eax, eax
seg000:04ED retn
seg000:04ED FindAttribute endp
seg000:04ED
seg000:04EE
seg000:04EE ; ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ S U B R O U T I N E ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦
seg000:04EE
seg000:04EE ; Description:
seg000:04EE ;
seg000:04EE ; Finds the specified file's index entry in the given
seg000:04EE ; index buffer.
seg000:04EE ;
seg000:04EE ; Arguments:
seg000:04EE ;
seg000:04EE ; DS:EAX - Pointer to the index buffer header.
seg000:04EE ;
seg000:04EE ; DS:EBX - Pointer to the filename.
seg000:04EE ;
seg000:04EE ; ECX - Length of the filename.
seg000:04EE ;
seg000:04EE ; Returns:
seg000:04EE ;
seg000:04EE ; DS:EAX - Pointer to the file's index entry. If the
seg000:04EE ; file index entry was not found, EAX is zero.
seg000:04EE ;
seg000:04EE ; Preserves/modifies:
seg000:04EE ;
seg000:04EE ; (No explicit preservations)
seg000:04EE
seg000:04EE FindFileIndexEntry proc near
seg000:04EE mov esi, ebx
seg000:04F1 call UnicodeStringLwr
seg000:04F4 add eax, [eax+INDEX_HDR.FirstEntryOffset]
seg000:04F8
seg000:04F8 search_next:
seg000:04F8 test word ptr [eax+INDEX_ENTRY.Flags], 2
seg000:04FE jnz entry_not_found
seg000:0502 lea edx, [eax+(size INDEX_ENTRY)]
seg000:0507 cmp cl, [edx+INDEX_ENTRY_FILENAME.FileNameLength]
seg000:050B jnz next_entry
seg000:050F lea esi, [edx+INDEX_ENTRY_FILENAME.FileName]
seg000:0514 call UnicodeStringLwr
seg000:0517 push ecx
seg000:0519 push ds
seg000:051A pop es
seg000:051B mov edi, ebx
seg000:051E repe cmpsw
seg000:0520 pop ecx
seg000:0522 jnz next_entry
seg000:0526 retn
seg000:0527 ; ---------------------------------------------------------------------------
seg000:0527
seg000:0527 next_entry:
seg000:0527 cmp [eax+INDEX_ENTRY.IndexEntryLength], 0
seg000:052C jz entry_not_found
seg000:0530 add ax, [eax+INDEX_ENTRY.IndexEntryLength]
seg000:0534 jmp short search_next
seg000:0536 ; ---------------------------------------------------------------------------
seg000:0536
seg000:0536 entry_not_found:
seg000:0536 xor eax, eax
seg000:0539 retn
seg000:0539 FindFileIndexEntry endp
seg000:0539
seg000:053A
seg000:053A ; ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ S U B R O U T I N E ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦
seg000:053A
seg000:053A ; Description:
seg000:053A ;
seg000:053A ; Retrieves the specified attribute's data.
seg000:053A ;
seg000:053A ; Arguments:
seg000:053A ;
seg000:053A ; DS:EBX - Pointer to the attribute's standard
seg000:053A ; attribute header.
seg000:053A ;
seg000:053A ; ES:EDI - Memory buffer for the attribute's data.
seg000:053A ;
seg000:053A ; Returns:
seg000:053A ;
seg000:053A ; (No return value)
seg000:053A ;
seg000:053A ; Preserves/modifies:
seg000:053A ;
seg000:053A ; (No explicit preservations)
seg000:053A
seg000:053A GetAttributeData proc near
seg000:053A cmp [ebx+STD_ATTRIB_HDR.NonresidentFlag], 0
seg000:053F jnz is_non_resident
seg000:0543 push es
seg000:0544 push ds
seg000:0545 pushad
seg000:0547 lea edx, [ebx+(size STD_ATTRIB_HDR)]
seg000:054C mov ecx, [edx+ATTRIB_HDR_RESIDENT.AttributeLength]
seg000:0550 mov esi, ebx
seg000:0553 add si, [edx+ATTRIB_HDR_RESIDENT.AttributeOffset]
seg000:0557 rep movsb
seg000:0559 popad
seg000:055B nop
seg000:055C pop ds
seg000:055D pop es
seg000:055E retn
seg000:055F ; ---------------------------------------------------------------------------
seg000:055F
seg000:055F is_non_resident:
seg000:055F lea edx, [ebx+(size STD_ATTRIB_HDR)]
seg000:0564 mov ecx, dword ptr [edx+ATTRIB_HDR_NONRESIDENT.LastVcn]
seg000:0569 inc ecx
seg000:056B sub eax, eax
seg000:056E call ReadAttribDataClusters
seg000:0571 retn
seg000:0571 GetAttributeData endp
seg000:0571
seg000:0572
seg000:0572 ; ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ S U B R O U T I N E ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦
seg000:0572
seg000:0572 ; Description:
seg000:0572 ;
seg000:0572 ; Reads the specified number of clusters from the
seg000:0572 ; specified virtual cluster number from the specified
seg000:0572 ; attribute's data. The attribute must be non-resident.
seg000:0572 ;
seg000:0572 ; Arguments:
seg000:0572 ;
seg000:0572 ; DS:EBX - Pointer to the attribute's standard
seg000:0572 ; attribute header. The attribute must be
seg000:0572 ; non-resident.
seg000:0572 ;
seg000:0572 ; EAX - Virtual cluster number to read from.
seg000:0572 ;
seg000:0572 ; ECX - Number of clusters to read.
seg000:0572 ;
seg000:0572 ; ES:EDI - Memory buffer for the attribute's data to
seg000:0572 ; be read.
seg000:0572 ;
seg000:0572 ; Returns:
seg000:0572 ;
seg000:0572 ; (No return value. Errors produce a fatal error
seg000:0572 ; display message.)
seg000:0572 ;
seg000:0572 ; Preserves/modifies:
seg000:0572 ;
seg000:0572 ; Preserves 32-bit GP registers, DS, ES.
seg000:0572
seg000:0572 ReadAttribDataClusters proc near
seg000:0572 push es
seg000:0573 push ds
seg000:0574 pushad
seg000:0576 cmp [ebx+STD_ATTRIB_HDR.NonresidentFlag], 1
seg000:057B jz check_more_data
seg000:057F jmp disk_read_error
seg000:0582 ; ---------------------------------------------------------------------------
seg000:0582
seg000:0582 check_more_data:
seg000:0582 cmp ecx, 0
seg000:0586 jnz read_more_data
seg000:058A popad
seg000:058C nop
seg000:058D pop ds
seg000:058E pop es
seg000:058F retn
seg000:0590 ; ---------------------------------------------------------------------------
seg000:0590
seg000:0590 read_more_data:
seg000:0590 push ebx
seg000:0592 push eax
seg000:0594 push ecx
seg000:0596 push edi
seg000:0598 push es
seg000:0599 call GetLcnOfAttrDataVcn
seg000:059C mov edx, ecx
seg000:059F pop es
seg000:05A0 pop edi
seg000:05A2 pop ecx
seg000:05A4 cmp ecx, edx
seg000:05A7 jge @@1
seg000:05AB mov edx, ecx
seg000:05AE
seg000:05AE @@1:
seg000:05AE call ReadDiskClusters
seg000:05B1 sub ecx, edx
seg000:05B4 mov ebx, edx
seg000:05B7 mov eax, edx
seg000:05BA movzx edx, ds:NtfsBpbEbpb.SectorsPerCluster
seg000:05C0 mul edx
seg000:05C3 movzx edx, ds:NtfsBpbEbpb.BytesPerSector
seg000:05C9 mul edx
seg000:05CC add edi, eax
seg000:05CF pop eax
seg000:05D1 add eax, ebx
seg000:05D4 pop ebx
seg000:05D6 jmp short check_more_data
seg000:05D6 ReadAttribDataClusters endp
seg000:05D6
seg000:05D8
seg000:05D8 ; ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ S U B R O U T I N E ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦
seg000:05D8
seg000:05D8 ; Description:
seg000:05D8 ;
seg000:05D8 ; Reads the specified number of sectors from the
seg000:05D8 ; specified virtual sector number from the specified
seg000:05D8 ; attribute's data. The attribute must be non-resident.
seg000:05D8 ;
seg000:05D8 ; Arguments:
seg000:05D8 ;
seg000:05D8 ; DS:EBX - Pointer to the attribute's standard
seg000:05D8 ; attribute header. The attribute must be
seg000:05D8 ; non-resident.
seg000:05D8 ;
seg000:05D8 ; EAX - Virtual sector number to read from.
seg000:05D8 ;
seg000:05D8 ; ECX - Number of sectors to read.
seg000:05D8 ;
seg000:05D8 ; ES:EDI - Memory buffer for the attribute's data to
seg000:05D8 ; be read.
seg000:05D8 ;
seg000:05D8 ; Returns:
seg000:05D8 ;
seg000:05D8 ; (No return value. Errors produce a fatal error
seg000:05D8 ; display message.)
seg000:05D8 ;
seg000:05D8 ; Preserves/modifies:
seg000:05D8 ;
seg000:05D8 ; Preserves 32-bit GP registers, DS, ES.
seg000:05D8
seg000:05D8 ReadAttribDataSectors proc far
seg000:05D8 push es
seg000:05D9 push ds
seg000:05DA pushad
seg000:05DC cmp [ebx+STD_ATTRIB_HDR.NonresidentFlag], 1
seg000:05E1 jz check_more_data
seg000:05E5 jmp disk_read_error
seg000:05E8 ; ---------------------------------------------------------------------------
seg000:05E8
seg000:05E8 check_more_data:
seg000:05E8 cmp ecx, 0
seg000:05EC jnz read_more_data
seg000:05F0 popad
seg000:05F2 nop
seg000:05F3 pop ds
seg000:05F4 pop es
seg000:05F5 retn
seg000:05F6 ; ---------------------------------------------------------------------------
seg000:05F6
seg000:05F6 read_more_data:
seg000:05F6 push ebx
seg000:05F8 push eax
seg000:05FA push ecx
seg000:05FC push edi
seg000:05FE push es
seg000:05FF push ecx
seg000:0601 xor edx, edx
seg000:0604 movzx ecx, ds:NtfsBpbEbpb.SectorsPerCluster
seg000:060A div ecx
seg000:060D push edx
seg000:060F call GetLcnOfAttrDataVcn
seg000:0612 movzx ebx, ds:NtfsBpbEbpb.SectorsPerCluster
seg000:0618 mul ebx
seg000:061B pop edx
seg000:061D add eax, edx
seg000:0620 push eax
seg000:0622 movzx eax, ds:NtfsBpbEbpb.SectorsPerCluster
seg000:0628 mul ecx
seg000:062B mov edx, eax
seg000:062E pop eax
seg000:0630 pop ecx
seg000:0632 pop es
seg000:0633 pop edi
seg000:0635 pop ecx
seg000:0637 cmp ecx, edx
seg000:063A jge @@1
seg000:063E mov edx, ecx
seg000:0641
seg000:0641 @@1:
seg000:0641 mov ds:NtfsBpbEbpb.LsnToRead, eax
seg000:0645 mov ds:NtfsBpbEbpb.NoOfSectorsToRead, dx
seg000:0649 push es
seg000:064A push ds
seg000:064B pushad
seg000:064D mov bx, di
seg000:064F and bx, 0Fh
seg000:0652 mov ax, es
seg000:0654 shr edi, 4
seg000:0658 add ax, di
seg000:065A push ax
seg000:065B pop es
seg000:065C call ReadDiskSectors
seg000:065F popad
seg000:0661 nop
seg000:0662 pop ds
seg000:0663 pop es
seg000:0664 sub ecx, edx
seg000:0667 mov ebx, edx
seg000:066A mov eax, edx
seg000:066D movzx edx, ds:NtfsBpbEbpb.BytesPerSector
seg000:0673 mul edx
seg000:0676 add edi, eax
seg000:0679 pop eax
seg000:067B add eax, ebx
seg000:067E pop ebx
seg000:0680 jmp check_more_data
seg000:0680 ReadAttribDataSectors endp
seg000:0680
seg000:0683
seg000:0683 ; ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ S U B R O U T I N E ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦
seg000:0683
seg000:0683 ; Description:
seg000:0683 ;
seg000:0683 ; Restores the given file record segment from fixups
seg000:0683 ; in the record's update sequence array.
seg000:0683 ;
seg000:0683 ; Arguments:
seg000:0683 ;
seg000:0683 ; DS:EDI - Pointer to the file record segment.
seg000:0683 ;
seg000:0683 ; Returns:
seg000:0683 ;
seg000:0683 ; (No return value. Errors produce a fatal error
seg000:0683 ; display message.)
seg000:0683 ;
seg000:0683 ; Preserves/modifies:
seg000:0683 ;
seg000:0683 ; Preserves 32-bit GP registers, DS, ES.
seg000:0683
seg000:0683 RestoreRecordFixups proc near
seg000:0683 push es
seg000:0684 push ds
seg000:0685 pushad
seg000:0687 movzx ebx, es:[edi+NTFS_FILE_RECORD.UpdateSequenceOffset]
seg000:068E movzx ecx, es:[edi+NTFS_FILE_RECORD.UpdateSequenceSize]
seg000:0695 or ecx, ecx
seg000:0698 jz disk_read_error
seg000:069C add ebx, edi
seg000:069F add ebx, 2
seg000:06A3 add edi, 1FEh
seg000:06AA dec ecx
seg000:06AC
seg000:06AC loop:
seg000:06AC or ecx, ecx
seg000:06AF jz done
seg000:06B3 mov ax, es:[ebx]
seg000:06B7 mov es:[edi], ax
seg000:06BB add ebx, 2
seg000:06BF add edi, 200h
seg000:06C6 dec ecx
seg000:06C8 jmp short loop
seg000:06CA ; ---------------------------------------------------------------------------
seg000:06CA
seg000:06CA done:
seg000:06CA popad
seg000:06CC nop
seg000:06CD pop ds
seg000:06CE pop es
seg000:06CF retn
seg000:06CF RestoreRecordFixups endp
seg000:06CF
seg000:06D0
seg000:06D0 ; ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ S U B R O U T I N E ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦
seg000:06D0
seg000:06D0 ; Description:
seg000:06D0 ;
seg000:06D0 ; Initializes a data structure that is used for
seg000:06D0 ; accessing the contents of the MFT (i.e. file records,
seg000:06D0 ; stored in the $MFT file's unnamed $DATA attribute
seg000:06D0 ; stream). The structure contains the $MFT base file
seg000:06D0 ; record segment, a file record segment buffer for use
seg000:06D0 ; in reading other $MFT file record segments (also
seg000:06D0 ; known as record extents), and a run-list describing
seg000:06D0 ; the location and size of each fragment of every file
seg000:06D0 ; record segment that makes up the $MFT file record
seg000:06D0 ; (i.e. the base file record and all file record
seg000:06D0 ; extents).
seg000:06D0 ;
seg000:06D0 ; Arguments:
seg000:06D0 ;
seg000:06D0 ; (None)
seg000:06D0 ;
seg000:06D0 ; Returns:
seg000:06D0 ;
seg000:06D0 ; (No return value. Errors produce a fatal error
seg000:06D0 ; display message.)
seg000:06D0 ;
seg000:06D0 ; Preserves/modifies:
seg000:06D0 ;
seg000:06D0 ; Preserves 32-bit GP registers, DS, ES.
seg000:06D0
seg000:06D0 MftFrInitialize proc near
seg000:06D0 push es
seg000:06D1 push ds
seg000:06D2 pushad
seg000:06D4 mov eax, 1
seg000:06DA mov ds:MftFrsCount, eax
seg000:06DE mov eax, ds:pMftBfrs
seg000:06E2 add eax, ds:BytesPerFrs
seg000:06E7 mov ds:pMftFrInfo, eax
seg000:06EB add eax, ds:BytesPerFrs
seg000:06F0 mov ds:pMftFrInfoEnd, eax
seg000:06F4 mov eax, dword ptr ds:NtfsBpbEbpb.LcnOfMftBfrs
seg000:06F8 movzx ebx, ds:NtfsBpbEbpb.SectorsPerCluster
seg000:06FE mul ebx
seg000:0701 mov ebx, ds:pMftFrInfoEnd
seg000:0706 mov [bx], eax
seg000:0709 mov ds:NtfsBpbEbpb.LsnToRead, eax
seg000:070D add bx, 4
seg000:0710 mov eax, ds:SectorsPerFrs
seg000:0714 mov [bx], eax
seg000:0717 mov ds:NtfsBpbEbpb.NoOfSectorsToRead, ax
seg000:071A add bx, 4
seg000:071D mov ds:pMftFrInfoEnd, ebx
seg000:0722 mov ebx, ds:pMftBfrs
seg000:0727 push ds
seg000:0728 pop es
seg000:0729 call ReadDiskSectors
seg000:072C mov edi, ebx
seg000:072F call RestoreRecordFixups
seg000:0732 mov eax, ds:pMftBfrs
seg000:0736 mov ebx, $ATTRIBUTE_LIST
seg000:073C mov ecx, 0
seg000:0742 mov edx, 0
seg000:0748 call FindAttribute
seg000:074B or eax, eax
seg000:074E jz return
seg000:0752 mov ebx, eax
seg000:0755 push ds
seg000:0756 pop es
seg000:0757 mov edi, ds:pAttribListData
seg000:075C call GetAttributeData
seg000:075F mov ebx, ds:pAttribListData
seg000:0764
seg000:0764 find_first_data:
seg000:0764 cmp [bx+STD_ATTRIB_HDR.Type], $DATA
seg000:076B jz find_next_data
seg000:076F add bx, word ptr [bx+STD_ATTRIB_HDR.Length]
seg000:0772 jmp short find_first_data
seg000:0774 ; ---------------------------------------------------------------------------
seg000:0774
seg000:0774 add_segment_to_runlist:
seg000:0774 push ebx
seg000:0776 mov eax, dword ptr [bx+ATTRIB_LIST_ENTRY.BaseFileReference]
seg000:077A mul ds:SectorsPerFrs
seg000:077F push eax
seg000:0781 xor edx, edx
seg000:0784 movzx ebx, ds:NtfsBpbEbpb.SectorsPerCluster
seg000:078A div ebx
seg000:078D push edx
seg000:078F call GetLcnOfMftVcn
seg000:0792 or eax, eax
seg000:0795 jz disk_read_error
seg000:0799 mov ecx, ds:SectorsPerFrs
seg000:079E movzx ebx, ds:NtfsBpbEbpb.SectorsPerCluster
seg000:07A4 mul ebx
seg000:07A7 pop edx
seg000:07A9 add eax, edx
seg000:07AC mov ebx, ds:pMftFrInfoEnd
seg000:07B1 mov [bx], eax
seg000:07B4 add bx, 4
seg000:07B7 movzx eax, ds:NtfsBpbEbpb.SectorsPerCluster
seg000:07BD sub eax, edx
seg000:07C0 cmp eax, ecx
seg000:07C3 jbe @@1
seg000:07C7 mov eax, ecx
seg000:07CA
seg000:07CA @@1:
seg000:07CA mov [bx], eax
seg000:07CD
seg000:07CD check_segment_is_complete:
seg000:07CD sub ecx, eax
seg000:07D0 pop edx
seg000:07D2 jz segment_is_complete
seg000:07D6 add eax, edx
seg000:07D9 push eax
seg000:07DB xor edx, edx
seg000:07DE movzx ebx, ds:NtfsBpbEbpb.SectorsPerCluster
seg000:07E4 div ebx
seg000:07E7 push ecx
seg000:07E9 call GetLcnOfMftVcn
seg000:07EC pop ecx
seg000:07EE or eax, eax
seg000:07F1 jz disk_read_error
seg000:07F5 movzx ebx, ds:NtfsBpbEbpb.SectorsPerCluster
seg000:07FB mul ebx
seg000:07FE mov ebx, ds:pMftFrInfoEnd
seg000:0803 mov edx, [bx]
seg000:0806 add bx, 4
seg000:0809 add edx, [bx]
seg000:080C cmp edx, eax
seg000:080F jnz fragment_is_noncontiguous
seg000:0813 movzx eax, ds:NtfsBpbEbpb.SectorsPerCluster
seg000:0819 cmp eax, ecx
seg000:081C jbe @@2
seg000:0820 mov eax, ecx
seg000:0823
seg000:0823 @@2:
seg000:0823 add [bx], eax
seg000:0826 jmp short check_segment_is_complete
seg000:0828 ; ---------------------------------------------------------------------------
seg000:0828
seg000:0828 fragment_is_noncontiguous:
seg000:0828 add bx, 4
seg000:082B mov ds:pMftFrInfoEnd, ebx
seg000:0830 mov [bx], eax
seg000:0833 add bx, 4
seg000:0836 movzx eax, ds:NtfsBpbEbpb.SectorsPerCluster
seg000:083C cmp eax, ecx
seg000:083F jbe @@3
seg000:0843 mov eax, ecx
seg000:0846
seg000:0846 @@3:
seg000:0846 mov [bx], eax
seg000:0849 jmp short check_segment_is_complete
seg000:084B ; ---------------------------------------------------------------------------
seg000:084B
seg000:084B segment_is_complete:
seg000:084B add bx, 4
seg000:084E inc ds:MftFrsCount
seg000:0853 mov ds:pMftFrInfoEnd, ebx
seg000:0858 pop ebx
seg000:085A
seg000:085A find_next_data:
seg000:085A add bx, word ptr [bx+STD_ATTRIB_HDR.Length]
seg000:085D cmp [bx+STD_ATTRIB_HDR.Type], $DATA
seg000:0864 jz add_segment_to_runlist
seg000:0868
seg000:0868 return:
seg000:0868 popad
seg000:086A nop
seg000:086B pop ds
seg000:086C pop es
seg000:086D retn
seg000:086D MftFrInitialize endp
seg000:086D
seg000:086E
seg000:086E ; ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ S U B R O U T I N E ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦
seg000:086E
seg000:086E ; Description:
seg000:086E ;
seg000:086E ; Translates the specified virtual cluster number in
seg000:086E ; the MFT to its corresponding logical cluster number.
seg000:086E ; Additionally reports the number of contiguous
seg000:086E ; clusters available at this logical cluster.
seg000:086E ;
seg000:086E ; Arguments:
seg000:086E ;
seg000:086E ; EAX - Virtual cluster number in the MFT.
seg000:086E ;
seg000:086E ; Returns:
seg000:086E ;
seg000:086E ; EAX - The logical cluster number corresponding to
seg000:086E ; the specified virtual cluster number in the
seg000:086E ; MFT. If the virtual cluster number is invalid
seg000:086E ; then EAX is zero.
seg000:086E ; (Errors produce a fatal error display message.)
seg000:086E ;
seg000:086E ; ECX - The number of contiguous clusters available at
seg000:086E ; this logical cluster. (Only valid if the
seg000:086E ; virtual cluster number was valid.)
seg000:086E ;
seg000:086E ; Preserves/modifies:
seg000:086E ;
seg000:086E ; (No explicit preservations)
seg000:086E
seg000:086E GetLcnOfMftVcn proc near
seg000:086E mov edx, eax
seg000:0871 mov ecx, ds:MftFrsCount
seg000:0876 mov esi, ds:pMftFrInfo
seg000:087B add esi, ds:BytesPerFrs
seg000:0880
seg000:0880 search_next_segment:
seg000:0880 push edx
seg000:0882 push ecx
seg000:0884 push edx
seg000:0886 mov ebx, ds:pMftFrInfo
seg000:088B mov edi, ds:SectorsPerFrs
seg000:0890
seg000:0890 read_segment_fragment:
seg000:0890 mov eax, [si]
seg000:0893 mov ds:NtfsBpbEbpb.LsnToRead, eax
seg000:0897 add si, 4
seg000:089A mov eax, [si]
seg000:089D mov ds:NtfsBpbEbpb.NoOfSectorsToRead, ax
seg000:08A0 add si, 4
seg000:08A3 push ds
seg000:08A4 pop es
seg000:08A5 call ReadDiskSectors
seg000:08A8 sub edi, eax
seg000:08AB jz check_record_segment
seg000:08AF mul ds:NtfsBpbEbpb.BytesPerSector
seg000:08B3 add bx, ax
seg000:08B5 jmp short read_segment_fragment
seg000:08B7 ; ---------------------------------------------------------------------------
seg000:08B7
seg000:08B7 check_record_segment:
seg000:08B7 mov edi, ds:pMftFrInfo
seg000:08BC push ds
seg000:08BD pop es
seg000:08BE call RestoreRecordFixups
seg000:08C1 mov eax, ds:pMftFrInfo
seg000:08C5 mov ebx, $DATA
seg000:08CB mov ecx, 0
seg000:08D1 mov edx, ecx
seg000:08D4 call FindAttribute
seg000:08D7 or eax, eax
seg000:08DA jz disk_read_error
seg000:08DE mov ebx, eax
seg000:08E1 pop eax
seg000:08E3 push esi
seg000:08E5 call GetLcnOfAttrDataVcn
seg000:08E8 pop esi
seg000:08EA or eax, eax
seg000:08ED jz not_found_in_segment
seg000:08F1 pop ebx
seg000:08F3 pop ebx
seg000:08F5 retn
seg000:08F6 ; ---------------------------------------------------------------------------
seg000:08F6
seg000:08F6 not_found_in_segment:
seg000:08F6 pop ecx
seg000:08F8 pop edx
seg000:08FA loop search_next_segment
seg000:08FC xor eax, eax
seg000:08FF retn
seg000:08FF GetLcnOfMftVcn endp
seg000:08FF
seg000:0900
seg000:0900 ; ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ S U B R O U T I N E ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦
seg000:0900
seg000:0900 ; Description:
seg000:0900 ;
seg000:0900 ; Reads the specified number of sectors from the
seg000:0900 ; specified virtual sector number in the MFT.
seg000:0900 ;
seg000:0900 ; Arguments:
seg000:0900 ;
seg000:0900 ; EAX - Virtual sector number of the MFT data to read.
seg000:0900 ;
seg000:0900 ; ECX - Number of sectors of the MFT data to read.
seg000:0900 ;
seg000:0900 ; ES:EDI - Memory buffer for the sectors to be read.
seg000:0900 ;
seg000:0900 ; Returns:
seg000:0900 ;
seg000:0900 ; (No return value. Errors produce a fatal error
seg000:0900 ; display message.)
seg000:0900 ;
seg000:0900 ; Preserves/modifies:
seg000:0900 ;
seg000:0900 ; Preserves 32-bit GP registers, DS, ES.
seg000:0900
seg000:0900 GetMftData proc near
seg000:0900 push es
seg000:0901 push ds
seg000:0902 pushad
seg000:0904
seg000:0904 read_more_data:
seg000:0904 push eax
seg000:0906 push ecx
seg000:0908 xor edx, edx
seg000:090B movzx ebx, ds:NtfsBpbEbpb.SectorsPerCluster
seg000:0911 div ebx
seg000:0914 push edx
seg000:0916 push edi
seg000:0918 call GetLcnOfMftVcn
seg000:091B pop edi
seg000:091D or eax, eax
seg000:0920 jz disk_read_error
seg000:0924 movzx ebx, ds:NtfsBpbEbpb.SectorsPerCluster
seg000:092A mul ebx
seg000:092D pop edx
seg000:092F add eax, edx
seg000:0932 mov ds:NtfsBpbEbpb.LsnToRead, eax
seg000:0936 pop ecx
seg000:0938 movzx ebx, ds:NtfsBpbEbpb.SectorsPerCluster
seg000:093E cmp ecx, ebx
seg000:0941 jle @@1
seg000:0945 mov ds:NtfsBpbEbpb.NoOfSectorsToRead, bx
seg000:0949 sub ecx, ebx
seg000:094C pop eax
seg000:094E add eax, ebx
seg000:0951 push eax
seg000:0953 push ecx
seg000:0955 jmp short read_data_sectors
seg000:0957 ; ---------------------------------------------------------------------------
seg000:0957 nop
seg000:0958
seg000:0958 @@1:
seg000:0958 pop eax
seg000:095A add eax, ecx
seg000:095D push eax
seg000:095F mov ds:NtfsBpbEbpb.NoOfSectorsToRead, cx
seg000:0963 mov ecx, 0
seg000:0969 push ecx
seg000:096B
seg000:096B read_data_sectors:
seg000:096B push es
seg000:096C push edi
seg000:096E mov bx, di
seg000:0970 and bx, 0Fh
seg000:0973 mov ax, es
seg000:0975 shr edi, 4
seg000:0979 add ax, di
seg000:097B push ax
seg000:097C pop es
seg000:097D call ReadDiskSectors
seg000:0980 pop edi
seg000:0982 pop es
seg000:0983 add edi, ds:BytesPerCluster
seg000:0988 pop ecx
seg000:098A pop eax
seg000:098C cmp ecx, 0
seg000:0990 jg read_more_data
seg000:0994 popad
seg000:0996 nop
seg000:0997 pop ds
seg000:0998 pop es
seg000:0999 retn
seg000:0999 GetMftData endp
seg000:0999
seg000:099A
seg000:099A ; ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ S U B R O U T I N E ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦
seg000:099A
seg000:099A ; Description:
seg000:099A ;
seg000:099A ; Retrieves the specified file record segment from the
seg000:099A ; MFT.
seg000:099A ;
seg000:099A ; Arguments:
seg000:099A ;
seg000:099A ; EAX - File record number.
seg000:099A ;
seg000:099A ; ES:EDI - Memory buffer for the file record segment.
seg000:099A ;
seg000:099A ; Returns:
seg000:099A ;
seg000:099A ; (No return value)
seg000:099A ;
seg000:099A ; Preserves/modifies:
seg000:099A ;
seg000:099A ; Preserves 32-bit GP registers, DS, ES.
seg000:099A
seg000:099A GetFileRecord proc near
seg000:099A push es
seg000:099B push ds
seg000:099C pushad
seg000:099E mul ds:SectorsPerFrs
seg000:09A3 mov ecx, ds:SectorsPerFrs
seg000:09A8 call GetMftData
seg000:09AB call RestoreRecordFixups
seg000:09AE popad
seg000:09B0 nop
seg000:09B1 pop ds
seg000:09B2 pop es
seg000:09B3 retn
seg000:09B3 GetFileRecord endp
seg000:09B3
seg000:09B4
seg000:09B4 ; ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ S U B R O U T I N E ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦
seg000:09B4
seg000:09B4 ; Description:
seg000:09B4 ;
seg000:09B4 ; Retrieves the specified index allocation entry.
seg000:09B4 ;
seg000:09B4 ; Arguments:
seg000:09B4 ;
seg000:09B4 ; EAX - Index allocation entry number.
seg000:09B4 ;
seg000:09B4 ; Returns:
seg000:09B4 ;
seg000:09B4 ; (No return value)
seg000:09B4 ;
seg000:09B4 ; Preserves/modifies:
seg000:09B4 ;
seg000:09B4 ; Preserves 32-bit GP registers, DS, ES.
seg000:09B4
seg000:09B4 GetIndexAllocEntry proc near
seg000:09B4 push es
seg000:09B5 push ds
seg000:09B6 pushad
seg000:09B8 mul ds:SectorsPerIaEntry
seg000:09BD mov ebx, ds:pIndexAllocHdr
seg000:09C2 mov ecx, ds:SectorsPerIaEntry
seg000:09C7 push ds
seg000:09C8 pop es
seg000:09C9 mov edi, ds:pIndexAllocEntry
seg000:09CE call near ptr ReadAttribDataSectors
seg000:09D1 call RestoreRecordFixups
seg000:09D4 popad
seg000:09D6 nop
seg000:09D7 pop ds
seg000:09D8 pop es
seg000:09D9 retn
seg000:09D9 GetIndexAllocEntry endp
seg000:09D9
seg000:09DA
seg000:09DA ; ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ S U B R O U T I N E ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦
seg000:09DA
seg000:09DA ; Description:
seg000:09DA ;
seg000:09DA ; Checks whether or not the specified index allocation
seg000:09DA ; entry is in use by querying the corresponding bit in
seg000:09DA ; the allocation bitmap.
seg000:09DA ;
seg000:09DA ; Arguments:
seg000:09DA ;
seg000:09DA ; EAX - Index allocation entry number.
seg000:09DA ;
seg000:09DA ; Returns:
seg000:09DA ;
seg000:09DA ; Carry flag is CLEAR if the index allocation entry
seg000:09DA ; is in use. It is SET if NOT in use.
seg000:09DA ;
seg000:09DA ; Preserves/modifies:
seg000:09DA ;
seg000:09DA ; Explicitly preserves EAX, EBX, ECX. No other 32-bit
seg000:09DA ; GP registers modified. No segment registers modified.
seg000:09DA ;
seg000:09DA
seg000:09DA CheckIaEntryIsInUse proc near
seg000:09DA push eax
seg000:09DC push ebx
seg000:09DE push ecx
seg000:09E0 mov ebx, ds:pBitmapData
seg000:09E5 mov ecx, eax
seg000:09E8 shr eax, 3
seg000:09EC and ecx, 7
seg000:09F0 add ebx, eax
seg000:09F3 mov eax, 1
seg000:09F9 shl eax, cl
seg000:09FC test [ebx], al
seg000:09FF jz not_in_use
seg000:0A03 clc
seg000:0A04 jmp short return
seg000:0A06 ; ---------------------------------------------------------------------------
seg000:0A06 nop
seg000:0A07
seg000:0A07 not_in_use:
seg000:0A07 stc
seg000:0A08
seg000:0A08 return:
seg000:0A08 pop ecx
seg000:0A0A pop ebx
seg000:0A0C pop eax
seg000:0A0E retn
seg000:0A0E CheckIaEntryIsInUse endp
seg000:0A0E
seg000:0A0F
seg000:0A0F ; ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ S U B R O U T I N E ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦
seg000:0A0F
seg000:0A0F ; Description:
seg000:0A0F ;
seg000:0A0F ; Translates the specified virtual cluster number in
seg000:0A0F ; the specified attribute's data to its corresponding
seg000:0A0F ; logical cluster number. Additionally reports the
seg000:0A0F ; number of contiguous clusters available at this
seg000:0A0F ; logical cluster. The attribute must be non-resident.
seg000:0A0F ;
seg000:0A0F ; Arguments:
seg000:0A0F ;
seg000:0A0F ; DS:EBX - Pointer to the attribute's standard
seg000:0A0F ; attribute header. The attribute must be
seg000:0A0F ; non-resident.
seg000:0A0F ;
seg000:0A0F ; EAX - Virtual cluster number in the attribute's data.
seg000:0A0F ;
seg000:0A0F ; Returns:
seg000:0A0F ;
seg000:0A0F ; EAX - The logical cluster number corresponding to
seg000:0A0F ; the specified virtual cluster number in the
seg000:0A0F ; attribute's data. If the virtual cluster
seg000:0A0F ; number is invalid then EAX is zero.
seg000:0A0F ;
seg000:0A0F ; ECX - The number of contiguous clusters available at
seg000:0A0F ; this logical cluster. (Only valid if the
seg000:0A0F ; virtual cluster number was valid.)
seg000:0A0F ;
seg000:0A0F ; Preserves/modifies:
seg000:0A0F ;
seg000:0A0F ; (No explicit preservations)
seg000:0A0F
seg000:0A0F GetLcnOfAttrDataVcn proc near
seg000:0A0F cmp [ebx+STD_ATTRIB_HDR.NonresidentFlag], 1
seg000:0A14 jz is_non_resident
seg000:0A18 sub eax, eax
seg000:0A1B retn
seg000:0A1C ; ---------------------------------------------------------------------------
seg000:0A1C
seg000:0A1C is_non_resident:
seg000:0A1C lea esi, [ebx+(size STD_ATTRIB_HDR)]
seg000:0A21 mov edx, dword ptr [esi+ATTRIB_HDR_NONRESIDENT.LastVcn]
seg000:0A26 cmp eax, edx
seg000:0A29 ja vcn_out_of_range
seg000:0A2D mov edx, dword ptr [esi+ATTRIB_HDR_NONRESIDENT.StartingVcn]
seg000:0A31 cmp eax, edx
seg000:0A34 jnb @@1
seg000:0A38
seg000:0A38 vcn_out_of_range:
seg000:0A38 sub eax, eax
seg000:0A3B retn
seg000:0A3C ; ---------------------------------------------------------------------------
seg000:0A3C
seg000:0A3C @@1:
seg000:0A3C add bx, [esi+ATTRIB_HDR_NONRESIDENT.DataRunsOffset]
seg000:0A40 sub esi, esi
seg000:0A43
seg000:0A43 next_data_run:
seg000:0A43 cmp byte ptr [ebx], 0
seg000:0A47 jz error_end_of_data_runs
seg000:0A4B call GetDataRunOffset
seg000:0A4E add esi, ecx
seg000:0A51 call GetDataRunLength
seg000:0A54 add ecx, edx
seg000:0A57 cmp eax, ecx
seg000:0A5A jl found_data_run_for_vcn
seg000:0A5E mov edx, ecx
seg000:0A61 push eax
seg000:0A63 movzx ecx, byte ptr [ebx]
seg000:0A68 mov eax, ecx
seg000:0A6B and eax, 0Fh
seg000:0A6F shr ecx, 4
seg000:0A73 add ebx, ecx
seg000:0A76 add ebx, eax
seg000:0A79 inc ebx
seg000:0A7B pop eax
seg000:0A7D jmp short next_data_run
seg000:0A7F ; ---------------------------------------------------------------------------
seg000:0A7F
seg000:0A7F found_data_run_for_vcn:
seg000:0A7F sub ecx, eax
seg000:0A82 sub eax, edx
seg000:0A85 add eax, esi
seg000:0A88 retn
seg000:0A89 ; ---------------------------------------------------------------------------
seg000:0A89
seg000:0A89 error_end_of_data_runs:
seg000:0A89 sub eax, eax
seg000:0A8C retn
seg000:0A8C GetLcnOfAttrDataVcn endp
seg000:0A8C
seg000:0A8D
seg000:0A8D ; ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ S U B R O U T I N E ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦
seg000:0A8D
seg000:0A8D ; Description:
seg000:0A8D ;
seg000:0A8D ; Retrieves the data run length value from the
seg000:0A8D ; given data run.
seg000:0A8D ;
seg000:0A8D ; Arguments:
seg000:0A8D ;
seg000:0A8D ; DS:EBX - Pointer to the data run.
seg000:0A8D ;
seg000:0A8D ; Returns:
seg000:0A8D ;
seg000:0A8D ; ECX - Data run length value. If the value could not
seg000:0A8D ; be retrieved then ECX is zero.
seg000:0A8D ;
seg000:0A8D ; Preserves/modifies:
seg000:0A8D ;
seg000:0A8D ; Explicitly preserves EBX, EDX. No other 32-bit
seg000:0A8D ; GP registers modified. No segment registers modified.
seg000:0A8D ;
seg000:0A8D
seg000:0A8D GetDataRunLength proc near
seg000:0A8D sub ecx, ecx
seg000:0A90 mov cl, [ebx]
seg000:0A93 and cl, 0Fh
seg000:0A96 cmp ecx, 0
seg000:0A9A jnz get_length_value
seg000:0A9E sub ecx, ecx
seg000:0AA1 retn
seg000:0AA2 ; ---------------------------------------------------------------------------
seg000:0AA2
seg000:0AA2 get_length_value:
seg000:0AA2 push ebx
seg000:0AA4 push edx
seg000:0AA6 add ebx, ecx
seg000:0AA9 movsx edx, byte ptr [ebx]
seg000:0AAE dec ecx
seg000:0AB0 dec ebx
seg000:0AB2
seg000:0AB2 loop:
seg000:0AB2 cmp ecx, 0
seg000:0AB6 jz have_length_value
seg000:0ABA shl edx, 8
seg000:0ABE mov dl, [ebx]
seg000:0AC1 dec ebx
seg000:0AC3 dec ecx
seg000:0AC5 jmp short loop
seg000:0AC7 ; ---------------------------------------------------------------------------
seg000:0AC7
seg000:0AC7 have_length_value:
seg000:0AC7 mov ecx, edx
seg000:0ACA pop edx
seg000:0ACC pop ebx
seg000:0ACE retn
seg000:0ACE GetDataRunLength endp
seg000:0ACE
seg000:0ACF
seg000:0ACF ; ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ S U B R O U T I N E ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦
seg000:0ACF
seg000:0ACF ; Description:
seg000:0ACF ;
seg000:0ACF ; Retrieves the data run offset value from the
seg000:0ACF ; given data run.
seg000:0ACF ;
seg000:0ACF ; Arguments:
seg000:0ACF ;
seg000:0ACF ; DS:EBX - Pointer to the data run.
seg000:0ACF ;
seg000:0ACF ; Returns:
seg000:0ACF ;
seg000:0ACF ; ECX - Data run offset value. If the value could not
seg000:0ACF ; be retrieved then ECX is zero.
seg000:0ACF ;
seg000:0ACF ; Preserves/modifies:
seg000:0ACF ;
seg000:0ACF ; Explicitly preserves EBX, EDX. No other 32-bit
seg000:0ACF ; GP registers modified. No segment registers modified.
seg000:0ACF ;
seg000:0ACF
seg000:0ACF GetDataRunOffset proc near
seg000:0ACF push ebx
seg000:0AD1 push edx
seg000:0AD3 sub edx, edx
seg000:0AD6 mov dl, [ebx]
seg000:0AD9 and edx, 0Fh
seg000:0ADD sub ecx, ecx
seg000:0AE0 mov cl, [ebx]
seg000:0AE3 shr cl, 4
seg000:0AE6 cmp ecx, 0
seg000:0AEA jnz get_offset_value
seg000:0AEE sub ecx, ecx
seg000:0AF1 pop edx
seg000:0AF3 pop ebx
seg000:0AF5 retn
seg000:0AF6 ; ---------------------------------------------------------------------------
seg000:0AF6
seg000:0AF6 get_offset_value:
seg000:0AF6 add ebx, edx
seg000:0AF9 add ebx, ecx
seg000:0AFC movsx edx, byte ptr [ebx]
seg000:0B01 dec ecx
seg000:0B03 dec ebx
seg000:0B05
seg000:0B05 loop:
seg000:0B05 cmp ecx, 0
seg000:0B09 jz have_offset_value
seg000:0B0D shl edx, 8
seg000:0B11 mov dl, [ebx]
seg000:0B14 dec ebx
seg000:0B16 dec ecx
seg000:0B18 jmp short loop
seg000:0B1A ; ---------------------------------------------------------------------------
seg000:0B1A
seg000:0B1A have_offset_value:
seg000:0B1A mov ecx, edx
seg000:0B1D pop edx
seg000:0B1F pop ebx
seg000:0B21 retn
seg000:0B21 GetDataRunOffset endp
seg000:0B21
seg000:0B22
seg000:0B22 ; ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ S U B R O U T I N E ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦
seg000:0B22
seg000:0B22 ; Description:
seg000:0B22 ;
seg000:0B22 ; Converts the given unicode string to lowercase.
seg000:0B22 ;
seg000:0B22 ; Arguments:
seg000:0B22 ;
seg000:0B22 ; DS:ESI - Pointer to the unicode string.
seg000:0B22 ;
seg000:0B22 ; ECX - Number of characters in the string.
seg000:0B22 ;
seg000:0B22 ; Returns:
seg000:0B22 ;
seg000:0B22 ; (No return value)
seg000:0B22 ;
seg000:0B22 ; Preserves/modifies:
seg000:0B22 ;
seg000:0B22 ; Explicitly preserves ECX, ESI. No other 32-bit
seg000:0B22 ; GP registers modified. No segment registers modified.
seg000:0B22 ;
seg000:0B22
seg000:0B22 UnicodeStringLwr proc near
seg000:0B22 or ecx, ecx
seg000:0B25 jnz @@1
seg000:0B29 retn
seg000:0B2A ; ---------------------------------------------------------------------------
seg000:0B2A
seg000:0B2A @@1:
seg000:0B2A push ecx
seg000:0B2C push esi
seg000:0B2E
seg000:0B2E loop:
seg000:0B2E cmp word ptr [esi], 'a'
seg000:0B32 jl @@2
seg000:0B36 cmp word ptr [esi], 'z'
seg000:0B3A jg @@2
seg000:0B3E sub word ptr [esi], 20h
seg000:0B42
seg000:0B42 @@2:
seg000:0B42 add esi, 2
seg000:0B46 loop loop
seg000:0B48 pop esi
seg000:0B4A pop ecx
seg000:0B4C retn
seg000:0B4C UnicodeStringLwr endp
seg000:0B4C
seg000:0B4D
seg000:0B4D ; ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ S U B R O U T I N E ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦
seg000:0B4D
seg000:0B4D ; Description:
seg000:0B4D ;
seg000:0B4D ; Finds the specified file's index entry in the
seg000:0B4D ; root directory index.
seg000:0B4D ;
seg000:0B4D ; Arguments:
seg000:0B4D ;
seg000:0B4D ; DS:EAX - Pointer to the filename.
seg000:0B4D ;
seg000:0B4D ; ECX - Length of the filename.
seg000:0B4D ;
seg000:0B4D ; Returns:
seg000:0B4D ;
seg000:0B4D ; DS:EAX - Pointer to the file's index entry. If the
seg000:0B4D ; file index entry was not found, EAX is zero.
seg000:0B4D ;
seg000:0B4D ; Preserves/modifies:
seg000:0B4D ;
seg000:0B4D ; (No explicit preservations)
seg000:0B4D
seg000:0B4D FindFileInRootdIndex proc near
seg000:0B4D push eax
seg000:0B4F push ecx
seg000:0B51 mov edx, eax
seg000:0B54 mov eax, ds:pRootdIndexRootHdr
seg000:0B58 lea ebx, [eax+(size STD_ATTRIB_HDR)]
seg000:0B5D add ax, [ebx+ATTRIB_HDR_RESIDENT.AttributeOffset]
seg000:0B61 lea eax, [eax+(size INDEX_ROOT_ATTRIB)]
seg000:0B66 mov ebx, edx
seg000:0B69 call FindFileIndexEntry
seg000:0B6C or eax, eax
seg000:0B6F jz not_found_in_index_root
seg000:0B73 pop ecx
seg000:0B75 pop ecx
seg000:0B77 retn
seg000:0B78 ; ---------------------------------------------------------------------------
seg000:0B78
seg000:0B78 not_found_in_index_root:
seg000:0B78 mov eax, ds:pIndexAllocHdr
seg000:0B7C or eax, eax
seg000:0B7F jnz search_in_index_allocation
seg000:0B83 pop ecx
seg000:0B85 pop ecx
seg000:0B87 xor eax, eax
seg000:0B8A retn
seg000:0B8B ; ---------------------------------------------------------------------------
seg000:0B8B
seg000:0B8B search_in_index_allocation:
seg000:0B8B mov edx, ds:pIndexAllocHdr
seg000:0B90 lea edx, [edx+(size STD_ATTRIB_HDR)]
seg000:0B95 mov eax, dword ptr [edx+ATTRIB_HDR_NONRESIDENT.LastVcn]
seg000:0B9A inc eax
seg000:0B9C mov ebx, ds:BytesPerCluster
seg000:0BA1 mul ebx
seg000:0BA4 xor edx, edx
seg000:0BA7 div ds:SizeOfIaEntry
seg000:0BAC push eax
seg000:0BAE
seg000:0BAE search_next_index_buffer:
seg000:0BAE pop eax
seg000:0BB0 or eax, eax
seg000:0BB3 jz not_found_in_index_allocation
seg000:0BB7 dec eax
seg000:0BB9 push eax
seg000:0BBB call CheckIaEntryIsInUse
seg000:0BBE jb short search_next_index_buffer
seg000:0BC0 call GetIndexAllocEntry
seg000:0BC3 pop edx
seg000:0BC5 pop ecx
seg000:0BC7 pop ebx
seg000:0BC9 push ebx
seg000:0BCB push ecx
seg000:0BCD push edx
seg000:0BCF mov eax, ds:pIndexAllocEntry
seg000:0BD3 lea eax, [eax+(size NTFS_INDEX_RECORD)]
seg000:0BD8 call FindFileIndexEntry
seg000:0BDB or eax, eax
seg000:0BDE jz short search_next_index_buffer
seg000:0BE0 pop ecx
seg000:0BE2 pop ecx
seg000:0BE4 pop ecx
seg000:0BE6 retn
seg000:0BE7 ; ---------------------------------------------------------------------------
seg000:0BE7
seg000:0BE7 not_found_in_index_allocation:
seg000:0BE7 pop ecx
seg000:0BE9 pop ecx
seg000:0BEB xor eax, eax
seg000:0BEE retn
seg000:0BEE FindFileInRootdIndex endp
seg000:0BEE
seg000:0BEF
seg000:0BEF ; ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ S U B R O U T I N E ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦
seg000:0BEF
seg000:0BEF ; Description:
seg000:0BEF ;
seg000:0BEF ; Retrieves the specified directory attribute from
seg000:0BEF ; the root directory file record.
seg000:0BEF ;
seg000:0BEF ; Arguments:
seg000:0BEF ;
seg000:0BEF ; EAX - Directory attribute type.
seg000:0BEF ;
seg000:0BEF ; DS:ECX - Memory buffer for the root directory's
seg000:0BEF ; file record segment containing the specified
seg000:0BEF ; directory attribute's header.
seg000:0BEF ;
seg000:0BEF ; Returns:
seg000:0BEF ;
seg000:0BEF ; DS:EAX - Pointer to the attribute's standard
seg000:0BEF ; attribute header. If the specified
seg000:0BEF ; directory attribute was not found, EAX is
seg000:0BEF ; zero.
seg000:0BEF ;
seg000:0BEF ; Preserves/modifies:
seg000:0BEF ;
seg000:0BEF ; (No explicit preservations)
seg000:0BEF
seg000:0BEF GetRootdAttribHdr proc near
seg000:0BEF push ecx
seg000:0BF1 push eax
seg000:0BF3 mov eax, FILE_ROOT_DIRECTORY
seg000:0BF9 push ds
seg000:0BFA pop es
seg000:0BFB mov edi, ecx
seg000:0BFE call GetFileRecord
seg000:0C01 mov eax, ecx
seg000:0C04 pop ebx
seg000:0C06 push ebx
seg000:0C08 movzx ecx, ds:aI30_length
seg000:0C0E mov edx, offset aI30 ; "$I30"
seg000:0C14 call FindAttribute
seg000:0C17 pop ebx
seg000:0C19 pop ecx
seg000:0C1B or eax, eax
seg000:0C1E jnz return
seg000:0C22 mov eax, ecx
seg000:0C25 mov ecx, ebx
seg000:0C28 push eax
seg000:0C2A push ebx
seg000:0C2C call GetFrsWithAttribType
seg000:0C2F pop ebx
seg000:0C31 pop edi
seg000:0C33 or eax, eax
seg000:0C36 jz return
seg000:0C3A push ds
seg000:0C3B pop es
seg000:0C3C call GetFileRecord
seg000:0C3F mov eax, edi
seg000:0C42 movzx ecx, ds:aI30_length
seg000:0C48 mov edx, offset aI30 ; "$I30"
seg000:0C4E call FindAttribute
seg000:0C51
seg000:0C51 return:
seg000:0C51 retn
seg000:0C51 GetRootdAttribHdr endp
seg000:0C51
seg000:0C52
seg000:0C52 ; ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦ S U B R O U T I N E ¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦¦
seg000:0C52
seg000:0C52 ; Description:
seg000:0C52 ;
seg000:0C52 ; Retrieves the file record number of the file record
seg000:0C52 ; segment containing the specified attribute type.
seg000:0C52 ;
seg000:0C52 ; Arguments:
seg000:0C52 ;
seg000:0C52 ; ECX - Attribute type.
seg000:0C52 ;
seg000:0C52 ; DS:EAX - Pointer to the base file record segment.
seg000:0C52 ;
seg000:0C52 ; Returns:
seg000:0C52 ;
seg000:0C52 ; EAX - File record number of the file record segment
seg000:0C52 ; containing the specified attribute type.
seg000:0C52 ;
seg000:0C52 ; Preserves/modifies:
seg000:0C52 ;
seg000:0C52 ; (No explicit preservations)
seg000:0C52
seg000:0C52 GetFrsWithAttribType proc near
seg000:0C52 push ecx
seg000:0C54 mov ebx, $ATTRIBUTE_LIST
seg000:0C5A mov ecx, 0
seg000:0C60 mov edx, 0
seg000:0C66 call FindAttribute
seg000:0C69 or eax, eax
seg000:0C6C jz no_record_extents_exist
seg000:0C70 mov ebx, eax
seg000:0C73 push ds
seg000:0C74 pop es
seg000:0C75 mov edi, ds:pAttribListData
seg000:0C7A call GetAttributeData
seg000:0C7D push ds
seg000:0C7E pop es
seg000:0C7F mov ebx, ds:pAttribListData
seg000:0C84 pop ecx
seg000:0C86
seg000:0C86 search_next_attribute:
seg000:0C86 cmp es:[bx+ATTRIB_LIST_ENTRY.Type], ecx
seg000:0C8A jz found_attribute
seg000:0C8E cmp es:[bxATTRIB_LIST_ENTRY.Type], -1
seg000:0C93 jz attribute_not_found
seg000:0C97 cmp es:[bx+ATTRIB_LIST_ENTRY.RecordLength], 0
seg000:0C9C jz attribute_not_found
seg000:0CA0 movzx eax, es:[bx+ATTRIB_LIST_ENTRY.RecordLength]
seg000:0CA6 add bx, ax
seg000:0CA8 mov ax, bx
seg000:0CAA and ax, 8000h
seg000:0CAD jz short search_next_attribute
seg000:0CAF mov ax, es
seg000:0CB1 add ax, 800h
seg000:0CB4 mov es, ax
seg000:0CB6 assume es:nothing
seg000:0CB6 and bx, 7FFFh
seg000:0CBA jmp short search_next_attribute
seg000:0CBC ; ---------------------------------------------------------------------------
seg000:0CBC
seg000:0CBC found_attribute:
seg000:0CBC mov eax, dword ptr es:[bx+ATTRIB_LIST_ENTRY.BaseFileReference]
seg000:0CC1 retn
seg000:0CC2 ; ---------------------------------------------------------------------------
seg000:0CC2
seg000:0CC2 no_record_extents_exist:
seg000:0CC2 pop ecx
seg000:0CC4
seg000:0CC4 attribute_not_found:
seg000:0CC4 xor eax, eax
seg000:0CC7 retn
seg000:0CC7 GetFrsWithAttribType endp
seg000:0CC7
seg000:0CC8 ; ---------------------------------------------------------------------------
seg000:0CC8
seg000:0CC8 error_ntldr_missing:
seg000:0CC8 mov al, ds:ntldrIsMissingMsg
seg000:0CCB jmp display_error_message
seg000:0CCE ; ---------------------------------------------------------------------------
seg000:0CCE
seg000:0CCE error_ntldr_compressed:
seg000:0CCE mov al, ds:ntldrIsCompressedMsg
seg000:0CD1 jmp display_error_message
seg000:0CD1 ; ---------------------------------------------------------------------------
seg000:0CD4 align 2000h
seg000:0CD4 seg000 ends
seg000:0CD4
seg000:0CD4
seg000:0CD4 end
FFFFFFFF
FFFFFFFF ; enum ATTRIBUTE_TYPES
FFFFFFFF $ATTRIBUTE_LIST = 20h
FFFFFFFF $DATA = 80h
FFFFFFFF $INDEX_ROOT = 90h
FFFFFFFF $INDEX_ALLOCATION = 0A0h
FFFFFFFF $BITMAP = 0B0h
FFFFFFFF
FFFFFFFF ; ---------------------------------------------------------------------------
FFFFFFFF
FFFFFFFF ; enum NTFS_FILES
FFFFFFFF FILE_ROOT_DIRECTORY = 5
FFFFFFFF
00000000 NTFS_BPB_EBPB struc ; (sizeof=0x51)
00000000 OemId db 8 dup(?) ; char
00000008 BytesPerSector dw ?
0000000A SectorsPerCluster db ?
0000000B NoOfSectorsToRead dw ?
0000000D LsnToRead dd ?
00000011 ExtDiskAccessAvl db ?
00000012 MediaDescriptor db ?
00000013 db ? ; undefined
00000014 db ? ; undefined
00000015 SectorsPerTrack dw ?
00000017 NumberOfHeads dw ?
00000019 PartitionBase dd ?
0000001D ChsLimit dd ?
00000021 DiskNumber db ?
00000022 db ? ; undefined
00000023 db ? ; undefined
00000024 db ? ; undefined
00000025 TotalSectors dq ?
0000002D LcnOfMftBfrs dq ?
00000035 LcnOfMftMirrorBfrs dq ?
0000003D ClustersPerFrs dd ?
00000041 ClustersPerIndexBlock dd ?
00000045 VolumeSerialNumber db 8 dup(?)
0000004D Checksum dd ?
00000051 NTFS_BPB_EBPB ends
00000051
00000000 ; ---------------------------------------------------------------------------
00000000
00000000 NTFS_FILE_RECORD struc ; (sizeof=0x30)
00000000 Magic dd ?
00000004 UpdateSequenceOffset dw ?
00000006 UpdateSequenceSize dw ?
00000008 LogFileSequenceNumber dq ?
00000010 SequenceNumber dw ?
00000012 HardLinkCount dw ?
00000014 FirstAttribOffset dw ?
00000016 Flags dw ?
00000018 RealSize dd ?
0000001C AllocatedSize dd ?
00000020 BfrReference dq ?
00000028 NextAttributeId dw ?
0000002A db ? ; undefined
0000002B db ? ; undefined
0000002C MftRecordNumber dd ?
00000030 NTFS_FILE_RECORD ends
00000030
00000000 ; ---------------------------------------------------------------------------
00000000
00000000 ATTRIB_LIST_ENTRY struc ; (sizeof=0x1A)
00000000 Type dd ?
00000004 RecordLength dw ?
00000006 NameLength db ?
00000007 NameOffset db ?
00000008 StartingVcn dq ?
00000010 BaseFileReference dq ?
00000018 AttributeId dw ?
0000001A ATTRIB_LIST_ENTRY ends
0000001A
00000000 ; ---------------------------------------------------------------------------
00000000
00000000 STD_ATTRIB_HDR struc ; (sizeof=0x10)
00000000 Type dd ?
00000004 Length dd ?
00000008 NonresidentFlag db ?
00000009 NameLength db ?
0000000A NameOffset dw ?
0000000C Flags dw ?
0000000E AttributeId dw ?
00000010 STD_ATTRIB_HDR ends
00000010
00000000 ; ---------------------------------------------------------------------------
00000000
00000000 ATTRIB_HDR_RESIDENT struc ; (sizeof=0x7)
00000000 AttributeLength dd ?
00000004 AttributeOffset dw ?
00000006 IndexedFlag db ?
00000007 ATTRIB_HDR_RESIDENT ends
00000007
00000000 ; ---------------------------------------------------------------------------
00000000
00000000 ATTRIB_HDR_NONRESIDENT struc ; (sizeof=0x30)
00000000 StartingVcn dq ?
00000008 LastVcn dq ?
00000010 DataRunsOffset dw ?
00000012 CompressionUnitSize dw ?
00000014 db ? ; undefined
00000015 db ? ; undefined
00000016 db ? ; undefined
00000017 db ? ; undefined
00000018 AllocatedSize dq ?
00000020 RealSize dq ?
00000028 InitializedDataSize dq ?
00000030 ATTRIB_HDR_NONRESIDENT ends
00000030
00000000 ; ---------------------------------------------------------------------------
00000000
00000000 INDEX_ROOT_ATTRIB struc ; (sizeof=0x10)
00000000 AttributeType dd ?
00000004 CollationRule dd ?
00000008 SizeOfIaEntry dd ?
0000000C ClustersPerIndxRecd db ?
0000000D padding db 3 dup(?)
00000010 INDEX_ROOT_ATTRIB ends
00000010
00000000 ; ---------------------------------------------------------------------------
00000000
00000000 NTFS_INDEX_RECORD struc ; (sizeof=0x18)
00000000 Magic dd ?
00000004 UpdateSequenceOffset dw ?
00000006 UpdateSequenceSize dw ?
00000008 LogFileSequenceNumber dq ?
00000010 VcnInIndexAlloc dq ?
00000018 NTFS_INDEX_RECORD ends
00000018
00000000 ; ---------------------------------------------------------------------------
00000000
00000000 INDEX_HDR struc ; (sizeof=0x10)
00000000 FirstEntryOffset dd ?
00000004 TotalSize dd ?
00000008 AllocatedSize dd ?
0000000C Flags db ?
0000000D padding db 3 dup(?)
00000010 INDEX_HDR ends
00000010
00000000 ; ---------------------------------------------------------------------------
00000000
00000000 INDEX_ENTRY struc ; (sizeof=0x10)
00000000 FileReference dq ?
00000008 IndexEntryLength dw ?
0000000A StreamLength dw ?
0000000C Flags db ?
0000000D padding db 3 dup(?)
00000010 INDEX_ENTRY ends
00000010
00000000 ; ---------------------------------------------------------------------------
00000000
00000000 INDEX_ENTRY_FILENAME struc ; (sizeof=0x43)
00000000 ParentFileReference dq ?
00000008 FileCreationTime dq ?
00000010 LastModificationTime dq ?
00000018 FileRecordLastModTime dq ?
00000020 LastAccessTime dq ?
00000028 AllocatedFileSize dq ?
00000030 RealFileSize dq ?
00000038 FileFlags dq ?
00000040 FileNameLength db ?
00000041 FileNameNamespace db ?
00000042 FileName db ?
00000043 INDEX_ENTRY_FILENAME ends
00000043