fix: we're so back (again)

will do a writeup on this later, for now you can read the code
This commit is contained in:
eva
2026-02-12 17:53:52 +00:00
parent ec17281ee6
commit a548b455b6
3 changed files with 90 additions and 71 deletions
+51 -35
View File
@@ -7,6 +7,14 @@ const randomChoice = <T>(arr: T[]): T => arr[Math.floor(Math.random() * arr.leng
const BASE_URL = 'https://eu-west-1.faceassure.com';
function generateId(id: string, sub: string, sessionId: string, delimiter = '|') {
let s = 0;
for (let a = '' + id + delimiter + sub + delimiter + sessionId, i = 0; i < a.length; i++) {
s = (s << 5) - s + a.charCodeAt(i);
s &= s;
}
return '' + s;
}
function generateUserAgent() {
const agents = [
'Mozilla/5.0 (iPhone; CPU iPhone OS 17_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.0 Mobile/15E148 Safari/604.1',
@@ -103,7 +111,7 @@ function getRandomLocation() {
return locations[Math.floor(Math.random() * locations.length)];
}
function generateMediaMetadata() {
function generateMediaMetadata(sub: string, sessionId: string) {
const randomHex = () =>
Array.from({ length: 32 }, () =>
Math.floor(Math.random() * 16)
@@ -143,7 +151,7 @@ function generateMediaMetadata() {
];
const spec = randomChoice(specs);
const deviceId = randomHex();
const deviceId = generateId(randomHex(), sub, sessionId, '-');
return [
{
@@ -305,7 +313,6 @@ async function verify(qrCodeUrlStr: string) {
const userAgent = generateUserAgent();
const parsedUserAgent = parseUserAgent(userAgent);
const location = getRandomLocation();
const mediaMetadata = generateMediaMetadata();
const commonHeaders = {
'User-Agent': userAgent,
@@ -394,8 +401,22 @@ async function verify(qrCodeUrlStr: string) {
'SLOWLY_DISTANCE_YOURSELF_FROM_THE_CAMERA',
'TOO_DARK'
];
const noState = [
'VIDEO_PROCESSING',
'STAY_STILL',
'TURN_RIGHT',
'ALIGN_YOUR_FACE_WITH_THE_CAMERA_UP',
'ALIGN_YOUR_FACE_WITH_THE_CAMERA_DOWN',
'SLIGHTLY_TILT_YOUR_HEAD_LEFT',
'SLIGHTLY_TILT_YOUR_HEAD_RIGHT',
'OPEN_YOUR_MOUTH'
];
const timelines: Record<string, number[][]> = {};
states.forEach((state) => (timelines[state] = generateTimeline(completionTime)));
noState.forEach((state) => {
timelines[state] = [];
});
return timelines;
};
const baseAge = randomFloat(25.2, 26.0);
@@ -433,6 +454,25 @@ async function verify(qrCodeUrlStr: string) {
const { speeds: failedOpennessSpeeds, intervals: failedOpennessIntervals } =
calculateSpeedAndIntervals(failedMeasurements, failedTimestamps);
const stateTimelines = generateStateTimelines(completionTime);
const stateCompletionTimes: Record<string, number> = {};
for (const [key, timeline] of Object.entries(stateTimelines)) {
if (timeline.length < 1) continue;
let completionTime = 0;
for (const time of timeline) {
completionTime += time.reduce((accumulator, currentValue) => accumulator + currentValue, 0);
}
stateCompletionTimes[key] = completionTime;
}
const mediaMetadata = generateMediaMetadata(jwtPayload.sub, sessionData.session_id);
const ageCheckSession = generateId(
mediaMetadata.find((m) => m.mediaKind === 'videoinput')!.mediaId,
jwtPayload.sub,
sessionData.session_id
);
let payload = {
request_type: 'complete_transaction',
transaction_id: sessionData.transaction_id,
@@ -468,7 +508,7 @@ async function verify(qrCodeUrlStr: string) {
ver: 'v1.10.22',
ufi: []
},
ageCheckSession: '-' + randomInt(1000000000, 9999999999),
ageCheckSession: ageCheckSession,
miscellaneous: {
recordedOpennessStreak: recordedMeasurements,
recordedSpeeds,
@@ -547,8 +587,8 @@ async function verify(qrCodeUrlStr: string) {
sdk_path: './face-capture-v1.10.22.js',
model_version: 'v.2025.0',
cropper_version: 'v.0.0.3',
start_time_stamp: currentTime - randomFloat(20, 60),
end_time_stamp: currentTime,
start_time_stamp: currentTime + Number(Math.random().toFixed(3)),
end_time_stamp: currentTime + completionTime + Number(Math.random().toFixed(3)),
device_timezone: location.timezone,
referring_page: `https://d3ogqhtsivkon3.cloudfront.net/?token=${token}&shi=false&from_qr_scan=true`,
parent_page: `https://d3ogqhtsivkon3.cloudfront.net/dynamic_index.html?sl=${jwtPayload.jti}&region=eu-central-1`,
@@ -603,7 +643,7 @@ async function verify(qrCodeUrlStr: string) {
initializationCharacteristics: {
cropperInitTime: randomInt(150, 250),
coreInitTime: randomInt(800, 1000),
pageLoadTime: randomInt(250, 350),
pageLoadTime: randomInt(250, 350) + Number(Math.random().toFixed(randomInt(7, 13))),
from_qr_scan: false,
blendShapesAvailable: true
},
@@ -639,7 +679,8 @@ async function verify(qrCodeUrlStr: string) {
},
isCameraPermissionGranted: true,
completionTime,
deferredComputationStartedAt: randomInt(10000, 14000),
deferredComputationStartedAt:
randomInt(10000, 14000) + Number(Math.random().toFixed(randomInt(1, 3))),
instructionCompletionTime: randomInt(10000, 14000),
initialAdjustmentTime: randomInt(10000, 14000),
completionState: 'COMPLETE',
@@ -665,33 +706,8 @@ async function verify(qrCodeUrlStr: string) {
'TOO_DARK'
].map((k) => [k, false])
),
// "stateCompletionTimes": {
// "TIME_UNTIL_CLICK_START": 2342,
// "GET_READY": 1130,
// "NO_FACE": 7132,
// "CENTRE_FACE": 551,
// "TOO_DARK": 29998,
// "TURN_LEFT": 30133,
// "LOOK_STRAIGHT": 441,
// "SLOWLY_DISTANCE_YOURSELF_FROM_THE_CAMERA": 0,
// "SLOWLY_COME_CLOSER_TO_THE_CAMERA": 1546,
// "CLOSE_YOUR_MOUTH": 1813,
// "KEEP_YOUR_MOUTH_OPEN": 9686
// },
stateCompletionTimes: {
TIME_UNTIL_CLICK_START: randomInt(800, 3200),
GET_READY: randomInt(1200, 4000),
NO_FACE: randomInt(2000, 5500),
CENTRE_FACE: randomInt(8000, 18000),
TOO_DARK: randomInt(1500, 3500),
TURN_LEFT: randomInt(3000, 8500),
LOOK_STRAIGHT: randomInt(100, 800),
SLOWLY_DISTANCE_YOURSELF_FROM_THE_CAMERA: 0,
SLOWLY_COME_CLOSER_TO_THE_CAMERA: randomInt(800, 3500),
CLOSE_YOUR_MOUTH: randomInt(1800, 5200),
KEEP_YOUR_MOUTH_OPEN: randomInt(3500, 9000)
},
stateTimelines: generateStateTimelines(completionTime),
stateCompletionTimes,
stateTimelines,
nonNeutralExpressionTimelines: Object.fromEntries(
[
'browDownLeft',
+1 -1
View File
@@ -3,7 +3,7 @@
let qrCodeError = $state<string | null>(null);
let qrCodeSuccess = $state(false);
const IS_PATCHED = true;
const IS_PATCHED = false;
</script>
<div class="mx-auto w-screen max-w-6xl items-center p-5 pb-16">
+38 -35
View File
@@ -22,6 +22,15 @@ const randomFloat = (min: number, max: number, decimals = 15) =>
parseFloat((Math.random() * (max - min) + min).toFixed(decimals));
const randomChoice = <T>(arr: T[]): T => arr[Math.floor(Math.random() * arr.length)];
function generateId(id: string, sub: string, sessionId: string, delimiter = '|') {
let s = 0;
for (let a = '' + id + delimiter + sub + delimiter + sessionId, i = 0; i < a.length; i++) {
s = (s << 5) - s + a.charCodeAt(i);
s &= s;
}
return '' + s;
}
function generateUserAgent() {
const agents = [
'Mozilla/5.0 (iPhone; CPU iPhone OS 17_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.0 Mobile/15E148 Safari/604.1',
@@ -118,7 +127,7 @@ function getRandomLocation() {
return locations[Math.floor(Math.random() * locations.length)];
}
function generateMediaMetadata() {
function generateMediaMetadata(sub: string, sessionId: string) {
const randomHex = () =>
Array.from({ length: 32 }, () =>
Math.floor(Math.random() * 16)
@@ -158,7 +167,7 @@ function generateMediaMetadata() {
];
const spec = randomChoice(specs);
const deviceId = randomHex();
const deviceId = generateId(randomHex(), sub, sessionId, '-');
return [
{
@@ -320,7 +329,6 @@ async function verify(
token: string
) {
const parsedUserAgent = parseUserAgent(userAgent);
const mediaMetadata = generateMediaMetadata();
const commonHeaders = {
'User-Agent': userAgent,
@@ -450,6 +458,25 @@ async function verify(
const { speeds: failedOpennessSpeeds, intervals: failedOpennessIntervals } =
calculateSpeedAndIntervals(failedMeasurements, failedTimestamps);
const stateTimelines = generateStateTimelines(completionTime);
const stateCompletionTimes: Record<string, number> = {};
for (const [key, timeline] of Object.entries(stateTimelines)) {
if (timeline.length < 1) continue;
let completionTime = 0;
for (const time of timeline) {
completionTime += time.reduce((accumulator, currentValue) => accumulator + currentValue, 0);
}
stateCompletionTimes[key] = completionTime;
}
const mediaMetadata = generateMediaMetadata(jwtPayload.sub, sessionData.session_id);
const ageCheckSession = generateId(
mediaMetadata.find((m) => m.mediaKind === 'videoinput')!.mediaId,
jwtPayload.sub,
sessionData.session_id
);
let payload = {
request_type: 'complete_transaction',
transaction_id: sessionData.transaction_id,
@@ -485,7 +512,7 @@ async function verify(
ver: 'v1.10.22',
ufi: []
},
ageCheckSession: '-' + randomInt(1000000000, 9999999999),
ageCheckSession: ageCheckSession,
miscellaneous: {
recordedOpennessStreak: recordedMeasurements,
recordedSpeeds,
@@ -564,8 +591,8 @@ async function verify(
sdk_path: './face-capture-v1.10.22.js',
model_version: 'v.2025.0',
cropper_version: 'v.0.0.3',
start_time_stamp: currentTime - randomFloat(20, 60),
end_time_stamp: currentTime,
start_time_stamp: currentTime + Number(Math.random().toFixed(3)),
end_time_stamp: currentTime + completionTime + Number(Math.random().toFixed(3)),
device_timezone: location.timezone,
referring_page: `https://d3ogqhtsivkon3.cloudfront.net/?token=${token}&shi=false&from_qr_scan=true`,
parent_page: `https://d3ogqhtsivkon3.cloudfront.net/dynamic_index.html?sl=${jwtPayload.jti}&region=eu-central-1`,
@@ -620,7 +647,7 @@ async function verify(
initializationCharacteristics: {
cropperInitTime: randomInt(150, 250),
coreInitTime: randomInt(800, 1000),
pageLoadTime: randomInt(250, 350),
pageLoadTime: randomInt(250, 350) + Number(Math.random().toFixed(randomInt(7, 13))),
from_qr_scan: false,
blendShapesAvailable: true
},
@@ -656,7 +683,8 @@ async function verify(
},
isCameraPermissionGranted: true,
completionTime,
deferredComputationStartedAt: randomInt(10000, 14000),
deferredComputationStartedAt:
randomInt(10000, 14000) + Number(Math.random().toFixed(randomInt(1, 3))),
instructionCompletionTime: randomInt(10000, 14000),
initialAdjustmentTime: randomInt(10000, 14000),
completionState: 'COMPLETE',
@@ -682,33 +710,8 @@ async function verify(
'TOO_DARK'
].map((k) => [k, false])
),
// "stateCompletionTimes": {
// "TIME_UNTIL_CLICK_START": 2342,
// "GET_READY": 1130,
// "NO_FACE": 7132,
// "CENTRE_FACE": 551,
// "TOO_DARK": 29998,
// "TURN_LEFT": 30133,
// "LOOK_STRAIGHT": 441,
// "SLOWLY_DISTANCE_YOURSELF_FROM_THE_CAMERA": 0,
// "SLOWLY_COME_CLOSER_TO_THE_CAMERA": 1546,
// "CLOSE_YOUR_MOUTH": 1813,
// "KEEP_YOUR_MOUTH_OPEN": 9686
// },
stateCompletionTimes: {
TIME_UNTIL_CLICK_START: randomInt(800, 3200),
GET_READY: randomInt(1200, 4000),
NO_FACE: randomInt(2000, 5500),
CENTRE_FACE: randomInt(8000, 18000),
TOO_DARK: randomInt(1500, 3500),
TURN_LEFT: randomInt(3000, 8500),
LOOK_STRAIGHT: randomInt(100, 800),
SLOWLY_DISTANCE_YOURSELF_FROM_THE_CAMERA: 0,
SLOWLY_COME_CLOSER_TO_THE_CAMERA: randomInt(800, 3500),
CLOSE_YOUR_MOUTH: randomInt(1800, 5200),
KEEP_YOUR_MOUTH_OPEN: randomInt(3500, 9000)
},
stateTimelines: generateStateTimelines(completionTime),
stateCompletionTimes,
stateTimelines,
nonNeutralExpressionTimelines: Object.fromEntries(
[
'browDownLeft',