测试用例
测试用例结构比较简单。  主要代码都在 MainActivity 和 Car 中。SecondActivity、MainService、MyReceiver以及布局文件并无实效代码,就不予展示了。
package com.zyc.objectiondemo;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
public static int CAR_COUNT = 0;
private Button btnShow;
private Button btnShow_int;
private Car car1;
private Car car2;
private Car car3;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btnShow = findViewById(R.id.btn_show);
btnShow.setOnClickListener(this);
btnShow_int = findViewById(R.id.btn_show_int);
btnShow_int.setOnClickListener(this);
car1 = new Car(1, "布加迪");
car2 = new Car(2, "奔驰qqqaaa");
car3 = new Car(3, "aaaqqq");
CAR_COUNT = 3;
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btn_show:
Car tempCar1 = new Car(4);
tempCar1.setName("Car4");
String txt = tempCar1.show();
Toast.makeText(this, txt, Toast.LENGTH_SHORT).show();
break;
case R.id.btn_show_int:
Car tempCar2 = new Car(5,"Car5");
String txt2 = tempCar2.show(989);
Toast.makeText(this, txt2, Toast.LENGTH_SHORT).show();
break;
}
}
public void toastSelf() {
Toast.makeText(this, "I'm MainActivity", Toast.LENGTH_SHORT).show();
}
}
package com.zyc.objectiondemo;
public class Car {
private int id;
private String name;
public Car(int id) {
this.id = id;
}
public Car(int id, String name) {
this.id = id;
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String show() {
return "id--> " + id + "\nname--> " + name;
}
public String show(int count) {
return "id--> " + id + "\nname--> " + name + "\ncount--> " + count;
}
}
运行 frida-server 后开启 objection 之旅:
objection -g com.zyc.objectiondemo explore
?
列出内存中加载的库
memory list modules 。  如果要把结果以json格式输出到本地可以在指令后添加参数,memory list modules --json /root/modules.json 。  ?
列出某个库的导出函数
假设要列出 libssl.so 文件的导出函数,memory list exports libssl.so 。  该指令同样支持输出到json文件,memory list exports libssl.so --json /root/exports.json 。  ?
搜索内存数据
在内存中通过字节串可以搜索数据,APP点击按钮创建带“aaaqqq”和“奔驰qqqaaa”字样的Car类后,想找到“aaaqqq”运行memory search "61 61 61 71 71 71" ,或者模糊搜索memory search "61 61 61 71" 、memory search "61 61 61 ?? ?? 71" 。  该指令貌似无法搜索出带中文的字符串。  也可以增加参数通过字符串搜索,运行memory search "aaaqqq" --string ,此方式不支持模糊搜索。  如果只展示搜索到的偏移地址,不需要展示附近内存,运行memory search "61 61 61 71 71 71" --offsets-only 。  ?
写入内存数据
通过内存地址可以写入数据,比如搜索TextView的文字“Helloword”并通过memory write 0x12fc9c78 '61 61 61' 修改其中一处结果,再把进程切换一下后台&前台,就刷新成修改的数据了。  ?
提取内存数据
有了内存数据的偏移和长度,就可以通过memory dump from_base 0x12fc9c78 9 /root/memory.txt 指令把刚才的内存dump到本地。  ?
列出内存中所有的类
android hooking list classes ,本次找到了5511个类。  ?
列出指定类的所有方法
假设要查看APP MainActivity 类的方法,运行android hooking list class_methods com.zyc.objectiondemo.MainActivity ,可以看到只打印了属于该类的方法,继承来的并不会打印。  ?
在内存中所有的类里搜索类
从已加载的类里查找和“zyc”关键字,运行android hooking search classes zyc 。  ?
在内存中所有的类里搜索方法
假设要搜索带“onCreate”的方法,运行android hooking search methods onCreate 。该指令会遍历内存中所有已加载类的所有方法执行搜索,数据量非常大,过程相当耗时,甚至容易卡死和崩溃,所以会在运行前手动输入“y”同意。  ?
列出所有Activity、Service、Receiver
查看APP的组件使用android hooking list activities 、android hooking list services 、android hooking list receivers 命令。  ?
启动Activity
使用android intent launch_activity com.zyc.objectiondemo.SecondActivity 会以 Intent.FLAG_ACTIVITY_NEW_TASK 的方式直接启动Activity页面,通过此命令有时可以直接启动某些常规方式访问不到的页面。  ?
内存堆上搜索实例
从用例代码可知,运行APP进入 MainActivity 后会创建3个Car对象,此时如果想查看内存中的Car实例,运行android heap search instances com.zyc.objectiondemo.Car 。  ?
调用实例的方法
搜索到实例获取地址后可调用其方法。如果要调用实例1的 show() 方法,运行android heap execute 68389604 show 。  ?
实时注入实例
拿到实例后可以直接在实例上书写js注入,运行android heap evaluate 23973990 会进入js编辑器,可以实时编写、注入、调试,但没有代码提示。  ?
导入Hook代码
objection支持导入Hook js文件使用,比如 /root/Desktop/objectionHook.js 有下面Hook代码:
function main() {
Java.perform(function () {
console.log("Hook start...");
var Car = Java.use("com.zyc.objectiondemo.Car");
Car.show.overload("int").implementation = function (arg1) {
console.log("Hook show..." + arg1);
return this.show(arg1);
}
});
}
setImmediate(main())
运行import /root/Desktop/objectionHook.js 就可以在objection中直接使用了。  ?
Hook类所有方法
运行android hooking watch class com.zyc.objectiondemo.Car 可以Hook到Car类下所有方法(不包括构造方法)的调用。  ?
Hook类单个方法
如果只需要Hook单个方法(包括其重载),比如上面没有Hook到的Car类构造函数,可以运行android hooking watch class_method com.zyc.objectiondemo.Car.$init 。  ? 如果不需要Hook方法的重载,可以在方法名后面加上参数类型android hooking watch class_method com.zyc.objectiondemo.Car.$init "int,java.lang.String" 。  指令末尾加上对应选项可以展示参数、返回值和调用栈,运行android hooking watch class_method com.zyc.objectiondemo.Car.show --dump-args --dump-return --dump-backtrace 。  ?
任务系统
objection可以同时运行多项任务,比如下图创建Hook任务时打印了任务id 629342,通过指令jobs list 能查看当前运作的任务。  可以通过id结束某项任务,运行jobs kill 629342 。  ?
参考资料
实用FRIDA进阶:内存漫游、hook anywhere、抓包
|