安卓那档事02

安卓四大组件

组件 描述
Activity(活动) 在应用中的一个Activity可以用来表示一个界面,意思可以理解为“活动”,即一个活动开始,代表 Activity组件启动,活动结束,代表一个Activity的生命周期结束。一个Android应用必须通过Activity来运行和启动,Activity的生命周期交给系统统一管理。
Service(服务) Service它可以在后台执行长时间运行操作而没有用户界面的应用组件,不依赖任何用户界面,例如后台播放音乐,后台下载文件等。
Broadcast Receiver(广播接收器) 一个用于接收广播信息,并做出对应处理的组件。比如我们常见的系统广播:通知时区改变、电量低、用户改变了语言选项等。
Content Provider(内容提供者) 作为应用程序之间唯一的共享数据的途径,Content Provider主要的功能就是存储并检索数据以及向其他应用程序提供访问数据的接口。Android内置的许多数据都是使用Content Provider形式,供开发者调用的(如视频,音频,图片,通讯录等)

activity的切换

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<!---声明实现应用部分可视化界面的 Activity,必须使用 AndroidManifest 中的 <activity> 元素表示所有 Activity。系统不会识别和运行任何未进行声明的Activity。----->
<activity
android:label="@string/app_name"
android:name="com.zj.wuaipojie.ui.MainActivity"
android:exported="true"> <!--当前Activity是否可以被另一个Application的组件启动:true允许被启动;false不允许被启动-->
<!---指明这个activity可以以什么样的意图(intent)启动--->
<intent-filter>
<!--表示activity作为一个什么动作启动,android.intent.action.MAIN表示作为主activity启动--->
<action
android:name="android.intent.action.MAIN" />
<!--这是action元素的额外类别信息,android.intent.category.LAUNCHER表示这个activity为当前应用程序优先级最高的Activity-->
<category
android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name="com.zj.wuaipojie.ui.ChallengeFirst" />
<activity
android:name="com.zj.wuaipojie.ui.ChallengeFifth"
android:exported="true" />
<activity
android:name="com.zj.wuaipojie.ui.ChallengeFourth"
android:exported="true" />
<activity
android:name="com.zj.wuaipojie.ui.ChallengeThird"
android:exported="false" />
<activity
android:name="com.zj.wuaipojie.ui.ChallengeSecond"
android:exported="false" />
<activity
android:name="com.zj.wuaipojie.ui.AdActivity" />

activity的生命周期

函数名称 描述
onCreate() 一个Activity启动后第一个被调用的函数,常用来在此方法中进行Activity的一些初始化操作。例如创建View,绑定数据,注册监听,加载参数等。
onStart() 当Activity显示在屏幕上时,此方法被调用但此时还无法进行与用户的交互操作。
onResume() 这个方法在onStart()之后调用,也就是在Activity准备好与用户进行交互的时候调用,此时的Activity一定位于Activity栈顶,处于运行状态。
onPause() 这个方法是在系统准备去启动或者恢复另外一个Activity的时候调用,通常在这个方法中执行一些释放资源的方法,以及保存一些关键数据。
onStop() 这个方法是在Activity完全不可见的时候调用的。
onDestroy() 这个方法在Activity销毁之前调用,之后Activity的状态为销毁状态。
onRestart() 当Activity从停止stop状态恢进入start状态时调用状态。
105514fnc44338qubb43t3

安卓动调

修改debug权限

1、修改AndroidManifest.xml

在AndroidManifest.xml添加可调试权限

1
android:debuggable="true"

2、XappDebug模块hook对应的app

项目地址

3、Magisk命令(重启失效)

1
2
3
4
1. adb shell
2. su
3. magisk resetprop ro.debuggable 1
4. stop;start; #一定通过这个方法重启

4、刷入MagiskHide Props Config模块(永久有效,但可能有的手机刷不上)

一般来说,在4选项中如果有ro.debuggable那就直接修改 没有的话就选5

105323jzffqjyzb6qyhfqc

开启adb调试

安卓版本号点击七次开启开发者模式并开启adb调试权限

Jeb调试

注意,Jeb调试要保证调试机和宿主机两端apk一致

CTRL+B 是下断点

在高版本安卓(8.1以上)中,会看不到大部分的寄存器:

1699197872060

像这里就只能进入到这个base64函数里面查看p1返回值寄存器了

Log插桩

定义:Log插桩指的是反编译APK文件时,在对应的smali文件里,添加相应的smali代码,将程序中的关键信息,以log日志的形式进行输出。

插入如下命令即可

1
invoke-static {对应寄存器}, Lcom/mtools/LogUtils;->v(Ljava/lang/Object;)V

将别人写的一个日志插桩的文件重命名为class2.dex,然后再插入命令即可。

image-20231105233814345

最后使用工具(算法助手)捕获日志即可。

frida完爆

有一说一,这玩意一应该frida完爆吧。。。。

确实完爆,据某位不愿意透露姓名的安卓大神(已经给头像打码了)所说:

1699199120877

应该能做到执行到某个地方返回寄存器的值,回头试一试。


2023/11/6 更新

中午试了试:

image-20231106142849488

分析知道是和最后的base64的返回值做比较,那就hook这个base64:

image-20231106142942681

发现是自己写的base64,那就简单好hook了,hook脚本:

1
2
3
4
5
6
7
8
9
10
11
12
13
Java.perform(() => {
console.log("1. start hook");
const base64 = Java.use("com.zj.wuaipojie.util.Base64Utils");
if(base64 != undefined){
console.log("2. find class!");
base64.encodeToString.implementation = function(bArr){
var res = this.encodeToString(bArr);
console.log("base64结果: "+res);

return res;
}
}
})

hook结果:

image-20231106143130794

得到了base64。酷,这很符合我对frida的想像。


今天的安卓就学到这了(