class Log { static TAG = '[telephony]' static Debug = true static format(...msg) { let m = [] for (let i = 0; i < msg.length; i++) { if (typeof msg[i] === 'object') { m.push(msg[i] + '') } else { m.push(msg[i]) } } m = m.join(' ') return m } static i(...msg) { if (!this.Debug) return console.log(`\x1b[30m${this.TAG} ${this.format(...msg)}\x1b[0m`) } static w(...msg) { console.log(`\x1b[33m${this.TAG} ${this.format(...msg)}\x1b[0m`) } static e(...msg) { console.log(`\x1b[31m${this.TAG} ${this.format(...msg)}\x1b[0m`) } static s(...msg) { console.log(`\x1b[32m${this.TAG} ${this.format(...msg)}\x1b[0m`) } } function trace(tag) { Log.e((tag || '') + Java.use('android.util.Log').getStackTraceString(Java.use('java.lang.Throwable').$new())) } function randomMac() { var mac = '00:16:3e' for (var i = 0; i < 3; i++) { mac += ':' + ('00' + Math.floor(Math.random() * 256).toString(16)).slice(-2) } return mac } function buff2json(buf) { console.log(`buffer length: ${buf.byteLength}`) try { var decoded = String.fromCharCode(...new Uint8Array(buf)) console.log(`decoded: ${decoded}`) return JSON.parse(decoded.trim()) } catch (e) { console.error(e) return null } } class Interaction { failure(err) { console.error(err.message) Java.use('android.util.Log').d('frida-system_server', err.message) } accepted(connection) { console.warn('accepted') connection.input.read(2000).then((data) => { Java.use('android.util.Log').d('frida-system_server', data + '') try { const json = buff2json(data) console.log('received', json) this.messageFn && this.messageFn(json) } catch (e) {} connection.close() }) } accept_loop(listener) { var next_iter = this.accept_loop.bind(this, listener) listener .accept() .then(this.accepted.bind(this)) .catch(this.failure.bind(this)) .finally(function () { setImmediate(next_iter) }) } listened(listener) { console.warn('listened') this.accept_loop(listener) } start(port, messageFn) { this.messageFn = messageFn console.warn('starting on port', port) Socket.listen({ family: 'ipv4', host: '0.0.0.0', port: port }) .then(this.listened.bind(this)) .catch(this.failure.bind(this)) } } function getContext() { try { var ActivityThread = Java.use('android.app.ActivityThread') var application = ActivityThread.currentApplication() return application.getApplicationContext() } catch (e) { console.log(e) return null } } setImmediate(() => { Java.perform(function () { const GsmCdmaPhone = Java.use('com.android.internal.telephony.GsmCdmaPhone') Log.i('GsmCdmaPhone', GsmCdmaPhone) GsmCdmaPhone.getServiceState.overload().implementation = function () { Log.i('GsmCdmaPhone.getServiceState') return this.getServiceState.apply(this, arguments) } GsmCdmaPhone.getState.overload().implementation = function () { Log.i('GsmCdmaPhone.getState') return this.getState.apply(this, arguments) } GsmCdmaPhone.getSignalStrengthController.overload().implementation = function () { Log.i('GsmCdmaPhone.getSignalStrengthController') return this.getSignalStrengthController.apply(this, arguments) } Java.choose('com.android.internal.telephony.GsmCdmaPhone', { onMatch: function (instance) { Log.i('GsmCdmaPhone', instance) }, onComplete: function () { Log.i('GsmCdmaPhone onComplete') } }) const PhoneInterfaceManager = Java.use('com.android.phone.PhoneInterfaceManager') PhoneInterfaceManager.getSignalStrength.overload('int').implementation = function (i) { Log.i('PhoneInterfaceManager.getSignalStrength') return this.getSignalStrength(i) } const SignalStrengthController = Java.use('com.android.internal.telephony.SignalStrengthController') SignalStrengthController.onSignalStrengthResult.overload('android.os.AsyncResult').implementation = function ( result ) { Log.i('SignalStrengthController.onSignalStrengthResult ' + result.result) return this.onSignalStrengthResult(result) } }) })