VX Heaven

Library Collection Sources Engines Constructors Simulators Utilities Links Forum

Full Thunderbyte Stealth...

[Back to index] [Comments]

What we are trying to do here is to enumerate all the possible Thunderbyte flags, so that you can be certain that your virus will not trigger an alarm under any specific circumstances. This text is essentially the same as the one in the previous issue, only now it's more complete.

Flag "B" - Back to entry point

This flag appears when a program at some point in its code jumps to the Entry Point. For a COM that would be a jump to the beginning (offset 100h).

	MOV AX, 100h

It can be spoofed like this:

	PUSH 100h

Flag "E" - Flexible entry point

This one pops up when we are calculating the actual offset, remember? Well, the classic way to code it is as follows:


The anti-TB form would be to simulate that POP:


Flag "Z" - EXE/COM determination

This is the party guilty of detecting many viruses... it's not so commonly used in conventional programming. Originally, what we did was to read the first two bytes of a file, toss them into a buffer and compare against 'ZM' (watch it! ZM and not MZ since the word is stored in inverse order!)

For example, supposing we already have the first two bytes in a buffer...:


Ok, that's the conventional way of doing it. But another way is to compare byte for byte:

	CMP BYTE PTR [BUFFER], 'M'	;Remember! we are not
					; comparing against ZM since we
					; are comparing byte by byte. First
					; we compare against M and then Z.
	... 				;<--- If it got this far, it's
	... 				; an EXE.

Flag "S" - Search for executables

This one traps the routine which searches for executables.... The search routine is imperative in non-resident viruses, therefore it is imperative to hide it. We used to search for *.COM or *.EXE in any directory; what we can do, instead, is to search for *.C?M and *.E?E and later verify if the center letter is an "o" or an "X" respectively. For example (assuming we already have the filename in DTA_AREA):

;Verify that it really is a .COM, not .CAM or something like that..
;To do that, move the pointer to the beginning of the extension
;(look for the period in the file name) and I increment it by 1 so
;that it's at the center of the extension, which is what interests
;us. Now I look for the period:

	MOV CX, 13d			;13d is the maximum filename size.
	LEA SI, DTA_AREA+1Eh		;1Eh filename displacement in
					; DTA area.
	LEA DI, PUNTOS			;'Puntos' is a variable full of
					; periods (.)

;Once the period is found, I increment the pointer so that it
;points to the extension's center character:

	...				;<--- If it got this far, it's because it's a
	...				; real .COM, not a CAM or some such thing

Flag "U" - Undocumented interrupt/DOS calls

This is set off when you make calls to undocumented services, like deactivating V-Safe, for example. To get around it we do the same as before: instead of MOVing, we pass the values through the stack and it's done.

Flag "T" - Incorrect time stamp

TB warns of this problem when it encounters an incorrect or impossible date. A file with a creation date of 2094, for example.

This generally seen in files infected by stealth viruses, which do this to test for infection since if it had to open every file it would be the world's slowest virus. The traditional way is to add 100 or 200 to the year so that a DIR list appears unchanged but the virus 'knows' it's 100 years 'later'. Example:

File name Real Date Date shown by DIR command

MEM.EXE 01/01/1994 01/01/94 ;<-- Not infected
MEM.EXE 01/01/2094 01/01/94 ;<-- Infected

Flag "M" - Memory resident code

TB displays this warning when it finds that we obtain or set the interrupt vectors. One way of spoofing it is typical. Instead of the following, for example:

	MOV AX, 3521H
	INT 21H

Try this:

	PUSH 3521H
	INT 21H

But another way of doing the same thing is, instead of hiding the service, hide the VECTOR! TB warns of resident code only on critical interrupts, like 13h or 21h. So what we do is to call for vector 'N-1' instead of vector 'N' and later ad '1' to it. For example:

	MOV AX, 3521H
	INT 21H

Change it to:

	MOV AX, 3520H
	INT 21H

Flag "L" - The program traps the loading of software

This flag triggers the moment TB becomes 'aware' of the typical comparison used to verify if it is the file execution service(4bh) once Int 21h is hooked:


To spoof this, instead of comparing AH to 4BH, we can pass the value to be compared to another place and compare it in another register, so it won't be so obvious to TB that we are comparing the service:

	XCHG AH, AL			; The XCHG instructions are mostly
	CMP AL, 4BH			; used to avoid changing registers
	XCHG AH, AL			;

Flag "c" - No checksum data

This flag pops up when TB can't find ANTI-VIR.DAT, a small file TB creates in each directory. TB store critical information about each program in it, such as the first few bytes and the size of a COM, or the EXE Entry Point, or other crap like that, as well as storing the CRC of the original file. If a file is infected, and ANTI-VIR.DAT still exists, TB realizes that file was modified and displays the flag, maybe even managing to clean the file.

In other words, it behooves us to make sure that this little file no longer exists, or better yet, that TB can't recognize it as its checksum file. So, instead of erasing it, what we can do is to modify its header... just the first bytes are enough. We overwrite 'Thunderbyte' with garbage......

The advantage to modifying the file instead of erasing it is that we avoid the possibility of TB realizing that ANTI-VIR.DAT is missing. This way, the file is still there but it's unusable. :-)

Flag "G" - Garbage instructions,

Flag "#" - Found an instruction decryption routine,

Flag "!" - Invalid opcode

This is what TB displays when it finds "garbage" in the file. This "pseudo-garbage" is what is usually found after an encryption... When a virus is encrypted, the remaining code (obviously not executable) is read as garbage by TB, which then interprets this as the possible result of encryption and displays the flag.

