spoof_phone.js 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267
  1. class Log {
  2. static TAG = '[Phone]'
  3. static Debug = true
  4. static format(...msg) {
  5. let m = []
  6. for (let i = 0; i < msg.length; i++) {
  7. if (typeof msg[i] === 'object') {
  8. m.push(JSON.stringify(msg[i]))
  9. } else {
  10. m.push(msg[i])
  11. }
  12. }
  13. m = m.join(' ')
  14. return m
  15. }
  16. static i(...msg) {
  17. if (!this.Debug) return
  18. console.log(`\x1b[30m${this.TAG} ${this.format(...msg)}\x1b[0m`)
  19. }
  20. static w(...msg) {
  21. console.log(`\x1b[33m${this.TAG} ${this.format(...msg)}\x1b[0m`)
  22. }
  23. static e(...msg) {
  24. console.log(`\x1b[31m${this.TAG} ${this.format(...msg)}\x1b[0m`)
  25. }
  26. static s(...msg) {
  27. console.log(`\x1b[32m${this.TAG} ${this.format(...msg)}\x1b[0m`)
  28. }
  29. }
  30. function trace(tag) {
  31. Log.e((tag || '') + Java.use('android.util.Log').getStackTraceString(Java.use('java.lang.Throwable').$new()))
  32. }
  33. const config = {
  34. mcc: '310',
  35. mnc: '240',
  36. iccid: '15003704960405101503',
  37. number: '4432486416',
  38. imei: '359028036674149',
  39. imsi: '310240158368215',
  40. country: 'us'
  41. }
  42. setImmediate(() => {
  43. Java.perform(function () {
  44. function checkPackage(name) {
  45. // return (
  46. // name.startsWith('com.google.android.gsf') ||
  47. // name.startsWith('com.google.android.gms') ||
  48. // name.startsWith('com.google.android.apps') ||
  49. // name.startsWith('com.example')
  50. // )
  51. return true
  52. }
  53. const PhoneInterfaceManager = Java.use('com.android.phone.PhoneInterfaceManager')
  54. PhoneInterfaceManager.getLine1NumberForDisplay.overload(
  55. 'int',
  56. 'java.lang.String',
  57. 'java.lang.String'
  58. ).implementation = function (subId, callingPackage, callingFeatureId) {
  59. const res = this.getLine1NumberForDisplay(subId, callingPackage, callingFeatureId)
  60. if (!checkPackage(callingPackage)) {
  61. return res
  62. }
  63. Log.i(
  64. `spoof PhoneInterfaceManager.getLine1NumberForDisplay(${subId}, ${callingPackage}, ${callingFeatureId}): ${res} -> ${config.number}`
  65. )
  66. return config.number
  67. }
  68. PhoneInterfaceManager.getNetworkCountryIsoForPhone.overload('int').implementation = function (phoneId) {
  69. const res = this.getNetworkCountryIsoForPhone(phoneId)
  70. Log.i(`spoof PhoneInterfaceManager.getNetworkCountryIsoForPhone(${phoneId}): ${res} -> ${config.country}`)
  71. return config.country
  72. }
  73. PhoneInterfaceManager.getImeiForSlot.overload('int', 'java.lang.String', 'java.lang.String').implementation =
  74. function (slotId, callingPackage, callingFeatureId) {
  75. const res = this.getImeiForSlot(slotId, callingPackage, callingFeatureId)
  76. if (!checkPackage(callingPackage)) {
  77. return res
  78. }
  79. Log.i(
  80. `spoof PhoneInterfaceManager.getImeiForSlot(${slotId}, ${callingPackage}, ${callingFeatureId}): ${res} -> ${config.imei}`
  81. )
  82. return config.imei
  83. }
  84. const SystemProperties = Java.use('android.os.SystemProperties')
  85. SystemProperties.get.overload('java.lang.String').implementation = function (key) {
  86. if ('gsm.sim.operator.iso-country' === key) {
  87. Log.i(`spoof SystemProperties.get(${key}): ${config.countryIso}`)
  88. return config.country
  89. }
  90. if ('gsm.sim.operator.numeric' === key) {
  91. Log.i(`spoof SystemProperties.get(${key}): ${config.mcc + config.mnc}`)
  92. return config.mcc + config.mnc
  93. }
  94. if ('gsm.operator.numeric' === key) {
  95. Log.i(`spoof SystemProperties.get(${key}): ${config.mcc + config.mnc}`)
  96. return config.mcc + config.mnc
  97. }
  98. return this.get(key)
  99. }
  100. const SubscriptionController = Java.use('com.android.internal.telephony.SubscriptionController')
  101. SubscriptionController.getSimStateForSlotIndex.overload('int').implementation = function (slotIndex) {
  102. const res = this.getSimStateForSlotIndex(slotIndex)
  103. Log.i(`spoof SubscriptionController.getSimStateForSlotIndex(${slotIndex}): ${res} -> 5`)
  104. return 5
  105. }
  106. SubscriptionController.getPhoneNumberFromFirstAvailableSource.overload(
  107. 'int',
  108. 'java.lang.String',
  109. 'java.lang.String'
  110. ).implementation = function (subId, callingPackage, callingFeatureId) {
  111. const res = this.getPhoneNumberFromFirstAvailableSource(subId, callingPackage, callingFeatureId)
  112. if (!checkPackage(callingPackage)) {
  113. return res
  114. }
  115. Log.i(
  116. `spoof SubscriptionController.getPhoneNumberFromFirstAvailableSource(${subId}, ${callingPackage}, ${callingFeatureId}): ${res} -> ${config.number}`
  117. )
  118. return config.number
  119. }
  120. const CharSequence = Java.use('java.lang.CharSequence')
  121. const stringClzz = Java.use('java.lang.String')
  122. const SubscriptionInfo = Java.use('android.telephony.SubscriptionInfo')
  123. const name = Java.cast(stringClzz.$new('T-Mobile'), CharSequence)
  124. const uicc = Java.array('android.telephony.UiccAccessRule', [])
  125. const BitmapConfig = Java.use('android.graphics.Bitmap$Config')
  126. const Bitmap = Java.use('android.graphics.Bitmap')
  127. console.log(
  128. Java.use('java.lang.Integer').valueOf(1),
  129. config.iccid,
  130. 0,
  131. name,
  132. name,
  133. 0,
  134. 0,
  135. config.number,
  136. 0,
  137. Bitmap.createBitmap(1, 1, BitmapConfig.ARGB_8888.value),
  138. config.mcc,
  139. config.mnc,
  140. config.country,
  141. false,
  142. Java.cast(uicc.$w, Java.use('[Landroid.telephony.UiccAccessRule;')),
  143. config.iccid
  144. )
  145. SubscriptionInfo.$init(
  146. 1,
  147. config.iccid,
  148. 0,
  149. name,
  150. name,
  151. 0,
  152. 0,
  153. config.number,
  154. 0,
  155. Bitmap.createBitmap(1, 1, BitmapConfig.ARGB_8888.value),
  156. config.mcc,
  157. config.mnc,
  158. config.country,
  159. false,
  160. Java.cast(uicc.$w, Java.use('[Landroid.telephony.UiccAccessRule;')),
  161. config.iccid
  162. )
  163. SubscriptionController.getActiveSubscriptionInfoList.overload('java.lang.String').implementation = function (
  164. callingPackage
  165. ) {
  166. const res = this.getActiveSubscriptionInfoList(callingPackage)
  167. if (!checkPackage(callingPackage)) {
  168. return res
  169. }
  170. Log.i(`spoof SubscriptionController.getActiveSubscriptionInfoList(${callingPackage})`)
  171. for (let i = 0; i < res.size(); i++) {
  172. const info = Java.cast(res.get(i), SubscriptionInfo)
  173. info.mMcc.value = config.mcc
  174. info.mMnc.value = config.mnc
  175. info.mCountryIso.value = config.country
  176. info.mIccId.value = config.iccid
  177. }
  178. SystemProperties.set('gsm.sim.operator.iso-country', config.country)
  179. SystemProperties.set('gsm.sim.operator.numeric', config.mcc + config.mnc)
  180. SystemProperties.set('gsm.operator.numeric', config.mcc + config.mnc)
  181. return res
  182. }
  183. SubscriptionController.getActiveSubscriptionInfoList.overload(
  184. 'java.lang.String',
  185. 'java.lang.String'
  186. ).implementation = function (callingPackage, callingFeatureId) {
  187. const res = this.getActiveSubscriptionInfoList(callingPackage, callingFeatureId)
  188. if (!checkPackage(callingPackage)) {
  189. return res
  190. }
  191. Log.i(`spoof SubscriptionController.getActiveSubscriptionInfoList(${callingPackage}, ${callingFeatureId})`)
  192. for (let i = 0; i < res.size(); i++) {
  193. const info = Java.cast(res.get(i), SubscriptionInfo)
  194. info.mMcc.value = config.mcc
  195. info.mMnc.value = config.mnc
  196. info.mCountryIso.value = config.country
  197. info.mIccId.value = config.iccid
  198. }
  199. SystemProperties.set('gsm.sim.operator.iso-country', config.country)
  200. SystemProperties.set('gsm.sim.operator.numeric', config.mcc + config.mnc)
  201. SystemProperties.set('gsm.operator.numeric', config.mcc + config.mnc)
  202. return res
  203. }
  204. SubscriptionController.getActiveSubscriptionInfoList.overload('java.lang.String').implementation = function (
  205. callingPackage
  206. ) {
  207. const res = this.getActiveSubscriptionInfoList(callingPackage)
  208. if (!checkPackage(callingPackage)) {
  209. return res
  210. }
  211. Log.i(`spoof SubscriptionController.getActiveSubscriptionInfoList(${callingPackage})`)
  212. for (let i = 0; i < res.size(); i++) {
  213. const info = Java.cast(res.get(i), SubscriptionInfo)
  214. info.mMcc.value = config.mcc
  215. info.mMnc.value = config.mnc
  216. info.mCountryIso.value = config.country
  217. info.mIccId.value = config.iccid
  218. }
  219. SystemProperties.set('gsm.sim.operator.iso-country', config.country)
  220. SystemProperties.set('gsm.sim.operator.numeric', config.mcc + config.mnc)
  221. SystemProperties.set('gsm.operator.numeric', config.mcc + config.mnc)
  222. return res
  223. }
  224. const PhoneSubInfoController = Java.use('com.android.internal.telephony.PhoneSubInfoController')
  225. PhoneSubInfoController.getIccSerialNumberForSubscriber.overload(
  226. 'int',
  227. 'java.lang.String',
  228. 'java.lang.String'
  229. ).implementation = function (subId, callingPackage, callingFeatureId) {
  230. const res = this.getIccSerialNumberForSubscriber(subId, callingPackage, callingFeatureId)
  231. if (!checkPackage(callingPackage)) {
  232. return res
  233. }
  234. Log.i(
  235. `spoof PhoneInterfaceManager.getIccSerialNumberForSubscriber(${subId}, ${callingPackage}, ${callingFeatureId}): ${res} -> ${config.iccid}`
  236. )
  237. return config.iccid
  238. }
  239. PhoneSubInfoController.getSubscriberIdForSubscriber.overload(
  240. 'int',
  241. 'java.lang.String',
  242. 'java.lang.String'
  243. ).implementation = function (subId, callingPackage, callingFeatureId) {
  244. const res = this.getSubscriberIdForSubscriber(subId, callingPackage, callingFeatureId)
  245. if (!checkPackage(callingPackage)) {
  246. return res
  247. }
  248. Log.i(
  249. `spoof PhoneInterfaceManager.getSubscriberIdForSubscriber(${subId}, ${callingPackage}, ${callingFeatureId}): ${res} -> ${config.imsi}`
  250. )
  251. return config.imsi
  252. }
  253. })
  254. })