| This document attempts to explain technically NewExe infection for the virus writer. This isn't for the novice coder and you'll need to understand DOS EXE infection before being able to use any of it. The infection described in detail here is the same as used by the accompanying WinSurfer virus, there are other methods that can be done but they aren't our concern (it's up to you to develop new code!) You will want a copy of the New Exe header information which is available in Ralf Browns interrupt listings under Int21h AH=4Bh, a copy of which is included at the end of this article. This is a map of what we are trying to do: Before infection After Infection 0h--------------------- 0h--------------------- | | | | | DOS EXE header | | DOS EXE header | | | | | --------------------- --------------------- | | | | | DOS Code | | DOS Code | | | | | | | 3F8h--------------------- 400h--------------------- | | | | <- Move | New EXE Header | | New EXE Header | this | and some tables | | and some tables | up | | | | | ----------------- | | ----------------- | | Segment | | Segment | | Table | | Table | | | | | | | | | Insert -> | ----------------- | Virus segment | ----------------- | this | ----------------- | entry | Misc Other | | Misc Other | | Tables | | Tables | | | | | x x x x x x x x x x x x CS:IP --------------------- --------------------- | | | | | Windows Code | | Windows Code | | and Misc | | and Misc | | Segments | | Segments | | | | | End --------------------- CS:IP --------------------- | Virus segment | Append all | with code etc | this -> | | --------------------- Virus | | Relocation End --------------------- Entry Infection Theory: ----------------- Test the EXE to make sure its windows and that the NE is at offset 1024. Reduce the NE pointer at 3ch by eight. Reduce DOS SP by eight. Any NE offsets which are larger than the segment table offset must be increased by eight. Increment the segment counter. Save the CS:IP. Point the CS:IP to the new segment entry Calculate the position of the end of the segment table, move all data up to and including the segment table up by eight bytes. Add another segment entry Write the virus to the end of the file Write relocation entry to the end of the file. --- That is a very basic overview of what is wanted. The main idea of it all is moving the NE header forward to add a new segment table entry, and changing the CS:IP to point to it. We'll go through all the stages step by step. Testing for a Windows executable. --------------------------------- A NewEXE file always begins with a DOS header and some DOS executable code. With a windows executable: The word at offset 0 is 'MZ'. The word at offset 18h is 40h or greater. assuming that these conditions are met then we also want the pointer to the NE header (3ch) to be equal to 400h. The reason for this is that room is needed to move the NE header forward by 8. Rewriting the DOS header. ------------------------- Before rewriting the DOS header, reduce the DOS SP field (10h) by 8, because if it was pointing to the end of the DOS code section it would point to the start of the NE header. (No real reason for doing it really) The NE header pointer at 3ch must be reduced by 8, because we intend on moving most of the NE header forward to that position. Modifications to the NE header. ------------------------------- From this point onwards we are referring to the offsets in relation to the NE header. The pointer to the segment table is a word at 22h. If any of the pointers at 4,24h,26h,28h,2ah are larger than [22h], then increase that pointer by eight. The reason for this is that since we are inserting a new segment table entry, all tables behind the segment table will be eight bytes further from the start of the header. The segment counter is a word at offset 1ch. Increment it by one because since we are adding another segment, we need to indicate this in the header. At offset 14h is the dword pointer to the program entry point, CS:IP where the CS is actually the segment table entry number. Save this pointer for use in your relocation entry (that part will be explained in detail later on). Now point the CS:IP instead to the virus segment. Do this by writing the necessary starting IP value to 14h (offset of the entry into your segment) and the segment counter value into 16h (since the virus segment is the last in the segment table it will be equal to the segment counter value which we have incremented). You can work this out for yourself, but what you need to do now is move the entire NE header, upto and including the segment table, but not the data behind it, forward by eight bytes. Heres an equation on calculating how much to move: ((segmentcounter-1)*8)+word ptr [22h] Directly after this position is where to insert the new virus segment entry. The Virus Segment Entry. ------------------------ Format of new executable segment table record: 00h WORD offset in file (shift left by alignment shift for byte offs) 02h WORD length of image in file (0000h = 64K) 04h WORD segment attributes (see below) 06h WORD number of bytes to allocate for segment (0000h = 64K) Offsets 2 and 6 in the segment record are just the virus size. Offset 4 is the segment attribute, we use 180h, which makes the segment executable with relocations. Calculating offset 0 is more difficult. It is necessary to get the file length and shift it right by the alignment shift value which was saved earlier. I wouldn't know how to do a dword shift so I convert it to a division. File length into DX:AX : mov ax,4202h xor cx,cx cwd int 21h Shift right DX:AX by alignment shift: mov cl,byte ptr alignment_shift push bx mov bx,1 shl bx,cl mov cx,bx pop bx div cx AX=required offset 0 value Write this eight byte table behind all the moved header. Writing the Virus. ------------------ Lseek to the end of the executable and write the virus. Writing the Relocation Entry. ----------------------------- You need a relocation entry so that you can return control to the host after the virus has done its dirty work. The relocation entries follow the segment itself. Format of relocation entry: Offset Size Description 00 WORD Number of relocation entries Offset Size Description 00 BYTE relocation type 01 BYTE relocation flags 02 WORD offset within segment 04 WORD target address segment 06 WORD target address offset The first word will be 1 because only 1 relocation entry. First byte is 3 to signal a 32bit pointer (a far jump). Second byte is 4 to signal additive relocation. (doesn't work without this) Word at offset 2 is the offset of the dword after the 'far jump' opcode. Word at offset 4 is the CS of the original host CS:IP Word at offset 6 is the IP of the original host CS:IP To put all this into code: db 0eah ;Opcode of JMP FAR PTR ret_ip dw 0 dw 0ffffh relocation dw 1 ;One relocation entry db 3 ;32bit pointer relocation db 4 ;Additive relocation dw offset ret_ip ;Offset of the relocation in segment hostcs dw 0 ;CS:IP of place we want our relocation to hostip dw 0 ; point. Note: the relocation address data (ret_ip) _must_ be FFFF:0000 as above because windows treats it as a linked list. If you don't understand don't worry, just do it! It won't work otherwise. It is important that before writing the virus body to the executable that you set this address to FFFF:0000 so that executable will be setup correctly. Write the relocation entry to the end of the file. Windows allows a standard Int 21h call just fine so all file manipulation is as simple as ever, with a few minor changes. Writting |