While analyzing an attack in the wild I saw victims being redirected to a website hosting index.html (slightly beautified). The JavaScript code in the file does some very interesting fingerprinting before redirecting the user (perhaps based on fingerprint?).
The code has 88 functions, A1 to A92 (with some gaps), each probing/testing different properties. The goal of this project is to analyze and explain what each function does and why. And of course, understand how these are used in the rest of the script.
Please feel free to add information about the script or the individual functions. Perhaps this is a known library already? Help with deobfuscation is also appreciated!
go()
Returns the OS based on Navigator.userAgent.
Very similar to this code in FingerprintJS https://github.com/fingerprintjs/fingerprintjs/blob/bf7039da92655f981b2b958bb51a031e15601dbe/fingerprint2.js#L1110-L1129
gb()
Returns the browser based on Navigator.userAgent.
Each function window.screen.colorDepth
.
For each function I think it would be good to add:
- What does the code do?
- Why does it do it?
- Links and references.
Returns 1 if the two first characters in navigator.language
is
the same as the two first characters in navigator.languages[0]
.
This should always be true as per the standard: https://developer.mozilla.org/en-US/docs/Web/API/Navigator/languages
Maybe stolen from https://github.com/fingerprintjs/fingerprintjs
It is very similar to getHasLiedLanguages
that checks if the client is lying about its languages.
This is in version 2.1.0, can't find it in the latest version.
Does a few comparisons of screen width and height to available width and height, using
window.screen.width
, window.screen.availWidth
, etc.
Once again, similar to fingerprint JS, in particular getHasLiedResolution
https://github.com/fingerprintjs/fingerprintjs/blob/bf7039da92655f981b2b958bb51a031e15601dbe/fingerprint2.js#L1106-L1108
However, in this code they do more checks, including this with the magic number 0x14 = 20 in decimal.
window[ 'screen' ][ 'width' ] === window[ 'screen' ][ 'availHeight' ] + 0x14
Tries to detect if the client is lying about its OS by comparing Navigator.oscpu and the Navigator.userAgent.
Again, copying FingerprintJS: fingerprint2.js:1139-1152.
Returns 1 if Kaspersky is detected. Looks for an element with id "frmin" and then checks for related strings, such as "kaspersky"
Code is very similar to: https://vah13.github.io/AVDetection/.
Simple color depth check.
https://developer.mozilla.org/en-US/docs/Web/API/Screen/colorDepth
Checks if the function navigator.sendBeacon
is available.
https://developer.mozilla.org/en-US/docs/Web/API/Navigator/sendBeacon
Checks if the function navigator.geolocation
is available.
https://developer.mozilla.org/en-US/docs/Web/API/Navigator/geolocation
Returns 'true' if Puppeteer is used.
Throws an error with new Error( 'Test Error' );
then inspects the stack trace looking for
puppeteer_evaluation_script
https://www.blackhatworld.com/seo/how-to-detect-puppeteer-with-100-accuracy.1235754/
Also checks if Puppeteer is used.
First triggers an exception using document.createElement(0);
then looks for a line in the stack trace matching the regex
/Ob[cej]{3}t.a[lp]{3}y[(< ]{3}an[oynm]{5}us>/
.
For example matching Object.apply (:80:31)
.
Related:
Similar code was also found in the wild in this report: https://www.joesandbox.com/analysis/598617/0/lighthtml
Work in progress / TODO
Seems to compare speed for array push/pop vs adding/removing to localStorage using setItem and removeItem.
When I tried on both Chrome and Firefox, the number of operations for localStorage was orders of magnitude lower than for the array. Maybe Puppeteer or similar implement localStorage as an array?