点击上方“Python爬虫与数据挖掘”,进行关注

回复“书籍”即可获赠Python从入门到进阶共10本电子书

蜡烛有心还惜别,替人垂泪到天明。

大家好,我是码农星期八!本教程只用于学习探讨,不允许任何人使用技术进行违法操作,阅读教程即表示同意!

前言

上节课学习了如何hook关键代码定位,本节课来继续学习如何学习更多的frida API吧!

官方文档

frida的官方JavaScriptAPI:https://frida.re/docs/javascript-api/

用到的app

app-release.apk

hook普通方法和静态方法

普通方法和静态方法hook是一样的,不需要区分。

如果是主动调用的话,是需要区分静态方法和普通方法的。

代码

//普通方法
let money = Java.use("com.xiaojianbang.hook.Money");money.getInfo.implementation = function () {console.log("money.getInfo 被调用");return this.getInfo();
}
//静态方法
money.setFlag.overload('java.lang.String').implementation = function (str) {console.log("money.getInfo 被调用");console.log("参数 str:", str);return this.setFlag(str);
}

函数参数和返回值的修改

let money = Java.use("com.xiaojianbang.hook.Money");
money.getInfo.implementation = function () {console.log("money.getInfo 被调用");return "getInfo 返回值被修改了";
}

hook构造方法($init)

let money = Java.use("com.xiaojianbang.hook.Money");
money.$init.implementation = function (str, i) {console.log(str, i)return this.$init("张三", 2000);}

对象参数的构造与修改($new)

//构造
let wallet = Java.use("com.xiaojianbang.hook.Wallet");
let money = Java.use("com.xiaojianbang.hook.Money");wallet.deposit.implementation = function (arg_money) {console.log("arg arg_money:",arg_money);//deposit需要的是Money对象,这里通过$new new出来return this.deposit(money.$new("张三",10))
}
修改
wallet.deposit.implementation = function (a) {console.log("arg a:", a);//修改传过来Money对象的值a.setAmount(15);console.log(a.getAmount())return this.deposit(a)
}

打印HashMap

function printMap(map) {var result = {};var keyset = map.keySet();var it = keyset.iterator();while (it.hasNext()) {var keystr = it.next().toString();var valuestr = map.get(keystr).toString();result[keystr] = valuestr;}return JSON.stringify(result);
}

通过类型上转方式

function printMap2(map) {return Java.cast(map, Java.use("java.util.HashMap"));
}

重载方法 使用overload进行区分

var utils = Java.use("com.xiaojianbang.hook.Utils");
utils.getCalc.overload('int', 'int').implementation = function (a, b) {console.log(a, b);return this.getCalc(a, b);
}
utils.getCalc.overload('int', 'int', 'int').implementation = function (a, b, c) {console.log(a, b, c);return this.getCalc(a, b, c);
}
utils.getCalc.overload('int', 'int', 'int', 'int').implementation = function (a, b, c, d) {console.log(a, b, c, d);return this.getCalc(a, b, c, d);
}

hook所有重载

