; ******************************************************

;       Name: Disk System
;       Author: Peter Kleissner
;       Version: 0.1
;       Date: 17.02.2008 17:11:31
;       last Update: 30.11.2008 13:14:58

;       Forensic Lockdown Software
;       (C) 2008 Vienna Computer Products

; ------------------------------------------------------

;       Access and Management of
;         - FAT file system
;         - NTFS file system
;         - Hard drives
;         - Partitions

; ------------------------------------------------------

;       Exported Functions:
;         - Mount_Boot_Partitions
;         - Load_System_File
;         - Open_File_Callback
;         - Read_File
;         - Seek_File
;         - Overwrite_File

; ******************************************************

[bits 16]                                       ; create a 16 Bit Code
CPU 386                                         ; Assemble instructions up to the 386 instruction set

%include "Module Functions.asm"
%include "Kernel Storage.asm"
%include "Errors.asm"

;%define _Debug

org Disk_System





; Boot Drive Manager Functions
;     Mount_Boot_Partitions
;     Load_System_File
;     Open_File_Callback
;     Read_File
;     Seek_File
;     Overwrite_File


; limitations:
;    - only one file per reading allowed (not multitasking compliant)
;        [only one file handle allowed currently]
;    - only loading whole files
;    - currently only partitions of the boot drive are mounted
;    - currently no raw sector access possible


; ChangeLog:
;    10.07.2007 09:36    removed Open File / Read File functions, integreated into Load System File
;                        removed Handle stack-variable; Boot System Handle is now always accessed
;                        masked out unused stack variables
;    10.07.2007 10:43    Initial Import from MBR-Version
;                        Function Import Mount_Boot_Partition_FAT
;               11:36    Initial Import of NTFS Support from Drive Manager
;               19:23    Added crossover call to NTFS module
;    22.02.2008 00:40    Implementation for Forensic Lockdown Software OS
;    25.11.2008 21:51    Implementation for the Hibernation File Attack
;    26.11.2008 21:08    Out-sourcing disk device driver
;    30.11.2008 14:44    Added Handles back again
;    08.12.2008 11:34    Added Seek File function




; export functions

jmp word Mount_Boot_Partitions
jmp word Load_System_File
jmp word Open_File_Callback
jmp word Read_File
jmp word Seek_File
jmp word Overwrite_File






; define stack variables for both FAT driver and NTFS driver


%define System_Var                      bp

;%define Drive                           System_Var-4
;%define Drive_Pointer                   System_Var-8
%define Drive_Context_Pointer           System_Var-8
;%define Partitions                      System_Var-12
%define Partition_Table                 System_Var-16
;define Handle                          System_Var-20
%define Position                        System_Var-24
%define Temp                            System_Var-28
%define Temp2                           System_Var-32

%define Add_Position                    System_Var-36           ; [NTFS-only]
%define File_Record_48high              System_Var-40           ; [NTFS-only]
%define File_Record                     System_Var-44           ; operating File Record [NTFS-only]
;define Current_File_Record             System_Var-48           ; [NTFS-only]
;define Name_Type                       System_Var-49           ; [NTFS-only, Win32/DOS terminology]


; drive variables [only for standalone version]
;define Sector_Count                    System_Var-53
;define Sector_Number_48high            System_Var-57
;define Sector_Number                   System_Var-61
;define Floppy_drive                    System_Var-65


; special ^4 ("CASB") variables
%define Able_sectors                    System_Var-69           ; sectors per able sector
%define Able_sectors_counter            System_Var-73           ; able sectors per cluster remaining
%define Able_sectors_counter_static     System_Var-77           ; able sectors per cluster
%define Current_Sector                  System_Var-81           ; current sector (of cluster)
%define Current_Cluster                 System_Var-85           ; current cluster

;define Current_Record                  System_Var-89           ; current Record Number [NTFS-only]
%define Cluster_Count                   System_Var-93           ; Count of Cluster to read remaining [NTFS-only]
%define Current_LCN                     System_Var-97           ; Current LCN [NTFS-only]
%define Index_Entry_Flags               System_Var-98           ; Index Flags [NTFS-only]
%define Attribute_Base                  System_Var-100          ; Base of Attribute [NTFS-only]

