Created
June 30, 2025 19:00
-
-
Save framp/9747e1517017b1f3d23b6ffb8d4f8433 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const jwt = '...' | |
// Split JWT by dots | |
const sections = jwt.split('.'); | |
// Function to check if a string is valid base64 | |
function isValidBase64(str) { | |
try { | |
// Add padding if needed | |
while (str.length % 4 !== 0) { | |
str += '='; | |
} | |
// Try to decode | |
const decoded = Buffer.from(str, 'base64'); | |
return true; | |
} catch (error) { | |
return false; | |
} | |
} | |
// Function to decode base64 and show result | |
function decodeBase64(str) { | |
try { | |
// Add padding if needed | |
while (str.length % 4 !== 0) { | |
str += '='; | |
} | |
const decoded = Buffer.from(str, 'base64'); | |
return decoded.toString('utf8'); | |
} catch (error) { | |
return null; | |
} | |
} | |
// New approach: Use regex to find and replace I/l characters systematically | |
function fixJwtSection(str) { | |
// First, try the original string | |
if (isValidBase64(str)) { | |
return { combination: str, decoded: decodeBase64(str) }; | |
} | |
// Create a regex pattern to match I and l characters | |
const pattern = /[Il]/g; | |
const matches = [...str.matchAll(pattern)]; | |
if (matches.length === 0) { | |
return null; | |
} | |
console.log(`Found ${matches.length} I/l characters to test`); | |
// Use a more efficient approach: try common patterns first | |
const commonReplacements = [ | |
// Try replacing all with 'I' | |
str.replace(pattern, 'I'), | |
// Try replacing all with 'l' | |
str.replace(pattern, 'l'), | |
// Try alternating pattern | |
str.replace(pattern, (match, index) => index % 2 === 0 ? 'I' : 'l'), | |
// Try reverse alternating pattern | |
str.replace(pattern, (match, index) => index % 2 === 0 ? 'l' : 'I'), | |
]; | |
// Test common patterns first | |
for (const replacement of commonReplacements) { | |
if (isValidBase64(replacement)) { | |
const decoded = decodeBase64(replacement); | |
if (decoded) { | |
return { combination: replacement, decoded }; | |
} | |
} | |
} | |
// If common patterns don't work, use a more targeted approach | |
// Try replacing only the first occurrence | |
let testStr = str; | |
for (let i = 0; i < matches.length; i++) { | |
const match = matches[i]; | |
const char = match[0]; | |
const replacement = char === 'I' ? 'l' : 'I'; | |
// Replace this specific occurrence | |
testStr = testStr.substring(0, match.index) + replacement + testStr.substring(match.index + 1); | |
if (isValidBase64(testStr)) { | |
const decoded = decodeBase64(testStr); | |
if (decoded) { | |
return { combination: testStr, decoded }; | |
} | |
} | |
} | |
// If still no success, try a limited brute force (max 8 characters) | |
if (matches.length <= 8) { | |
const totalCombinations = Math.pow(2, matches.length); | |
for (let i = 0; i < totalCombinations; i++) { | |
let combination = str.split(''); | |
for (let j = 0; j < matches.length; j++) { | |
const match = matches[j]; | |
const useI = (i >> j) & 1; | |
combination[match.index] = useI ? 'I' : 'l'; | |
} | |
const testStr = combination.join(''); | |
if (isValidBase64(testStr)) { | |
const decoded = decodeBase64(testStr); | |
if (decoded) { | |
return { combination: testStr, decoded }; | |
} | |
} | |
} | |
} | |
return null; | |
} | |
// Process each section | |
sections.forEach((section, index) => { | |
console.log(`\n=== Section ${index + 1} ===`); | |
console.log(`Original: ${section}`); | |
const result = fixJwtSection(section); | |
if (result) { | |
console.log(`\nValid combination found: ${result.combination}`); | |
console.log(`Decoded: ${result.decoded}`); | |
} else { | |
console.log('No valid base64 combination found for this section'); | |
} | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment