82,12 → 82,24 |
#else |
// Unfortunately, with this compiler, we the value needs to be in the .data segment... |
// Due to "const volatile", this value will only exist a single time in the binary file. |
const volatile uint64_t seed = 0x7416972a52830517ull; |
const volatile uint64_t obfusc_seed = 0x7416972a52830517ull; |
uint64_t GetObfuscSeed() { |
return seed; |
return obfusc_seed; |
} |
#endif |
|
// Random seed #2 for obfuscation "86 21 1f 3e f1 a2 87 ef" |
// Lies in the data segment. Same rules like for the random seed #1. |
const volatile uint64_t obfusc_seed2 = 0xef87a2f13e1f2186ull; |
#ifdef _MSC_VER |
__declspec(noinline) |
#endif |
uint64_t GetObfuscSeed2() { |
// Additional seed for Obfusc V7. It is always in the data segment, |
// while obfusc seed 1 is in the code segment (if the compiler allows it) |
return obfusc_seed2; |
} |
|
int rand_msvcc(unsigned int* seed) { |
*seed = *seed * 214013L + 2531011L; |
return (*seed >> 16) & 0x7fff; /* Scale between 0 and RAND_MAX */ |
112,6 → 124,19 |
*p = x; |
} |
|
void xorshift64(unsigned char** p, uint64_t* x64, size_t num) { |
// https://de.wikipedia.org/wiki/Xorshift |
size_t i; |
unsigned char* x = *p; |
for (i = 0; i < num; i++) { |
*x64 ^= *x64 << 13; |
*x64 ^= *x64 >> 7; |
*x64 ^= *x64 << 17; |
*x++ ^= *x64; |
} |
*p = x; |
} |
|
#ifndef CHAR_BIT |
#define CHAR_BIT 8 |
#endif |
279,7 → 304,8 |
// Version 4 obfuscation (Filter Foundry 1.7.0.7) |
// Version 5 obfuscation (Filter Foundry 1.7.0.8) |
// Version 6 obfuscation (Filter Foundry 1.7.0.10) |
// Future: Version 7, 8, ... 255 |
// Version 7 obfuscation (Filter Foundry 1.7.0.17) |
// Future: Version 8, ... 255 |
return obfusc_info; |
} |
else { |
289,28 → 315,36 |
} |
} |
|
uint64_t obfusc(PARM_T* pparm) { |
// Version 6 obfuscation (Introduced in Filter Foundry 1.7.0.10) |
void obfusc(PARM_T* pparm, uint64_t* out_initial_seed, uint64_t* out_initial_seed2) { |
// Version 7 obfuscation (Introduced in Filter Foundry 1.7.0.17) |
|
unsigned char* p; |
uint64_t initial_seed, rolseed; |
uint64_t initial_seed, initial_seed2, rolseed; |
uint32_t xorseed; |
uint64_t xorseed2; |
|
pparm->unknown1 = 0; |
pparm->unknown2 = 0; |
pparm->unknown3 = 0; |
|
#ifdef MAC_ENV |
// Currently, make_mac.c does not implement modifying the executable code (TODO), |
// so we will use the default initial_seed! |
initial_seed = GetObfuscSeed(); |
initial_seed2 = GetObfuscSeed2(); |
#else |
// Give always the same seed if the parameters are the same. No random values. |
// This initial seed will be returned and built into the executable code by make_win.c |
pparm->unknown1 = 0; |
pparm->unknown2 = 0; |
pparm->unknown3 = 0; |
initial_seed = crc64((unsigned char*)pparm, sizeof(PARM_T)); |
pparm->unknown3 = crc32b((char*)pparm, sizeof(PARM_T)); // make sure that the second seed is different |
pparm->unknown2 = crc32b((char*)pparm, sizeof(PARM_T)); // make sure that the second seed is different |
pparm->unknown1 = crc32b((char*)pparm, sizeof(PARM_T)); // make sure that the second seed is different |
initial_seed2 = crc64((unsigned char*)pparm, sizeof(PARM_T)); |
#endif |
|
// AFTER unknown1-3 have been set to 0, calculate the checksum! |
// AFTER unknown1-3 have been set to 0 (again), calculate the checksum! |
pparm->unknown1 = 0; |
pparm->unknown2 = 0; |
pparm->unknown3 = 0; |
pparm->unknown1 = crc32b((char*)pparm, sizeof(PARM_T)); |
|
xorseed = initial_seed & 0xFFFFFFFF; |
321,9 → 355,14 |
p = (unsigned char*)pparm; |
rolshift(&p, &rolseed, sizeof(PARM_T)); |
|
pparm->unknown2 = 6; // obfusc version |
xorseed2 = initial_seed2; |
p = (unsigned char*)pparm; |
xorshift64(&p, &xorseed2, sizeof(PARM_T)); |
|
return initial_seed; |
pparm->unknown2 = 7; // obfusc version |
|
*out_initial_seed = initial_seed; |
*out_initial_seed2 = initial_seed2; |
} |
|
void deobfusc(PARM_T* pparm) { |
473,6 → 512,46 |
|
break; |
} |
case 7: { |
// Version 7 obfuscation (Filter Foundry 1.7.0.17) |
// Not compiler dependent, but individual for each standalone filter |
// It is important that this code works for both x86 and x64 indepdently from the used compiler, |
// otherwise, the cross-make x86/x64 won't work! |
|
unsigned char* p; |
uint32_t xorseed, checksum; |
uint64_t xorseed2; |
uint64_t initial_seed, initial_seed2, rolseed; |
|
initial_seed = GetObfuscSeed(); // this value will be manipulated during the building of each individual filter (see make_win.c) |
initial_seed2 = GetObfuscSeed2(); // this value will be manipulated during the building of each individual filter (see make_win.c) |
|
// This is the difference between V6 and V7 |
xorseed2 = initial_seed2; |
p = (unsigned char*)pparm; |
xorshift64(&p, &xorseed2, sizeof(PARM_T)); |
|
rolseed = initial_seed; |
p = (unsigned char*)pparm; |
rolshift(&p, &rolseed, sizeof(PARM_T)); |
|
xorseed = initial_seed & 0xFFFFFFFF; |
p = (unsigned char*)pparm; |
xorshift(&p, &xorseed, sizeof(PARM_T)); |
|
checksum = pparm->unknown1; |
|
pparm->unknown1 = 0; |
pparm->unknown2 = 0; |
pparm->unknown3 = 0; |
|
if (checksum != crc32b((char*)pparm, sizeof(PARM_T))) { |
// Integrity check failed! |
memset(pparm, 0, sizeof(PARM_T)); // invalidate everything |
} |
|
break; |
} |
default: { |
// Obfuscation version unexpected! |
memset(pparm, 0, sizeof(PARM_T)); // invalidate everything |