Skip to content

Commit 505abde

Browse files
committed
Anti-Fingerprint
1 parent 2d54929 commit 505abde

File tree

14 files changed

+2061
-15
lines changed

14 files changed

+2061
-15
lines changed

README.md

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -223,12 +223,12 @@ Examples:
223223
### Larger Scan Radius
224224
- Extended up to 65×65 chunks for all chunk-based features.
225225

226-
### Above Ground (New Option)
226+
### Above Ground (New ESP Option)
227227
- ItemESP, MobSearch, Search, ChestESP, BedESP, SignESP, PortalESP, RedstoneESP and WorkstationESP now have an adjustable Y limit (default 62 which is approximately sea level)
228228
- There is a global toggle and setting that can apply to all, or the user can set toggle and set them individually in the hack's settings (```.aboveground on/off```, ```.aboveground toggle```, ```.aboveground y #```)
229-
- This will help prevent you from detecting inaccessible mobs/items and essentially only scanning the surface of the world
229+
- This will help prevent you from detecting inaccessible mobs/items and help you focus on scanning the surface of the world (if that's your goal)
230230

231-
### Sticky Area (New Option)
231+
### Sticky Area (New ESP Option)
232232
- Added to chunk-based ESPs (Search, Portal ESP, BedESP, SignESP, WorkstationESP, RedstoneESP, ChestESP).
233233
- Keeps results anchored as you move. Default OFF.
234234

@@ -246,6 +246,17 @@ Examples:
246246

247247
![Disc](https://i.imgur.com/b327XLx.png)
248248

249+
### Anti-Fingerprint
250+
- Detects and stops resource-pack fingerprinting.
251+
- Policies: Observe (vanilla prompt + log), BlockLocal (decline private/LAN), BlockAll (decline all), SandboxAll (server sees fail; client saves copy).
252+
- Detects burst requests (N in M ms) with toasts; supports host whitelist.
253+
- Cache defenses: clear before download and per-session cache isolation.
254+
- Sandbox: optional auto-extract of resource-packs for inspection.
255+
- Telemetry: toast verbosity + audit log (host/IP/URL/UUID/required, cache/sandbox paths).
256+
- Access via Other → Anti-Fingerprint, Wurst Options, and Multiplayer/Server Finder buttons.
257+
258+
![AntiFingerprint](https://i.imgur.com/4xycaQG.png)
259+
249260
### Usability
250261
- Right-click Area setting resets it to default.
251262

Lines changed: 322 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,322 @@
1+
/*
2+
* Copyright (c) 2014-2025 Wurst-Imperium and contributors.
3+
*
4+
* This source code is subject to the terms of the GNU General Public
5+
* License, version 3. If a copy of the GPL was not distributed with this
6+
* file, You can obtain one at: https://www.gnu.org/licenses/gpl-3.0.txt
7+
*/
8+
package net.cevapi.config;
9+
10+
import java.util.Arrays;
11+
import java.util.Collections;
12+
import java.util.LinkedHashSet;
13+
import java.util.List;
14+
import java.util.Locale;
15+
import java.util.Set;
16+
17+
import net.wurstclient.settings.CheckboxSetting;
18+
import net.wurstclient.settings.EnumSetting;
19+
import net.wurstclient.settings.Setting;
20+
import net.wurstclient.settings.SliderSetting;
21+
import net.wurstclient.settings.SliderSetting.ValueDisplay;
22+
import net.wurstclient.settings.TextFieldSetting;
23+
24+
/**
25+
* Configuration model for the Anti-Fingerprint protections.
26+
*/
27+
public final class AntiFingerprintConfig
28+
{
29+
public static final AntiFingerprintConfig INSTANCE =
30+
new AntiFingerprintConfig();
31+
32+
private static final int THRESHOLD_MIN = 2;
33+
private static final int THRESHOLD_MAX = 10;
34+
private static final int WINDOW_MIN = 250;
35+
private static final int WINDOW_MAX = 15000;
36+
37+
private final EnumSetting<Policy> policy =
38+
new EnumSetting<>("Policy", Policy.values(), Policy.OBSERVE);
39+
40+
private final EnumSetting<ToastVerbosity> toastVerbosity =
41+
new EnumSetting<>("Toast verbosity", ToastVerbosity.values(),
42+
ToastVerbosity.IMPORTANT_ONLY);
43+
44+
private final CheckboxSetting auditLog =
45+
new CheckboxSetting("Audit log", false);
46+
47+
private final CheckboxSetting purgeCache =
48+
new CheckboxSetting("Clear cache before download",
49+
"Deletes the local server resource-pack cache right before every"
50+
+ " request, forcing a fresh download each time.",
51+
false);
52+
53+
private final CheckboxSetting isolateCache = new CheckboxSetting(
54+
"Isolate cached packs",
55+
"Stores server resource packs inside a per-session directory so cached copies can't be reused for fingerprinting.",
56+
false);
57+
58+
private final CheckboxSetting extractSandbox = new CheckboxSetting(
59+
"Extract sandbox copy",
60+
"After sandboxing a pack, automatically extract it using Minecraft's resource-pack loader so you can inspect the contents.",
61+
false);
62+
63+
private final SliderSetting fingerprintThreshold = new SliderSetting(
64+
"Fingerprint threshold",
65+
"Number of packs within the window before a fingerprint attempt is assumed.",
66+
3, THRESHOLD_MIN, THRESHOLD_MAX, 1, ValueDisplay.INTEGER);
67+
68+
private final SliderSetting fingerprintWindowMs =
69+
new SliderSetting("Fingerprint window (ms)",
70+
"Time window used to detect rapid pack requests.", 1500, WINDOW_MIN,
71+
WINDOW_MAX, 250, ValueDisplay.INTEGER);
72+
73+
private final TextFieldSetting whitelistedHosts = new TextFieldSetting(
74+
"Whitelisted hosts",
75+
"Comma separated list of hostnames or host:port entries that should bypass the protector.",
76+
"", AntiFingerprintConfig::isValidHostList);
77+
78+
private AntiFingerprintConfig()
79+
{
80+
81+
}
82+
83+
public EnumSetting<Policy> getPolicySetting()
84+
{
85+
return policy;
86+
}
87+
88+
public EnumSetting<ToastVerbosity> getToastVerbositySetting()
89+
{
90+
return toastVerbosity;
91+
}
92+
93+
public CheckboxSetting getAuditLogSetting()
94+
{
95+
return auditLog;
96+
}
97+
98+
public CheckboxSetting getPurgeCacheSetting()
99+
{
100+
return purgeCache;
101+
}
102+
103+
public CheckboxSetting getIsolateCacheSetting()
104+
{
105+
return isolateCache;
106+
}
107+
108+
public CheckboxSetting getExtractSandboxSetting()
109+
{
110+
return extractSandbox;
111+
}
112+
113+
public SliderSetting getFingerprintThresholdSetting()
114+
{
115+
return fingerprintThreshold;
116+
}
117+
118+
public SliderSetting getFingerprintWindowSetting()
119+
{
120+
return fingerprintWindowMs;
121+
}
122+
123+
public TextFieldSetting getWhitelistSetting()
124+
{
125+
return whitelistedHosts;
126+
}
127+
128+
public Policy getPolicy()
129+
{
130+
return policy.getSelected();
131+
}
132+
133+
public ToastVerbosity getToastVerbosity()
134+
{
135+
return toastVerbosity.getSelected();
136+
}
137+
138+
public boolean isAuditLogEnabled()
139+
{
140+
return auditLog.isChecked();
141+
}
142+
143+
public boolean shouldClearCache()
144+
{
145+
return purgeCache.isChecked();
146+
}
147+
148+
public boolean shouldIsolateCache()
149+
{
150+
return isolateCache.isChecked();
151+
}
152+
153+
public boolean shouldExtractSandbox()
154+
{
155+
return extractSandbox.isChecked();
156+
}
157+
158+
public int getFingerprintThreshold()
159+
{
160+
return Math.max(2, fingerprintThreshold.getValueI());
161+
}
162+
163+
public long getFingerprintWindowMs()
164+
{
165+
return Math.max(250L, fingerprintWindowMs.getValueI());
166+
}
167+
168+
public int getThresholdMin()
169+
{
170+
return THRESHOLD_MIN;
171+
}
172+
173+
public int getThresholdMax()
174+
{
175+
return THRESHOLD_MAX;
176+
}
177+
178+
public int getWindowMin()
179+
{
180+
return WINDOW_MIN;
181+
}
182+
183+
public int getWindowMax()
184+
{
185+
return WINDOW_MAX;
186+
}
187+
188+
public String getWhitelistRaw()
189+
{
190+
return whitelistedHosts.getValue();
191+
}
192+
193+
public void setWhitelistRaw(String value)
194+
{
195+
whitelistedHosts.setValue(value);
196+
}
197+
198+
public Set<String> getWhitelistedHosts()
199+
{
200+
String value = whitelistedHosts.getValue();
201+
if(value.isBlank())
202+
return Collections.emptySet();
203+
204+
String[] items = value.split(",");
205+
LinkedHashSet<String> set = new LinkedHashSet<>();
206+
for(String item : items)
207+
{
208+
String trimmed = item.trim().toLowerCase(Locale.ROOT);
209+
if(trimmed.isEmpty())
210+
continue;
211+
set.add(trimmed);
212+
}
213+
214+
return Collections.unmodifiableSet(set);
215+
}
216+
217+
public List<Setting> getAllSettings()
218+
{
219+
return Arrays.asList(policy, toastVerbosity, auditLog, purgeCache,
220+
isolateCache, extractSandbox, fingerprintThreshold,
221+
fingerprintWindowMs, whitelistedHosts);
222+
}
223+
224+
private static boolean isValidHostList(String value)
225+
{
226+
if(value == null)
227+
return false;
228+
229+
if(value.isEmpty())
230+
return true;
231+
232+
String[] items = value.split(",");
233+
for(String item : items)
234+
{
235+
String trimmed = item.trim();
236+
if(trimmed.isEmpty())
237+
return false;
238+
239+
if(trimmed.length() > 128)
240+
return false;
241+
242+
if(!trimmed.matches("^[A-Za-z0-9\\-._:\\[\\]]+$"))
243+
return false;
244+
}
245+
246+
return true;
247+
}
248+
249+
public static enum Policy
250+
{
251+
OBSERVE("Observe"),
252+
BLOCK_LOCAL("Block Local"),
253+
SANDBOX_ALL("Sandbox All"),
254+
BLOCK_ALL("Block All");
255+
256+
private final String displayName;
257+
258+
private Policy(String displayName)
259+
{
260+
this.displayName = displayName;
261+
}
262+
263+
@Override
264+
public String toString()
265+
{
266+
return displayName;
267+
}
268+
}
269+
270+
public static enum ToastVerbosity
271+
{
272+
SILENT("Silent")
273+
{
274+
@Override
275+
public boolean allows(ToastLevel level)
276+
{
277+
return false;
278+
}
279+
},
280+
IMPORTANT_ONLY("Important")
281+
{
282+
@Override
283+
public boolean allows(ToastLevel level)
284+
{
285+
return level != ToastLevel.INFO;
286+
}
287+
},
288+
VERBOSE("Verbose")
289+
{
290+
@Override
291+
public boolean allows(ToastLevel level)
292+
{
293+
return true;
294+
}
295+
};
296+
297+
private final String displayName;
298+
299+
private ToastVerbosity(String displayName)
300+
{
301+
this.displayName = displayName;
302+
}
303+
304+
public boolean allows(ToastLevel level)
305+
{
306+
return true;
307+
}
308+
309+
@Override
310+
public String toString()
311+
{
312+
return displayName;
313+
}
314+
}
315+
316+
public static enum ToastLevel
317+
{
318+
INFO,
319+
WARN,
320+
ERROR
321+
}
322+
}

0 commit comments

Comments
 (0)