|
6 | 6 |
|
7 | 7 | ```js |
8 | 8 | // ByteString.of是用来把byte[]数组转成hex字符串的函数, Android系统自带ByteString类 |
9 | | - var ByteString = Java.use("com.android.okhttp.okio.ByteString"); |
10 | | - var j = Java.use("c.business.comm.j"); |
11 | | - j.x.implementation = function() { |
12 | | - var result = this.x(); |
13 | | - console.log("j.x:", ByteString.of(result).hex()); |
14 | | - return result; |
15 | | - }; |
16 | | - |
17 | | - j.a.overload('[B').implementation = function(bArr) { |
18 | | - this.a(bArr); |
19 | | - console.log("j.a:", ByteString.of(bArr).hex()); |
20 | | - }; |
| 9 | + function hookSign() { |
| 10 | + Java.perform(function () { |
| 11 | + var NativeApi = Java.use('com.weibo.xvideo.NativeApi'); |
| 12 | + // 使用系统工具类将byte数组转成hex、utf8. |
| 13 | + var ByteString = Java.use("com.android.okhttp.okio.ByteString"); |
| 14 | + NativeApi.s.implementation = function (str1, str2) { |
| 15 | + var result = this.s(str1, str2); |
| 16 | + console.log("str:" + ByteString.of(str1).utf8()) |
| 17 | + console.log("hex:" + ByteString.of(str1).hex()) |
| 18 | + console.log(result); |
| 19 | + return result; |
| 20 | + } |
| 21 | + }); |
| 22 | + } |
21 | 23 | ``` |
22 | 24 |
|
23 | 25 | 2. [构造一个字符串](https://github.com/heyhu/frida-agent-example/blob/master/code/rouse/hook_java/challenge_hook.js#L23) |
|
234 | 236 | 很多对象都可以用 .toString() 来打印字符串 |
235 | 237 | ``` |
236 | 238 |
|
237 | | -24. hook方法的所有重载 |
238 | | - ```js |
239 | | - //目标类 |
240 | | - var hook = Java.use(targetClass); |
241 | | - //重载次数 |
242 | | - var overloadCount = hook[targetMethod].overloads.length; |
243 | | - //打印日志:追踪的方法有多少个重载 |
244 | | - console.log("Tracing " + targetClassMethod + " [" + overloadCount + " overload(s)]"); |
245 | | - //每个重载都进入一次 |
246 | | - for (var i = 0; i < overloadCount; i++) { |
247 | | - //hook每一个重载 |
248 | | - hook[targetMethod].overloads[i].implementation = function() { |
249 | | - console.warn("\n*** entered " + targetClassMethod); |
250 | | - |
251 | | - //可以打印每个重载的调用栈,对调试有巨大的帮助,当然,信息也很多,尽量不要打印,除非分析陷入僵局 |
252 | | - Java.perform(function() { |
253 | | - var bt = Java.use("android.util.Log").getStackTraceString(Java.use("java.lang.Exception").$new()); |
254 | | - console.log("\nBacktrace:\n" + bt); |
255 | | - }); |
256 | | - |
257 | | - // 打印参数 |
258 | | - if (arguments.length) console.log(); |
259 | | - for (var j = 0; j < arguments.length; j++) { |
260 | | - console.log("arg[" + j + "]: " + arguments[j]); |
261 | | - } |
262 | | - |
263 | | - //打印返回值 |
264 | | - var retval = this[targetMethod].apply(this, arguments); // rare crash (Frida bug?) |
265 | | - console.log("\nretval: " + retval); |
266 | | - console.warn("\n*** exiting " + targetClassMethod); |
267 | | - return retval; |
268 | | - } |
269 | | - } |
270 | | - ``` |
271 | | -
|
272 | | -25. hook类的所有方法 |
273 | | - ```js |
274 | | - function traceClass(targetClass) |
275 | | - { |
276 | | - //Java.use是新建一个对象哈,大家还记得么? |
277 | | - var hook = Java.use(targetClass); |
278 | | - //利用反射的方式,拿到当前类的所有方法 |
279 | | - var methods = hook.class.getDeclaredMethods(); |
280 | | - //建完对象之后记得将对象释放掉哈 |
281 | | - hook.$dispose; |
282 | | - //将方法名保存到数组中 |
283 | | - var parsedMethods = []; |
284 | | - methods.forEach(function(method) { |
285 | | - parsedMethods.push(method.toString().replace(targetClass + ".", "TOKEN").match(/\sTOKEN(.*)\(/)[1]); |
286 | | - }); |
287 | | - //去掉一些重复的值 |
288 | | - var targets = uniqBy(parsedMethods, JSON.stringify); |
289 | | - //对数组中所有的方法进行hook,traceMethod也就是第一小节的内容 |
290 | | - targets.forEach(function(targetMethod) { |
291 | | - traceMethod(targetClass + "." + targetMethod); |
292 | | - }); |
293 | | - } |
294 | | - ``` |
295 | | -
|
296 | | -#### JAVA api |
297 | | -
|
298 | | -1. hook类的所有子类 |
299 | | -
|
300 | | - ```js |
301 | | - //枚举所有已经加载的类 |
302 | | - Java.enumerateLoadedClasses({ |
303 | | - onMatch: function(aClass) { |
304 | | - //迭代和判断 |
305 | | - if (aClass.match(pattern)) { |
306 | | - //做一些更多的判断,适配更多的pattern |
307 | | - var className = aClass.match(/[L]?(.*);?/)[1].replace(/\//g, "."); |
308 | | - //进入到traceClass里去 |
309 | | - traceClass(className); |
310 | | - } |
311 | | - }, |
312 | | - onComplete: function() {} |
313 | | - });Hook Java |
314 | | - ``` |
315 | | -
|
316 | | -2. Java.available |
317 | | -
|
318 | | - ``` |
319 | | - // 该函数一般用来判断当前进程是否加载了JavaVM,Dalvik或ART虚拟机 |
320 | | - function frida_Java() { |
321 | | - Java.perform(function () { |
322 | | - //作为判断用 |
323 | | - if(Java.available) |
324 | | - { |
325 | | - //注入的逻辑代码 |
326 | | - console.log("hello java vm"); |
327 | | - }else{ |
328 | | - //未能正常加载JAVA VM |
329 | | - console.log("error"); |
330 | | - } |
331 | | - }); |
332 | | - } |
333 | | - setImmediate(frida_Java,0); |
334 | | - |
335 | | - 输出如下。 |
336 | | - hello java vm |
337 | | - 核心注入的逻辑代码写在<注入的逻辑代码>内会非常的安全万无一失~ |
338 | | - |
339 | | - ``` |
340 | | -
|
341 | | -3. Java.androidVersion |
342 | | - ``` |
343 | | - // 显示android系统版本号 |
344 | | - function frida_Java() { |
345 | | - Java.perform(function () { |
346 | | - //作为判断用 |
347 | | - if(Java.available) |
348 | | - { |
349 | | - //注入的逻辑代码 |
350 | | - console.log("",Java.androidVersion); |
351 | | - }else{ |
352 | | - //未能正常加载JAVA VM |
353 | | - console.log("error"); |
354 | | - } |
355 | | - }); |
356 | | - } |
357 | | - setImmediate(frida_Java,0); |
358 | | - |
359 | | - 输出如下。 |
360 | | - 9 ,因为我的系统版本是9版本~ |
361 | | - |
362 | | - ``` |
363 | | -
|
364 | | -4. 获取类Java.use |
365 | | - ```js |
366 | | - // Java.use(className),动态获取className的类定义,通过对其调用$new()来调用构造函数,可以从中实例化对象。当想要回收类时可以调用$Dispose()方法显式释放,当然也可以等待JavaScript的垃圾回收机制,当实例化一个对象之后,可以通过其实例对象调用类中的静态或非静态的方法,官方代码示例定义如下。 |
367 | | - |
368 | | - Java.perform(function () { |
369 | | - //获取android.app.Activity类 |
370 | | - var Activity = Java.use('android.app.Activity'); |
371 | | - //获取java.lang.Exception类 |
372 | | - var Exception = Java.use('java.lang.Exception'); |
373 | | - //拦截Activity类的onResume方法 |
374 | | - Activity.onResume.implementation = function () { |
375 | | - //调用onResume方法的时候,会在此处被拦截并且调用以下代码抛出异常! |
376 | | - throw Exception.$new('Oh noes!'); |
377 | | - }; |
378 | | - }); |
379 | | - ``` |
380 | | -
|
381 | | -5. Java.vm对象 |
382 | | - ```js |
383 | | - //Java.vm对象十分常用,比如想要拿到JNI层的JNIEnv对象,可以使用getEnv();我们来看看具体的使用和基本小实例。~ |
384 | | - |
385 | | - function frida_Java() { |
386 | | - Java.perform(function () { |
387 | | - //拦截getStr函数 |
388 | | - Interceptor.attach(Module.findExportByName("libhello.so" , "Java_com_roysue_roysueapplication_hellojni_getStr"), { |
389 | | - onEnter: function(args) { |
390 | | - console.log("getStr"); |
391 | | - }, |
392 | | - onLeave:function(retval){ |
393 | | - //它的返回值的是retval 在jni层getStr的返回值的jstring |
394 | | - //我们在这里做的事情就是替换掉结果 |
395 | | - //先获取一个Env对象 |
396 | | - var env = Java.vm.getEnv(); |
397 | | - //通过newStringUtf方法构建一个jstirng字符串 |
398 | | - var jstring = env.newStringUtf('roysue'); |
399 | | - //replace替换掉结果 |
400 | | - retval.replace(jstring); |
401 | | - console.log("getSum方法返回值为:roysue") |
402 | | - } |
403 | | - }); |
404 | | - })} |
405 | | - setImmediate(frida_Java,0); |
406 | | - ``` |
407 | 239 |
|
0 commit comments