var utils = Java.use("com.xiaojianbang.hook.Utils");
//overloads获取的重载的函数
var overloadsArr = utils.getCalc.overloads;
for (var i = 0; i < overloadsArr.length; i++) {overloadsArr[i].implementation = function () {showStack();var params = "";for (var j = 0; j < arguments.length; j++) {//arguments是参数列表,arguments[0]就是第一个参数params += arguments[j] + " ";}console.log("utils.getCalc is called! params is: ", params);// if(arguments.length == 2){//     return this.getCalc(arguments[0], arguments[1]);// }else if(arguments.length == 3){//     return this.getCalc(arguments[0], arguments[1], arguments[2]);// }else if(arguments.length == 4){//     return this.getCalc(arguments[0], arguments[1], arguments[2], arguments[3]);// }console.log(this);return this.getCalc.apply(this, arguments);}
}

主动调用

var money = Java.use("com.xiaojianbang.hook.Money");
money.setFlag("静态方法主动调用");
// 普通方法 实例化+对象.方法()
var moneyObj = money.$new("卢布", 1000);
console.log(moneyObj.getInfo());//Java.choose,搜索内存中的某个对象,传入类即可
Java.choose("com.xiaojianbang.hook.Money", {onMatch: function (obj) {
//可以调用对象的字段和方法,如果字段和属性重名,字段需要加_console.log(obj.getInfo(),obj.currency.value,obj._currency.value);}, onComplete: function () {console.log("内存中的Money对象搜索完毕");}
})

获取和修改类的字段

let money = Java.use("com.xiaojianbang.hook.Money");
//静态字段需要通过value才能获取具体值
console.log(money.flag.value);
//设置值直接设置即可
money.flag.value = "fuck";
console.log(money.flag.value);
//普通字段
let moneyObj = money.$new("张三", 10);
console.log(moneyObj.currency.value);
moneyObj.currency.value = "普通字段修改";
console.log(moneyObj.currency.value);

hook内部类和匿名类

内部类

内部类好说,直接后面+$即可

let wallet$InnerStructure = Java.use("com.xiaojianbang.hook.Wallet$InnerStructure")
console.log(wallet$InnerStructure)
//通过choose找到InnerStructure对象,然后调用它的方法或值
Java.choose("com.xiaojianbang.hook.Wallet$InnerStructure", {onMatch: function (obj) {console.log("Java.choose Wallet$InnerStructure: ", obj.bankCardsList.value);}, onComplete: function () {}
});

匿名类

匿名类通常是所在的类后面跟$数字,在smail中比较容易看到。

let money$1 = Java.use("com.xiaojianbang.app.MainActivity$1");
money$1.getInfo.implementation = function () {var result = this.getInfo();console.log("money.getInfo result: ", result);return result;
}

枚举所有已加载的类

console.log(Java.enumerateLoadedClassesSync().join("\n"))

枚举类的所有方法

let wallet = Java.use("com.xiaojianbang.hook.Wallet")
//方法
let methods = wallet.class.getDeclaredMethods();
for (let i = 0; i < methods.length; i++) {console.log(methods[i].getName());
}
//构造
let constructors = wallet.class.getDeclaredConstructors();
console.log("============================");
for (let i = 0; i < constructors.length; i++) {console.log(constructors[i].getName());
}
// 字段
let fields = wallet.class.getDeclaredFields()
console.log("============================");
for (let i = 0; i < fields.length; i++) {console.log(fields[i].getName());
}
//内部类
var classes = wallet.class.getDeclaredClasses();
console.log("============================");
for (let i = 0; i < classes.length; i++) {console.log(classes[i].getName());//classes[i] 这里得到的已经是类的字节码,不需要再.calssvar Wallet$InnerStructure = classes[i].getDeclaredFields();for (let j = 0; j < Wallet$InnerStructure.length; j++) {console.log(Wallet$InnerStructure[j].getName());}
}

hook类的所有方法

function hookFunc(cls,methodName) {console.log(methodName);var overloadsArr = cls[methodName].overloads;for (let j = 0; j < overloadsArr.length; j++) {overloadsArr[j].implementation = function () {var params = "";for (var k = 0; k < arguments.length; k++) {params += arguments[k] + " ";}console.log("cls." + methodName + " is called! params is: ", params);return this[methodName].apply(this, arguments);}}
}
//
var utils = Java.use("com.xiaojianbang.hook.Utils");
var methods = utils.class.getDeclaredMethods();
for (let i = 0; i < methods.length; i++) {var methodName = methods[i].getName();hookFunc(utils,methodName);
}

registerClass 给app注入一个类

const MyWeirdTrustManager = Java.registerClass({name: 'com.xiaojianbang.app.MyRegisterClass',implements: [Java.use("com.xiaojianbang.app.TestRegisterClass")],fields: {description: 'java.lang.String',limit: 'int',},methods: {$init() {console.log('Constructor called');},test1: [{returnType: 'void',argumentTypes: [],implementation() {console.log('test1 called');}}, {returnType: 'void',argumentTypes: ['java.lang.String', 'int'],implementation(str, num) {console.log('test1(str, num) called', str, num);}}],test2(str, num) {console.log('test2(str, num) called', str, num);return null;},}
});
var myObj = MyWeirdTrustManager.$new();
myObj.test1();
myObj.test1("xiaojianbang1", 100);
myObj.test2("xiaojianbang2", 200);
myObj.limit.value = 10000;
console.log(myObj.limit.value);

frida注入dex

Java.openClassFile("/data/local/tmp/patch.dex").load();
var test = Java.use("com.xiaojianbang.myapplication.Test");
var utils = Java.use("com.xiaojianbang.hook.Utils");
utils.shufferMap.implementation = function (map) {var result = test.print(map);console.log(result);return result;
}

hook 枚举类(Java.choose)

Java.choose("com.xiaojianbang.app.Season", {onMatch: function (obj) {console.log(obj.ordinal());}, onComplete: function () {}
})
//打印枚举类的属性
console.log(Java.use("com.xiaojianbang.app.Season").values());

frida写文件

var ios = new File("/sdcard/xiaojianbang.txt", "w");
ios.write("xiaojianbang is very good!!!\n");
ios.flush();
ios.close();

android Context(上下文)的获取

var current_application = Java.use('android.app.ActivityThread').currentApplication();
var context = current_application.getApplicationContext();

Java.cast  向上转型的

// 向上转型的,不能用toString直接得到结果,比如Map、List类型的打印
var utils = Java.use("com.xiaojianbang.hook.Utils");
utils.shufferMap2.implementation = function (map) {console.log("map: ", map);console.log("map: ", printMap(map));console.log("map: ", printMap2(map));var result = Java.cast(map, Java.use("java.util.HashMap"));console.log("map: ", result);return this.shufferMap2(result);
}

数组的构建

var utils = Java.use("com.xiaojianbang.hook.Utils");
console.log(utils.myPrint(["xiaojianbang", "QQ:243757", "VX:xia88", "公众号"])
);
//构建
var strarr = Java.array("Ljava.lang.String;",["123", "123", "VX:123", "123"]
);
console.log(utils.myPrint(strarr));

Object数组的构建

var utils = Java.use("com.xiaojianbang.hook.Utils");
var bankCard = Java.use("com.xiaojianbang.hook.BankCard");
var bankCardObj = bankCard.$new("xiaojianbang", "123456789", "CBDA", 1, "15900000000");
var integer = Java.use("java.lang.Integer");
var boolean = Java.use("java.lang.Boolean");
//var objarr = Java.array(
// "Ljava.lang.Object;",
// ["xiaojianbang", integer.$new(30), boolean.$new(true), bankCardObj]
//);
console.log(utils.myPrint(["xiaojianbang", integer.$new(30), boolean.$new(true), bankCardObj])
);

Arraylist的主动调用

let arrayList = Java.use("java.util.ArrayList").$new();
let integer = Java.use("java.lang.Integer");
let boolean = Java.use("java.lang.Boolean");
let bankCard = Java.use("com.xiaojianbang.hook.BankCard");
let bankCardObj = bankCard.$new("xiaojianbang", "123456789", "CBDA", 1, "15900000000");
arrayList.add("xiaojianbang");
arrayList.add(integer.$new(30));
arrayList.add(boolean.$new(true));
arrayList.add(bankCardObj);var utils = Java.use("com.xiaojianbang.hook.Utils");
console.log(utils.myPrint(arrayList));

hook动态加载的dex(Java.enumerateClassLoaders)

console.log("-->:", Java.enumerateLoadedClassesSync().join("\n"));
// 这样hook的话基本上是加载之后的,不会出现hook不到,所以需要通过这种方式
Java.enumerateClassLoaders({onMatch: function (loader) {try {//loader这就是红波浪线Java.classFactory.loader = loader;var dynamic = Java.use("com.xiaojianbang.app.Dynamic");console.log("dynamic: ", dynamic);//console.log(dynamic.$new().sayHello());dynamic.sayHello.implementation = function () {console.log("hook dynamic.sayHello is run!");return "xiaojianbang";}} catch (e) {console.log("e:",loader);}},onComplete: function () {}
});

hook动态加载的dex(DexClassLoader)

var dexClassLoader = Java.use("dalvik.system.DexClassLoader");
dexClassLoader.loadClass.overload('java.lang.String').implementation = function (className) {//console.log(className);var result = this.loadClass(className);//console.log("class: ", result);//console.log("class.class: ", result.class);//console.log("xxxxxxxx: ", result.getDeclaredMethods());if("com.xiaojianbang.app.Dynamic" === className){Java.classFactory.loader = this;var dynamic = Java.use("com.xiaojianbang.app.Dynamic");console.log("dynamic: ", dynamic);//var clazz = dynamic.class;//console.log("xxxxxxxx: ", clazz.getDeclaredMethods()[0].invoke(clazz.newInstance(), []));//console.log(dynamic.$new().sayHello());dynamic.sayHello.implementation = function () {console.log("dynamic.sayHello is called");return "xiaojianbang";}console.log(dynamic.$new().sayHello());}return result;
}

让hook只在指定函数内生效

var mainActivity = Java.use("com.xiaojianbang.app.MainActivity");
var stringBuilder = Java.use('java.lang.StringBuilder');
mainActivity.generateAESKey.implementation = function () {console.log("mainActivity.generateAESKey is called!");stringBuilder.toString.implementation = function () {var result = this.toString();console.log(result);return result;};var result = this.generateAESKey.apply(this, arguments);stringBuilder.toString.implementation = null;  //取消hookreturn result;
};

简单示例

主动调用登录按钮

xx牛.apk

如何通过frida点击这个登录按钮呢?

代码

//主动点击登录按钮
function call_login_btn() {Java.perform(function () {//通过寻找内存中的对象方式找到LoginActivityJava.choose("com.dodonew.online.ui.LoginActivity", {onMatch: function (objectWrapper) {//构建上下文let current_application = Java.use('android.app.ActivityThread').currentApplication();let context = current_application.getApplicationContext();//构建OnClick需要的Viewlet view = Java.use("android.view.View")let viewObj = view.$new(context);//设置按钮idviewObj.setId(2131558593);//点击objectWrapper.onClick(viewObj);}, onComplete: function () {}})})
}

效果演示

总结

本次主要还是一些理论知识,其实有的之前都已经了解过了,只不过这次把常用的都列出来了。主要还是各种hook,和主动调用。

人生没有白走的路,加油!如果在操作过程中有任何问题,记得下面留言,我们看到会第一时间解决问题。

越努力,越幸运。我是码农星期八,如果觉得还不错,记得动手点赞一下哈,感谢你的观看。

小伙伴们,快快用实践一下吧!如果在学习过程中,有遇到任何问题,欢迎加我好友,我拉你进Python学习交流群共同探讨学习。

------------------- End -------------------

往期精彩文章推荐:

  • requests库请求获取不到数据怎么办?不妨试试看这种妙法

  • Python网络爬虫之js逆向之远程调用(rpc)免去抠代码补环境简介

  • 盘点一款自研的Python虚拟环境管理器——带GUI界面的那种

  • 盘点一道Python网络爬虫中使用正则表达式匹配字符的题目

欢迎大家点赞,留言,转发,转载,感谢大家的相伴与支持

想加入Python学习群请在后台回复【入群

万水千山总是情,点个【在看】行不行

/今日留言主题/

随便说一两句吧~~

手把手教你使用更多的原生安卓开发app的框架frida API相关推荐

  1. 原生安卓开发app的框架frida常用关键代码定位

    点击上方"Python爬虫与数据挖掘",进行关注 回复"书籍"即可获赠Python从入门到进阶共10本电子书 今 日 鸡 汤 多情却似总无情,唯觉樽前笑不成. ...

  2. 小米 android 7.0彩蛋,手把手教你小米怎么刷入安卓7.0!

    原标题:手把手教你小米怎么刷入安卓7.0! 小米3/4/Note用上原生Android 7.0,还不赶快升级?手把手教你小米怎么刷入安卓7.0! Android 7.0发布已数月,但国内仅有华为EMU ...

  3. 手把手教你写网站:Python WEB开发技术实战

    摘要:本文详细介绍了Python WEB开发的基础入门.以一个博客站点的开发为例讲解了基于Django框架开发WEB站点的全过程.通过本文的学习可以快速掌握基于Django的Python WEB的开发 ...

  4. uniapp 原生安卓开发插件(module),以及android环境本地调试(一)

    uniapp 原生安卓开发插件(module),以及android环境本地调试 1.开发前景 由于uniapp 框架的局限先,有很多功能不能如原生android开发使用顺畅,因此,需要使用插件进行辅助 ...

  5. 手把手教你用AirtestIDE无线连接安卓手机

    1. 前言 一直以来,我们发现同学们都挺喜欢用无线的方式连接手机,正好安卓11出了个无线连接的新姿势,我们今天就一起来看看,如何用AirtestIDE无线连接你的Android设备~ 2. Andro ...

  6. 手把手教你使用ADB卸载手机内置App软件

    [一.前言] 不知道你们有没有那么一段黑暗时期,刚买个手机,手机上内置一堆app,还卸载不掉,然后每天各种广告,手机一共1G的运行内存,那些流氓app还要再占走一些内存,真是让人欲哭无泪啊,后来我就学 ...

  7. 2019-1-30手把手教你怎么用AbaqusGUI二次开发攻略

    2019年1月30日13:05:51 手把手教你怎么用Abaqus进行GUI二次开发攻略 1.前言: 最近研究了下GUI二次开发,做了如下几个插件,学到了一些东西特地就跟大家做个分享,其中插件注册到了 ...

  8. 大佬手把手教你如何仿写出大厂的APP,原理+实战+视频+源码

    除了Bug,最让你头疼的问题是什么?单身?秃头?996?面试造火箭,工作拧螺丝? 作为安卓开发者,除了Bug,经常会碰到下面这些问题: 应用卡顿,丢帧,屏幕画面撕裂,操作界面刷新缓慢,UI不美观,布局 ...

  9. ui uview 安卓开发_uni-app UI框架之uview-ui使用教程

    image uviewUI 多平台快速开发的UI框架 uni-app2018年初发布以来,一直蓬勃发展,一派欣欣向荣,社区也是人声鼎沸,众望所归. 因此,uView应运而生,uView的目标是成为un ...

最新文章

  1. linux centos 7 crontab 启动,CentOS 7 Linux执行crontab 计划任务实操 - 好应网
  2. 数据可视化图表,你选对了吗?
  3. idea 编辑区设置
  4. 为什么我直接在servlet里面直接输出message不乱码,而跳转到web页面就出现乱码,而且存到数据库的也是乱码,我尝试了网上的各种方法,还是不成功。。
  5. CrystalMaker 10.6.2 mac版 CrystalMaker X最新版
  6. 微信公众号Web页面CSS文件里面的样式不加载
  7. 妙用TurboMail企业通讯平台,重要邮件不再躲猫猫
  8. 这款开源带采集的漫画cms,宅男的大爱
  9. 视频教程-Photoshop零基础快速入门及PS照片抠图修饰技巧-Photoshop
  10. matlab计算并联电阻怎么输入,如何用计算器快速计算并联电阻,并联电阻的计算方法...
  11. java.exe 0xc000012d_应用程序无法正常启动0xc000012d,此情况要怎么解决,望大神交一交...
  12. [附源码]SSM计算机毕业设计中华美食网站JAVA
  13. DELETE * FROM和DELETE FROM的区别
  14. 波段测试软件,超好用的波段副图(通达信公式 副图 源码 测试图)
  15. C++多线程——CreateThread
  16. kali linux 中的网卡驱动,kali linux 安装Realtek 8812AU网卡驱动
  17. 宏观经济学——第一章
  18. 盘一盘 Python 特别篇 19 - 天数计数|年限
  19. 福州大学计算机类分专业排名,福州大学a类学科名单-福州大学第四轮学科评估情况...
  20. jquery dataTable 隐藏某列

热门文章

  1. 装node-modules
  2. java SQLexists用法,exists用法-EXISTS,用法
  3. 剑指OFFER----51、数组中的逆数对(js实现)
  4. 改变了世界历史的13台计算机
  5. Facebook广告投放技巧及思路、如何最大化发挥广告效益!
  6. Android——单选多选按钮的使用详解
  7. 计算机东西太多了怎么清理,电脑越来越慢,电脑c盘东西太多,该如何清理?...
  8. 让我们深度理解Java中的抽象类与接口
  9. WinForm-SuspendLayout、ResumeLayout、PerformLayout
  10. Windows修改软件默认安装目录