mirror of
https://github.com/httptoolkit/frida-interception-and-unpinning.git
synced 2026-10-04 15:02:18 +02:00
57 lines
2.9 KiB
JavaScript
57 lines
2.9 KiB
JavaScript
/**
|
|
* The first step in intercepting HTTP & HTTPS traffic is to set the default proxy settings,
|
|
* telling the app that all requests should be sent via our HTTP proxy.
|
|
*
|
|
* In this script, we set that up via a few different mechanisms, which cumulatively should
|
|
* ensure that all connections are sent via the proxy, even if they attempt to use their
|
|
* own custom proxy configurations to avoid this.
|
|
*
|
|
* Despite that, this still only covers well behaved apps - it's still possible for apps
|
|
* to send network traffic directly if they're determined to do so, or if they're built
|
|
* with a framework that does not do this by default (Flutter is notably in this category).
|
|
* To handle those less tidy cases, we manually capture traffic to recognized target ports
|
|
* in the native connect() hook script.
|
|
*/
|
|
|
|
setTimeout(() => {
|
|
Java.perform(() => {
|
|
// Set default JVM system properties for the proxy address:
|
|
Java.use('java.lang.System').setProperty('http.proxyHost', PROXY_HOST);
|
|
Java.use('java.lang.System').setProperty('http.proxyPort', PROXY_PORT.toString());
|
|
Java.use('java.lang.System').setProperty('https.proxyHost', PROXY_HOST);
|
|
Java.use('java.lang.System').setProperty('https.proxyPort', PROXY_PORT.toString());
|
|
|
|
// Configure the proxy indirectly, by overriding the return value for all ProxySelectors everywhere:
|
|
const Collections = Java.use('java.util.Collections');
|
|
const ProxyType = Java.use('java.net.Proxy$Type');
|
|
const InetSocketAddress = Java.use('java.net.InetSocketAddress');
|
|
const ProxyCls = Java.use('java.net.Proxy'); // 'Proxy' is reserved in JS
|
|
|
|
const targetProxy = ProxyCls.$new(
|
|
ProxyType.HTTP.value,
|
|
InetSocketAddress.$new(PROXY_HOST, PROXY_PORT)
|
|
);
|
|
const getTargetProxyList = () => Collections.singletonList(targetProxy);
|
|
|
|
const ProxySelector = Java.use('java.net.ProxySelector');
|
|
|
|
// Find every implementation of ProxySelector by quickly scanning method signatures, and
|
|
// then checking whether each match actually implements java.net.ProxySelector:
|
|
const proxySelectorClasses = Java.enumerateMethods('*!select(java.net.URI): java.util.List/s')
|
|
.flatMap((matchingLoader) => matchingLoader.classes
|
|
.map((classData) => Java.use(classData.name))
|
|
.filter((Cls) => ProxySelector.class.isAssignableFrom(Cls.class))
|
|
);
|
|
|
|
// Replace the 'select' of every implementation, so they all send traffic to us:
|
|
proxySelectorClasses.forEach(ProxySelectorCls => {
|
|
console.log('Rewriting', ProxySelectorCls.toString());
|
|
ProxySelectorCls.select.implementation = () => getTargetProxyList()
|
|
});
|
|
|
|
console.log(
|
|
`Rewrote ${proxySelectorClasses.length} proxy selector classes ` +
|
|
`to send traffic to ${PROXY_HOST}:${PROXY_PORT}`
|
|
);
|
|
});
|
|
}); |