A possible solution is to ensure that the result of the encryption is not larger than the highest instruction. One way of doing this is to rotate one bit. Another way is to create a false exit ahead of the encrypted code... TB then thinks that what follows is program data and does not read it as garbage. Structure:

	JMP DECRYPT			; Jump to the virus
	...				; Host program

DECRYPT:...				; Decryption routine
	JMP TE_CAGUE			; Jump to bypass exit to DOS
	MOV AH, 4Ch			; Code which is never executed
	INT 21h 			;
	... 				; Continuation of decryption routine.
	.... 				; Encrypted virus (garbage)

Well, since we delayed too long in getting out this second issue, it happens that TBav now catches on to the "JMP before the DOS exit" trick. This doesn't mean TB is going to shit on us, right? RIGHT! It isn't going to shit on us at all, because what we can do (thanks to Leviathan's ingenuity, who, totally perturbed because TB was shitting on his Xou da Xuxa, went without sleep a whole night and got out a new ANTI-TB 6.20 version) is to make a DOS call at random, such as to ask for the date. I don't mean make just ANY call, just calls which won't destroy the contents of the key registers and such. The code should appear as follows:

	JMP DECRYPT			; Jump to virus
	...				; Host program
DECRYPT:...				; Decryption routine

	JMP TE_CAGUE			; Jump to bypass exit to DOS
	MOV AH, 4Ch			; Code which is never executed
	INT 21h				;
	MOV AH, XXX			; Random call, but make sure nothing

	INT XX				; is damaged.
	...				; Continuation of decryption routine.

	...				; Encrypted virus (garbage)

Flag "p" - Packed program

This flag isn't really an alarm. It merely tells us that the file is packed and that it could contain a virus.

Flag "F" - Suspicious file access

This flag appears when TB detects code capable of modifying file attributes. We can spoof it in the same manner: instead of MOVing the value of the service in AH, PUSH and POP it.

Flag "?" - Inconsistent EXE header

This flag is displayed when TB finds inconsistent information in the EXE header. For example: the header file size field is different from the actual size of the file. This could be caused by overlays in the program, but it could also be caused by a virus which calculates the new file size improperly.

Flag "O" - Code that overwrites/moves a prog. in memory

This appears when we try the restore the first few bytes of a COM file. Generally what we do is:

	mov di, 100h
	lea si, [offset BYTES_ORIGINALES+bx] ;<- BX contains the
					     ;offset of the virus

(This, of course, can be done in several different ways, but basically the above example is representative.) All we need to do here is to replace 'MOV DI, 100' with 'PUSH 100', 'POP DI'.

Flag "A" - Suspicious memory allocation

The following is an example of the type of code which sets off this flag:

	mov ax, ds
	dec ax
	mov es, ax
	cmp byte ptr es:[0], 5ah
	mov ax, es:[3]
	mov dx, es
	add dx, ax
	... etc...

(As can be seen, we're trying to manipulate the MCBs) The flag can be avoided by changing the value 5Ah for another in the following manner:

	;instead of...
	cmp byte ptr es:[0], 5ah

	inc byte ptr es:[0]
	cmp byte ptr es:[0], 5bh

It modifies the MCB value, but it's the only way... :-).

Flag "J" - Suspicious jump construct

This is set off by a chain of Jumps (at least 2) to positions more or less widely separated in the code. Example:

Start:	JMP Continuar
	JMP Virus
Virus:	<Virus>

Replacing JUMPs with the equivalent PUSH and RET instructions is ineffective, including PUSH immediate. The same thing happens when you try to replaces plain and simple JUMPs with a more elaborate schema, such as using variables, etc. This can be solved by replacing JUMP with CALL. You use CALL then you get rid of the offset that remains in the stack, making everything work as if it were a JMP. For example:

Start:	CALL Continuar
	ADD SP, 2
	CALL Virus
Virus:	ADD SP, 2

Flag "K" - Unusual stack

We see this pop up with infected EXE's. The problem with this flag is that it appears when one of the 2 following conditions is met:

  1. When the Stack Segment (SS) and the Code Segment (CS) point to the same segment. This is normal, of course, because typically we place some bytes in SS after the virus, sharing the same segment as the virus's CS (the same CS that is shown in the header).....
  2. When the Stack Pointer (SP) is odd (odd stack).. this is due to micro computer design, which can't handle segment overflow with an odd SP.... the machine would hang. Ok, you can use an od SP, but it's not advisable... the machine won't hang, but keep the possibilities in mind. But if TB doesn't like it, WE DON'T DO IT, AND THAT'S ALL! OK? :)

Well, the first is easy to spoof. All we have to do when we calculate the new CS:IP (pointing to the virus) is to increment the CS and set is as a new SS:

;Now we have to pass the incremented CS to the header variable
;in the corresponding field
; Initial Stack Segment: header offset 0eh
; Initial Stack Pointer: header offset 10h
	INC AX				;<--- In AX for example we have the
					; calculated CS and after the INC it
					; becomes the new SS.
	MOV WORD PTR DS:[HEADER+0eh], AX; Or whatever the fuck you do
					; to pass the data to the new header.

Ok, all that remains is the SP which has to be even. Well, what can I say? Since you put the stack wherever you want, just calculate it so it comes out even. The virus has a constant length, and since determine the length of the separation between the end of the virus and the stack, we calculate it so that the sum of the two is even and there we are.....

Flag "D" - Disk write access

It is rumored that this one appears when you try direct writes to the hard drive. Avoid it by simply camouflaging the call to the interrupt.

Flag "R" - Relocator

To elude this flag simply camouflage the registers by using operations such as PUSH and POP or something like that. If this flag still pops up, kill yourselves! Your virus is a "mierda".

[Back to index] [Comments]
By accessing, viewing, downloading or otherwise using this content you agree to be bound by the Terms of Use! aka