首页
社区
课程
招聘
[原创]短视频某手sig3算法调用
发表于: 2020-4-20 00:55 76500

[原创]短视频某手sig3算法调用

2020-4-20 00:55
76500

本人菜鸟,初入逆向,前段时间把sig算法通过ida阅读伪代码和arm汇编进行了还原,花了4天时间,殊不知已有大神已经发有分析帖子了 

link:https://bbs.pediy.com/thread-254328.htm


一、前言
目标APP的sig3算法前面已经做足了功夫,这里只陈述一下我是如何找到sig3算法的,并没有把算法还原,因为so层onload有大量ollvm,目前还处于学习阶段,还没有触及,日后学成在继续发帖分享下学习笔记。


二、定位入口
本次目标APP版本是7.2.4.13202,这里使用Charles抓包知道了sig3的全称

sig3全称是 _NS_sig3 ,这里将app拖入jadx-gui进行分析,使用字符串搜索大法进行初步查找:


通过框选区域发现,a3是来自a2.a方法,且str2通过上方代码得知是sig签名结果,b2是一个url,但是执行了b()可能进行了一些处理,这里暂时先不管b2数据是什么,先最终到最终a调用的地方。

本次目标APP版本是7.2.4.13202,这里使用Charles抓包知道了sig3的全称

sig3全称是 _NS_sig3 ,这里将app拖入jadx-gui进行分析,使用字符串搜索大法进行初步查找:


通过框选区域发现,a3是来自a2.a方法,且str2通过上方代码得知是sig签名结果,b2是一个url,但是执行了b()可能进行了一些处理,这里暂时先不管b2数据是什么,先最终到最终a调用的地方。

三、算法最终定位
三、算法最终定位
String a3 = a2.a(b2 + str2);  跟进a方法的声明

 通过查看a的方法声明,发现是一个interface,这里直接右键查看调用例

发现只有一处地方使用了implements,进去查看具体代码实现

继续跟进getSigWrapper方法实现

继续跟进j.c(str)方法实现


发现还在继续深入调用  String atlasSign = KSecurity.atlasSign(str);,继续跟进方法声明。

继续阅读下代码,我们可以直接双击str变量,查看他引用地方:

发现是执行 d().a(str) ,继续跟进查看实现方法:

这里传了个参数2,false,继续跟进。

