In this article I will announce my aproach to infection of strange platforms as are Windows VxD or dos DOS4GW. Both platforms are running under similar environment - in FLAT memory model both are extended 32-bit so this is the reason why I have dealed with both of them.

So let's start
In both cases we will infect host with small loader, that will load and execute main part of virii. This strategy is nice because there is no code executed in last section and so on.
LE (as I will call LX too, because there are similar or even the same), is intel friendly, because it uses 4096 bytes long pages. Each section is aligned to page. This means, that in average case 2000 bytes in code section is unused and free. Nice, isn't it :-). This wasting of space we will use to insert our short "loader" that will load other stuff from end of file (if you want, it may be placed elsewhere, or you may groove last section - i have a feeling that there may be debug info or other shit, so not so fast) and execute it. Because of flat model and you never knows where will you be loaded, this piece of code must be self-relocating. Enough of talking, go on.

VxD starts as regular dos-executable with pointer to next header at 3Ch (just like in PE). With DOS4GW it is a bit difficult. DOS4GW starts with some stupid stub, that will load main LE/LX executable. I don't deal with this too much, I just looked at some Dos4GW and wrote this part of code

readfile is macro as follows:

now file_base should point to regular DOS 'MZ' exacutable with dword at 3ch set as it should have. So just get start of LE header like this and check some formalities:

Now we have to understand some LE specific stuff. At first LE is fragmented to sections (similary like PE). Sections are called Objects here. Objects are in header and there is usually not enough space to create your own object. This code will compute offset of eax-th section descriptor:

Object descriptor structure is as follows:

This offset of object in file should be computed as

objectr = *(dword *)[le_header+80h] + pageindex<<12

Object in file is (of course) not fragmented. It starts at objectr and ends at (objectr+pageen3z<<12-1)

The second new entity in LE are entries. This is some kind of exports in PE. This is how to assume offset of eax-th entry: (objectr will point to start of entry).

And the last thing you need to know about are relocations. Because code may be stored anywhere between 0-4GB, each access to memory has to be relocated. (The only one exceptions are jumps which are relative to itself). Because of this LE has very complex structure of relocation (much more complicated than PE). Because of complex structure of relocations, many compilers are seting values to be relocated to 0.
If you really want to deal with this i will advise you to some documentation. But if you don't this is a fragment of code that scans for relocation:

This is code i wrote to parse relocation table and to find some relocation that relocates eax: I wrote it so far ago so i will be not trying to explan this - just see documentation (as far as i know there is no good documentation :-( ).

This is way i proceed VxDs:

  1. some check
  2. check if there is enough space in code section. i assume code section is section 1 (first section).
  3. assume DDB entry - this is entry that describes VxD in Windows this contains pointer to control dispatcher. This is a functions that handles various events, and this is how we get to turn. Pointer to dispatcher is first 4-bytes of DDB
  4. find fixup for dispatcher
  5. write your code to end of code section, groove this section and change fixup to start of your code. be sure that after end of your loader you return control to previous dispatcher. Note: the value of relocation is more trustable than value in DDB

And what your dispatcher should do:

  1. test for special event (number in eax). I used 2 (Init_Complete) that is sent to all VxDs after init of windows is complete.
  2. check wether there is anybody resident (because you are at VxD level, you have full control of computer, you don't need to have multiple instances)
  3. load your dropper from end of file (file name will be stored by infection - vxd should not be moved)
  4. run your code

Some hints on ring 0

That's all about this .... happy coding

And now some few words about DOS4GW LE:
In DOS4GW you may relay to DPMI (that should be supportet quite good) under any platform it works.

  1. get entry point at le_header+1ch is offset (relative to start of section and at le_header+18h is object no
  2. groove object (if enough space) and store loader at end of section
  3. set new entry offset

You don't need to deal with fixupps and other shit.

Your loader will do this:

  1. start with short jump followed by "WATCOM" if this is not loader will say something like "Invalid executable" and this is way how to test wether executable is compiled by WATCOM too
  2. load code from end of file and run it (environment segment is at ES:2C like usually, you may use dos services (int 21h) and DPMI (int 31h) - that is all you need)

As you see DOS4GW is pretty easy target ...

What to say at the end? ... do your best!