首页
社区
课程
招聘
[原创]新版a+1站ollvm算法分析
发表于: 2023-6-9 10:48 6884

[原创]新版a+1站ollvm算法分析

2023-6-9 10:48
6884

闲来无聊,想看下b占安全防护做的如何,于是分析了下新版b占的最新版app,最后把算法弄了出来,虽然相较于原版算法并没有啥改变,但是分析的难度确增加了很多。




⊙1.反调试绕过



2.算法定位


3.ollvm流程trace


⊙4.ollvm arm指令trace


5.结果及其彩蛋







1.反调试绕过


笔者分析在arm32位下和arm64位下,关于检测frida的点



在armv8中对应

0x1A858


1b8b4




针对这个两个关键点进行patch

然后进入/data/app/tv.danmaku.bili-AK6NWgW6BtysktmJyUc8Ag==/lib/arm64,libmsaoaidsec.so换成我们patch的so即可

2.算法定位

frida-trace -U -j '*!sign' -f  tv.**.bili



发现有那么多的结果,还是光重复一条,根本不适合我们定位算法

frida-trace -U -j '*!sign'   -J ‘*!*signal*’   -f tv.

这里经过了好多种试法,终于找到了。。。。

frida-trace -U -j '?igned!' -J '!signal'   -f  tv.



frida-trace -U -j 'LibBili!'   -f  tv.danmaku.bili

停留在b占主页面,然后稍微下滑一点,我们可以看出日志

可以得出每次调用算法的时候,总会拿到getAppKey然后去调用  lubBili.s

