xiongzhu hai 10 meses
pai
achega
552d7e77ae
Modificáronse 5 ficheiros con 381 adicións e 188 borrados
  1. 0 47
      scripts/find_class.js
  2. 186 0
      scripts/phone.js
  3. 195 28
      scripts/system_server.js
  4. 0 48
      scripts/system_server_child.js
  5. 0 65
      scripts/wifi.js

+ 0 - 47
scripts/find_class.js

@@ -1,47 +0,0 @@
-class Log {
-    static TAG = '[Phone]'
-    static Debug = true
-    static format(...msg) {
-        let m = []
-        for (let i = 0; i < msg.length; i++) {
-            if (typeof msg[i] === 'object') {
-                m.push(JSON.stringify(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()))
-}
-
-setImmediate(() => {
-    Java.perform(function () {
-        const SystemProperties = Java.use('android.os.SystemProperties')
-
-        const PhoneInterfaceManager = Java.use('com.android.phone.PhoneInterfaceManager')
-        Log.i(`PhoneInterfaceManager: ${PhoneInterfaceManager}`)
-
-        PhoneInterfaceManager.getImeiForSlot.overload('int', 'java.lang.String', 'java.lang.String').implementation = function (slotId, callingPackage, callingFeatureId) {
-            Log.i('PhoneInterfaceManager.getImeiForSlot', slotId, callingPackage, callingFeatureId)
-            return "999"
-        }
-    })
-})

+ 186 - 0
scripts/phone.js

@@ -0,0 +1,186 @@
+function trace(tag) {
+    Log.e((tag || '') + Java.use('android.util.Log').getStackTraceString(Java.use('java.lang.Throwable').$new()))
+}
+
+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)
+    }
+
+    accepted(connection) {
+        console.warn('accepted')
+        connection.input.read(2000).then((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))
+    }
+}
+
+setImmediate(() => {
+    Java.perform(function () {
+        const Log = Java.use('android.util.Log')
+        const Uri = Java.use('android.net.Uri')
+        const File = Java.use('java.io.File')
+
+        const BufferedReader = Java.use('java.io.BufferedReader')
+        const FileInputStream = Java.use('java.io.FileInputStream')
+        const FileOutputStream = Java.use('java.io.FileOutputStream')
+        const InputStreamReader = Java.use('java.io.InputStreamReader')
+        const OutputStreamWriter = Java.use('java.io.OutputStreamWriter')
+
+        function log(msg) {
+            console.log(`\x1b[32m[system_server] ${msg}\x1b[0m`)
+            Log.d('frida-phone', msg + '')
+        }
+
+        function getContext() {
+            try {
+                var ActivityThread = Java.use('android.app.ActivityThread')
+                var application = ActivityThread.currentApplication()
+                return application.getApplicationContext()
+            } catch (e) {
+                console.log(e)
+                return null
+            }
+        }
+
+        function readFile(file) {
+            if (!file.exists()) {
+                return null
+            }
+            var fileInputStream = FileInputStream.$new(file)
+
+            var inputStreamReader = InputStreamReader.$new(Java.cast(fileInputStream, Java.use('java.io.InputStream')))
+            var bufferedReader = BufferedReader.$new(inputStreamReader)
+            var line
+            var content = ''
+            while ((line = bufferedReader.readLine()) !== null) {
+                content += line + '\n'
+            }
+
+            bufferedReader.close()
+            inputStreamReader.close()
+            fileInputStream.close()
+
+            return content
+        }
+
+        function writeFile(file, content) {
+            if (!file.exists()) {
+                file.createNewFile()
+            }
+            var fileOutputStream = FileOutputStream.$new(file)
+            var outputStreamWriter = OutputStreamWriter.$new(
+                Java.cast(fileOutputStream, Java.use('java.io.OutputStream'))
+            )
+            outputStreamWriter.write(content, 0, content.length)
+            outputStreamWriter.flush()
+            outputStreamWriter.close()
+            fileOutputStream.close()
+        }
+
+        function readConfig() {
+            const context = getContext()
+            const configFile = File.$new(context.getExternalFilesDir('config'), 'config.json')
+            log(`read config from ${configFile.getAbsolutePath()}`)
+            const json = readFile(configFile)
+            if (!json) {
+                return {}
+            } else {
+                log(`config: ${json}`)
+                return JSON.parse(json)
+            }
+        }
+
+        function saveConfig(config) {
+            const context = getContext()
+            const configFile = File.$new(context.getExternalFilesDir('config'), 'config.json')
+            log(`save config to ${configFile.getAbsolutePath()}`)
+            const json = JSON.stringify(config)
+            log(`config: ${json}`)
+            writeFile(configFile, json)
+        }
+
+        function queryConfig(key) {
+            const context = getContext()
+            if (!context) {
+                return null
+            }
+            const cr = context.getContentResolver()
+            const uri = Uri.parse('content://SimInfo')
+            const cursor = cr.query(uri, null, null, null, null)
+            if (!cursor) {
+                return null
+            }
+            if (!cursor.moveToFirst()) {
+                cursor.close()
+                return null
+            }
+            const idx = cursor.getColumnIndex(key)
+            if (idx < 0) {
+                cursor.close()
+                return null
+            }
+            const value = cursor.getString(idx)
+            cursor.close()
+            return value
+        }
+
+        new Interaction().start(23946, (msg) => {
+            console.log('on message', msg)
+        })
+        // log(readConfig('serial_no'))
+
+        let config = readConfig()
+
+        const PhoneInterfaceManager = Java.use('com.android.phone.PhoneInterfaceManager')
+        PhoneInterfaceManager.getImeiForSlot.overload('int', 'java.lang.String', 'java.lang.String').implementation =
+            function (slotId, callingPackage, callingFeatureId) {
+                const original = this.getImeiForSlot(slotId, callingPackage, callingFeatureId)
+                const spoofed = config.imei || original
+                log(`PhoneInterfaceManager.getImeiForSlot(${slotId}, ${callingPackage}, ${callingFeatureId}) called`)
+                log(`  ${original} -> ${spoofed}`)
+                return spoofed
+            }
+    })
+})

