phone.js 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243
  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.startsWith('com.android.phone')) {
  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/spoof_phone.js'))
  76. await script.load()
  77. }
  78. }
  79. }
  80. async function onSpawnAdded(spawn) {
  81. try {
  82. if (spawn.identifier.startsWith('com.android.phone')) {
  83. Log.i('[*] Tracing', spawn.pid, spawn.identifier)
  84. const tracer = await Tracer.open(spawn.pid, '../scripts/spoof_phone.js')
  85. tracers.push(tracer)
  86. } else {
  87. Log.i('[*] Resuming', spawn.pid, spawn.identifier)
  88. await device.resume(spawn.pid)
  89. }
  90. } catch (e) {
  91. Log.e(`err: ${e}`)
  92. }
  93. }
  94. class Tracer {
  95. static async open(pid, source) {
  96. const tracer = new Tracer(pid, source)
  97. await tracer._initialize()
  98. return tracer
  99. }
  100. constructor(pid, sourceFile) {
  101. this.pid = pid
  102. this.sourceFile = sourceFile
  103. this.source = loadSource(sourceFile)
  104. this.session = null
  105. this.script = null
  106. }
  107. async _initialize() {
  108. const session = await device.attach(this.pid)
  109. this.session = session
  110. session.detached.connect(this._onSessionDetached.bind(this))
  111. const script = await session.createScript(this.source)
  112. this.script = script
  113. script.message.connect(this._onScriptMessage.bind(this))
  114. await script.load()
  115. // const script_ssl = await session.createScript(source_ssl)
  116. // await script_ssl.load()
  117. try {
  118. await device.resume(this.pid)
  119. } catch (e) {
  120. Log.e(e)
  121. }
  122. }
  123. async reload() {
  124. if (this.script) {
  125. this.script.unload()
  126. }
  127. this.source = loadSource(this.sourceFile)
  128. this.script = await this.session.createScript(this.source)
  129. this.script.message.connect(this._onScriptMessage.bind(this))
  130. await this.script.load()
  131. }
  132. _onSessionDetached(reason) {
  133. Log.i(`[PID ${this.pid}] onSessionDetached(reason='${reason}')`)
  134. const i = tracers.findIndex((tracer) => tracer.pid === this.pid)
  135. if (i !== -1) {
  136. tracers.splice(i, 1)
  137. }
  138. }
  139. _onScriptMessage(message, data) {
  140. if (message.type === 'error') {
  141. Log.e(`[PID ${this.pid}] onScriptMessage()`, message, data ? JSON.stringify(data) : '')
  142. } else {
  143. Log.i(`[PID ${this.pid}] onScriptMessage()`, message, data ? JSON.stringify(data) : '')
  144. }
  145. }
  146. }
  147. main()
  148. const vorpal = new Vorpal()
  149. vorpal.sigint(function () {
  150. stop()
  151. })
  152. vorpal.command('clear [app]').action(async function (args, callback) {
  153. try {
  154. const app = args.app
  155. if ('sms' === app) {
  156. execSync('adb shell pm clear com.google.android.apps.messaging')
  157. } else if ('gms' === app) {
  158. execSync('adb shell pm clear com.google.android.gms')
  159. } else if ('gsf' === app) {
  160. execSync('adb shell pm clear com.google.android.gsf')
  161. } else if ('all' === app) {
  162. execSync('adb shell pm clear com.google.android.apps.messaging')
  163. await setTimeout(1000)
  164. execSync('adb shell pm clear com.google.android.gms')
  165. }
  166. } catch (error) {
  167. Log.e(error)
  168. }
  169. callback()
  170. })
  171. vorpal.command('stop').action(function (args, callback) {
  172. try {
  173. execSync('adb shell am force-stop com.google.android.apps.messaging')
  174. execSync('adb shell am force-stop com.google.android.gms')
  175. } catch (error) {
  176. Log.e(error)
  177. }
  178. callback()
  179. })
  180. vorpal.command('gen').action(function (args, callback) {
  181. execSync(`node ${path.resolve(__dirname, '../gen.js')}`)
  182. callback()
  183. })
  184. vorpal.command('reload').action(function (args, callback) {
  185. tracers.forEach((tracer) => {
  186. tracer.reload()
  187. })
  188. callback()
  189. })
  190. vorpal.command('otp [code]').action(async function (args, callback) {
  191. const code = args.code
  192. let phoneProcess
  193. try {
  194. phoneProcess = await device.getProcess('com.android.phone')
  195. } catch (error) {
  196. try {
  197. phoneProcess = await device.getProcess('SIM 卡工具包')
  198. } catch (error) {}
  199. }
  200. if (!phoneProcess) {
  201. Log.e('Phone process not found')
  202. callback()
  203. return
  204. }
  205. const session = await device.attach(phoneProcess.pid)
  206. const script = await session.createScript(
  207. loadSource('../scripts/sendsms.js')
  208. .replace('{{sender}}', '3538')
  209. .replace('{{msg}}', `Your Messenger verification code is G-${code}`)
  210. )
  211. script.message.connect((message) => {
  212. console.log('[*] Message:', message)
  213. if (message.type === 'send' && message.payload === 'ok') {
  214. script.unload()
  215. }
  216. })
  217. await script.load()
  218. callback()
  219. })
  220. vorpal.delimiter('rcs$').show()