mirror of
https://github.com/httptoolkit/frida-interception-and-unpinning.git
synced 2026-10-08 17:02:29 +02:00
Fix lots of errors in unpinning patch application logic
This commit is contained in:
@@ -113,7 +113,7 @@ const PINNING_FIXES = {
|
||||
'android.security.net.config.NetworkSecurityConfig': [
|
||||
{
|
||||
methodName: '$init',
|
||||
overloads: '*',
|
||||
overload: '*',
|
||||
replacement: () => {
|
||||
const PinSet = Java.use('android.security.net.config.PinSet');
|
||||
const EMPTY_PINSET = PinSet.EMPTY_PINSET.value;
|
||||
@@ -366,66 +366,90 @@ setTimeout(function () {
|
||||
Java.perform(function () {
|
||||
if (DEBUG_MODE) console.debug('=== Disablig all recognized unpinning libraries ===');
|
||||
|
||||
Object.keys(PINNING_FIXES).forEach((targetClass) => {
|
||||
const Cls = getJavaClassIfExists(targetClass);
|
||||
if (!Cls) {
|
||||
const classesToPatch = Object.keys(PINNING_FIXES);
|
||||
|
||||
classesToPatch.forEach((targetClassName) => {
|
||||
const TargetClass = getJavaClassIfExists(targetClassName);
|
||||
if (!TargetClass) {
|
||||
// We skip patches for any classes that don't seem to be present. This is common
|
||||
// as not all libraries we handle are necessarily used.
|
||||
if (DEBUG_MODE) console.debug(`[ ] ${targetClass} *`);
|
||||
if (DEBUG_MODE) console.debug(`[ ] ${targetClassName} *`);
|
||||
return;
|
||||
}
|
||||
|
||||
const patches = PINNING_FIXES[targetClass];
|
||||
const patches = PINNING_FIXES[targetClassName];
|
||||
|
||||
let patchApplied = false;
|
||||
|
||||
patches.forEach(({ methodName, getMethod, overload, replacement }) => {
|
||||
const namedTargetMethod = getMethod
|
||||
? getMethod(targetClass)
|
||||
: targetClass[methodName];
|
||||
? getMethod(TargetClass)
|
||||
: TargetClass[methodName];
|
||||
|
||||
const methodDescription = `${methodName}${
|
||||
overload
|
||||
overload === '*'
|
||||
? '(*)'
|
||||
: overload
|
||||
? '(' + overload.map((argType) => {
|
||||
// Simplify arg names to just the class name for simpler logs:
|
||||
const argClassName = argType.split('.').slice(-1)[0];
|
||||
if (argType.startsWith('[L')) return `${argClassName}[]`;
|
||||
else return argClassName;
|
||||
}).join(', ') + ')'
|
||||
// No overload:
|
||||
: ''
|
||||
}`
|
||||
|
||||
const targetMethodImplementations = !namedTargetMethod
|
||||
? [] // Method not found
|
||||
: !overload
|
||||
? [namedTargetMethod] // No overload specified
|
||||
: overload === '*'
|
||||
? namedTargetMethod.overloads // Targetting _all_ overloads
|
||||
// Or targetting a specific overload:
|
||||
: [namedTargetMethod.overload(...overload)];
|
||||
let targetMethodImplementations = [];
|
||||
try {
|
||||
if (namedTargetMethod) {
|
||||
if (!overload) {
|
||||
// No overload specified
|
||||
targetMethodImplementations = [namedTargetMethod];
|
||||
} else if (overload === '*') {
|
||||
// Targetting _all_ overloads
|
||||
targetMethodImplementations = namedTargetMethod.overloads;
|
||||
} else {
|
||||
// Or targetting a specific overload:
|
||||
targetMethodImplementations = [namedTargetMethod.overload(...overload)];
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
// Overload not present
|
||||
}
|
||||
|
||||
|
||||
// We skip patches for any methods that don't seem to be present. This is rarer, but does
|
||||
// happen due to methods that only appear in certain library versions or whose signatures
|
||||
// have changed over time.
|
||||
if (targetMethodImplementations.length === 0) {
|
||||
// We skip patches for any methods that don't seem to be present. This is
|
||||
// rarer, but happens due to methods that only appear in certain library
|
||||
// versions or whose signatures have changed over time.
|
||||
if (DEBUG_MODE) console.debug(`[ ] ${targetClass} ${methodDescription}`);
|
||||
if (DEBUG_MODE) console.debug(`[ ] ${targetClassName} ${methodDescription}`);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
targetMethodImplementations.forEach((targetMethod) => {
|
||||
targetMethodImplementations.forEach((targetMethod, i) => {
|
||||
const patchName = `${targetClassName} ${methodDescription}${
|
||||
targetMethodImplementations.length > 1 ? ` (${i})` : ''
|
||||
}`;
|
||||
|
||||
try {
|
||||
targetMethod.implementation = replacement(targetMethod);
|
||||
if (DEBUG_MODE) console.debug(`[+] ${patchName} ${methodDescription}`);
|
||||
})
|
||||
patchApplied = true;
|
||||
} catch (e) {
|
||||
// In theory, errors like this should never happen - it means the patch is broken
|
||||
// (e.g. an expected method doesn't exist at all)
|
||||
console.warn(`[!] ERROR: ${patchName} failed: ${e}`);
|
||||
}
|
||||
|
||||
if (DEBUG_MODE) console.debug(`[+] ${patchName}`);
|
||||
patchApplied = true;
|
||||
} catch (e) {
|
||||
// In theory, errors like this should never happen - it means the patch is broken
|
||||
// (e.g. some dynamic patch building fails completely)
|
||||
console.error(`[!] ERROR: ${patchName} failed: ${e}`);
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
console.log(`[!] Matched class ${targetClass} but could not patch any methods`);
|
||||
if (!patchApplied) {
|
||||
console.log(`[!] Matched class ${targetClassName} but could not patch any methods`);
|
||||
}
|
||||
});
|
||||
|
||||
console.log('== Certificate unpinning completed ==');
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user