安卓逆向系列-Frida实战修改某族数字健康锁定应用时间
1. 介绍
现在很多手机都具有能够控制手机应用运行时长或者允许运行的时间段,例如EMUI就可以将手机直接锁定,在未到设定的时间之前都无法打开应用。魅族Flyme中内置了数字健康能够监控老人、小孩的手机应用运行时长,远程设定应用运行状态,能够规避老人小孩沉迷应用,如下所示。本文利用frida工具修改应用时间成功解除限制。
http://43.135.123.94:8090/upload/2022/10/image-1665655287143.png
2. 需求配置
为了快速定位应用包名,我们直接打开应用置于最上层,运行如下代码就能够发现其Class和Activity,代码如下:
adb shell "dumpsys window | grep mCurrentFocus"
结果如下:
http://43.135.123.94:8090/upload/2022/10/image-1665655673394.png
由图可见这个com.meizu.sceneinfo
这个就是包名,com.meizu.familyguard.ui.usage.UsageActivity
就是Activity
的名字。
3.2 找到jar包
这种系统应用的安装包一般会在system/app
或者system/pri-app
里面,但是去找实际上是找不到的,并不带有ScenInfo
之类的关键字。这里我们换个思路,直接从data
目录开始寻找,即可找到,代码如下:
ls | grep com.meizu
结果如下,安卓系统为了防止应用报名冲突,会在包名后面自动补充部分base64的字符串,所以com.meizu.base64
的报名即是我们想要的。
http://43.135.123.94:8090/upload/2022/10/image-1665659738360.png
进入其中,提取出base.apk
,拖入jadx即可开始分析。
3.3 找到关键代码
首先根据Activity
的路径找到对应的Activity
,定位到UsageActivity
代码如下:
http://43.135.123.94:8090/upload/2022/10/image-1665660033016.png
很明显,这只是展示View的地方,而且将当球Activity分成了today
和week
也就是今天和近七天两个fragment
组件。进入UsageFragment
,在onCreate
方法中,我们看到一个a
方法,如下:
http://43.135.123.94:8090/upload/2022/10/image-1665660539940.png
其他代码都是在创建View,我们进入这个a
方法,在a
方法中我们可以看到定义了很多个onChanged()
方法,猜测这个应该是当屏幕刷新的时候产生的动作,现在很多短视频APP和论坛APP通过这个刷新后续数据。在其中,我们可以看到一个参数是UsingTimeStats
方法如下,根据名字来说就比较像使用时间了。
http://43.135.123.94:8090/upload/2022/10/image-1665660827317.png
我们接着进入该类,该类代码如下:
package com.meizu.digitalwellbeing.server.data;
import android.os.Parcel;
import android.os.Parcelable;
import androidx.annotation.Keep;
@Keep
/* loaded from: classes.dex */
public class UsingTimeStats extends f {
public static final Parcelable.Creator<UsingTimeStats> CREATOR = new Parcelable.Creator<UsingTimeStats>() { // from class: com.meizu.digitalwellbeing.server.data.UsingTimeStats.1
/* renamed from: a */
public UsingTimeStats createFromParcel(Parcel parcel) {
return new UsingTimeStats(parcel);
}
/* renamed from: a */
public UsingTimeStats[] newArray(int i) {
return new UsingTimeStats[i];
}
};
private long mUsingTime;
@Override // com.meizu.digitalwellbeing.server.data.f, android.os.Parcelable
public int describeContents() {
return 0;
}
public UsingTimeStats() {
}
public UsingTimeStats(int i, long j, long j2, long j3) {
super(i, j, j2);
setUsingTime(j3);
}
/* JADX INFO: Access modifiers changed from: protected */
public UsingTimeStats(Parcel parcel) {
super(parcel);
setUsingTime(parcel.readLong());
}
@Override // com.meizu.digitalwellbeing.server.data.f, android.os.Parcelable
public void writeToParcel(Parcel parcel, int i) {
super.writeToParcel(parcel, i);
parcel.writeLong(getUsingTime());
}
public long getUsingTime() {
return this.mUsingTime;
}
public void setUsingTime(long j) {
this.mUsingTime = j;
}
@Override // com.meizu.digitalwellbeing.server.data.f
public String toString() {
String fVar = super.toString();
int length = fVar.length();
return new StringBuilder(fVar).replace(length - 2, length, ", mUsingTime = " + getUsingTime() + " }").toString();
}
}
根据代码意思,基本可以确定,这就是存放APP的使用时间的类了。
3.4 Hook代码
这里找到的只是其中一个业务相关类,Hook点也有很多,我这里就直接HookgetPackageName()
方法,假设我们这里需要修改皮皮虾:com.sup.android.superb
软件的运行时间,那么利用frida的hook方法可以写如下代码:
Java.perform(function(){
var PackageUsingTimeStats = Java.use("com.meizu.digitalwellbeing.server.data.PackageUsingTimeStats");
console.log("PackageUsingTimeStats:", PackageUsingTimeStats);
PackageUsingTimeStats.getPackageName.implementation = function(){
var mPackageName = this.getPackageName();
var mUsingTime = this.getUsingTime();
if (mPackageName=="com.sup.android.superb"){
console.log("detected");
this.setUsingTime(0);
mUsingTime = this.getUsingTime();
}
console.log("getPackageName:",mPackageName,"===>",mUsingTime);
return mPackageName;
}
console.log("end");
});
hook思路是当匹配到皮皮虾的包名的时候就设定其使用时间为0。
3.5 运行效果
通过注入frida代码,运行效果如下,这里为了显示效果,我将其使用时间方法10000倍。结果如下:
http://43.135.123.94:8090/upload/2022/10/image-1665661378011.png
4. 分析总结
- 属于新手级别的hook测试,难度不大,但是是一次分析练手的好机会
- hook点就在
Activity
附近,比较好找,第三方厂家开发的应用不会这么好找
- 多用frida找到所有方法,有些方法经过混淆完全找不到