这里我们看到,他new了一个i(),并且一直在里面赋值,通过简单的课文阅读理解,我们去掉无用的代码:
i iVar = new i();
iVar.a(KSecurity.getkSecurityParameterContext().getAppkey());
iVar.a((Map<String, String>) null);
iVar.b(0);
iVar.a(z2);
iVar.b(str.getBytes("UTF-8"));
if (i.a(this.a).b().a(iVar, "0335") && iVar.j() != null) {
最终发现是调用了i.a(this.a).b().a(iVar, "0335") 实现,继续跟进查看

发现是interface,继续右键查看用例。

找到引用的地方,双击找到具体实现 a(i,string)的方法

我们继续进行简单的语文阅读理解
String trim = new String(iVar.i()).trim();
String str2 = (String) this.a.getRouter().a(10405, new String[]{trim}, KSecurity.getkSecurityParameterContext().getAppkey(), -1, false, KSecurity.getkSecurityParameterContext().getContext(), null, Boolean.valueOf(iVar.b()));
iVar.c(str2.getBytes("UTF-8"));
我们是否还记得,他需要算法的参数都放在了iVar,这里他使用 iVar.i() 将要签名的信息拿出来,紧接着调用 this.a.getRouter().a 获得结果,发现a这里传了很多东西,估计是最终算法,我们先继续跟一下a方法。

好家伙,又是interface,继续右键,我们稳住。

继续跟进查看实现

return JNICLibrary.doCommandNative(i, objArr);  我们发现,最终是传给了navite进行了计算。

那么我们继续hook下他都传了什么信息,这里我选择的hook点是
com.kuaishou.android.security.a.a.a.a(com.kuaishou.android.security.kfree.c.i,java.lang.String)
因为最后面这2个传的东西太多,而且很多都是固定值,懒得码这么多代码。

编写好的frida代码,先将手机的frida运行起来,具体frida的搭建文章我们可以阅读: 
https://zhuanlan.kanxue.com/article-350.htm
https://www.jianshu.com/p/dadacd02fefd


我们看道传的参数是域名的路径和sig(我们第一次看到他是str+str2的合并,原来str是域名路径)

这里我们回到a方法,查看他最终传给navite的参数:
参数一:10405
参数二: new String[]{trim}
参数三: KSecurity.getkSecurityParameterContext().getAppkey()
参数四: -1
参数五:false
参数六: KSecurity.getkSecurityParameterContext().getContext()
参数七:null
参数八: Boolean.valueOf(iVar.b())

参数二就是hook打印的内容。
参数三是一个固定的appkey,通过查看appkey的调用例找到了

这里因为文章长度问题,就不具体展示细节。
参数八:就是一开始传的false 逻辑变量,这里我们可以回到一开始传的时候查看他的赋值就知道了,这里的b()只是获取当时赋值的结果


参数全部找到了,由于so层看到了大量ollvm,我就没有进一步还原,只能通过hook方式主动调用了。

 通过查看a的方法声明,发现是一个interface,这里直接右键查看调用例

发现只有一处地方使用了implements,进去查看具体代码实现

继续跟进getSigWrapper方法实现

继续跟进j.c(str)方法实现


发现还在继续深入调用  String atlasSign = KSecurity.atlasSign(str);,继续跟进方法声明。

继续阅读下代码,我们可以直接双击str变量,查看他引用地方:

发现是执行 d().a(str) ,继续跟进查看实现方法:
 通过查看a的方法声明,发现是一个interface,这里直接右键查看调用例

发现只有一处地方使用了implements,进去查看具体代码实现

继续跟进getSigWrapper方法实现

继续跟进j.c(str)方法实现


发现还在继续深入调用  String atlasSign = KSecurity.atlasSign(str);,继续跟进方法声明。

继续阅读下代码,我们可以直接双击str变量,查看他引用地方:

发现是执行 d().a(str) ,继续跟进查看实现方法:

这里传了个参数2,false,继续跟进。

这里我们看到,他new了一个i(),并且一直在里面赋值,通过简单的课文阅读理解,我们去掉无用的代码:
i iVar = new i();
iVar.a(KSecurity.getkSecurityParameterContext().getAppkey());
iVar.a((Map<String, String>) null);
iVar.b(0);
iVar.a(z2);
iVar.b(str.getBytes("UTF-8"));
if (i.a(this.a).b().a(iVar, "0335") && iVar.j() != null) {
最终发现是调用了i.a(this.a).b().a(iVar, "0335") 实现,继续跟进查看
i iVar = new i();
iVar.a(KSecurity.getkSecurityParameterContext().getAppkey());
iVar.a((Map<String, String>) null);
iVar.b(0);
iVar.a(z2);
iVar.b(str.getBytes("UTF-8"));
if (i.a(this.a).b().a(iVar, "0335") && iVar.j() != null) {
最终发现是调用了i.a(this.a).b().a(iVar, "0335") 实现,继续跟进查看

发现是interface,继续右键查看用例。

找到引用的地方,双击找到具体实现 a(i,string)的方法

我们继续进行简单的语文阅读理解
String trim = new String(iVar.i()).trim();
String str2 = (String) this.a.getRouter().a(10405, new String[]{trim}, KSecurity.getkSecurityParameterContext().getAppkey(), -1, false, KSecurity.getkSecurityParameterContext().getContext(), null, Boolean.valueOf(iVar.b()));
iVar.c(str2.getBytes("UTF-8"));
我们是否还记得,他需要算法的参数都放在了iVar,这里他使用 iVar.i() 将要签名的信息拿出来,紧接着调用 this.a.getRouter().a 获得结果,发现a这里传了很多东西,估计是最终算法,我们先继续跟一下a方法。
String trim = new String(iVar.i()).trim();
String str2 = (String) this.a.getRouter().a(10405, new String[]{trim}, KSecurity.getkSecurityParameterContext().getAppkey(), -1, false, KSecurity.getkSecurityParameterContext().getContext(), null, Boolean.valueOf(iVar.b()));
iVar.c(str2.getBytes("UTF-8"));
我们是否还记得,他需要算法的参数都放在了iVar,这里他使用 iVar.i() 将要签名的信息拿出来,紧接着调用 this.a.getRouter().a 获得结果,发现a这里传了很多东西,估计是最终算法,我们先继续跟一下a方法。

好家伙,又是interface,继续右键,我们稳住。

继续跟进查看实现

return JNICLibrary.doCommandNative(i, objArr);  我们发现,最终是传给了navite进行了计算。

return JNICLibrary.doCommandNative(i, objArr);  我们发现,最终是传给了navite进行了计算。


[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

收藏
免费 9
支持
分享
最新回复 (41)
雪    币: 159
活跃值: (339)
能力值: ( LV8,RANK:130 )
在线值:
发帖
回帖
粉丝
2
很不错的分析!
最后于 2020-4-20 14:39 被LowRebSwrd编辑 ,原因:
2020-4-20 10:50
0
雪    币: 249
活跃值: (57)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
加油
2020-4-20 11:23
0
雪    币: 1744
活跃值: (3449)
能力值: ( LV6,RANK:80 )
在线值:
发帖
回帖
粉丝
4
Lenus 很不错的分析!欢迎坛子里面的各位大牛,给快手移动安全多提意见和建议,帮助我们的防护技术更上一层。(但是不要做坏事哟)有兴趣加盟快手的可以把简历发到我的邮箱majun@kuaishou.comAndro ...
大...大佬
2020-4-20 13:10
0
雪    币: 1392
活跃值: (5177)
能力值: ( LV13,RANK:240 )
在线值:
发帖
回帖
粉丝
5
Lenus 很不错的分析!欢迎坛子里面的各位大牛,给快手移动安全多提意见和建议,帮助我们的防护技术更上一层。(但是不要做坏事哟)有兴趣加盟快手的可以把简历发到我的邮箱majun@kuaishou.comAndro ...
楼主快把菊花洗干净。等大佬临幸
最后于 2020-4-20 13:54 被IamHuskar编辑 ,原因:
2020-4-20 13:54
0
雪    币:
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
6
doCommandNative 阿里一直在用的安全就是这种写法。包括动态库加载的方式,都和阿里很类似。
jniOnload倒不需要花太大时间研究,直接hook register方法就能拿到doCommandNative的函数地址。
关键的是doCommandNative内部的根据command转发的函数地址是动态注册的,这个需要研究一下。
还有就是里面大概率有一些花指令要写脚本修复一下,还要看有没有用VMP,阿里当时我研究的时候他们的签名没有用VMP,主要还是花指令和代码膨胀要花些时间处理
2020-4-20 15:08
0
雪    币: 484
活跃值: (872)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
7
sig3的复杂程度已经超过dy了,话说这个frida到底怎么打印String[],因为这个类型我不得不用xp去拦截.
2020-4-20 16:15
0
雪    币: 455
活跃值: (3925)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
8
sig3  比dy  复杂程度高吧。。。  xpsed检测、frida 检测,头疼。
2020-4-20 16:29
1
雪    币: 1744
活跃值: (3449)
能力值: ( LV6,RANK:80 )
在线值:
发帖
回帖
粉丝
9
hczhong sig3 比dy 复杂程度高吧。。。 xpsed检测、frida 检测,头疼。
dy 一样会检测的,甚至包括usb、root、cydia、frida、http proxy、hookList等等。
2020-4-20 19:06
0
雪    币: 1744
活跃值: (3449)
能力值: ( LV6,RANK:80 )
在线值:
发帖
回帖
粉丝
10
badby doCommandNative 阿里一直在用的安全就是这种写法。包括动态库加载的方式,都和阿里很类似。 jniOnload倒不需要花太大时间研究,直接hook register方法就能拿到doCom ...
谢谢大腿指点,学到了
2020-4-20 19:07
0
雪    币: 3040
活跃值: (1150)
能力值: ( LV8,RANK:120 )
在线值:
发帖
回帖
粉丝
11
果然天下乌鸦一般抄,哈哈, 和无线保镖竟然如此的相似,连名字都懒得改  哈哈
2020-4-20 19:08
0
雪    币: 1744
活跃值: (3449)
能力值: ( LV6,RANK:80 )
在线值:
发帖
回帖
粉丝
12
IamHuskar Lenus 很不错的分析!欢迎坛子里面的各位大牛,给快手移动安全多提意见和建议,帮助我们的防护技术更上一层。(但是不要做坏事哟)有兴趣加盟快手的可以把简历发到 ...
2020-4-20 19:08
0
雪    币: 1744
活跃值: (3449)
能力值: ( LV6,RANK:80 )
在线值:
发帖
回帖
粉丝
13
angelToms 果然天下乌鸦一般抄,哈哈, 和无线保镖竟然如此的相似,连名字都懒得改 哈哈
 无线保镖是啥
2020-4-20 19:10
0
雪    币: 1744
活跃值: (3449)
能力值: ( LV6,RANK:80 )
在线值:
发帖
回帖
粉丝
14
天荒怨未泯 sig3的复杂程度已经超过dy了,话说这个frida到底怎么打印String[],因为这个类型我不得不用xp去拦截.
 var b = Java.use("[B");
 var buf  = Java.cast(iVar.i(),b);     //iVar.i() 就是java返回的byte[]
 var barr = Java.array('byte',buf) 
ByteArrayString(barr);

function ByteArrayString(byteArray) {
    var str = "";
    var barr = new Uint8Array(byteArray);
    for(var i=0;i<barr.length;i++){
        str+=String.fromCharCode(barr[i]);
    }
    return str;
}
我当时打印的是这个string[]在之前的,那个时候他还只是byte[]。
2020-4-20 19:14
0
雪    币: 3040
活跃值: (1150)
能力值: ( LV8,RANK:120 )
在线值:
发帖
回帖
粉丝
15
阿里安全的一些东西,哈哈
2020-4-20 19:32
0
雪    币: 1744
活跃值: (3449)
能力值: ( LV6,RANK:80 )
在线值:
发帖
回帖
粉丝
16
angelToms 阿里安全的一些东西,哈哈
好复杂哦
2020-4-20 21:53
0
雪    币:
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
17
阿里安全现在广招安全同学,HC满满~~~~想看最新原版无线保镖,不学4年前老技术,记得发简历到邮箱 lihang.lh@alibaba-inc.com ,一起搞事情~
最后于 2020-4-21 10:54 被lh@88编辑 ,原因:
2020-4-21 10:53
0
雪    币: 250
活跃值: (251)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
18
抄代码好歹把包名,接口名称改一下吧?      
2020-4-21 10:59
0
雪    币: 159
活跃值: (339)
能力值: ( LV8,RANK:130 )
在线值:
发帖
回帖
粉丝
19
OnlyEnd 抄代码好歹把包名,接口名称改一下吧? [em_64]
这是个feature
2020-4-21 13:14
0
雪    币: 17
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
20
.....
最后于 2020-4-21 14:28 被wx_hook_996编辑 ,原因:
2020-4-21 13:22
0
雪    币: 1744
活跃值: (3449)
能力值: ( LV6,RANK:80 )
在线值:
发帖
回帖
粉丝
21
wx_hook_996 sig3写的挺复杂的,前9位私时间戳,里面有一个变形的hmac-sha256算法,先从一张图片里面解析出密钥,里面还有几个超级大的数组再循环加密,还经过一次base64加密,最后拼接
 专业
2020-4-21 13:43
0
雪    币: 4853
活跃值: (3776)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
22
这是四年前的技术了,好可怕
2020-4-21 15:16
0
雪    币: 0
活跃值: (1003)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
23
hzzheyang 这是四年前的技术了,好可怕
大佬科普下四年前的技术是什么样的
2020-4-21 22:15
0
雪    币: 4853
活跃值: (3776)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
24
冷瞳 大佬科普下四年前的技术是什么样的
不是我说的,是17楼说的
2020-4-22 10:05
0
雪    币: 482
活跃值: (1007)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
25
牛逼啊,大佬
2020-4-24 18:06
0
游客
登录 | 注册 方可回帖
返回
//