├── README.md ├── openApp.js └── HookIntent.js /README.md: -------------------------------------------------------------------------------- 1 | # HookIntent 2 | 基于Frida, Hook Intent 3 | 4 | openApp.js -> 根据Activity和bundle进行跳转 5 | HookInent.js -> intent拦截 6 | 7 | 暂时弃了, 用JumpReplay. 这个项目唯一有用的就是用 openApp 自己配置下能打开自定义Extra. 虽然后面JumpReplay也会支持上 8 | -------------------------------------------------------------------------------- /openApp.js: -------------------------------------------------------------------------------- 1 | function Main() { 2 | Java.perform(function () { 3 | var ActivityThread = Java.use("android.app.ActivityThread"); 4 | var currentActivityThread = ActivityThread.currentActivityThread(); 5 | var appContext = currentActivityThread.getApplication(); 6 | 7 | var Handler = Java.use("android.os.Handler"); 8 | var Looper = Java.use("android.os.Looper"); 9 | var Intent = Java.use("android.content.Intent"); 10 | var Bundle = Java.use("android.os.Bundle"); 11 | 12 | var Activity = "com.tencent.mm.plugin.profile.ui.ContactInfoUI" 13 | 14 | var MainActivity = Java.use(Activity); 15 | 16 | var mainLooper = Looper.getMainLooper(); 17 | var handler = Handler.$new(mainLooper); 18 | 19 | var Runnable = Java.use("java.lang.Runnable"); 20 | var MyRunnable = Java.registerClass({ 21 | name: 'MyRunnable', 22 | implements: [Runnable], 23 | methods: { 24 | run: function () { 25 | var intent = Intent.$new(appContext, MainActivity.class); // use appContext here 26 | intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK.value) 27 | var bundle = Bundle.$new(); 28 | 29 | bundle.putInt('Kdel_from', 0); 30 | bundle.putString('Contact_User', 'wxid_i5e2pseumhih21'); 31 | bundle.putBoolean('Contact_RoomMember', true); 32 | // bundle.putLong('preAct_time', 1698050303122); 33 | 34 | intent.putExtras(bundle); 35 | appContext.startActivity(intent); // start activity from appContext 36 | } 37 | } 38 | }); 39 | 40 | handler.post(MyRunnable.$new()); 41 | }); 42 | } 43 | 44 | setTimeout(Main, 1000) 45 | 46 | 47 | // frida -U -l openApp.js -f com.shizhuang.duapp --no-pause -------------------------------------------------------------------------------- /HookIntent.js: -------------------------------------------------------------------------------- 1 | var logger = (function () { 2 | var levels = { 3 | 'error': '\x1b[31m', // Red 4 | 'Activity': '\x1b[33m', // Yellow 5 | 'info': '\x1b[32m', // Green 6 | 'Bundle': '\x1b[34m', // Blue 7 | 'MainActivity': '\x1b[32m' 8 | }; 9 | 10 | function printBundleType(extras) { 11 | if (extras != null) { 12 | var keySet = extras.keySet(); 13 | var iterator = keySet.iterator(); 14 | while (iterator.hasNext()) { 15 | var key = iterator.next(); 16 | var value = extras.get(key); 17 | 18 | if (value !== null) { 19 | var valueType = Java.use("java.lang.Object").getClass.call(value).getName(); 20 | console.log( 21 | " ", 22 | "\x1b[36m" + "[BundleType]" + "\x1b[0m", 23 | `Type: ${valueType}`.padEnd(30), 24 | `Key: ${key}`.padEnd(40), 25 | `Value: ${value}`.padEnd(50) 26 | ); 27 | } 28 | } 29 | } 30 | console.log() 31 | } 32 | 33 | function log(level, message) { 34 | var reset = '\x1b[0m'; 35 | console.log(levels[level] + '[' + level + ']' + reset + ' ' + message); 36 | if (level !== "Bundle" && level !== "MainActivity") { 37 | console.log() 38 | } 39 | } 40 | 41 | return { 42 | Bundle: function (message, extras) { 43 | log('Bundle', message); 44 | printBundleType(extras); 45 | }, 46 | 47 | info: function (message) { 48 | log('info', message); 49 | }, 50 | 51 | Activity: function (message) { 52 | log('Activity', message); 53 | }, 54 | 55 | error: function (message) { 56 | log('error', message); 57 | }, 58 | MainActivity: function (message, extras) { 59 | log('MainActivity', message); 60 | printBundleType(extras) 61 | } 62 | }; 63 | })(); 64 | 65 | function Main() { 66 | Java.perform(function () { 67 | 68 | var Activity = Java.use("android.app.Activity"); 69 | 70 | // var onResume = Activity.onResume; 71 | // Interceptor.replace(onResume, new NativeCallback(function () { 72 | // var intent = this.getIntent(); 73 | // var extras = intent.getExtras(); 74 | // console.log('MainActivity:', this.$className, extras); 75 | // onResume.call(this); 76 | // }, 'void', [])); 77 | // 78 | // // 接收 'input' 消息并触发 onResume() 方法 79 | // recv('input', function (data) { 80 | // if (data.payload === '\n') { 81 | // console.log('Input received, triggering onResume()...'); 82 | // onResume.call(Activity.$new()); 83 | // } 84 | // }); 85 | Activity.onResume.implementation = function () { 86 | var intent = this.getIntent(); 87 | var extras = intent.getExtras(); 88 | logger.MainActivity(this.$className, extras); 89 | try { 90 | this.onResume.overload().call(this); 91 | } catch (e) { 92 | logger.error('Error calling onResume: ', e.message); 93 | } 94 | }; 95 | Activity.startActivity.overload('android.content.Intent').implementation = function (intent) { 96 | var extras = intent.getExtras(); 97 | logger.Bundle(`startActivity intent: ${extras}`, extras); 98 | this.startActivity(intent); 99 | }; 100 | 101 | Activity.startActivityForResult.overload('android.content.Intent', 'int').implementation = function (intent, requestCode) { 102 | var extras = intent.getExtras(); 103 | 104 | logger.Bundle(`startActivityForResult intent: ${extras}, ${requestCode}`, extras); 105 | 106 | this.startActivityForResult(intent, requestCode); 107 | } 108 | ; 109 | Activity.startActivity.overload('android.content.Intent').implementation = function (intent) { 110 | var extras = intent.getExtras(); 111 | logger.Bundle(`startActivityForResult intent: ${extras}`, extras) 112 | return this.startActivity(intent); 113 | }; 114 | 115 | var Intent = Java.use("android.content.Intent"); 116 | 117 | Intent.$init.overload('android.content.Context', 'java.lang.Class').implementation = function (context, cls) { 118 | var instance = this.$init(context, cls); 119 | logger.Activity(`new Intent: ${context}, ${cls.toString()}`); 120 | return instance; 121 | }; 122 | 123 | Intent.$init.overload('android.content.Intent').implementation = function (intent) { 124 | var instance = this.$init(intent); 125 | logger.Activity(`new Intent: ${intent}`); 126 | return instance; 127 | }; 128 | Intent.putExtras.overload('android.os.Bundle').implementation = function (intent) { 129 | // var extras = intent.getExtras(); 130 | // logger.Bundle(`intent.putExtras: ${extras}`, extras) 131 | // return this.putExtras(intent); 132 | // var extras = intent.getExtras(); 133 | logger.Bundle(`intent.putExtras: ${intent}`, intent) 134 | return this.putExtras(intent); 135 | }; 136 | 137 | Intent.setClassName.overload('android.content.Context', 'java.lang.String').implementation = function (context, className) { 138 | logger.Activity(`Hooked setClassName: ${context}, ${className}`); 139 | // console.log('Context:', context); 140 | // console.log('Class Name:', className); 141 | this.setClassName(context, className); 142 | 143 | return this; 144 | }; 145 | 146 | Intent.setClassName.overload('java.lang.String', 'java.lang.String').implementation = function (packageName, className) { 147 | logger.Activity(`Hooked setClassName: ${packageName}, ${className}`); 148 | this.setClassName(packageName, className); 149 | return this; 150 | }; 151 | 152 | var Context = Java.use("android.content.Context"); 153 | 154 | Context.startActivity.overload('android.content.Intent').implementation = function (intent) { 155 | var extras = intent.getExtras(); 156 | 157 | // log before original Impl 158 | console.log("Context.startActivity intent: ", extras); 159 | 160 | // call original Impl 161 | this.startActivity(intent); 162 | }; 163 | 164 | Context.sendBroadcast.overload('android.content.Intent').implementation = function (intent) { 165 | var extras = intent.getExtras(); 166 | 167 | // log before original Impl 168 | console.log("Context.sendBroadcast intent: ", extras); 169 | 170 | // call original Impl 171 | this.sendBroadcast(intent); 172 | }; 173 | 174 | Context.startService.overload('android.content.Intent').implementation = function (intent) { 175 | var extras = intent.getExtras(); 176 | 177 | // log before original Impl 178 | console.log("Context.startService intent: ", extras); 179 | 180 | // call original Impl 181 | this.startService(intent); 182 | }; 183 | 184 | // Intent.setAction.implementation = function (action) { 185 | // console.log('Intent.setAction: action=' + action); 186 | // return this.setAction(action); 187 | // }; 188 | // 189 | // Intent.addCategory.implementation = function (category) { 190 | // console.log('Intent.addCategory: category=' + category); 191 | // return this.addCategory(category); 192 | // }; 193 | // 194 | // Intent.setData.implementation = function (uri) { 195 | // console.log('Intent.setData: uri=' + uri.toString()); 196 | // return this.setData(uri); 197 | // }; 198 | // 199 | // Intent.putExtra.overload('java.lang.String', 'java.lang.String').implementation = function (key, value) { 200 | // console.log('Intent.putExtra: key=' + key + ', value=' + value); 201 | // return this.putExtra(key, value); 202 | // }; 203 | // 204 | // Intent.putExtra.overload('java.lang.String', 'int').implementation = function (key, value) { 205 | // console.log('Intent.putExtra: key=' + key + ', value=' + value); 206 | // return this.putExtra(key, value); 207 | // }; 208 | } 209 | ) 210 | } 211 | 212 | setTimeout(Main, 500) 213 | 214 | 215 | // frida -U -l HookIntent.js com.tencent.mm --no-pause 216 | // frida -U -l HookIntent.js com.tencent.mobileqq --no-pause 217 | // frida -U -l HookIntent.js com.ccssoft.ywt --no-pause 218 | // frida -U -l HookIntent.js lozn.hookui --no-pause 219 | // frida -U -l HookIntent.js com.android.launcher3 --no-pause --------------------------------------------------------------------------------