; FAT filesystem variables
%define Name_Buffer_Position            System_Var-97
%define FAT_order                       System_Var-98
%define FAT_checksum                    System_Var-99
%define FAT_entry_count                 System_Var-100
%define Last_entry                      System_Var-104          ; [NTFS-also]
%define Bytes_copy                      System_Var-108          ; [NTFS-also]
%define cluster_type                    System_Var-112          ; [NTFS-also, File/Directory determination]


; partition values
%define	Partition_4_values	        System_Var-128
%define	Partition_3_values	        System_Var-144
%define	Partition_2_values	        System_Var-160
%define	Partition_1_values	        System_Var-176


; currently working contextes
%define Drive_Context                   System_Var-207
%define Handle_Context                  System_Var-256


; size of all stack variables (used for stack frame creation)
%define Stack_Frame_Size                256


; Storage Device Driver definitions
%define	Drive_Context_Size              1Fh
%define	Handle_Context_Size             17+32                   ; size = Handle + System File Information [FAT only]






; Error Handlers are resisting in the Bootloader module
;%define	Boot_Error		Bootloader + 1AFh
%define	Read_Error		Bootloader + 1B2h




; macros for reading sectors

%macro	Read 3

; %1 = sector
; %2 = sector count
; %3 = Error Label

; add the Partition Start Sector (to get absolute sector number)
mov eax,dword %1
add eax,[Drive_Context + 0]
mov [dap_LBA_low],eax

push dword %2
pop dword [dap_Count]
mov [dap_Buffer],dword Sector_Buffer

; interrupt 13h, Function 42h: Extended Read
mov si,dap
mov dl,[Drive_Context + 1Eh]
mov ah,42h
int 13h

jc %3

%endmacro



%macro	Read 4

; %1 = sector
; %2 = sector count
; %3 = Error Label
; %4 = Buffer

; set data segment to zero to access disk address packet (for NTFS relocated module only)
push word 0
pop word ds

; add the Partition Start Sector (to get absolute sector number)
mov eax,dword %1
add eax,[Drive_Context + 0]
mov [dap_LBA_low],eax

push dword %2
pop dword [dap_Count]
push dword %4
pop dword [dap_Buffer]

; interrupt 13h, Function 42h: Extended Read
mov si,dap
mov dl,[Drive_Context + 1Eh]
mov ah,42h
int 13h

; set data buffer to read buffer (NTFS only, Extended Sector Buffer)
mov ax,Ext_Sector_Buffer / 16
mov ds,ax
jc %3

%endmacro



%macro	WriteSectors 4

; %1 = sector
; %2 = sector count
; %3 = Error Label
; %4 = Buffer

; set data segment to zero to access disk address packet (for NTFS relocated module only)
push word 0
pop word ds

; add the Partition Start Sector (to get absolute sector number)
mov eax,dword %1
add eax,[Drive_Context + 0]
mov [dap_LBA_low],eax

push dword %2
pop dword [dap_Count]
push dword %4
pop dword [dap_Buffer]

; interrupt 13h, Function 43h: Extended Write
mov si,dap                                                      ; offset of disk address packet
mov dl,[Drive_Context + 1Eh]                                    ; BIOS drive number
mov ah,43h
mov al,0                                                        ; nothing to verify
int 13h

; set data buffer to read buffer (NTFS only, Extended Sector Buffer)
mov ax,Ext_Sector_Buffer / 16
mov ds,ax
jc %3

%endmacro













Mount_Boot_Partitions:

; API Mount_Boot_Partitions

; mounts all partitions and drives


; create the stack frame for the variables
enter Stack_Frame_Size, 0

; push the default of GPRs
mpush eax, ds, esi, es, edi, ebx, ecx, edx


; init Storage Device Driver variables
mov [Device_Context_Count],dword 0
mov [Handle_Context_Count],dword 0
mov [Last_Device_Context],word 0
mov [Last_Handle_Context],word 0

; load the default for the disk address packet
mov [dap_Size],byte 10h
mov [dap_Reserved],byte 0
mov [dap_LBA_low],dword 0
mov [dap_LBA_high],dword 0


