最近一直在折腾ollvm,结果折腾了几天一直编译不通过,持续踩坑中,只好暂时放在一边整点app分析分析
该app为某动画app,我在看雪上看到有人分析过这个app:https://bbs.pediy.com/thread-258593.htm,
感觉分析的不是很详细,就自己分析了一下,写了一篇分析过程
目的:修改该app为永久会员
首先打开apk看了一下:
显然想要修改会员日期就需要找到该界面对应的activity,修改方式很多,比如直接搜索会员字符串,然后就能定位到相关位置UserInfoActivity
查看getExpire:
查看setExpire:
发现就是dateFormat对象进行了几次转换变成字符串和“2100-01-01”字符串进行比较,只要大于等于该值就是永久会员了。
那么久很简单了,直接使用androidKiller修改getExpire返回值就可。
然后当我反编译之后开始运行的时候,却发现并不行
那怎么办呢,我首先考虑到的是搜索字符串,果然软件没有这么单纯,搜不到,所以估计是在服务器端进行的验证
使用fiddler抓个包:
imei映入眼帘,直接搜索一下试试:
果然搜到了,查看getV():
原来是一个native方法,返回类型为String,传入了一个当前的时间戳,想来直接修改返回值是不现实的了,只能看so层代码分析校验码是怎么产生的了。
然而不幸的是使用ida静态分析发现有些参数没有显示,所幸找到了参数的位置,可以根据动态调试找到具体的值:
但是网上说jeb也有了查看so的功能,用其查看发现非常的清晰:
由图中可知,一共有三个check分别和定值"dt8re"+"rt9ws"拼接其中有两个参数一个hash1,一个hash2
经过计算得出
目前想到过两种方法动态调试也可以:(1)动态调试获取该值;(2)使用hook技术取定值的时间戳并打印返回值,按照控制变量法计算出结果
下面仅展示hook法:
(1)首先使用frida hook js脚本
Java.perform(function () {
var CheckUtils = Java.use("info.zzjian.dididh.util.CheckUtils");
CheckUtils.getV.overload("long").implementation = function (j) {
var ret = this.getV(j);
console.log(this.getV(0));
return (ret);
};
});
打印结果为:
33cc6f39fdt8re3af08b80crt9ws3ff2a033f
根据结果拆分为:
(check1)33cc6f39f + dt8re + (check2)3af08b80c + 9ws3f + (check3)f2a033f
根据控制变量法求出
hash1 = -1916912749L;
hash2 = 1344359219L;
求出最终的字符串为:
String check1 = Long.toHexString(13904573343L + ts * 2);
String check2 = Long.toHexString(15821486092L + ts);
String check3 = Long.toHexString(17165845311L + ts);
return check1 + "dt8re" + check2 + "rt9ws" + check3;
根据还原的算法,重写一个CheckUtils.java让它在java层直接返回字符串
public class CheckUtils {
public CheckUtils() {
}
public String getV(long ts) {
String check1 = Long.toHexString(13904573343L + ts * 2);
String check2 = Long.toHexString(15821486092L + ts);
String check3 = Long.toHexString(17165845311L + ts);
return check1 + "dt8re" + check2 + "rt9ws" + check3;
}
}
使用命令行将编写的java文件转化为smali文件,这里有写好的脚本可以在我的资源文件中查看下载(转化的根据实际情况对包名进行更改):
.class public Linfo/zzjian/dididh/util/CheckUtils;
.super Ljava/lang/Object;
.source "CheckUtils.java"
# direct methods
.method public constructor <init>()V
.registers 1
.prologue
.line 3
invoke-direct {p0}, Ljava/lang/Object;-><init>()V
.line 4
return-void
.end method
# virtual methods
.method public getV(J)Ljava/lang/String;
.registers 8
.prologue
.line 7
const-wide v0, 0x33cc6f39fL
const-wide/16 v2, 0x2
mul-long/2addr v2, p1
add-long/2addr v0, v2
invoke-static {v0, v1}, Ljava/lang/Long;->toHexString(J)Ljava/lang/String;
move-result-object v0
.line 8
const-wide v2, 0x3af08b80cL
add-long/2addr v2, p1
invoke-static {v2, v3}, Ljava/lang/Long;->toHexString(J)Ljava/lang/String;
move-result-object v1
.line 9
const-wide v2, 0x3ff2a033fL
add-long/2addr v2, p1
invoke-static {v2, v3}, Ljava/lang/Long;->toHexString(J)Ljava/lang/String;
move-result-object v2
.line 10
new-instance v3, Ljava/lang/StringBuilder;
invoke-direct {v3}, Ljava/lang/StringBuilder;-><init>()V
invoke-virtual {v3, v0}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;
move-result-object v0
const-string v3, "dt8re"
invoke-virtual {v0, v3}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;
move-result-object v0
invoke-virtual {v0, v1}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;
move-result-object v0
const-string v1, "rt9ws"
invoke-virtual {v0, v1}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;
move-result-object v0
invoke-virtual {v0, v2}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;
move-result-object v0
invoke-virtual {v0}, Ljava/lang/StringBuilder;->toString()Ljava/lang/String;
move-result-object v0
return-object v0
.end method
再用写好的代码覆盖androidkiller中的类
然后在反编译就成功的得到了结果:
补:当然由于这个apk是没有检测hook的,我们可以直接通过Xposed或者fridahook实现破解VIP的功能,当我查看作者声明的时候发现作者也不反对使用Xposed等进行修改:
因此还是非常感谢作者给了我这个学习的机会,但是破解版的apk就不在这里提供了,如果大家有需要可以直接上官网下载原版:http://dddh.pub/
补:经过动态调试发现该程序是64位的程序,所以ida32会无法显示字符串,使用ida64能够正常看到字符串