Subversion Repositories filter_foundry

Rev

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