Subversion Repositories filter_foundry

Rev

Rev 375 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
267 daniel-mar 1
# Obfuscated filters
2
 
272 daniel-mar 3
## Resource location
267 daniel-mar 4
 
5
Obfuscated standalone filters:
375 daniel-mar 6
- Windows resource: OBFS\16\0 (previously RCDATA\16001\0)
7
- MacOS resource: 'obFS' 16 (previously 'DATA' 16001)
267 daniel-mar 8
 
9
Normal standalone filters:
375 daniel-mar 10
- Windows resource: PARM\16\0 (previously PARM\16000\0)
11
- MacOS resource: 'PARM' 16 (previously 'PARM' 16000)
267 daniel-mar 12
 
271 daniel-mar 13
## Implementation
270 daniel-mar 14
 
292 daniel-mar 15
Defined in **ff.h**, implemented in **obfusc.c**:
267 daniel-mar 16
 
347 daniel-mar 17
    // Implements Obfusc V6.
317 daniel-mar 18
    // Returns a seed that needs to be stored in the executable code.
347 daniel-mar 19
    uint64_t obfusc(PARM_T* pparm);
282 daniel-mar 20
 
21
    // In V1+V2: Seed is hardcoded
317 daniel-mar 22
    // In V3:    Seed is in PARM (field "unknown2")
347 daniel-mar 23
    // In V4-V6: Seed is in the program code and will me modified with a binary search+replace
271 daniel-mar 24
    void deobfusc(PARM_T* pparm);
25
 
347 daniel-mar 26
### Obfuscation "Version 6"
27
 
28
Introduced in **Filter Foundry 1.7.0.10**
29
 
441 daniel-mar 30
First, the fields `unknown1`, `unknown2`, aned `unknown3` are set to 0.
347 daniel-mar 31
 
348 daniel-mar 32
A 64 bit seed will be generated.
349 daniel-mar 33
On Windows, the seed is the ECMA 182 CRC64 checksum of the PARM.
34
On Macintosh, it stays at the default value `0x38AD972A52830517`
35
(because the manipulation of the binary code is not implemented).
348 daniel-mar 36
 
349 daniel-mar 37
Then, the CRC32b checksum of the PARM will be written to `unknown1`.
38
 
39
The PARM will then be XORed with a random data stream of the lower 32 bits of the 64 bit seed.
347 daniel-mar 40
The algorithm is the XORshift which was introcuced in obfuscation version 2.
41
Unlike obfuscation version 3-5, while generating and applying the random data
42
stream, no bytes are skipped.
43
 
348 daniel-mar 44
After this, PARM will be XORed with the 64 bit seed,
45
which will be ROLed by 1 bit after each byte:
347 daniel-mar 46
 
348 daniel-mar 47
    uint64_t rol_u64(uint64_t value, uint64_t by) {
48
        return value << by | value >> (sizeof(uint64_t) * 8 - by);
49
    }
50
 
51
The 64 bit seed is stored in the executable.
52
 
347 daniel-mar 53
The DWORD value `0x00000006` will be stored at field `unknown2`
54
(byte 0x30..0x33; the field is not used in the `PARM` resource).
55
 
56
During de-obfuscation, the program will check if the checksum in `unknown1`
57
matches. If it does not match, the data will be discarded.
58
 
292 daniel-mar 59
### Obfuscation "Version 5"
60
 
61
Introduced in **Filter Foundry 1.7.0.8**
62
 
63
Obfuscation version 5 is the same as version 4, but there is a constraint
311 daniel-mar 64
that the seed must be equal to the CRC32b checksum of the deobfuscated PARM.
292 daniel-mar 65
This is done to check the integrity of the deobfuscation.
311 daniel-mar 66
 
309 daniel-mar 67
Also, the xor-shifting is intentionally incompatible with version 4
311 daniel-mar 68
(to avoid downgrade-attacks) by XORing the initial seed with 0xFFFFFFFF.
292 daniel-mar 69
 
329 daniel-mar 70
The DWORD value `0x00000005` will be stored at field `unknown2`
71
(byte 0x30..0x33; the field is not used in the `PARM` resource).
72
 
73
While generating and applying the random data stream, the bytes
74
0x30..0x33 (the location where the version info is stored) are skipped,
75
like in version 3.
76
 
276 daniel-mar 77
### Obfuscation "Version 4"
78
 
292 daniel-mar 79
Introduced in **Filter Foundry 1.7.0.7**
276 daniel-mar 80
 
81
It is not compiler-dependant, but different between every standalone filter.
82
 