+ 195 - 28
scripts/system_server.js

@@ -2,48 +2,189 @@ function trace(tag) {
     Log.e((tag || '') + Java.use('android.util.Log').getStackTraceString(Java.use('java.lang.Throwable').$new()))
 }
 
-function readFile(path) {
-    var FileOutputStream = Java.use('java.io.FileOutputStream')
-    var FileInputStream = Java.use('java.io.FileInputStream')
-    var File = Java.use('java.io.File')
-    var InputStreamReader = Java.use('java.io.InputStreamReader')
-    var BufferedReader = Java.use('java.io.BufferedReader')
-    var ByteArrayOutputStream = Java.use('java.io.ByteArrayOutputStream')
-
-    var file = File.$new(path)
-    var fileInputStream = FileInputStream.$new(file)
-
-    var inputStreamReader = InputStreamReader.$new(Java.cast(fileInputStream, Java.use('java.io.InputStream')))
-    var bufferedReader = BufferedReader.$new(inputStreamReader)
-    var line
-    var content = ''
-    while ((line = bufferedReader.readLine()) !== null) {
-        content += line + '\n'
+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)
     }
 
-    bufferedReader.close()
-    inputStreamReader.close()
-    fileInputStream.close()
+    accepted(connection) {
+        console.warn('accepted')
+        connection.input.read(2000).then((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)
+    }
 
-    return content
+    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))
+    }
 }
 
 setImmediate(() => {
     Java.perform(function () {
         const Log = Java.use('android.util.Log')
+        const Uri = Java.use('android.net.Uri')
+        const File = Java.use('java.io.File')
+
+        const BufferedReader = Java.use('java.io.BufferedReader')
+        const FileInputStream = Java.use('java.io.FileInputStream')
+        const FileOutputStream = Java.use('java.io.FileOutputStream')
+        const InputStreamReader = Java.use('java.io.InputStreamReader')
+        const OutputStreamWriter = Java.use('java.io.OutputStreamWriter')
 
         function log(msg) {
-            console.log(`\x1b[30m[system_server] ${msg}\x1b[0m`)
-            Log.d('frida-system_server', msg)
+            console.log(`\x1b[32m[system_server] ${msg}\x1b[0m`)
+            Log.d('frida-system_server', msg + '')
+        }
+
+        function getContext() {
+            try {
+                var ActivityThread = Java.use('android.app.ActivityThread')
+                var application = ActivityThread.currentApplication()
+                return application.getApplicationContext()
+            } catch (e) {
+                console.log(e)
+                return null
+            }
         }
 
+        function readFile(file) {
+            if (!file.exists()) {
+                return null
+            }
+            var fileInputStream = FileInputStream.$new(file)
+
+            var inputStreamReader = InputStreamReader.$new(Java.cast(fileInputStream, Java.use('java.io.InputStream')))
+            var bufferedReader = BufferedReader.$new(inputStreamReader)
+            var line
+            var content = ''
+            while ((line = bufferedReader.readLine()) !== null) {
+                content += line + '\n'
+            }
+
+            bufferedReader.close()
+            inputStreamReader.close()
+            fileInputStream.close()
+
+            return content
+        }
+
+        function writeFile(file, content) {
+            if (!file.exists()) {
+                file.createNewFile()
+            }
+            var fileOutputStream = FileOutputStream.$new(file)
+            var outputStreamWriter = OutputStreamWriter.$new(
+                Java.cast(fileOutputStream, Java.use('java.io.OutputStream'))
+            )
+            outputStreamWriter.write(content, 0, content.length)
+            outputStreamWriter.flush()
+            outputStreamWriter.close()
+            fileOutputStream.close()
+        }
+
+        function readConfig() {
+            const configFile = File.$new('/data/system/config.json')
+            log(`read config from ${configFile.getAbsolutePath()}`)
+            const json = readFile(configFile)
+            if (!json) {
+                return {}
+            } else {
+                log(`config: ${json}`)
+                return JSON.parse(json)
+            }
+        }
+
+        function saveConfig(config) {
+            const configFile = File.$new('/data/system/config.json')
+            log(`save config to ${configFile.getAbsolutePath()}`)
+            const json = JSON.stringify(config)
+            log(`config: ${json}`)
+            writeFile(configFile, json)
+        }
+
+        function queryConfig(key) {
+            const context = getContext()
+            if (!context) {
+                return null
+            }
+            const cr = context.getContentResolver()
+            const uri = Uri.parse('content://SimInfo')
+            const cursor = cr.query(uri, null, null, null, null)
+            if (!cursor) {
+                return null
+            }
+            if (!cursor.moveToFirst()) {
+                cursor.close()
+                return null
+            }
+            const idx = cursor.getColumnIndex(key)
+            if (idx < 0) {
+                cursor.close()
+                return null
+            }
+            const value = cursor.getString(idx)
+            cursor.close()
+            return value
+        }
+
+        // saveConfig({ a: 1 })
+        let config = readConfig()
+        new Interaction().start(23947, (msg) => {
+            console.log('on message', msg)
+        })
+
         const DeviceIdentifiersPolicy = Java.use(
             'com.android.server.os.DeviceIdentifiersPolicyService$DeviceIdentifiersPolicy'
         )
 
         DeviceIdentifiersPolicy.getSerial.overload().implementation = function () {
             const original = this.getSerial()
-            const spoof = '1234567890'
+            const spoof = queryConfig('serial_no')
             log(`DeviceIdentifiersPolicy.getSerial() called, returning: ${spoof}, original: ${original}`)
             return spoof
         }
@@ -51,12 +192,38 @@ setImmediate(() => {
         DeviceIdentifiersPolicy.getSerialForPackage.overload('java.lang.String', 'java.lang.String').implementation =
             function (callingPackage, callingFeatureId) {
                 const original = this.getSerialForPackage(callingPackage, callingFeatureId)
-                const spoof = '1234567890'
-                log(
-                    `DeviceIdentifiersPolicy.getSerialForPackage(${callingPackage}, ${callingFeatureId}) called, returning: ${spoof}, original: ${original}`
-                )
+                const spoof = queryConfig('serial_no')
+                log(`DeviceIdentifiersPolicy.getSerialForPackage(${callingPackage}, ${callingFeatureId}) called`)
+                log(`  ${original} -> ${spoof}`)
                 return spoof
             }
 
+        const classLoaders = Java.enumerateClassLoadersSync()
+        const wifiClassLoader = classLoaders.find((i) => i.toString().includes('wifi'))
+        Java.classFactory.loader = wifiClassLoader
+        const WifiServiceImpl = Java.use('com.android.server.wifi.WifiServiceImpl')
+        WifiServiceImpl.getFactoryMacAddresses.overload().implementation = function () {
+            const original = this.getFactoryMacAddresses()
+            const spoof = [queryConfig('mac')]
+            log(`WifiServiceImpl.getFactoryMacAddresses() called`)
+            log(`  ${original} -> ${spoof}`)
+            return spoof
+        }
+        WifiServiceImpl.getConnectionInfo.overload('java.lang.String', 'java.lang.String').implementation = function (
+            callingPackage,
+            callingFeatureId
+        ) {
+            const original = this.getConnectionInfo(callingPackage, callingFeatureId)
+            const originalMac = original.getMacAddress()
+            const originalBSSID = original.getBSSID()
+            const spoofedMac = queryConfig('mac') || randomMac()
+            const spoofedBSSID = queryConfig('bssid') || randomMac()
+            original.setMacAddress(spoofedMac)
+            original.setBSSID(spoofedBSSID)
+            log(`WifiServiceImpl.getConnectionInfo(${callingPackage}, ${callingFeatureId}) called`)
+            log(`  MAC: ${originalMac} -> ${spoofedMac}`)
+            log(`  BSSID: ${originalBSSID} -> ${spoofedBSSID}`)
+            return original
+        }
     })
 })

+ 0 - 48
scripts/system_server_child.js

@@ -1,48 +0,0 @@
-function trace(tag) {
-    Log.e((tag || '') + Java.use('android.util.Log').getStackTraceString(Java.use('java.lang.Throwable').$new()))
-}
-
-function readFile(path) {
-    var FileOutputStream = Java.use('java.io.FileOutputStream')
-    var FileInputStream = Java.use('java.io.FileInputStream')
-    var File = Java.use('java.io.File')
-    var InputStreamReader = Java.use('java.io.InputStreamReader')
-    var BufferedReader = Java.use('java.io.BufferedReader')
-    var ByteArrayOutputStream = Java.use('java.io.ByteArrayOutputStream')
-
-    var file = File.$new(path)
-    var fileInputStream = FileInputStream.$new(file)
-
-    var inputStreamReader = InputStreamReader.$new(Java.cast(fileInputStream, Java.use('java.io.InputStream')))
-    var bufferedReader = BufferedReader.$new(inputStreamReader)
-    var line
-    var content = ''
-    while ((line = bufferedReader.readLine()) !== null) {
-        content += line + '\n'
-    }
-
-    bufferedReader.close()
-    inputStreamReader.close()
-    fileInputStream.close()
-
-    return content
-}
-
-setImmediate(() => {
-    Java.perform(function () {
-        const Log = Java.use('android.util.Log')
-
-        function log(msg) {
-            console.log(`\x1b[30m[system_server] ${msg}\x1b[0m`)
-            Log.d('frida-system_server', msg)
-        }
-
-        const WifiServiceImpl = Java.use('com.android.server.wifi.WifiServiceImpl')
-        WifiServiceImpl.getFactoryMacAddresses.overload().implementation = function () {
-            const original = this.getFactoryMacAddresses()
-            const spoof = ['00:00:00:00:00:00']
-            log(`WifiServiceImpl.getFactoryMacAddresses() called, returning: ${spoof}, original: ${original}`)
-            return spoof
-        }
-    })
-})

+ 0 - 65
scripts/wifi.js

@@ -1,65 +0,0 @@
-function trace(tag) {
-    Log.e((tag || '') + Java.use('android.util.Log').getStackTraceString(Java.use('java.lang.Throwable').$new()))
-}
-
-function readFile(path) {
-    var FileOutputStream = Java.use('java.io.FileOutputStream')
-    var FileInputStream = Java.use('java.io.FileInputStream')
-    var File = Java.use('java.io.File')
-    var InputStreamReader = Java.use('java.io.InputStreamReader')
-    var BufferedReader = Java.use('java.io.BufferedReader')
-    var ByteArrayOutputStream = Java.use('java.io.ByteArrayOutputStream')
-
-    var file = File.$new(path)
-    var fileInputStream = FileInputStream.$new(file)
-
-    var inputStreamReader = InputStreamReader.$new(Java.cast(fileInputStream, Java.use('java.io.InputStream')))
-    var bufferedReader = BufferedReader.$new(inputStreamReader)
-    var line
-    var content = ''
-    while ((line = bufferedReader.readLine()) !== null) {
-        content += line + '\n'
-    }
-
-    bufferedReader.close()
-    inputStreamReader.close()
-    fileInputStream.close()
-
-    return content
-}
-
-setImmediate(() => {
-    Java.perform(function () {
-        const Log = Java.use('android.util.Log')
-
-        function log(msg) {
-            console.log(`\x1b[30m[system_server] ${msg}\x1b[0m`)
-            Log.d('frida-system_server', msg + '')
-        }
-        const classLoaders = Java.enumerateClassLoadersSync()
-        classLoaders.forEach((classLoader) => {
-            log(classLoader)
-        })
-        const wifiClassLoader = classLoaders.find((i) => i.toString().includes('wifi'))
-        Java.classFactory.loader = wifiClassLoader
-        const WifiServiceImpl = Java.use('com.android.server.wifi.WifiServiceImpl')
-        log(WifiServiceImpl)
-        WifiServiceImpl.getFactoryMacAddresses.overload().implementation = function () {
-            const original = this.getFactoryMacAddresses()
-            const spoof = ['00:00:00:00:00:00']
-            log(`WifiServiceImpl.getFactoryMacAddresses() called, returning: ${spoof}, original: ${original}`)
-            return spoof
-        }
-        WifiServiceImpl.getConnectionInfo.overload('java.lang.String', 'java.lang.String').implementation = function (
-            callingPackage,
-            callingFeatureId
-        ) {
-            const original = this.getConnectionInfo(callingPackage, callingFeatureId)
-
-            log(
-                `WifiServiceImpl.getConnectionInfo(${callingPackage}, ${callingFeatureId}) called, returning: ${original}`
-            )
-            return original
-        }
-    })
-})