Open Illya9999 opened 1 year ago
Nice! This looks incredible.
This could be a valuable addition to the test page, allowing for a comparative analysis of its performance across various engines. Additionally, I am contemplating eliminating the majority of lie detections and a significant portion of the main script on the client side, and instead focusing on detecting anomalies and tracing fingerprints in the server-side time series. The main objective of the idea is to make the client-side code so simple that it will appear embarrassing and easy to fool. All the client-side analysis, including proxy detection, will probably be moved to the test pages.
I'm best reached here or anywhere in open-source repos on GitHub, discussions or issues.
The main objective of the idea is to make the client-side code so simple that it will appear embarrassing and easy to fool
Ah I see. Well if you are interested in an example of some stronger proxy code for testing, this is the code I like to use. It's still in a very early WIP stage but it still works fairly nicely for most things. Even if you assume all the todo comments were completed, there are still quite a few ways to detect it. However it should still bypass most ways to detect things with just the current code. Also keep in mind this code is primarily written for chromium on windows.
const hooked = new WeakMap();
const getHook = WeakMap.prototype.get.bind(hooked);
const setHook = WeakMap.prototype.set.bind(hooked);
const hasHook = WeakMap.prototype.has.bind(hooked);
const proxies = new WeakMap();
const getProxy = WeakMap.prototype.get.bind(proxies);
const setProxy = WeakMap.prototype.set.bind(proxies);
const hasProxy = WeakMap.prototype.has.bind(proxies);
const initWin = new WeakSet();
const addInit = WeakSet.prototype.add.bind(initWin);
const hasInit = WeakSet.prototype.has.bind(initWin);
const Prox = Proxy;
const init = (win) => {
if(hasInit(win))
return;
const getOwnPropDesc = win.Object.getOwnPropertyDescriptor.bind(win.Object);
const defineProp = win.Object.defineProperty.bind(win.Object);
const apply = win.Reflect.apply.bind(win.Reflect);
const toString = win.Function.prototype.call.bind(win.Function.prototype.toString);
const createArray = win.Array.from.bind(win.Array);
const hook = (func, applyF) => {
if(hasHook(func))
return getHook(func);
const proxy = new Prox(func, {
__proto__: null,
apply: applyF
});
setHook(func, proxy);
setProxy(proxy, func);
return proxy;
}
win.Function.prototype.toString = hook(win.Function.prototype.toString, function(target, thisArg, argumentsList) {
if(hasProxy(thisArg)) {
return toString(getProxy(thisArg));
} else {
return apply(target, thisArg, argumentsList)
}
});
/* I hate this but its required. I think its probably the biggest weakpoint of the entire script */
win.Object.create = hook(win.Object.create, function (target, thisArg, argumentsList) {
/* the reason this is done like this is to emulate how apply would work with a proxy as the arguments array without giving away internal info to it */
let len = argumentsList.length - 0 | 0,
arr = createArray({ length: len, __proto__: null});
for(let i = 0; i < len; i++) {
arr[i] = argumentsList[i];
}
if(len > 0 && hasProxy(arr[0])) {
arr[0] = getProxy(arr[0]);
}
/* i believe this can cause a problem due to it activating .length getter on the arr object, should be an easy fix */
return apply(target, thisArg, arr)
});
/* i believe there can be some issues with this due to cross origin iframes. a solution needs to be created (chrome extension api?) */
const initFrame = (frame) => {
const contentWin = getOwnPropDesc(frame.prototype, 'contentWindow');
contentWin.get = hook(contentWin.get, function(target, thisArg, argumentsList) {
const frameWin = apply(target, thisArg, argumentsList);
if(frameWin && !hasInit(frameWin)) {
init(frameWin)
}
return frameWin;
});
defineProp(frame.prototype, 'contentWindow', contentWin);
/* make sure to get contentDocument as well */
}
/* do for the other frame elements not just iframe */
initFrame(win.HTMLIFrameElement);
initFrame(win.HTMLFrameElement);
/* make sure to add hooks for adding elements as well so incase they dont access the prop and the frame has code that would do stuff before u can hook */
/* make sure to add hooks for innerHTML and such adding in a frame element */
/* hook the error stack trace */
/* add hooks for popup windows like the iframes */
/* a solution should be added for service workers and such (chrome extension api?) */
addInit(win);
/* hooks here */
win.alert = hook(win.alert, function() { return 'lol no'});
}
init(window);
Hello, @abrahamjuliot ! I have seen the idea of implementing server side fingerprinting in your posts more than once. Can you suggest some articles to learn more about it?
I'll second this.
Curious to know what black-arts / necromancy you'd need to get better fingerprinting with fewer direct client interactions!
On Wed, Aug 30, 2023 at 10:04 AM amadeocomo @.***> wrote:
Hello, @abrahamjuliot https://github.com/abrahamjuliot ! I have seen the idea of implementing server side fingerprinting in your posts more than once. Can you suggest some articles to learn more about it?
— Reply to this email directly, view it on GitHub https://github.com/abrahamjuliot/creepjs/issues/238#issuecomment-1699356163, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAS6F54NQVG377SMWHNPUUTXX5I7PANCNFSM6AAAAAA37XRKAQ . You are receiving this because you are subscribed to this thread.Message ID: @.***>
What I'm doing is mostly experimental and straightforward. There is a confidence score that is satisfied by unique reporters per date over the span of a few days, and it gets marked for death if it becomes dormant. To review and purge data, I run 24-hour cron jobs.
Time series include multiple series that tell the code what segment of time we are in, such as the minute of 1444 in a day, or the current 10 minute and 30-minute episode in a day. The system then assembles pre-decided attributes into tiny spectra and observes erratic occurrences in the sequence. For instance, the code is capable of detecting in a 30-minute segment that features a and b are encountering an atypical amount of variation in feature c or c-z. It can do this for 100s or 1000s of different combinations and react to them.
I would recommend checking out the concepts below.
https://www.researchgate.net/publication/330357393_Deep_Learning_for_Anomaly_Detection_A_Survey https://www.researchgate.net/publication/362296986_Anomaly_detection_in_time_series_a_comprehensive_evaluation
Biological fingerprinting has some interesting techniques that can be transferred to browser fingerprinting. https://www.researchgate.net/publication/229886628_Fingerprinting_time_series_Dynamic_patterns_in_self-report_and_performance_measures_uncovered_by_a_graphical_non-linear_method https://www.researchgate.net/publication/333783134_Fingerprint_Presentation_Attack_Detection_utilizing_Time-Series_Color_Fingerprint_Captures
I believe stronger proxy detection as well as ways to recover the target object should be added to this project. I wrote up an example for some basic proxy detection/target recovery. Its fairly easy to bypass but for some reason people almost never add bypasses for this sort of basic detection method. There are also some easy changes here you could make to improve its resiliency to tampering and make it slightly more reliable.
I would also be interested in discussing more advanced detections/bypasses. Do you have some platform I can contact you directly on?