; currently only boot drive supported
mov dl,[Boot_Drive]
mov [Drive_Context + 1Eh],dl                                    ; set BIOS disk number

; initialize drive
;...


;Mount_Storage_Devices_loop:

; mount all partitions of the drive (assume hard disk)
call Mount_Drive_Partitions

;loop Mount_Storage_Devices_loop


; if no drives were found, output a warning
cmp [Device_Context_Count],dword 0
jne Handled_Boot_Partitions

; output the warning
push dword 22                   ; Y-Position
push dword 6                    ; X-Position
push dword 0Fh                  ; Attribute
push dword Warning_No_Drives_Mounted
call API_Screen_Text_Attribute_Position
add sp,4*4

Handled_Boot_Partitions:


; pop the default of GPRs
mpop eax, ds, esi, es, edi, ebx, ecx, edx

; destroy the stack frame of the variables
leave

; no error
clc
xor eax,eax

ret













Load_System_File:

; API Load_System_File, File, Buffer
; 
;   NTFS    Load_System_File_NTFS
;   FAT     Open_File_FAT, Read_File_FAT

; tries to load the file from any volume


; create the stack frame for the variables
enter Stack_Frame_Size, 0

; push the default of GPRs
mpush ds, esi, es, edi, ebx, ecx, edx


; check the first three letters of the filename ('C:\...')

mov si,[Param1]
inc si

lodsb
cmp al,":"
jne Load_System_File_Invalid_Name

lodsb
cmp al,"\"
je Load_System_File_1
cmp al,"/"
jne Load_System_File_Invalid_Name

Load_System_File_1:
add [Param1],word 3


; try last Boot drive - if available, for faster access
cmp [Last_Device_Context],word 0
je Load_System_File_Enumerate

; load the file from the last working boot drive drive buffer
mov si,[Last_Device_Context]
mov [Drive_Context_Pointer],si
lea di,[Drive_Context]
mov cx,Drive_Context_Size
rep movsb

call Load_File
jnc Load_System_File_Exit



Load_System_File_Enumerate:

; try to find the file with all enumerated Boot Partitions
mov dx,[Device_Context_Count]
mov bx,Storage_Device_Driver_Stack

or dx,dx
jz Load_System_File_Invalid_Name


Load_System_File_drive_loop:

; copy the next Drive Context
mov si,bx
mov [Last_Device_Context],si
mov [Drive_Context_Pointer],si
lea di,[Drive_Context]
mov cx,Drive_Context_Size
rep movsb

; load the file from the drive
mpush bx, dx
call Load_File
mpop bx, dx
jnc Load_System_File_Exit

; next Boot Partition if available
add bx,Drive_Context_Size
dec dx
jnz Load_System_File_drive_loop



Load_System_File_Invalid_Name:

; all partitions checked, but file wasn't found
mov [Last_Device_Context],word 0

mov eax,Invalid_Name
stc


Load_System_File_Exit:

; pop the default of GPRs
mpop ds, esi, es, edi, ebx, ecx, edx

; destroy the stack frame of the variables
leave

ret






; loads the file from current drive context

Load_File:

; store params (they will be modified)
mpush dword [Param1], dword [Param2]

; load file from NTFS file system?
cmp [Drive_Context+0Ah],byte 'N'
je Load_File_NTFS

; open/read the file from FAT file system?
cmp [Drive_Context+0Ah],byte 12
je Load_File_FAT
cmp [Drive_Context+0Ah],byte 16
je Load_File_FAT
cmp [Drive_Context+0Ah],byte 32
je Load_File_FAT

; else unkown file system
mov eax,Invalid_Filesystem
stc

Load_File_Exit:

; restore params
mpop dword [Param1], dword [Param2]

ret




; loads the file from a FAT volume

Load_File_FAT:

; Open the File
call Open_File_FAT
jc Load_File_Exit

; at this point we could create a handle

; if there are no bytes to read exit
cmp [Handle_Context + 17+28],dword 0
jz Load_File_FAT_Exit