277 daniel-mar 83
Windows version:
276 daniel-mar 84
The binary code of the 8BF file will be manipulated during building
282 daniel-mar 85
to store the seed into the `deobfusc()` function.
86
The placeholder value is `OBFUSC_V4_DEFAULT_SEED 0x52830517`
87
This allows that 32-bit and 64-bit filters are "cross built".
276 daniel-mar 88
 
277 daniel-mar 89
(Theoretical) Macintosh version:
329 daniel-mar 90
Obfuscation and deobfuscation has the seed `0x52830517`, since the
277 daniel-mar 91
manipulation of the binary code is not implemented.
92
 
282 daniel-mar 93
Algorithm: XOR-Shift like in version 2, but the seed is individual for
276 daniel-mar 94
each individual built standalone filter.
95
 
329 daniel-mar 96
The DWORD value `0x00000004` will be stored at field `unknown2`
97
(byte 0x30..0x33; the field is not used in the `PARM` resource).
276 daniel-mar 98
 
329 daniel-mar 99
While generating and applying the random data stream, the bytes
100
0x30..0x33 (the location where the version info is stored) are skipped,
101
like in version 3.
102
 
271 daniel-mar 103
### Obfuscation "Version 3"
104
 
292 daniel-mar 105
Introduced in **Filter Foundry 1.7.0.5**
267 daniel-mar 106
 
329 daniel-mar 107
A random seed is chosen and written to field `unknown2` (byte 0x30..0x33).
267 daniel-mar 108
 
329 daniel-mar 109
Then, the `PARM` resource will be obfuscated by applying an XOR operation to a random data stream:
267 daniel-mar 110
 
329 daniel-mar 111
    unsigned char *p;
112
    *p++ ^= (int)(rand() * 1.0 / (RAND_MAX + 1) * 256);
113
 
114
Bytes 0x30..0x33 (the location where the seed is stored) are skipped.
115
 
116
The `rand()` operation is compiler-dependant, and therefore the resource cannot be exchanged between plugins.
117
 
270 daniel-mar 118
32 bit plugin is built with OpenWatcom (for Win95 compatibility) which has following formula:
119
 
120
    int rand_openwatcom(unsigned int* seed) {
121
            *seed = *seed * 1103515245L + 12345L;
122
            return (*seed >> 16) & 0x7fff; /* Scale between 0 and RAND_MAX */
123
    }
124
 
271 daniel-mar 125
64 bit plugin is built with Visual C++ which has following formula:
270 daniel-mar 126
 
127
    int rand_msvcc(unsigned int* seed) {
272 daniel-mar 128
            *seed = *seed * 214013L + 2531011L;
129
            return (*seed >> 16) & 0x7fff; /* Scale between 0 and RAND_MAX */
270 daniel-mar 130
    }
131
 
271 daniel-mar 132
### Obfuscation "Version 2"
267 daniel-mar 133
 
292 daniel-mar 134
Introduced in **Filter Foundry 1.7b1**
267 daniel-mar 135
 
329 daniel-mar 136
It is compiler-independent!
267 daniel-mar 137
 
138
Algorithm: [XOR-Shift](https://de.wikipedia.org/wiki/Xorshift "XOR-Shift") with hardcoded seed `0x95d4a68f`.
139
 
140
    x32 = 0x95d4a68f;
141
    for(i = size, p = pparm; i--;) {
272 daniel-mar 142
            x32 ^= x32 << 13;
143
            x32 ^= x32 >> 17;
144
            x32 ^= x32 << 5;
145
            *p++ ^= x32;
267 daniel-mar 146
    }
147
 
271 daniel-mar 148
### Obfuscation "Version 1"
267 daniel-mar 149
 
150
Introduced in **Filter Foundry 1.4b8,9,10**
151
 
329 daniel-mar 152
It is compiler-dependant, and therefore the resource cannot be exchanged between plugins!
267 daniel-mar 153
 
154
Algorithm: XOR with `rand()`-stream with hardcoded seed `0xdc43df3c`.
155
 
156
    srand(0xdc43df3c);
157
    for(i = size, p = pparm; i--;) {
272 daniel-mar 158
            *p++ ^= rand();
271 daniel-mar 159
    }
160
 
161
The plugin is built with Visual C++ which has following formula:
162
 
163
    int rand_msvcc(unsigned int* seed) {
272 daniel-mar 164
            *seed = *seed * 214013L + 2531011L;
165
            return (*seed >> 16) & 0x7fff; /* Scale between 0 and RAND_MAX */
271 daniel-mar 166
    }
167