Node.js examples for reversing two parts of the hCaptcha hsj payload:
npayload encrypt/decrypt- event value encrypt/decrypt
example_n.js: example fornAES-GCM encrypt/decryptexample_events.js: example for event encrypt/decryptalgorithms/encrypt_n.js: encryptnalgorithms/decrypt_n.js: decryptnalgorithms/encrypt_event.js: encrypt one event valuealgorithms/decrypt_event.js: decrypt one event valuen_key_fetcher.js: helper for tracing thenkey fromhsj.js
n uses AES-256-GCM.
Key:
- 32 bytes
- passed as hex string into
aesGcmEncrypt/aesGcmDecrypt
Encrypted output layout:
base64(
ciphertext
+ authTag(16 bytes)
+ nonce(12 bytes)
+ version(1 byte, always 0x00)
)
const { aesGcmEncrypt } = require("./algorithms/encrypt_n");
const { aesGcmDecrypt } = require("./algorithms/decrypt_n");
const key = [
48, 174, 137, 138, 134, 125, 45, 5, 20, 156, 233, 94, 133, 192, 55, 42,
196, 197, 155, 237, 108, 44, 168, 232, 89, 152, 138, 44, 21, 60, 197, 150,
];
const hexKey = Buffer.from(key).toString("hex");
const plain = JSON.stringify({ sc: { availWidth: 1920 }, events: [] });
const encrypted = aesGcmEncrypt(hexKey, plain);
const decrypted = aesGcmDecrypt(hexKey, encrypted);
console.log("encrypted:", encrypted);
console.log("decrypted:", decrypted);One event value is stored as:
[encodedStr, shiftHex, splitHex, keyW]Example encrypted event values from example_events.js:
[2795229317, "[\"ZGZm5mJN=mJmxmZN\",\"4\",\"8\",\"YZCLWAMLYAUGJ\"]"]
[4009980312, "[\"bvDWESN2D1ZKmLYUAT9vvoFWEMLx\",\"14\",\"1b\",\"XLESAKRTDVMRC\"]"]
[3495389113, "[[\"lcMYUSQmvNLwiTJZd2Z5R2dok1ZNlhZ3\",\"12\",\"9\",\"VIBXVEEYNEHCF\"],[\"3PXYubjMLEjlz4CMwItJSFHanDnawItJOM0aRNgahNkMLAjMLcLSdhUq65WZyFmBPAjML80cLJgcpr2D6FmBwItJOAdDwAdMwkFMaFUKPMkMLAjMLGytxhnDh52aPAjMLOvYyvWehbjMLGytzvmYw9EZ\",\"16\",\"60\",\"PGQBLVTOVDGRB\"]]"]Decrypted values:
2795229317 -> "32137383936"
4009980312 -> "America/Los_Angeles"
3495389113 -> [
"Google Inc. (Google)",
"ANGLE (Google, Vulkan 1.3.0 (SwiftShader Device (Subzero) (0x0000C0DE)), SwiftShader driver)"
]