Subversion Repositories filter_foundry

Rev

Rev 507 | Go to most recent revision | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

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