; Read the File
push dword [Param3]                                             ; create a virtual param3 that holds the count of bytes to read
push dword [Handle_Context + 17+28]
pop dword [Param3]
call Read_File_FAT
pop dword [Param3]
jnc Load_File_FAT_Exit

; End of File?
cmp eax,File_EOF
je Load_File_FAT_Exit
cmp eax,File_EOF_end
je Load_File_FAT_Exit

; (error occured)
stc
jmp Load_File_Exit


Load_File_FAT_Exit:

; (no error)
clc
jmp Load_File_Exit




; loads the file from a NTFS volume

Load_File_NTFS:

mov [Handle_Context + 17],dword 'load'
mov [Handle_Context + 17+12],dword 'load'
call Load_System_File_NTFS

jmp Load_File_Exit













Open_File_Callback:

; API Open_File_Callback, File, Callback

;   FAT     Open_File_FAT
;   NTFS    Load_System_File_NTFS (in open-file mode)

; Errors (CF = 1)
;       Invalid file name, file not found......Invalid_Name
;       No free file handle....................No_free_Handle

; callback with every new handle called (with handle in eax)

enter Stack_Frame_Size, 0
mpush ds, esi, es, edi, ebx, ecx, edx


; validate file name (must have the "?:\directory\foo.bar" format)
mov si,[Param1]
inc si

lodsb
cmp al,':'
jne Open_File_Invalid_Filename

lodsb
cmp al,'\'
je Open_File_1
cmp al,'/'
jne Open_File_Invalid_Filename

Open_File_1:
add [Param1],word 3


; enumerate all storage devices and check if to open
mov bx,Storage_Device_Driver_Stack                              ; bx = pointer to currect drive context
mov dx,[Device_Context_Count]                                   ; dx = loop counter
or dx,dx
jz Open_File_Exit_normal

Open_File_Enumeration_loop:

; copy the next Drive Context
mov si,bx
mov [Drive_Context_Pointer],si
lea di,[Drive_Context]
mov cx,Drive_Context_Size
rep movsb

; try to open the file from the current drive
mpush bx, dx
call Open_File_from_Filesystem
mpop bx, dx
jc Open_File_Enumeration_loop_next

; create a handle
call Create_Handle_Context
or eax,eax
jz Open_File_NoFreeHandle

; and call the callback
;   eax = handle
push ds
push es
pushad
call [Param2]
popad
pop es
pop ds

Open_File_Enumeration_loop_next:

; next drive if available
add bx,Drive_Context_Size
dec dx
jnz Open_File_Enumeration_loop


Open_File_Exit_normal:
xor eax,eax
clc

Open_File_Exit:

mpop ds, esi, es, edi, ebx, ecx, edx
leave

ret



Open_File_Invalid_Filename:

mov eax,Invalid_Name
stc

jmp Open_File_Exit



Open_File_NoFreeHandle:

mov eax,No_free_Handle
stc

jmp Open_File_Exit



Open_File_from_Filesystem:

; trys to open the file from the current drive context

push dword [Param1]

; NTFS file system?
cmp [Drive_Context + 0Ah],byte 'N'
jne Open_File_notNTFS

mov [Handle_Context + 17],dword 'open'
call Load_System_File_NTFS
jnc Open_File_from_Filesystem_Exit

Open_File_notNTFS:

; open/read the file from FAT file system?
cmp [Drive_Context+0Ah],byte 12
je Open_File_from_FAT
cmp [Drive_Context+0Ah],byte 16
je Open_File_from_FAT
cmp [Drive_Context+0Ah],byte 32
jne Open_File_from_Unknown_Filesystem

Open_File_from_FAT:
call Open_File_FAT

Open_File_from_Filesystem_Exit:
pop dword [Param1]

ret


Open_File_from_Unknown_Filesystem:

; else unkown file system
mov eax,Invalid_Filesystem
stc

jmp Open_File_from_Filesystem_Exit













Read_File:

; API Read_File, Handle, Buffer, Size

enter Stack_Frame_Size, 0
mpush ds, esi, es, edi, ebx, ecx, edx

; load the handle
mov si,[Param1]
lea di,[Handle_Context]
mov cx,Handle_Context_Size
rep movsb

