var Java = Java;
function log(message) {
console.log('[Frida Hook] ' + message);
}
function hasNetworkCapability(cls) {
var className = cls.toString().split('(')[0];
return className.includes("Http") || className.includes("Https") ||
className.includes("Socket") || className.includes("URLConnection");
}
function avoidUnrelatedClass(cls) {
var className = cls.toString().split('(')[0];
return !className.includes("Http") && !className.includes("Https") &&
!className.includes("Socket") && !className.includes("URLConnection");
}
function hasNetworkPermission(cls) {
var className = cls.toString().split('(')[0];
return cls.hasPermission("android.permission.INTERNET") ||
cls.hasPermission("android.permission.ACCESS_NETWORK_STATE");
}
function hasNetworkInterface(cls) {
var className = cls.toString().split('(')[0];
return cls.implements('java.net.SocketFactory') ||
cls.implements('javax.net.ssl.SSLSocketFactory');
}
Java.vm.onLoad(function(className) {
try {
if (!avoidUnrelatedClass(Java.use(className))) {
if (hasNetworkCapability(Java.use(className)) ||
hasNetworkPermission(Java.use(className)) ||
hasNetworkInterface(Java.use(className))) {
log('Found potentially network-capable class: ' + className);
hookClass(className);
}
} else {
log('Skipping unrelated class: ' + className);
}
} catch (error) {
log('Error loading class: ' + className + '. Error: ' + error.message);
}
});
function hookClass(className) {
var classObj = Java.use(className);
try {
classObj.openConnection.overloads.forEach(function(overload) {
overload.implementation = function(url) {
var original = this.openConnection.apply(this, arguments);
return new Proxy(original, {
get: function(target, prop) {
if (prop === 'getInputStream') {
return function() {
var inputStream = target.getInputStream.apply(target, arguments);
var requestMethod = target.getRequestMethod();
var requestURL = target.getURL().toString();
var requestHeaders = target.getHeaderFields();
var responseBody = '';
var buffer = new java.nio.ByteBuffer.allocate(1024);
while (inputStream.read(buffer.array(), 0, buffer.capacity()) != -1) {
responseBody += String.fromCharCode.apply(null, buffer.array());
}
log('Request:', requestMethod + ' ' + requestURL);
log('Headers:', JSON.stringify(requestHeaders));
log('Response:', responseBody);
return inputStream;
};
}
return target[prop];
},
set: function(target, prop, value) {
if (prop === 'getInputStream') {
target.getInputStream = value;
}
return true;
}
});
};
};
} catch (error) {
log('Error hooking class ' + className + ': ' + error.message);
}
try {
['getOutputStream', 'setRequestProperty'].forEach(function(methodName) {
var overload = classObj[methodName].overloads[0];
if (overload && !avoidUnrelatedClass(classObj)) {
overload.implementation = function() {
log('Hooked method: ' + className + '.' + methodName);
var original = this[methodName].apply(this, arguments);
return original;
};
}
});
} catch (error) {
log('Error hooking additional methods in class ' + className + ': ' + error.message);
}
}
Java.vm.onExit(function(exitCode) {
log('App exited with code: ' + exitCode);
});
function forceGC() {
Java.vm.gc();
log('Forced Garbage Collection');
}
setTimeout(function() {
log('Frida script loaded. Starting dynamic network packet interception.');
Java.vm.onLoad(function(className) {
});
}, 1000);
log('Frida script initialized. Waiting for app launch...');