`

--javascripttypescriptbashsqljsonhtmlcssccppjavarubypythongorustmarkdown
/*
 * Auto-generated by Frida. Please modify to match the signature of LibBili.s.
 *
 * For full API reference, see: https://frida.re/docs/javascript-api/
 */

{

  onEnter(log, args, state) {
    log(`LibBili.s(${args.map(JSON.stringify).join(', ')})`);
    log(args[0].entrySet().toArray())
  },


  onLeave(log, retval, state) {
    if (retval !== undefined) {
      log(`<= ${JSON.stringify(retval)}`);

     log("结果"+retval.toString());

    }
  }
}

我们多拿几对结果值

appkey=1d8b6e7d45233436,build=7320400,c_locale=zh_CN,channel=bili,disable_rcmd=0,mobi_app=android,model=MI 8,platform=android,s_locale=zh_CN,statistics={"appId":1,"platform":3,"version":"7.32.0","abtest":""}

appkey=1d8b6e7d45233436&build=7320400&c_locale=zh_CN&channel=bili&disable_rcmd=0&mobi_app=android&model=MI%208&platform=android&s_locale=zh_CN&statistics=%7B%22appId%22%3A1%2C%22platform%22%3A3%2C%22version%22%3A%227.32.0%22%2C%22abtest%22%3A%22%22%7D&ts=1686105777&sign=5b1ec26ead34e091f6572749262b241d

我们在手机上打开评论

action=story_comment_click,appkey=1d8b6e7d45233436,build=7320400,c_locale=zh_CN,channel=bili,disable_rcmd=0,extra={"from_spmid":"tm.recommend.0.0","goto":"vertical_av","spmid":"main.ugc-video-detail-vertical.0.0","track_id":"all_42.router-pegasus-1165524-88564bbf7-k59s2.1686105778860.338"},item_id=783291971,item_type=story,mobi_app=android,platform=android,s_locale=zh_CN,statistics={"appId":1,"platform":3,"version":"7.32.0","abtest":""},uid=21837784


action=story_comment_click&appkey=1d8b6e7d45233436&build=7320400&c_locale=zh_CN&channel=bili&disable_rcmd=0&extra=%7B%22from_spmid%22%3A%22tm.recommend.0.0%22%2C%22goto%22%3A%22vertical_av%22%2C%22spmid%22%3A%22main.ugc-video-detail-vertical.0.0%22%2C%22track_id%22%3A%22all_42.router-pegasus-1165524-88564bbf7-k59s2.1686105778860.338%22%7D&item_id=783291971&item_type=story&mobi_app=android&platform=android&s_locale=zh_CN&statistics=%7B%22appId%22%3A1%2C%22platform%22%3A3%2C%22version%22%3A%227.32.0%22%2C%22abtest%22%3A%22%22%7D&ts=1686105979&uid=21837784&sign=1b2cbab0f3db64e63e96ca3bb7dfefa2

特征就是输入的都是原始的值,但是输出都进行了编码。

对第一对进行urldecode

appkey=1d8b6e7d45233436,build=7320400,c_locale=zh_CN,channel=bili,disable_rcmd=0,mobi_app=android,model=MI 8,platform=android,s_locale=zh_CN,statistics={"appId":1,"platform":3,"version":"7.32.0","abtest":""}
    appkey=1d8b6e7d45233436&build=7320400&c_locale=zh_CN&channel=bili&disable_rcmd=0&mobi_app=android&model=MI 8&platform=android&s_locale=zh_CN&statistics={"appId":1,"platform":3,"version":"7.32.0","abtest":""}&ts=1686105777&sign=5b1ec26ead34e091f6572749262b241d

进行对比,发现增加了ts 时间戳 和 sign 参数,其他的没有变化。

那去构造个主动调用吧

function funsign() {
    Java.perform(function () {

        var TreeMap = Java.use("java.util.TreeMap");
        var map = TreeMap.$new();

        map.put("appkey", "1d8b6e7d45233436");
        map.put("build","7320400");
        var result =Java.use("com.bilibili.nativelibrary.LibBili").s(map);
        console.log("result=>",result.toString());
        return result;
    });

}

但是我很好奇,每次生成时间戳,那么如果我给她固定时间戳呢,


会发现没有变化,那么肯定一个问题,就是输入+时间戳  进行加密,不掺杂其他的变量。

但是现在不知道哪个so调用,可以使用下方脚本进行测试,

https://github.com/lasting-yang/frida_hook_libart/blob/master/hook_RegisterNatives.js

最终确认加密的so在 libili


打开jni_onload,家人们谁懂啊,上来就是ollvm

我们上方得到动态注册的函数偏移是0x9110

进去了一看也是ollvm,按照我的做法,绝对不会去还原控制流的

3.ollvm流程trace




然后使用stalker得到了程序的执行路径

libbili.so!0x194e4 libbili.so!0xc464c -3
libbili.so!0xc4790 libart.so!0x38c380 -2
libbili.so!0xc479c libbili.so!0xb1444 -1
libbili.so!0xb1684 libart.so!0x3de338 0
libbili.so!0x19ca4 libart.so!0x3c450c -1
libbili.so!0x19cb8 libbili.so!0xc3b4c 0
libbili.so!0xc3b7c libbili.so!0xc3990 1
libbili.so!0xc3ac8 libart.so!0x38ac98 2
libbili.so!0xc3b88 libbili.so!0xb1444 2
libbili.so!0xb1684 libart.so!0x3de338 3
libbili.so!0x19950 libart.so!0x3c4ef4 2
libbili.so!0x19960 libbili.so!0x1b0b0 3
libbili.so!0x1be20 libbili.so!0x82a0 4
libbili.so!0x19e54 libbili.so!0x1a884 3
libbili.so!0x1a998 libart.so!0x3c450c 4
libbili.so!0x1a9ac libbili.so!0xc3b4c 5
libbili.so!0xc3b7c libbili.so!0xc3990 6
libbili.so!0xc3ac8 libart.so!0x38ac98 7
libbili.so!0xc3b88 libbili.so!0xb1444 7
libbili.so!0xb1684 libart.so!0x3de338 8
libbili.so!0x1ab00 libbili.so!0xb2634 7
libbili.so!0xb2778 libart.so!0x386ea8 8
libbili.so!0x1ab0c libbili.so!0xb2634 8
libbili.so!0xb2778 libart.so!0x386ea8 9
libbili.so!0x19e68 libbili.so!0x1ab44 8
libbili.so!0x1ab98 libart.so!0x3ae4dc 9
libbili.so!0x1acac libbili.so!0xb1118 10
libbili.so!0xb12fc libart.so!0x3de338 11
libbili.so!0x19e84 libart.so!0x3c4ef4 10
libbili.so!0x19f60 libart.so!0x3c548c 11
libbili.so!0x19f68 libbili.so!0x8390 12
libbili.so!0x19ae0 libbili.so!0x8320 12
libbili.so!0x19af4 libbili.so!0x1c000 12
libbili.so!0x1c07c libbili.so!0x83c0 13
libbili.so!0x1c084 libbili.so!0xfb28 13
libbili.so!0x1c094 libbili.so!0xfb3c 13
libbili.so!0x10224 libbili.so!0x83a0 14
libbili.so!0x1c104 libbili.so!0x82c0 13
libbili.so!0x1c114 libbili.so!0xfb3c 13
libbili.so!0x10224 libbili.so!0x83a0 14
libbili.so!0x1c104 libbili.so!0x82c0 13
libbili.so!0x1c114 libbili.so!0xfb3c 13
libbili.so!0x100d4 libbili.so!0x83a0 14
libbili.so!0x100e4 libbili.so!0x11384 14
libbili.so!0x135f4 libbili.so!0x15e44 15
libbili.so!0x10224 libbili.so!0x83a0 14
libbili.so!0x1c104 libbili.so!0x82c0 13
libbili.so!0x1c114 libbili.so!0xfb3c 13
libbili.so!0x10224 libbili.so!0x83a0 14
libbili.so!0x1c104 libbili.so!0x82c0 13
libbili.so!0x1c114 libbili.so!0xfb3c 13
libbili.so!0x10224 libbili.so!0x83a0 14
libbili.so!0x1c410 libbili.so!0x15a6c 13
libbili.so!0x15aa0 libbili.so!0x15b30 14
libbili.so!0x15ad4 libbili.so!0xfb3c 14
libbili.so!0x10224 libbili.so!0x83a0 15
libbili.so!0x15ae4 libbili.so!0xfb3c 14
libbili.so!0x100d4 libbili.so!0x83a0 15
libbili.so!0x100e4 libbili.so!0x11384 15
libbili.so!0x135f4 libbili.so!0x15e44 16
libbili.so!0x10224 libbili.so!0x83a0 15
libbili.so!0x15af4 libbili.so!0x15b30 14
libbili.so!0x15b04 libbili.so!0x83c0 14
libbili.so!0x1c444 libbili.so!0x82c0 13
libbili.so!0x1c444 libbili.so!0x82c0 13
libbili.so!0x1c444 libbili.so!0x82c0 13
libbili.so!0x1c444 libbili.so!0x82c0 13
libbili.so!0x1c444 libbili.so!0x82c0 13
libbili.so!0x1c444 libbili.so!0x82c0 13
libbili.so!0x1c444 libbili.so!0x82c0 13
libbili.so!0x1c444 libbili.so!0x82c0 13
libbili.so!0x1c444 libbili.so!0x82c0 13
libbili.so!0x1c444 libbili.so!0x82c0 13
libbili.so!0x1c444 libbili.so!0x82c0 13
libbili.so!0x1c444 libbili.so!0x82c0 13
libbili.so!0x1c444 libbili.so!0x82c0 13
libbili.so!0x1c444 libbili.so!0x82c0 13
libbili.so!0x1c444 libbili.so!0x82c0 13
libbili.so!0x1c444 libbili.so!0x82c0 13
libbili.so!0x19afc libbili.so!0x8410 12
libbili.so!0x19b10 libart.so!0x3c450c 12
libbili.so!0x19c28 libbili.so!0xb2634 13
libbili.so!0xb2778 libart.so!0x386ea8 14
libbili.so!0x1a050 libart.so!0x388b7c 14


这个时候我们看 v6的交叉引用是env,v70的交叉引用是 上方的a2

j经过一阵很长的分析,发现,,,没啥发现,函数太多了,还是直接trace指令吧

用stalker写了个脚本,去trace了下指令

4.ollvm arm指令trace


function funsign() {
    Java.perform(function () {

        var TreeMap = Java.use("java.util.TreeMap");
        var treemap = TreeMap.$new();

        treemap.put("appkey", "1d8b6e7d45233436");
        treemap.put("build","7320400");
        treemap.put("ts","1686106983");

        var result =Java.use("com.bilibili.nativelibrary.LibBili").s(treemap);
        console.log("result=>",result);
        return result;
    });

}

function  hook_1(){

    let base_bili = Module.findBaseAddress("libbili.so");

let sub_19024 = base_bili.add(0x15B30);
Interceptor.attach(sub_19024 , {
    onEnter(args) {

        console.log(hexdump(args[0]))
        console.log(hexdump(args[1]));
         console.log(hexdump(args[2]));
        //console.log(args[1])

    }, onLeave(retval) {
        console.log(retval)
        console.log("end-hook-------------")
    }
})


}

因为trace的结果是appkey=1d8b6e7d45233436&build=7320400&ts=1686106983&sign=e66bbde177f4978281656f64b62c696d

sign为32位盲猜md5,  首先b62c696d,把最后四个字节拿出来,转换一下端序为0x6d692cb6

那么就在trace文件中进行搜索

有四个结果,我们可以去看四个结果调用的偏移在ida的那个函数,其实就是根据这四个,然后去ida中定位


function funsign() {
    Java.perform(function () {

        var TreeMap = Java.use("java.util.TreeMap");
        var treemap = TreeMap.$new();

        treemap.put("appkey", "1d8b6e7d45233436");
        treemap.put("build","7320400");
        treemap.put("ts","1686106983");

        var result =Java.use("com.bilibili.nativelibrary.LibBili").s(treemap);
        console.log("result=>",result);
        return result;
    });

}

function  hook_1(){

    let base_bili = Module.findBaseAddress("libbili.so");

let sub_19024 = base_bili.add(0x11384);
Interceptor.attach(sub_19024 , {
    onEnter(args) {

        console.log(hexdump(args[0]))
        console.log(hexdump(args[1]));
         console.log(hexdump(args[2]));
        //console.log(args[1])

    }, onLeave(retval) {
        console.log(retval)
        console.log("end-hook-------------")
    }
})


}

5.结果及其彩蛋




ios我也搞了下,更简单就不记录了

appkey:27eb53fc9058f8c3, 2ed53a74eeefe3cf99fbd01d8c9c375是salt

图片描述


[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

收藏
免费 7
支持
分享
最新回复 (1)
雪    币: 270
活跃值: (499)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
前面看得明白,到ollvm就开始懵了。。。stalker得到路径有啥作用?trace的脚本是怎么写的?从sign拿出的四个字节”b62c696d“是因为这是MD5的计算吗?为啥搜索的时候是前后端要倒序?纯小白不太懂
2023-6-9 15:48
0
游客
登录 | 注册 方可回帖
返回
//