Subversion Repositories filter_foundry

Rev

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