WIP: Add CI diagnostics

This commit is contained in:
Tim Perry
2026-08-05 12:16:13 +02:00
parent 71210960b9
commit 4374ff9f17
+68 -1
View File
@@ -268,6 +268,66 @@ jobs:
}, 5000);
'''
# Spike-only diagnostics. native-tls-hook.js could not load libboringssl.dylib at
# startup, and its deferred hook never fired either, though the app plainly does use
# that library later on. Rather than guessing why, report what Frida actually sees:
#
# - two module observers, one retained in a global & one not, since config.js discards
# the handle its own observer returns
# - the modules Frida can see once the app has really made a TLS connection
# - a hook applied by hand at that point, so we learn whether timing is the only
# problem: if the app's later requests are then intercepted, the rest all works
diagnostics = '''
try {
globalThis.spikeRetainedObserver = Process.attachModuleObserver({
onAdded(module) {
const name = module.name || module.path || "(unnamed)";
if (name.indexOf("ssl") !== -1) console.log(`SPIKE-OBSERVER (retained): ${name}`);
}
});
Process.attachModuleObserver({
onAdded(module) {
const name = module.name || module.path || "(unnamed)";
if (name.indexOf("ssl") !== -1) console.log(`SPIKE-OBSERVER (unretained): ${name}`);
}
});
console.log("SPIKE-OBSERVER: both attached");
} catch (e) {
console.log(`SPIKE-OBSERVER: could not attach: ${e}`);
}
// Well after the app's first request, so anything TLS-related is definitely loaded:
setTimeout(() => {
try {
const modules = Process.enumerateModules()
.filter((module) => (module.name || "").indexOf("ssl") !== -1);
console.log(`SPIKE-MODULES: ${modules.length} loaded module(s) matching "ssl"`);
modules.forEach((module) =>
console.log(`SPIKE-MODULES: ${module.name} @ ${module.path}`));
} catch (e) {
console.log(`SPIKE-MODULES: could not enumerate: ${e}`);
}
["libboringssl.dylib", "/usr/lib/libboringssl.dylib"].forEach((name) => {
try {
const module = Process.getModuleByName(name);
console.log(`SPIKE-MODULES: getModuleByName(${name}) => ${module.path}`);
} catch (e) {
console.log(`SPIKE-MODULES: getModuleByName(${name}) failed: ${e}`);
}
});
try {
patchTargetLib(Process.getModuleByName("libboringssl.dylib"), "libboringssl.dylib");
console.log("SPIKE-TLS-LATE: hooked by hand");
} catch (e) {
console.log(`SPIKE-TLS-LATE: could not hook by hand: ${e}`);
}
}, 20000);
'''
# The gadget's console output doesn't reach the simulator log at all (established by the
# script mode check below), so we tee it to a file in the app's own data container,
# which we can read back afterwards. Without this our scripts fail silently:
@@ -300,7 +360,8 @@ jobs:
('native-connect-hook.js', open('native-connect-hook.js').read()),
('the spike additions',
send_a_request.replace('__MARKER_PATH__',
os.environ['DATA_DIR'] + '/scripts-loaded.txt'))
os.environ['DATA_DIR'] + '/scripts-loaded.txt')),
('the spike diagnostics', diagnostics)
]
body = '\n'.join(
@@ -605,6 +666,12 @@ jobs:
"native-connect-hook hooked, with our config applied"
check "== Redirecting Network framework connections to 127.0.0.1:8000 ==" \
"ios-connect-hook hooked Network framework"
# N.b. the spike's diagnostics hook libboringssl by hand 20s in, and that path logs the
# same message, so say so plainly rather than reporting a pass that isn't the script's:
if grep -qF "SPIKE-TLS-LATE: hooked by hand" <<< "$OUTPUT"; then
echo "N.b. the spike's diagnostics hooked libboringssl by hand, so the TLS checks" \
"below show that it can be hooked at all, not that native-tls-hook did it itself"
fi
check "== Hooked native TLS lib libboringssl.dylib ==" "native-tls-hook hooked iOS's TLS"
# The real question: does traffic actually end up intercepted? Redirection and