ThunderByte Anti-Virus DECRYPTION
Written by The Poltergeist
December 18, 1993
February 06, 1994
This is the documentation belonging to and explaining the use of: ThunderByte Anti-Virus DECRYPTION utility v2.0
TOPICS covered in this document:
- PURPOSE OF TB-DECRYPT
- GENERAL INFO
- HOW TO USE TB-DECRYPT
- MESSAGES / ERRORS
- AFTER TB-DECRYPT IS USED
- INFO ON ENCRYPTION IN TBAV EXECUTABLES
PURPOSE OF TB-DECRYPT:
TB-DECRYPT is a utility designed to remove the encryption from the executable files included in the ThunderByte Anti-Virus package. It works fine on the files included in release 6.09 of the package, and due to its design, it should work on new releases of TBAV. (Of course, as long as the encryption scheme is not changed). It should also work fine on previous releases of TBAV, at least version 6. If it is found that TB-DECRYPT will not work on a certain new release of TBAV, a new version of TB-DECRYPT will be released. Removal of the encryption permits easier examination and alteration of the code; that is my primary reason for writing TB-DECRYPT.
GENERAL INFO:
Before you try to use this, let me point out a few things. First, this utility will be of no use to you unless you are experienced with a debugger. The executable files, with the exception of TBSCAN and TBCLEAN, will still work after the encryption has been removed. However, most of the executable files have a checksum in the beginning in which it JMPs to the result of the check- sum, and that needs to be defeated, if you plan to byte-patch the file. Also, TBSCAN and TBCLEAN perform 'Sanity Checks' on themselves, and that needs to be defeated too.
HOW TO USE TB-DECRYPT:
To use TB-DECRYPT, simply run TBDCRYPT.COM. You will be presented with a menu of the TBAV utilities, each preceded by a letter. Press a letter to select the TBAV file you want to decrypt. The file will then automatically be decrypted. TB-DECRYPT will first check to make sure that the program is not already decrypted.
MESSAGES / ERRORS:
When you execute TB-DECRYPT you can get several lines of information.
File not found - TB-DECRYPT did not locate the file. The file must be in the current directory.
Unrecognized file or not TBAV file - Aborting - TB-DECRYPT has determined that the file is not one from the TBAV package.
Placing new instruction pointer in EXE header - TB-DECRYPT has altered the initial IP in the header, so the program will start right at the entrypoint of the actual program. TB-DECRYPT searches the executable file looking for the decryption routine, and knows where the IP (that it would have normally jumped to after the executable had finished decrypting itself) is stored from that reference. The inital IP is not changed if the TBAV file is a TSR.
Accessing stack pointer for use in decryption routine - due to the design of the encryption TBAV uses, the stack pointer reference is necessary for TB-DECRYPT to decrypt the file. TB-DECRYPT does a calculation on the initial SP in the header.
Placing new stack pointer in EXE header - TB-DECRYPT has altered the inital SP in the header. Though probably not necessary, TB-DECRYPT takes no chances, so the stack is the same (assuming TB-DECRYPT has changed the inital IP to point to the entrypoint of the actual program) as if it had just exited the decryption loop.
Patching memory-resident-type TBAV utility to bypass decryption loop - due to the location of the decryption routine in the TSR utilities included in the TBAV package, the initial IP can't be changed. So TB-DECRYPT patches the code right before the decryption loop so when the program is run, the decryption loop is bypassed. TB-DECRYPT searches the executable for the decryption loop, then does a couple of searches from that reference point to find the precise locations to patch, then does a few calculations to determine what to patch the locations with.
Removing scrambling from file - the heart of the program. TB-DECRYPT is removing the encryption from the executable, and replacing the un-scrambled result back into the file.
AFTER TB-DECRYPT IS USED:
Some programs need some patching to get them to work after TB-DECRYPT is used.
Everything except TBSCAN and TBCLEAN will work correctly after the encryption has been removed. However, if you plan to patch the files, you need to defeat a checksum. In TBSCAN and TBCLEAN, sanity checks need to be defeated. Some of the programs (such as TBKEY) have no checksum, so patches can be made to them with no resulting problems.
To defeat the checksum, you need to first view the decrypted file with a debugger, and note the location where the JMP WORD PTR [XXXX] references. That is how it jumps to the result of the checksum. That instruction is only a few instructions down from the first. Now, load up the original file (with the encryption still intact), and set a memory view to the location at which the JMP WORD PTR [XXXX] is referenced. (It is CS:XXXX. The executables make the DS, ES and CS the same). When the program terminates, the address to which it jumped to at that time is still in the location. Go back to the decrypted program and replace the JMP WORD PTR [XXXX] with a direct jump to that location. The 'Sanity Check' in TBSCAN and TBCLEAN is pretty easily smashed.
If you byte-patch the TB-MON utilities, you need to patch a checksum jump that is similar to the one present in the non-TSR utilities. It is harder to find the correct location that it is supposed to jump to when dealing with the TB-MON utilities. The reason being, is that the JMP WORD PTR [XXXX] is not near the beginning of the program, and you have to have TBDRIVER installed in order for the program you are tampering with to 'get to' the checksum jump. But you need to get the program to stop before it gets to the checksum jump, or the program will keep going and send itself resident, crashing the CPU. You have to set a VIRTUAL BREAKPOINT by having an INT 21 TRAP TSR go memory resident, then trap INT 21 function 30.. and you have to do this while debugging the original, un-decrypted file. Anyway, with that virtual breakpoint set at that interrupt, when you run the program, it will stop at a location a little bit before the JMP, and from there you can find where its supposed to JMP to, and make an appropriate patch. To make it use a pirate key, I suggest trapping INT 21 function 3D - the area to patch for that is not far from there. I have included a TSR to trap INT 21 in this package. Also, the reason you have to use the original, still-encrypted file to find out the location the JMP WORD PTR [XXXX] is supposed to jump it, is because the incorrect result is used if you attempt to step thru the de- crypt program to find it (even though the decrypted program will preform the proper jump if you run it outside of the debugger). And you can't step through the original encrypted file due to some fierce anti-debugger code.
INFO ON ENCRYPTION IN TBAV EXECUTABLES:
The first obstacle I encountered when debugging was INT 1 being re-mapped, which is the debuggers single step interrupt. It remaps it to point to somewhere in the code, the trap flag is set, and INT 1 is executed once. After that, it decrypts the decryption loop and pushes it onto the stack. It then jumps to a code segment slightly offset from the stack segment. This is where the real debugging problems occur. The stack is RIGHT UNDER the decryption loop, and if you try to single step anywhere past the RETF 0024 until after the RETF 001E is executed, the debuggers stack will inter- fere with the decryption loop and mess everything up. The decryption loop then proceeds to decrypt the program in memory. The decryption loop moves the stack pointer above and below the decryption loop as it cycles through. The near return loops back around to CS:0000 in the decryption routine. The RETF 001E jumps to the actual program.
1488:0018 B88CD3 MOV AX,D38C
1488:001B 153375 ADC AX,7533
1488:001E 72F9 JB 0019
1488:0020 D4FF AAM FF
1488:0022 8AC4 MOV AL,AH
1488:0024 83C33E ADD BX,+3E
1488:0027 8ED8 MOV DS,AX
1488:0029 B91500 MOV CX,0015
1488:002C F7D3 NOT BX
1488:002E 2E871E7E00 XCHG BX,Word Ptr CS:[007E]
1488:0033 FF77FE PUSH Word Ptr [BX-02] - preserves original
1488:0036 FF37 PUSH Word Ptr [BX] - INT 1 vector
1488:0038 8BEC MOV BP,SP
1488:003A C747FE4A00 MOV Word Ptr [BX-02],004A - INT 1 points to
1488:003F 8C0F MOV Word Ptr [BX],CS - CS:004A (hidden
1488:0041 72EC JB 002F code)
1488:0043 2EFF367A00 PUSH Word Ptr CS:[007A] - trap flag
1488:0048 9D POPF
1488:0049 1D5E5B SBB AX,5B5E - actually POP SI
1488:004C 8BD3 MOV DX,BX and POP BX..
1488:004E F7D2 NOT DX
1488:0050 2E87168400 XCHG DX,Word Ptr CS:[0084]
1488:0055 58 POP AX
1488:0056 8F060600 POP Word Ptr [0006] - INT 1 restored
1488:005A 83E6FD AND SI,-03
1488:005D 8F060400 POP Word Ptr [0004]
1488:0061 03F2 ADD SI,DX
1488:0063 2EAD LODSW CS: - Decrypts decryption
1488:0065 F7D0 NOT AX - loop and pushes it
1488:0067 50 PUSH AX - onto the stack
1488:0068 E0F9 LOOPNE 0063
1488:006A 83D302 ADC BX,+02
1488:006D 81D6E426 ADC SI,26E4
1488:0071 81C66EFF ADD SI,FF6E
1488:0075 8EDB MOV DS,BX
1488:0077 CA2400 RETF 0024 - to decryption loop
This is where it is after the RETF 0024:
1B81:0000 8704 XCHG AX,Word Ptr [SI] -|
1B81:0002 33C4 XOR AX,SP |
1B81:0004 8B4E00 MOV CX,Word Ptr [BP+00] |
1B81:0007 33CD XOR CX,BP |
1B81:0009 33C1 XOR AX,CX | Decryption
1B81:000B D1C8 ROR AX,1 | loop
1B81:000D 8904 MOV Word Ptr [SI],AX |
1B81:000F 4E DEC SI |
1B81:0010 83EC24 SUB SP,+24 |
1B81:0013 FB STI |
1B81:0014 4E DEC SI |
1B81:0015 E105 LOOPE 001C -|-when its done
1B81:0017 FA CLI |
1B81:0018 C22200 RET 0022 -|-jumps to cs:0000
1B81:001B 90 NOP
1B81:001C 58 POP AX
1B81:001D CA1E00 RETF 001E - to actual program
Thank you for checking out TB-DECRYPT!
- The Poltergeist