手把手教你使用更多的原生安卓开发app的框架frida API
点击上方“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相关推荐
- 原生安卓开发app的框架frida常用关键代码定位
点击上方"Python爬虫与数据挖掘",进行关注 回复"书籍"即可获赠Python从入门到进阶共10本电子书 今 日 鸡 汤 多情却似总无情,唯觉樽前笑不成. ...
- 小米 android 7.0彩蛋,手把手教你小米怎么刷入安卓7.0!
原标题:手把手教你小米怎么刷入安卓7.0! 小米3/4/Note用上原生Android 7.0,还不赶快升级?手把手教你小米怎么刷入安卓7.0! Android 7.0发布已数月,但国内仅有华为EMU ...
- 手把手教你写网站:Python WEB开发技术实战
摘要:本文详细介绍了Python WEB开发的基础入门.以一个博客站点的开发为例讲解了基于Django框架开发WEB站点的全过程.通过本文的学习可以快速掌握基于Django的Python WEB的开发 ...
- uniapp 原生安卓开发插件(module),以及android环境本地调试(一)
uniapp 原生安卓开发插件(module),以及android环境本地调试 1.开发前景 由于uniapp 框架的局限先,有很多功能不能如原生android开发使用顺畅,因此,需要使用插件进行辅助 ...
- 手把手教你用AirtestIDE无线连接安卓手机
1. 前言 一直以来,我们发现同学们都挺喜欢用无线的方式连接手机,正好安卓11出了个无线连接的新姿势,我们今天就一起来看看,如何用AirtestIDE无线连接你的Android设备~ 2. Andro ...
- 手把手教你使用ADB卸载手机内置App软件
[一.前言] 不知道你们有没有那么一段黑暗时期,刚买个手机,手机上内置一堆app,还卸载不掉,然后每天各种广告,手机一共1G的运行内存,那些流氓app还要再占走一些内存,真是让人欲哭无泪啊,后来我就学 ...
- 2019-1-30手把手教你怎么用AbaqusGUI二次开发攻略
2019年1月30日13:05:51 手把手教你怎么用Abaqus进行GUI二次开发攻略 1.前言: 最近研究了下GUI二次开发,做了如下几个插件,学到了一些东西特地就跟大家做个分享,其中插件注册到了 ...
- 大佬手把手教你如何仿写出大厂的APP,原理+实战+视频+源码
除了Bug,最让你头疼的问题是什么?单身?秃头?996?面试造火箭,工作拧螺丝? 作为安卓开发者,除了Bug,经常会碰到下面这些问题: 应用卡顿,丢帧,屏幕画面撕裂,操作界面刷新缓慢,UI不美观,布局 ...
- ui uview 安卓开发_uni-app UI框架之uview-ui使用教程
image uviewUI 多平台快速开发的UI框架 uni-app2018年初发布以来,一直蓬勃发展,一派欣欣向荣,社区也是人声鼎沸,众望所归. 因此,uView应运而生,uView的目标是成为un ...
最新文章
- linux centos 7 crontab 启动,CentOS 7 Linux执行crontab 计划任务实操 - 好应网
- 数据可视化图表,你选对了吗?
- idea 编辑区设置
- 为什么我直接在servlet里面直接输出message不乱码,而跳转到web页面就出现乱码,而且存到数据库的也是乱码,我尝试了网上的各种方法,还是不成功。。
- CrystalMaker 10.6.2 mac版 CrystalMaker X最新版
- 微信公众号Web页面CSS文件里面的样式不加载
- 妙用TurboMail企业通讯平台,重要邮件不再躲猫猫
- 这款开源带采集的漫画cms,宅男的大爱
- 视频教程-Photoshop零基础快速入门及PS照片抠图修饰技巧-Photoshop
- matlab计算并联电阻怎么输入,如何用计算器快速计算并联电阻,并联电阻的计算方法...
- java.exe 0xc000012d_应用程序无法正常启动0xc000012d,此情况要怎么解决,望大神交一交...
- [附源码]SSM计算机毕业设计中华美食网站JAVA
- DELETE * FROM和DELETE FROM的区别
- 波段测试软件,超好用的波段副图(通达信公式 副图 源码 测试图)
- C++多线程——CreateThread
- kali linux 中的网卡驱动,kali linux 安装Realtek 8812AU网卡驱动
- 宏观经济学——第一章
- 盘一盘 Python 特别篇 19 - 天数计数|年限
- 福州大学计算机类分专业排名,福州大学a类学科名单-福州大学第四轮学科评估情况...
- jquery dataTable 隐藏某列
热门文章
- 装node-modules
- java SQLexists用法,exists用法-EXISTS,用法
- 剑指OFFER----51、数组中的逆数对(js实现)
- 改变了世界历史的13台计算机
- Facebook广告投放技巧及思路、如何最大化发挥广告效益!
- Android——单选多选按钮的使用详解
- 计算机东西太多了怎么清理,电脑越来越慢,电脑c盘东西太多,该如何清理?...
- 让我们深度理解Java中的抽象类与接口
- WinForm-SuspendLayout、ResumeLayout、PerformLayout
- Windows修改软件默认安装目录