; load the device context
mov si,[Handle_Context]
lea di,[Drive_Context]
mov cx,Drive_Context_Size
rep movsb

; read file from NTFS?
cmp [Drive_Context + 0Ah],byte 'N'
je Read_File_from_NTFS

; read file from FAT?
cmp [Drive_Context+0Ah],byte 12
je Read_File_from_FAT
cmp [Drive_Context+0Ah],byte 16
je Read_File_from_FAT
cmp [Drive_Context+0Ah],byte 32
jne Read_File_from_FAT

; else invalid file system
mov eax,Invalid_Filesystem
stc

Read_File_Exit:

mpop ds, esi, es, edi, ebx, ecx, edx
leave

ret



Read_File_from_FAT:

; File Size = 0?
cmp [Handle_Context + 17+28],dword 0
clc
jz Read_File_Exit

; read the file
mov [Handle_Context + 17+12],dword 'read'
call Read_File_FAT
jc Read_File_Exit

; update the handle if no error occured
lea si,[Handle_Context]
mov di,[Param1]
mov cx,Handle_Context_Size
rep movsb

clc
jmp Read_File_Exit



Read_File_from_NTFS:

; read the file (read-mode)
mov [Handle_Context + 17+12],dword 'read'
call Read_File_NTFS
jc Read_File_Exit

; update the handle if no error occured
lea si,[Handle_Context]
mov di,[Param1]
mov cx,Handle_Context_Size
rep movsb

clc
jmp Read_File_Exit













Seek_File:

; API Seek_File, Handle, Type, Position

; Handle = Handle of the file to seek; returned by Open_File
; Type = add Position to the relative Type: start position (zero), current position (nonzero)
; Position = bytes to seek in the file

; enter stack frame
enter Stack_Frame_Size, 0
mpush ds, esi, es, edi, ebx, ecx, edx

; load the handle
mov si,[Param1]
lea di,[Handle_Context]
mov cx,Handle_Context_Size
rep movsb

; load the device context
mov si,[Handle_Context]
lea di,[Drive_Context]
mov cx,Drive_Context_Size
rep movsb

; seek file from NTFS?
cmp [Drive_Context + 0Ah],byte 'N'
je Seek_File_NTFS

; seek file from FAT?
cmp [Drive_Context+0Ah],byte 12
je Seek_File_from_FAT
cmp [Drive_Context+0Ah],byte 16
je Seek_File_from_FAT
cmp [Drive_Context+0Ah],byte 32
jne Seek_File_from_FAT

; else invalid file system
mov eax,Invalid_Filesystem
stc

Seek_File_Exit:

mpop ds, esi, es, edi, ebx, ecx, edx
leave

ret



Seek_File_from_FAT:

call Seek_File_FAT
jc Read_File_Exit

; update the handle if no error occured
lea si,[Handle_Context]
mov di,[Param1]
mov cx,Handle_Context_Size
rep movsb

clc
jmp Seek_File_Exit



Seek_File_NTFS:

; just update the handle
mov si,[Param1]
mov eax,[Param3]

; from beginning or current position?
cmp [Param2],dword 0
jne Seek_File_NTFS_Position_Add

mov [si + 12],dword 0

Seek_File_NTFS_Position_Add:
add [si + 12],eax
clc
jmp Seek_File_Exit













Overwrite_File:

; API Write_File, Handle, Buffer, Size

; very much like Read_File

enter Stack_Frame_Size, 0
mpush ds, esi, es, edi, ebx, ecx, edx

; load the handle
mov si,[Param1]
lea di,[Handle_Context]
mov cx,Handle_Context_Size
rep movsb

; load the device context
mov si,[Handle_Context]
lea di,[Drive_Context]
mov cx,Drive_Context_Size
rep movsb

; read file from NTFS?
cmp [Drive_Context + 0Ah],byte 'N'
je Write_File_to_NTFS

; read file from FAT?
cmp [Drive_Context+0Ah],byte 12
je Write_File_to_FAT
cmp [Drive_Context+0Ah],byte 16
je Write_File_to_FAT
cmp [Drive_Context+0Ah],byte 32
jne Write_File_to_FAT

