FOG A polymorphic encryption algorithm by Eclipse Disclaimer: I have made this mutation engine for fun purposes only. It is made for use in viruses, but not as to promote any intentional harm or damage on computer systems. This engine is dedicated to those of you out there who find the concept of replicating programs fascinating. Trojan and destructive virus writers: Get a life. USAGE: CODE MODIFICATION INSTRUCTIONS 1. Enter the statement "extrn fog:near, fog_init:near, rnd:near" into your code in your code segment. Its not really necessary to include the "rnd" part if you do not need a random number generator in your code. You might also find it handy to include the switch definition file (switches.inc) in your code. Example (ideal mode): ...... .model tiny .radix 16 ideal segment code word assume cs:code, ds:code, es:code, ss:code org 100h extrn fog:near, fog_init:near, rnd:near ;here include "switches.inc" ;and here ...... or (MASM simplified mode): ...... .model tiny .radix 16 .code org 100h extrn fog:near, fog_init:near, rnd:near ;here include switches.inc ;and here ...... or (MASM mode): ...... .model tiny .radix 16 code segment word assume cs:code, ds:code, es:code, ss:code org 100h extrn fog:near, fog_init:near, rnd:near ;here include switches.inc ;and here ...... 2. Initialise fog. Do so by calling fog_init with the appropriate parameters: AH : Debugger hostility switches (see below) AL : Junk generation switches ( ---"--- ) CL : General switches ( ---"--- ) CS:DX : Code to encrypt SI : Size of code to encrypt DI : Where in the decrypted code control should be passed. eg. if execution starts at the beginning of the code, DI = 0. Note that this initialization could be done only once, f.ex. at the installation of a TSR virus, and later only be called when there was need for updating the information, typically changing from COM to EXE mutation mode. On return from fog_init only one register will have changed; CX = Max size of decryptor and encrypted code. This will be the amount of bytes to stealth if you are making a stealth virus and have specified constant code size (sw_const_s) or if you want a tip of how much memory you gonna need for encryption, otherwise ignore. Example: .... mov ah, sw_prefetch or sw_int3 mov al, sw_015_gi ;or more efficiently: ;mov ax, (sw_prefetch or sw_int3) shl 8 or sw_015_gi mov cl, sw_const_s mov dx, cs:[myoffset] mov si, sizeofvirus xor di, di call fog_init .... 3. Mutate by calling fog with the following parameters: ES : Free segment. This is where the mutated code will be put. Must contain enough memory for the encrypted code and decryptor. When you define high junk generation, the decryptor can be rather ...errr... massive... BP : Offset of code. Eg. if you write the mutated code to the end of a COM file, then BP should be set to filesize+100h. Example: .... mov bp, ax add bp, 0100 mov ax, cs dec ax, (bufferneeded+0fh)/10h mov es, ax call fog mov ah, 40 ;CX = number of bytes, DS:DX = buffer int 21 .... 4. Take note of the register values on return from the fog mutation algorithm: DS:DX = ES:0 = Buffer where decryptor and encrypted code will be found. CX = Length of decryptor and encrypted code. All other registers are preserved. USAGE: MEMORY REQUIREMENTS When calling fog you should make sure that you have an encryption buffer big enough to accomodate even the largest decryptors + your encrypted code. On its most demanding setting (sw_255_gi / sw_maxhostile) fog will require approximately 16k of memory. If you use fixed file size, the memory required can be even more massive. However, if you reduce the junk generation, fog will need much less memory. When you call fog_init, CX will return the maximum size (in bytes) needed. Note: Take a look on what I do in AirRaid. I steal a temporary block of memory just to do the encryption, without allocating it. This will work nicely most of the time. USAGE: ASSEMBLY INSTRUCTIONS Fog is written in TASM 3.0 (C) Borland Inc. and is designed to work with tasm and tasm-compatible assemblers. To use the fog object module in your code: tasm /m3 myvir.asm tlink (/t) myvir fog If you select to assemble fog down from the source, you should use tasm /m3 fog.asm before linking the resultant object module into your code. ------------------------------------------------------------------- The code size of FOG in its present condition is 55Bh (1371) bytes. ------------------------------------------------------------------- If you modify the source, assemble with TASM /m3 /l and take a look on top of the lst file; there will be a constant named fogsize - this is FOG's effective length. TECHNICAL OVERVIEW: Fog constructs its decryptor in a stepwise manner. The flow of execution when encrypting can be summarised like this: * Choose Initialization strategy * Choose Crypt strategy * Choose Base updating strategy * Choose Loopback strategy (Decryptor and encryptor are finished here !!!) * Add a jump to starting point in code, often this will be just a JMP 0. * Encrypt main code * If some alignment or static code size is chosen, pad the encrypted code until it has the right size. * Set all registers according to the correct feedback values, and return to caller. STRATEGIES: **** Init Strategy **** This is done by randomly choosing registers for key, base and count and generate MOV reg, imm16 instructions with the appropriate numbers. Junk (if selected) will be filled in between these instructions. **** Crypt strategy **** The standard crypto instruction will be of the type: ( The / separates options that are used with equal probability ) RND 1..15 * (XOR/SUB/ADD CS:/DS:/ES:/SS: [BX/SI/DI]/[BX/SI/DI+disp16], imm16/reg) RND 0..7 * (ROL reg,1) The segment overrides DS:/ES:/SS: will of course only be created in COM file mode, in EXE mode only CS: will appear. So decryptors can look like this: XOR SS:[SI+0490],FD81 + junk XOR CS:[SI+0490],DX " ADD CS:[SI+0490],DX " SUB CS:[SI+0490],8755 " XOR ES:[SI+0490],5886 " ADD SS:[SI+0490],770B " ADD DS:[SI+0490],0322 " ROL DX,1 " ROL DX,1 " ROL DX,1 " or like this: XOR SS:[BX],DX + junk At the same time as the decryptor instructions are generated, the encryptor is inversely built in the encryptor buffer. As you will have noticed, the key is always word sized. **** Base updating strategy **** Base updating instructions can be of the type: ADD reg, 2/-2 or SUB reg, 2/-2 or DEC reg DEC reg or INC reg INC reg **** Loopback strategy **** Loopbacks will look like this: LOOP ... or DEC reg JNZ ..... (The above will only be used if backwards jump is less than 128 bytes.) or DEC reg JZ 03 JMP .... or DEC reg JZ 05 MOV reg, offset .... PUSH reg RET There are many more ways to do this, of course, use your imagination and add some. STRONG POINTS: * Cryptographic toughness FOG utilises a powerful mutation encryption algorithm, making the encryptors very variable indeed. Cryptanalysis is going to be hard on this one, as there is between 1 and 15 random xor/sub/add/rol operations with different keys on each element to be encrypted. With the change of just one constant in the enclosed source this number can be much increased. * Junk instruction generation The junk instructions, generically generated by FOG, includes instructions of 1, 2, 3, 4, 5 and even 2*7 bytes, and FOG can generate up to 255 such junk instructions between *each* good instruction. I've had test decryptors varying between 20 bytes and 10k (!). * Configurable FOG is configurable in most aspects. Based on what you tell it, it will behave very differently from configuration to configuration. Examples: 1. mov al, sw_nogarb call fog_init This will cause FOG to generate short decryptors without any garbage or debugger hostile instructions at all. Turning off garbage also turns off debugger hostility, so any value in AH will be ignored. The encryption will however be just as strong as before, and the decryptor will still mutate. 2. mov al, sw_007_gi mov ah, sw_int3 or sw_prefetch call fog_init This setting will cause FOG to generate between 1 and 7 junk instructions between each good one. Randomly interspersed in these junk instructions will be some debugger hostile instructions, in this case int 3's and prefetch traps. The int 3's are just bothersome when debugging, the prefetch traps will fool the unin- telligent debuggers and some of those programs who try to auto- matically decrypt the encrypted code; TbClean crashes spectacularly. 3. mov al, sw_255_gi mov ah, sw_debug call fog_init This setting will cause FOG to generate medium to very big decryptors, as there will be between 1 and 255 garbage instructions between each good instruction. However, setting ah to sw_debug causes the garbage generated to not contain any debugger hostility at all, and *no encryption will be performed*. 4. mov cl, (sw_r_garb or sw_r_host) call fog_init This will tell FOG to ignore any settings of AH or AL, and randomly choose a setting for itself. Thus the setting may be one of extreme garbage generation and/or hostility or the opposite. Note that FOG will behave according to this until next time you call fog_init, and another random setting will be chosen. If used in a virus, his would have the effect that samples of one generation could be *totally* different from samples of another generation 5. mov cl, sw_const_s call fog_init This will cause FOG to generate decryptor+encrypted code of constant size each time you encrypt. This will be of use for stealth virus production. Fog manages this by padding all encryptions up to the point where it's very unlikely that a bigger decryptor will be created. Note that with high junk configuration there often will be a nauseatingly huge pad area at the end of files. 6. mov cl, sw_align16 call fog_init Some people make viruses that need to be padded up to a paragraph border, for self recognition or other purposes. With this setting FOG will do that. 7. mov cl, sw_align256 call fog_init Same as previous, but with 256 byte page borders. * Generic programming This engine is released with the commented original source code. It's of course possible to improve the engine, and it's relatively easy to do so around its current framework. For instance is the garbage generation modular, by adding another module and updating the jump addresses FOG will spew out the new instructions just as easy and randomly as those included in the source. You may also note the vacant switches, where you may add more configurable options. One of FOG's strongest points is just this; by releasing the source it will mutate not just decryptors, but with time also it's own functionality. WEAK POINTS: * Decryptor obviousness Decryptors generated with this engine do not have any mechanisms to hide that they are decryptors (except junk). They do not generate any codesequence to fool scanners into believing that this is a legitimate program. Thus, heuristic scanners may smell a rat, especially TbScan when FOG uses low junk/hostility settings. TbScan detects the presence of a decryptor and sometimes succeed to decrypt the encrypted program. On high junk/hostility settings, however, TbScan mostly chokes and dies. The prefetch traps generate much noise, in the sense that they mess with memory and cause TbScan to whip out @, 1, D and U flags galore. On rare occasions they also cause the program to terminate or even hang. I have included jmp instructions in the standard set of functions from FOG, however these sometimes generate TbScan @ and J flags. * Scanning vulnerability When high debugger hostility is chosen, FOG generates fixed codesequences that might be scanned for, particularly the prefetch traps. This might be something to have in mind. * Huuuuuuge decryptors As mentioned before, with high garbage settings FOG may generate very large decryptors indeed. This may cause not only a considerable file growth, but also a noticeable timelag upon decrypting. * Statistical analysis vulnerability There is a chance that FOG will be vulnerable to statistical analysis. I have not performed any statistical computations on FOG's decryptors myself, but I think this might be done. However, scanners will have a hard time detecting *all* FOG encrypted viruses, due to FOG's variability. THE DEMO VIRUSES: Enclosed you will find the source and executables of different versions of AirRaid, which is the demo virus for this engine. AirRaid is a non-destructive resident *.com infector, made specifically for this purpose. Its lameness is also by intent. It will infect any *.com file (of proper size) executed. Infection marker is 'AR' at byte 4 and 5 in the file. The different versions are made to demonstrate the easy way you can configure the virus to do what you want. Ver 1. Plain virus, Fog not attached. Ver 2. Fog attached, configured to no garbage. Ver 3. Fog attached, configured to 15 garbage instructions, max hostility, fixed length Ver 4. Fog attached, configured to random garbage, random hostility. SWITCHES (as defined in the switches.inc file): AH AL Debugger hostility F E D C B A 9 8 7 6 5 4 3 2 1 0 Junk generation Unused ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ³ ³ ³ ³ ³ ³ ³ ³ ³ ³ ³ ³ ³ ³ À 1 junk instruction Unused ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ³ ³ ³ ³ ³ ³ ³ ³ ³ ³ ³ ³ ÀÄÄ 3 junk instructions Unused ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ³ ³ ³ ³ ³ ³ ³ ³ ³ ³ ÀÄÄÄÄ 7 junk instructions Use dos interrupts ÄÄÄÄÄÄÄÄÙ ³ ³ ³ ³ ³ ³ ³ ³ ÀÄÄÄÄÄÄ 15 junk instructions Unused ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ³ ³ ³ ³ ³ ³ ÀÄÄÄÄÄÄÄÄ 31 junk instructions Prefetch traps ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ³ ³ ³ ³ ÀÄÄÄÄÄÄÄÄÄÄ 63 junk instructions Unused ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ³ ³ ÀÄÄÄÄÄÄÄÄÄÄÄÄ 127 junk instructions Int 3 generation ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄ 255 junk instructions CH CL Internal switches F E D C B A 9 8 7 6 5 4 3 2 1 0 General switches Unused ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ³ ³ ³ ³ ³ ³ ³ ³ ³ ³ ³ ³ ³ ³ À random junk Unused ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ³ ³ ³ ³ ³ ³ ³ ³ ³ ³ ³ ³ ÀÄÄ random hostility Unused ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ³ ³ ³ ³ ³ ³ ³ ³ ³ ³ ÀÄÄÄÄ exe file Unused ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ³ ³ ³ ³ ³ ³ ³ ³ ÀÄÄÄÄÄÄ constant size Unused ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ³ ³ ³ ³ ³ ³ ÀÄÄÄÄÄÄÄÄ 256 byte alignment Down decryptor ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ³ ³ ³ ³ ÀÄÄÄÄÄÄÄÄÄÄ 16 byte alignment Use displacement ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ³ ³ ÀÄÄÄÄÄÄÄÄÄÄÄÄ Unused No jumps allowed ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Unused That's all for now. Take a look at the enclosed demo virus, AirRaid, to see how FOG can be used. ABOUT THE AUTHOR: I am a tertiary student from Australia's Sunshine State of Queensland. My interests include Rugby League, Cricket and low-level programming. Normally concentrating on visual and audio demonstrations, I turned my hand to polymorphism due to the unique challenge of that type of coding. I will only continue to pursue my virus programming career while the field remains interesting. HOW TO CONTACT THE AUTHOR: You can only contact me via my friend Qark, who is has internet access unlike myself. Included in the original package there should be 12 files: FOG .ASM Fog source code FOG .DOC This file FOG .OBJ Fog object module SWITCHES.INC Switch definition include file AIRRAID1.ASM AirRaid ver. 1 source AIRRAID2.ASM AirRaid ver. 2 source AIRRAID3.ASM AirRaid ver. 3 source AIRRAID4.ASM AirRaid ver. 4 source AIRRV1.ZIP AirRaid ver. 1 samples AIRRV2.ZIP AirRaid ver. 2 samples AIRRV3.ZIP AirRaid ver. 3 samples AIRRV4.ZIP AirRaid ver. 4 samples Any other file is not acknowledged by me. Eclipse. Queensland, Australia, June 1995.