BTX encryption BTS Bit Test and Set This instruction test in bit base: the bit specified by offset. Carry flag is set according to test, if bit was 0 then CF = 0 else CF = 1. The bit is then set to 1. This means that we can use BTS to set every bit individually from each virus value. You can use it to set random bit to complete a bit string: V-value 1 byte bit string: 11101111 V-value 1 byte bit string "encrypted" value: 10101010 So we know that we must set bit at offset 6, 4, 2, 0 in DWORD BTS: bts dword ptr [bitbase], offset You could also use full of zero so that there are no virus values, only large amount of BTS instructions. BTR Bit Test and Reset This instruction test in bit base: the bit specified by offset. Carry flag is set according to test, if bit was 0 then CF = 0 else CF = 1. The bit is then set to 0. This means that we can use BTR to unset every bit individually from each virus value. A long full of 1 (then the "encrypted" would look like FFFF FFFFF ;) ) could be used. Or an unset schema like BTS. BTC Bit Test and Complement This instruction test in bit base: the bit specified by offset. Carry flag is set according to test, if bit was 0 then CF = 0 else CF = 1. The bit is then complemented. A complement is NOT on the bit, so if bit is 0 then it will be set to 1 or if bit was 1 it will be set to zero. So, this is like having both BTS and BTR in one instruction! This means your virus can take the unusual shape of: FFFFFFFF 00000000 FFFFFFFF FFFF0000 FFFFFFFF 0000FFFF 00FF00FF or FFFFFFFF 00000000 FFFF1ED6 FFFF0000 FFFFFFFF 67DB6F7A 00FF00FF Registers Initialisation The problem with most decryptors outhere is that they use too many registers, this technique only needs 1 register if not ESP. The register points to the memory address where the virus will be decrypted. A register can be also set using BTS/BTR/BTC, but we must know the content of the register before using the instructions or it will be transformed to a random value, a crash might happen if we touch invalid memory. If we use BTS - and BTR to obfuscate - we can set any register in this way: (bit offset values are decimal) xor eax, eax btr eax, 21 bts eax, 22 btr eax, 23 bts eax, 14 btr eax, 13 bts eax, 12 btr eax, 11 EAX is now 00405000 If we use BTC - and BTR to obfuscate - we can set any register in this way: (bit offset values are decimal) or eax, -1 btc eax, 31 btr eax, 30 btr eax, 29 btc eax, 28 btr eax, 27 btr eax, 26 btr eax, 25 btc eax, 24 btr eax, 23 btr eax, 21 btc eax, 20 btr eax, 19 btc eax, 18 btr eax, 17 btc eax, 16 btr eax, 15 btc eax, 13 btr eax, 11 btr eax, 10 btc eax, 9 btc eax, 8 btr eax, 7 btc eax, 6 btr eax, 5 btc eax, 4 btr eax, 3 btr eax, 2 btr eax, 1 btc eax, 0 EAX is now 00405000 Another way to get the address is using CALL+POP, so we can support ASLR, too. Using the stack is another option if push every "encrypted" value. ESP would be bit base and thus no register is initialised. For more obfuscation on the bits we want to set, we can use larger offset. How? Very simple, using larger offset is just like using 0 to 31, but we must be careful: for instance, if bts 31 sets 00000000 to 80000000 then with larger offset we use bts 31 + 32. From now on, we go from 1 to 32 using 31 as base. (bit offset values are decimal) xor eax, eax bts eax, 32 + 22 bts eax, 32 + 14 bts eax, 32 + 12 EAX is now 00405000 hh86