写在前面的话
前排提示:求链接求联系方式均为违规!这是分析贴...
之前的某哩由于截图处理不恰当被删帖了,所以以后的相关帖,我尽量不放APP或网页的截图
我所使用到的工具和操作环境:
操作环境:
WIN10 64位 + 某遥模拟器
用到的工具
1.fiddler
以下简称为fd,Https抓包神器,具体的配置方法和连接方法请百度或论坛内搜索
2.jadx
(也可选择NP管理器或MT会员的可以不用这个)
最近看好多帖子都用这个jadx,所以下载了试了试,的确好使!github下载比较慢,论坛或百度均有各个版本的下载
github地址:https://github.com/skylot/jadx/releases
3.Android Killer
用来查看APP的输出日志,当然也可以直接用他反编译,但是会"APK 反编译失败,无法继续下一步源码反编译!",解决方法AndroidKillerPlugin,下载地址:https://github.com/supperlitt/AndroidKillerPlugin/releases
4.MT管理器
(可以用NP管理器代替MT和jadx,但是NP在模拟器上运行实在是慢。。。)
用来修改smali代码和查看内存卡中的文件
5.易安卓(e4a)
小弟不才,没学过JAVA,只能用用e4a的接口函数来调用某APP中的函数了.
我是这样操作的
1.查看是否加固
用MT查看APP的安装包是否加固,发现没有加固
2.用fd查看传送数据是否加密
3.分析fd中的接口、参数、数据
api_host.txt
host的地址,后面的60参数没试过是什么意思
user/me
个人信息,此时的用户id=5045738
apply-new-user
就字面意思来看,应该是注册一个新用户,请求类型为post,但是请求参数却是空白,那就看看别的。
然后,找到了imei/macaddr/uuid
imei: 867222638103442
macaddr: 20:37:CC:2E:B6:F6
uuid: 37f88eb579cf5f6708e51cc896a02af48032
把apply-new-user拖入组合器(英文版应该是composer),然后把imei/macaddr/uuid修改之后发现,变成非法操作了,说明uuid有类似signd的检验的功效
4.尝试清空应用数据修改imei+mac
为了测试,我们清空APP的数据,然后模拟器修改下imei和mac地址,然后重启
5.重启后打开APP,查看fd数据
发现apply-new-user中的imei/macaddr是变了,但是uuid却还是之前的那个,然后用户还是5045738
imei: 864238695757436
macaddr: 92:AB:8F:04:2C:5A
uuid: 37f88eb579cf5f6708e51cc896a02af48032
6.对uuid参数产生疑惑
正常更换imei和mac之后就相当于是一个新机器了,没有道理uuid不改变呀,难道APP在上一次注册用户的时候把uuid写到了文件里面?我们去看看
7.我们打开MT(NP)管理器
内部储存目录中,点击右上角把文件按照“日期”-“逆向”排序
然后过滤掉Download(下载目录),接下来是.xerox文件夹,打开,里面就一个.nomedia文件,我们选择文本编辑打开他
诺,和刚才的uuid一模一样有没有,看来真的是APP把uuid写出到.nomedia文件,如果存在.nomedia文件,那就算你如何修改imei和mac都不会注册新用户。
打开APP后apply-new-user,发现uuid变了。
imei: 862177069123472
macaddr: 38:74:A8:C2:11:11
uuid: 1da0e9d1c9de1ce568c183da22b977600e26
我们看看用户id是不是还是5045738
用户id也变成了5048859,那么问题来了uuid是从哪里冒出来的呢?推测:答案应该是在APP代码中,接下来我们就反编译
9.反编译
把APP拖入jadx
(PS:你也可以用MT管理器或者NP管理器)
我们搜索“uuid”,发现一个“uuid==”
点击去看看,发现函数I
public final String I() {
J();
c.c.a.g.a.ea = H.a();
String str = c.c.a.g.a.I + c.c.a.g.a.J + c.c.a.g.a.ea;
Intrinsics.checkExpressionValueIsNotNull(str, "uuidStrBuilder.toString()");
String lowerCase = str.toLowerCase();
Intrinsics.checkExpressionValueIsNotNull(lowerCase, "(this as java.lang.String).toLowerCase()");
r.b(com.umeng.commonsdk.statistics.idtracking.s.f2781a, "uuidStr==" + lowerCase);
String a2 = C0235a.a(lowerCase);
Intrinsics.checkExpressionValueIsNotNull(a2, "AbMd5.getMD5String(uuidStr)");
String lowerCase2 = a2.toLowerCase();
Intrinsics.checkExpressionValueIsNotNull(lowerCase2, "(this as java.lang.String).toLowerCase()");
r.b(com.umeng.commonsdk.statistics.idtracking.s.f2781a, "uuidStrMd5==" + lowerCase2);
String str2 = lowerCase2 + "systemuuid123";
Charset charset = Charsets.UTF_8;
if (str2 != null) {
byte[] bytes = str2.getBytes(charset);
Intrinsics.checkExpressionValueIsNotNull(bytes, "(this as java.lang.String).getBytes(charset)");
String a3 = C0239e.a(bytes);
r.b(com.umeng.commonsdk.statistics.idtracking.s.f2781a, "crc16CheckSum==" + a3);
String str3 = lowerCase2 + a3;
r.b(com.umeng.commonsdk.statistics.idtracking.s.f2781a, "uuid==" + str3);/* 这里的str3就是uuid */
c.c.a.g.a.fa = str3;
return str3;
}
throw new TypeCastException("null cannot be cast to non-null type java.lang.String");
}
查看APP的运行日志
我们打开Android killer,连接上模拟器,打开APP查看运行日志,发现。。。几乎是什么都没有???难道这个APP不输出日志?错,是因为没开启debug
开启APP的debug模式
我们根据上面的 uuid= ,查看下r.b是干啥的(类名:c.c.a.z.r)
public class r {
public static String f1177a = "TAG";
public static boolean f1178b;
static {
f1178b = a.f118a.booleanValue();
if (new File(c.b(), ".debug").exists()) {
f1178b = true;
}
}
@Deprecated
public static void b(String str, String str2) {/* a.b函数 */
if (f1178b) {
Log.e(str, str2);
}
}
}
咦,这不就是输出日志的吗?如果f1178b=true则Log,那么我们看
f1178b = a.f118a.booleanValue();
不管他。。直接用MT管理器反编译,把f1178b设置为true
sget-object v0, Lc/c/a/a;->a:Ljava/lang/Boolean;
invoke-virtual {v0}, Ljava/lang/Boolean;->booleanValue()Z
move-result v0
const/4 v0, 0x1 /* 此处把V0设置为1即JAVA中f1178b=true(0=false) */
修改后,打包签名,卸载旧应用,安装新应用
重新查看APP的运行日志
我们清空APP的数据,然后删除保存uuid的.nomedia文件,用Android killer查看运行日志,打开APP,发现。。。有输出日志了。
强行分析一波
由输出的uuidStr和现有的imei.mac.uuid可得出结论
imei='862177069123472';//c.c.a.g.a.I
macaddr='38:74:A8:C2:11:11';//c.c.a.g.a.J
uuidStr = imei+macaddr+ '2bbbbaeb8191555c';//uuidStr = 86217706912347238:74:a8:c2:11:112bbbbaeb8191555c
uuidStrMd5 = md5(uuidStr); //uuidStrMd5 = 1da0e9d1c9de1ce568c183da22b97760
//这个2bbbbaeb8191555c是c.c.a.g.a.ea,也就是安卓ID,固定即可
我们对比下uuidStrMd5和uuid
uuidStrMd5=1da0e9d1c9de1ce568c183da22b97760
uuid=1da0e9d1c9de1ce568c183da22b977600e26 //比md5多出来给0e26
那么这个0e26是从哪里来的??我们回到jadx查看下之前的代码
由图可知,0e26是由C0239e.a(str2.getBytes(charset))
而str2 = lowerCase2 + "systemuuid123"; 也就是str2 = uuidStrMd5 + “systemuuid123” = 1da0e9d1c9de1ce568c183da22b97760systemuuid123
我们跳转到C0239e看下C0239e.a是什么鬼
public class C0239e {
static {
ByteBuffer.allocate(8);
}
public static String a(byte[]bArr) { /* C0239e.a 函数*/
StringBuilder sb = new StringBuilder();
int i = 65535;
for (byte b2: bArr) {
i ^= b2 & 255;
for (int i2 = 0; i2 < 8; i2++) {
i = (i & 1) != 0 ? (i >> 1) ^ 40961 : i >> 1;
}
}
String hexString = Integer.toHexString(i);
return (hexString.trim().length() != 4 && hexString.trim().length() == 3) ? a.a(sb, "0", hexString) : hexString;
}
}
看到这不禁想起QQ空间的g_tk的hash计算函数,和这个C0239e.a稍微有点相似?不过小弟是半吊子水平。自学的java也不咋地,只能借用e4a的接口函数调用C0239e.a了。
咱把imei/mac带入测试下结果:
uuid=1da0e9d1c9de1ce568c183da22b97760e26
和之前的uuid一模一样,对吧。那么我们试试随机imei/随机mac/计算好的uuid放入fd能不能用apply-new-user生成一个新的用户呢?
再次使用fd组合器
成功获取到Authorization,再调用user/me接口,id的确是新的。那么就能写注册机无限注册了,当然也可以把邀请码加进来
在APP上显示的是这样的:
uuid算法Sample成品
仅是uuid算法的Sample。并没有什么别的
安卓APP,由E4A编写,无毒未加壳,还是没太搞懂那个hash算法,不然的话也可以搞个电脑端的Sample
密码:52pj 下载地址:https://wwa.lanzouj.com/iV9cekfic5a
总结下
1.因为小弟不太懂JAVA,所以只能通过查看APP的日志来得到uuid的算法,当然大佬们肯定会嗤之以鼻,但是对于我这种小白来说,看着日志反编译/推算法总是没错的
2.jadx的确强大。能查看java代码也能查看smali代码。(如果各位大佬还有更强大的工具,可以推荐下。一起学习学习)