; else invalid file system
mov eax,Invalid_Filesystem
stc

jmp Read_File_Exit



Write_File_to_FAT:

; File Size = 0?
cmp [Handle_Context + 17+28],dword 0
clc
jz Read_File_Exit

; write the file
mov [Handle_Context + 17+12],dword 'writ'                       ; write mode
call Read_File_FAT
jc Read_File_Exit

mov [Handle_Context + 17+12],dword 'norm'                       ; default mode

; update the handle if no error occured
lea si,[Handle_Context]
mov di,[Param1]
mov cx,Handle_Context_Size
rep movsb

clc
jmp Read_File_Exit



Write_File_to_NTFS:

; write the file (write-mode)
mov [Handle_Context + 17+12],dword 'writ'
call Read_File_NTFS
jc Read_File_Exit

mov [Handle_Context + 17+12],dword 'norm'                       ; default mode

; update the handle if no error occured
lea si,[Handle_Context]
mov di,[Param1]
mov cx,Handle_Context_Size
rep movsb

clc
jmp Read_File_Exit
















; Drive Buffer


; Offset   Size    Group     Sub Group     Name
; -----------------------------------------------------------------------------------------
; 00h      dword   Drive                   Partition Start Sector (if used, otherwise set to zero)
; 04h      word    Drive     unused        words per sector
; 06h      dword   Drive     unused        Total Sectors
; 0Ah      byte    Drive                   Type ('N' = NTFS, 12/16/32 = FAT, 'P'/'H' = raw sector access to partition/hard drive)
; -----------------------------------------------------------------------------------------
; 0Ah      byte    FAT                     Type
; 0Bh      byte    FAT                     Sectors per Cluster
; 0Ch      word    FAT                     dwords per Sector
; 0Eh      dword   FAT                     dwords per Cluster [unused]
; 12h      dword   FAT                     first data sector
; 16h      dword   FAT       12/16/32      first root directory sector
; 1Ah      word    FAT       12/16         last root directory sector
; 1Ch      word    FAT                     File Allocation Table (= reserved sector count)
; -----------------------------------------------------------------------------------------
; 0Ah      byte    NTFS                    Version
;                                             10h   NTFS 1.X   Windows NT 3.1, 3.5 and 3.51
;                                             20h   NTFS 2.X   Windows NT 4.0
;                                             30h   NTFS 3.0   Windows 2000
;                                             31h   NTFS 3.1   Windows XP, Windows Server 2003, Windows Vista
; 0Bh      byte    NTFS                    Sectors per Cluster
;                                              1    512 MB or less
;                                              2    512 MB - 1024 MB
;                                              4    1024 MB - 2048 MB
;                                              8    2048 MB and more
; 0Ch      word    NTFS                    Bytes per Sector = 512
; 0Eh      byte    NTFS                    Clusters per File Record
;                                             This can be negative, which means that the size of the MFT
;                                             record is smaller than a cluster. In this case the size of the
;                                             MFT record in bytes is equal to 2^(-1 * Clusters per MFT Record).
; 0Fh      dword   NTFS                    Sector Offset of $MFT
; 13h      byte    NTFS                    Clusters per Index Record
;                                             This can be negative, which means that the size of the Index
;                                             record is smaller than a cluster. In this case the size in bytes
;                                             is equal to 2^(-1 * Clusters per Index Record).
; 1Ah      word                            
; 1Ch      word                            
; -----------------------------------------------------------------------------------------
; 1Eh      byte    Drive                   BIOS disk number
; -----------------------------------------------------------------------------------------
; 1Fh                                      a Drive Buffer
; -----------------------------------------------------------------------------------------




; static Storage Device Driver variables

Device_Context_Count            dd      0
Handle_Context_Count            dd      0
Last_Device_Context             dw      0
Last_Handle_Context             dw      0



Warning_No_Drives_Mounted       db      "Warning: No drives mounted, file system will not be available", 0












; include the disk device driver
%include "Disk device driver.asm"

; include the FAT file system driver
%include "FAT driver.asm"

; include the NTFS file system driver
%include "NTFS driver.asm"




