spoof_provider.js 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. import frida from 'frida'
  2. import fs from 'fs'
  3. import url from 'url'
  4. import path from 'path'
  5. import util from 'util'
  6. import Vorpal from 'vorpal'
  7. import { spawn, execSync } from 'child_process'
  8. import { setTimeout } from 'timers/promises'
  9. const filePath = url.fileURLToPath(import.meta.url)
  10. const __dirname = path.dirname(filePath)
  11. function loadSource(filePath) {
  12. Log.s(`Loading ${filePath}`)
  13. return fs.readFileSync(path.resolve(__dirname, filePath)).toString()
  14. }
  15. class Log {
  16. static TAG = ''
  17. static format(...msg) {
  18. let m = []
  19. for (let i = 0; i < msg.length; i++) {
  20. if (typeof msg[i] === 'object') {
  21. if ('[object Object]' === msg[i].toString()) {
  22. m.push(util.inspect(msg[i]))
  23. }
  24. } else {
  25. m.push(msg[i])
  26. }
  27. }
  28. m = m.join(' ')
  29. return m
  30. }
  31. static i(...msg) {
  32. console.log(`\x1b[30m${this.TAG} ${this.format(...msg)}\x1b[0m`)
  33. }
  34. static w(...msg) {
  35. console.log(`\x1b[33m${this.TAG} ${this.format(...msg)}\x1b[0m`)
  36. }
  37. static e(...msg) {
  38. console.log(`\x1b[31m${this.TAG} ${this.format(...msg)}\x1b[0m`)
  39. }
  40. static s(...msg) {
  41. console.log(`\x1b[32m${this.TAG} ${this.format(...msg)}\x1b[0m`)
  42. }
  43. }
  44. let device = null
  45. let tracers = []
  46. async function stop() {
  47. Log.i('[*] Stopping all tracers')
  48. for (const tracer of tracers) {
  49. Log.i('[*] Stopping', tracer.pid)
  50. tracer.session.detach()
  51. try {
  52. await device.kill(tracer.pid)
  53. } catch (error) {}
  54. }
  55. process.exit(1)
  56. }
  57. process.on('SIGTERM', stop)
  58. process.on('SIGINT', stop)
  59. async function main() {
  60. device = await frida.getUsbDevice()
  61. device.spawnAdded.connect(onSpawnAdded)
  62. Log.i('[*] Enabling spawn gating')
  63. await device.enableSpawnGating()
  64. Log.i('[*] Enabled spawn gating')
  65. // Log.i("[*] Spawning com.google.android.apps.messaging")
  66. // const pid = await device.spawn("com.google.android.apps.messaging")
  67. // Log.i("[*] Spawned com.google.android.apps.messaging: " + pid)
  68. // const tracer = await Tracer.open(pid)
  69. // tracers.push(tracer)
  70. const processes = await device.enumerateProcesses()
  71. for (const process of processes) {
  72. if (process.name.toLowerCase().includes('system_server') ) {
  73. console.log('[*] Attaching to', process.pid, process.name)
  74. const session = await device.attach(process.pid)
  75. const script = await session.createScript(loadSource('../scripts/provider.js'))
  76. await script.load()
  77. }
  78. }
  79. }
  80. async function onSpawnAdded(spawn) {
  81. try {
  82. if (
  83. spawn.identifier.toLowerCase().includes('settings') ||
  84. spawn.identifier.toLowerCase().includes('provider')
  85. ) {
  86. Log.i('[*] Tracing', spawn.pid, spawn.identifier)
  87. const tracer = await Tracer.open(spawn.pid, '../scripts/provider.js')
  88. tracers.push(tracer)
  89. } else {
  90. Log.i('[*] Resuming', spawn.pid, spawn.identifier)
  91. await device.resume(spawn.pid)
  92. }
  93. } catch (e) {
  94. Log.e(`err: ${e}`)
  95. }
  96. }
  97. class Tracer {
  98. static async open(pid, source) {
  99. const tracer = new Tracer(pid, source)
  100. await tracer._initialize()
  101. return tracer
  102. }
  103. constructor(pid, sourceFile) {
  104. this.pid = pid
  105. this.sourceFile = sourceFile
  106. this.source = loadSource(sourceFile)
  107. this.session = null
  108. this.script = null
  109. }
  110. async _initialize() {
  111. const session = await device.attach(this.pid)
  112. this.session = session
  113. session.detached.connect(this._onSessionDetached.bind(this))
  114. const script = await session.createScript(this.source)
  115. this.script = script
  116. script.message.connect(this._onScriptMessage.bind(this))
  117. await script.load()
  118. // const script_ssl = await session.createScript(source_ssl)
  119. // await script_ssl.load()
  120. try {
  121. await device.resume(this.pid)
  122. } catch (e) {
  123. Log.e(e)
  124. }
  125. }
  126. async reload() {
  127. if (this.script) {
  128. this.script.unload()
  129. }
  130. this.source = loadSource(this.sourceFile)
  131. this.script = await this.session.createScript(this.source)
  132. this.script.message.connect(this._onScriptMessage.bind(this))
  133. await this.script.load()
  134. }
  135. _onSessionDetached(reason) {
  136. Log.i(`[PID ${this.pid}] onSessionDetached(reason='${reason}')`)
  137. const i = tracers.findIndex((tracer) => tracer.pid === this.pid)
  138. if (i !== -1) {
  139. tracers.splice(i, 1)
  140. }
  141. }
  142. _onScriptMessage(message, data) {
  143. if (message.type === 'error') {
  144. Log.e(`[PID ${this.pid}] onScriptMessage()`, message, data ? JSON.stringify(data) : '')
  145. } else {
  146. Log.i(`[PID ${this.pid}] onScriptMessage()`, message, data ? JSON.stringify(data) : '')
  147. }
  148. }
  149. }
  150. main()