首页
社区
课程
招聘
[原创]Frida配合BurpSuite的Brida插件自动解密取证
发表于: 2020-11-16 14:52 8380

[原创]Frida配合BurpSuite的Brida插件自动解密取证

2020-11-16 14:52
8380

这是2W班8月份的练习题第一题。题目要求是
参考文档:https://bbs.pediy.com/thread-260422.htm

本题加密流程已经由大佬给出,也就是在大佬的基础上进行取证。对Brida的使用花费了多一点的时间。

另外当时做这题的时候,自己对frida的操作还是停留在根据内存分布去处理数据,而10月课程学习后,其实有很多更简便兼容性也更强的方式。

这里的代码都是对应于7月份老版本的HOOK。新版本需要重新找hook点。

参考文档中已经给出了APP的加密流程和解密代码。这里就不再分析APP的加密,只是打印出解密后的数据。

直接定位图片解密函数,保存返回值。

可以保存但是速度极慢,因为不知道怎么取出result的地址,所以就新建buffer重写了一遍在保存。

这样下载图片速度不会影响app的正常运行了,只是批量下载需要滑动触发图片加载。

大量读取的话,还是用原作者写好的分页查询图片,然后依次下载脱离app运行方便很多,这里就下载一点测试。

由于解密的函数com.ilulutv.fulao2.other.g.b.a大多接口都会调用。这里我只想显示m3u8的数据,所以打印了堆栈,向上找了一些定位到了c.c.a.h.a.c.a。

这个函数应该是不同类型http请求解密后呈现数据的方法。筛选82018就是m3u8解密的数据。

这边就直接使用send打印出数据了。

这里app本身需要代理才能播放视频,但是ffmpeg下载确没有什么限制,可能是其他接口被干掉导致播放不了。

ffmpeg.exe -protocol_whitelist "file,http,crypto,tcp,https,tls" -i test.m3u8 -c copy test.mp4

根据作者给出的命令下载正常播放,确定解密的视频数据正确。

BurpSuite安装Brida从BApp Store直接安装比较方便,这里只有最新版,其他版本就是用jar包在Extensions中添加

配置碰到一些小坑,因为要求是最新版0.4版本,网上教程大多数是0.3版本的教程。所以直接看官方文档才能避免这些问题。

0.4版本主要更新是新增了Custonm Plugins选项卡,有4种类型的内部插件使用也比较方便。

还有一点就是RPC导出的函数没必要hex转来转去,直接使用字符串就可以了。如果是老版本代码去掉hexToString,stringToHex的调用即可。

Win10我配置后console.log获取不到打印,不知道什么原因,然后kali正常,后面测试也都是在kali上。

最开始写代码最好在Debug export中测试正常后再使用插件调用

1.首先使用Brida的IConetxtMenu添加右键菜单,在Repeater请求后右键选择添加的菜单解密。

2.接下来使用IHttpListener自动修改Repeater的返回值

3.都顺利后可以自动解密Proxy中所有带X-VTag的返回数据,配置和上一步差不多,只是不替换resphone,单纯打印

这样解密的日志可以直接在console中查看,这里是复制出来的数据,将其他类型的数据也一起打印出来了。

调用app解密函数代码就比较简单了

 
 
var class_decimg = Java.use("com.ilulutv.fulao2.other.g.b");
class_decimg.b.overload('[B', '[B', 'java.lang.String').implementation = function(bArr, bArr2, str){
    var result = this.b(bArr, bArr2, str);
    imgResult = result;
    console.log("imgResult.length->", imgResult.length);
    var fileName = "/sdcard/fulao2/"+imgResult.length+".jpg";
    try{
        var buffer = Memory.alloc(imgResult.length);
        for(var i=0;i<imgResult.length;i++){
            var ival = imgResult[i];
            if(ival < 0) {
                ival += 256;
            }
            // console.log("buffer:",buffer.add(i),ival);
            buffer.add(i).writeU8(ival);//imgResult[i]
        }
        console.log("buffer:", hexdump(buffer));
        var fd = new File(fileName, "ab+");
        if (fd && fd != null) {
            var dex_buffer = ptr(buffer).readByteArray(imgResult.length);
            fd.write(dex_buffer);
            fd.flush();
            fd.close();
            console.log("[dump img]:", fileName);
        }
    }
    catch(error){
        console.log("write_file_log error:",error);
    }
    return result;
}
var class_decimg = Java.use("com.ilulutv.fulao2.other.g.b");
class_decimg.b.overload('[B', '[B', 'java.lang.String').implementation = function(bArr, bArr2, str){
    var result = this.b(bArr, bArr2, str);
    imgResult = result;
    console.log("imgResult.length->", imgResult.length);
    var fileName = "/sdcard/fulao2/"+imgResult.length+".jpg";
    try{
        var buffer = Memory.alloc(imgResult.length);
        for(var i=0;i<imgResult.length;i++){
            var ival = imgResult[i];
            if(ival < 0) {
                ival += 256;
            }
            // console.log("buffer:",buffer.add(i),ival);
            buffer.add(i).writeU8(ival);//imgResult[i]
        }
        console.log("buffer:", hexdump(buffer));
        var fd = new File(fileName, "ab+");
        if (fd && fd != null) {
            var dex_buffer = ptr(buffer).readByteArray(imgResult.length);
            fd.write(dex_buffer);
            fd.flush();
            fd.close();
            console.log("[dump img]:", fileName);
        }
    }
    catch(error){
        console.log("write_file_log error:",error);
    }
    return result;
}
class_decimg.a-> [object Object]
class_decimg.a-> 56439
buffer:            0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F  0123456789ABCDEF
95e7f148  ff d8 ff e0 00 10 4a 46 49 46 00 01 01 00 00 01  ......JFIF......
95e7f158  00 01 00 00 ff fe 00 3b 43 52 45 41 54 4f 52 3a  .......;CREATOR:
95e7f168  20 67 64 2d 6a 70 65 67 20 76 31 2e 30 20 28 75   gd-jpeg v1.0 (u
95e7f178  73 69 6e 67 20 49 4a 47 20 4a 50 45 47 20 76 36  sing IJG JPEG v6
95e7f188  32 29 2c 20 71 75 61 6c 69 74 79 20 3d 20 39 30  2), quality = 90
95e7f198  0a ff db 00 43 00 03 02 02 03 02 02 03 03 03 03  ....C...........
95e7f1a8  04 03 03 04 05 08 05 05 04 04 05 0a 07 07 06 08  ................
95e7f1b8  0c 0a 0c 0c 0b 0a 0b 0b 0d 0e 12 10 0d 0e 11 0e  ................
95e7f1c8  0b 0b 10 16 10 11 13 14 15 15 15 0c 0f 17 18 16  ................
95e7f1d8  14 18 12 14 15 14 ff db 00 43 01 03 04 04 05 04  .........C......
95e7f1e8  05 09 05 05 09 14 0d 0b 0d 14 14 14 14 14 14 14  ................
95e7f1f8  14 14 14 14 14 14 14 14 14 14 14 14 14 14 14 14  ................
95e7f208  14 14 14 14 14 14 14 14 14 14 14 14 14 14 14 14  ................
95e7f218  14 14 14 14 14 14 14 14 14 14 14 ff c0 00 11 08  ................
95e7f228  01 ca 03 1b 03 01 22 00 02 11 01 03 11 01 ff c4  ......".........
95e7f238  00 1f 00 00 01 05 01 01 01 01 01 01 00 00 00 00  ................
[dump img]: /sdcard/fulao2/56439.jpg
class_decimg.a-> [object Object]
class_decimg.a-> 56439
buffer:            0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F  0123456789ABCDEF
95e7f148  ff d8 ff e0 00 10 4a 46 49 46 00 01 01 00 00 01  ......JFIF......
95e7f158  00 01 00 00 ff fe 00 3b 43 52 45 41 54 4f 52 3a  .......;CREATOR:
95e7f168  20 67 64 2d 6a 70 65 67 20 76 31 2e 30 20 28 75   gd-jpeg v1.0 (u
95e7f178  73 69 6e 67 20 49 4a 47 20 4a 50 45 47 20 76 36  sing IJG JPEG v6
95e7f188  32 29 2c 20 71 75 61 6c 69 74 79 20 3d 20 39 30  2), quality = 90
95e7f198  0a ff db 00 43 00 03 02 02 03 02 02 03 03 03 03  ....C...........
95e7f1a8  04 03 03 04 05 08 05 05 04 04 05 0a 07 07 06 08  ................
95e7f1b8  0c 0a 0c 0c 0b 0a 0b 0b 0d 0e 12 10 0d 0e 11 0e  ................
95e7f1c8  0b 0b 10 16 10 11 13 14 15 15 15 0c 0f 17 18 16  ................
95e7f1d8  14 18 12 14 15 14 ff db 00 43 01 03 04 04 05 04  .........C......
95e7f1e8  05 09 05 05 09 14 0d 0b 0d 14 14 14 14 14 14 14  ................
95e7f1f8  14 14 14 14 14 14 14 14 14 14 14 14 14 14 14 14  ................
95e7f208  14 14 14 14 14 14 14 14 14 14 14 14 14 14 14 14  ................
95e7f218  14 14 14 14 14 14 14 14 14 14 14 ff c0 00 11 08  ................
95e7f228  01 ca 03 1b 03 01 22 00 02 11 01 03 11 01 ff c4  ......".........
95e7f238  00 1f 00 00 01 05 01 01 01 01 01 01 00 00 00 00  ................
[dump img]: /sdcard/fulao2/56439.jpg
 
var class_decimg = Java.use("com.ilulutv.fulao2.other.g.b");
class_decimg.b.overload('[B', '[B', 'java.lang.String').implementation = function(bArr, bArr2, str){
    var result = this.b(bArr, bArr2, str);
    imgBase64Arr[imginx++] = gson.$new().toJson(result);
    return result;
}
 
rpc.exports = {
    getimgarr : function(i){
        var result = '';
        if(i in imgBase64Arr){
            try{
                result = imgBase64Arr[i];
                console.log("imgBase64Arr[i] result->", result.length);
            }
            catch(error){
                console.log(error);
            }
        }else{
            console.log("i in imgBase64Arr false");
        }
        return result;
    },
    getimginx : function(){
        return imginx;
    },
    clearimgarr: function(start,len){
        for(var i = 0; i< len;i++){
            // imgBase64Arr[start+i] = "clear";
            delete  imgBase64Arr[start+i];
        }
    }
}
var class_decimg = Java.use("com.ilulutv.fulao2.other.g.b");
class_decimg.b.overload('[B', '[B', 'java.lang.String').implementation = function(bArr, bArr2, str){
    var result = this.b(bArr, bArr2, str);
    imgBase64Arr[imginx++] = gson.$new().toJson(result);
    return result;
}
 
rpc.exports = {
    getimgarr : function(i){
        var result = '';
        if(i in imgBase64Arr){
            try{
                result = imgBase64Arr[i];
                console.log("imgBase64Arr[i] result->", result.length);
            }
            catch(error){
                console.log(error);
            }
        }else{
            console.log("i in imgBase64Arr false");
        }
        return result;
    },
    getimginx : function(){
        return imginx;
    },
    clearimgarr: function(start,len){
        for(var i = 0; i< len;i++){
            // imgBase64Arr[start+i] = "clear";
            delete  imgBase64Arr[start+i];
        }
    }
}
def downImg(imgDataStr):
    try:
        ms = re.findall("(-?\d+)", imgDataStr)
        intArr = []
        for m in ms:
            ival = int(m)
            if ival < 0:
                ival += 256
            intArr.append(ival) 
        bs = bytes(intArr)
        m = hashlib.md5()
        m.update(bs)
        downname = m.hexdigest()
        with open("download/"+downname+".jpg", 'ab') as f:
            f.write(bs)
        print("download sucess->"+ downname+".jpg")
    except Exception as e:
        print("downImg Error->")
 
imginx = 0
while True:
    try:
        imgArrValue = script.exports.getimginx()
        while imgArrValue > imginx:
            imgobj = script.exports.getimgarr(imginx)
            downImg(imgobj)
            script.exports.clearimgarr(imginx, 1)
            imginx += 1
        print(imgArrValue)
        time.sleep(3)
    except Exception as ex:
        print("Error:", ex)
        break
def downImg(imgDataStr):
    try:
        ms = re.findall("(-?\d+)", imgDataStr)
        intArr = []
        for m in ms:
            ival = int(m)
            if ival < 0:
                ival += 256
            intArr.append(ival) 
        bs = bytes(intArr)
        m = hashlib.md5()
        m.update(bs)
        downname = m.hexdigest()
        with open("download/"+downname+".jpg", 'ab') as f:
            f.write(bs)
        print("download sucess->"+ downname+".jpg")
    except Exception as e:
        print("downImg Error->")
 
imginx = 0
while True:
    try:
        imgArrValue = script.exports.getimginx()
        while imgArrValue > imginx:
            imgobj = script.exports.getimgarr(imginx)
            downImg(imgobj)
            script.exports.clearimgarr(imginx, 1)
            imginx += 1
        print(imgArrValue)
        time.sleep(3)
    except Exception as ex:
        print("Error:", ex)
        break
 
 
public void a(String str, int i2) {
    switch (i2) {
        case 82000:
            VideoInfoGson videoInfoGson = (VideoInfoGson) a(str, (Class<?>) VideoInfoGson.class);
            a(videoInfoGson.getStatus().getCode(), videoInfoGson.getStatus().getMessage(), videoInfoGson, this);
            return;
        case 82001:
            com.ilulutv.fulao2.other.b.t = str;
            g.m(str);
            if (str.isEmpty()) {
                Crashlytics.logException(new Exception("BC" + str));
            }
            MenuTitleGson menuTitleGson = (MenuTitleGson) a(str, (Class<?>) MenuTitleGson.class);
            if (g.v0()) {
                g.e(menuTitleGson.getResponse().getMenus().getUncoverX().size());
            } else {
                g.e(0);
            }
            if (g.u0()) {
                g.d(menuTitleGson.getResponse().getMenus().getCoverX().size());
            } else {
                g.d(0);
            }
            a(menuTitleGson.getStatus().getCode(), menuTitleGson.getStatus().getMessage(), menuTitleGson, this);
            return;
        case 82002:
            LikeGson likeGson = (LikeGson) a(str, (Class<?>) LikeGson.class);
            a(likeGson.getStatus().getCode(), likeGson.getStatus().getMessage(), likeGson, this);
            return;
        case 82003:
            ReportVideoGson reportVideoGson = (ReportVideoGson) a(str, (Class<?>) ReportVideoGson.class);
            a(reportVideoGson.getStatus().getCode(), reportVideoGson.getStatus().getMessage(), reportVideoGson, this);
            return;
        case 82004:
            VideoListGson videoListGson = (VideoListGson) a(str, (Class<?>) VideoListGson.class);
            a(videoListGson.getStatus().getCode(), videoListGson.getStatus().getMessage(), videoListGson, this);
            return;
        case 82005:
            c(str);
            return;
        case 82006:
            AdGson2 adGson2 = (AdGson2) a(str, (Class<?>) AdGson2.class);
            a(adGson2.getStatus().getCode(), adGson2.getStatus().getMessage(), adGson2, this);
            return;
        case 82007:
            ActorInfoGson actorInfoGson = (ActorInfoGson) a(str, (Class<?>) ActorInfoGson.class);
            a(actorInfoGson.getStatus().getCode(), actorInfoGson.getStatus().getMessage(), actorInfoGson, this);
            return;
        case 82008:
            a(str);
            return;
        case 82009:
            VideoLikeListGson videoLikeListGson = (VideoLikeListGson) a(str, (Class<?>) VideoLikeListGson.class);
            a(videoLikeListGson.getStatus().getCode(), videoLikeListGson.getStatus().getMessage(), videoLikeListGson, this);
            return;
        case 82010:
            e(str);
            return;
        case 82011:
            d(str);
            return;
        case 82012:
            CurrentOrderGson currentOrderGson = (CurrentOrderGson) a(str, (Class<?>) CurrentOrderGson.class);
            a(currentOrderGson.getStatus().getCode(), currentOrderGson.getStatus().getMessage(), currentOrderGson, this);
            return;
        case 82013:
            HistoryOrdersGson historyOrdersGson = (HistoryOrdersGson) a(str, (Class<?>) HistoryOrdersGson.class);
            a(historyOrdersGson.getStatus().getCode(), historyOrdersGson.getStatus().getMessage(), historyOrdersGson, this);
            return;
        case 82014:
            g(str);
            return;
        case 82015:
            f(str);
            return;
        case 82016:
            UserInfoGson userInfoGson = (UserInfoGson) a(str, (Class<?>) UserInfoGson.class);
            a(userInfoGson.getStatus().getCode(), userInfoGson.getStatus().getMessage(), userInfoGson, this);
            return;
        case 82017:
            AddUserSourceGson addUserSourceGson = (AddUserSourceGson) a(str, (Class<?>) AddUserSourceGson.class);
            a(addUserSourceGson.getStatus().getCode(), addUserSourceGson.getStatus().getMessage(), addUserSourceGson, this);
            return;
        case 82018:
            a((Object) str);
            return;
        case 82019:
            WatchHistoryListsGson watchHistoryListsGson = (WatchHistoryListsGson) a(str, (Class<?>) WatchHistoryListsGson.class);
            a(watchHistoryListsGson.getStatus().getCode(), watchHistoryListsGson.getStatus().getMessage(), watchHistoryListsGson, this);
            return;
        case 82020:
            b(str);
            return;
        case 82021:
            NoticeListGson noticeListGson = (NoticeListGson) a(str, (Class<?>) NoticeListGson.class);
            a(noticeListGson.getStatus().getCode(), noticeListGson.getStatus().getMessage(), noticeListGson, this);
            return;
        case 82022:
            NoticeListGsonTwo noticeListGsonTwo = (NoticeListGsonTwo) a(str, (Class<?>) NoticeListGsonTwo.class);
            a(noticeListGsonTwo.getStatus().getCode(), noticeListGsonTwo.getStatus().getMessage(), noticeListGsonTwo, this);
            return;
        default:
            return;
    }
}
public void a(String str, int i2) {
    switch (i2) {
        case 82000:
            VideoInfoGson videoInfoGson = (VideoInfoGson) a(str, (Class<?>) VideoInfoGson.class);
            a(videoInfoGson.getStatus().getCode(), videoInfoGson.getStatus().getMessage(), videoInfoGson, this);
            return;
        case 82001:
            com.ilulutv.fulao2.other.b.t = str;

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

收藏
免费 3
支持
分享
最新回复 (9)
雪    币: 1216
活跃值: (230)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2

大佬 你好 如果需要解密的串很长 会出现超时现象吗


Exception with execute method
java.util.concurrent.TimeoutException
java.base/java.util.concurrent.FutureTask.get(FutureTask.java:204

最后于 2020-11-30 11:30 被weishi编辑 ,原因:
2020-11-30 11:29
0
雪    币: 1636
活跃值: (653)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
3
BurpSuite 好像都是收费版
2020-12-9 10:15
0
雪    币: 2322
活跃值: (8735)
能力值: ( LV2,RANK:15 )
在线值:
发帖
回帖
粉丝
4
琅環玉碎 BurpSuite 好像都是收费版

善用搜索功能,有原包和KeyGen

最后于 2020-12-9 11:12 被2DCoXrq编辑 ,原因:
2020-12-9 11:12
0
雪    币: 1636
活跃值: (653)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
5
FleTime 琅環玉碎 BurpSuite 好像都是收费版 善用搜索功能,有原包和KeyGen
试过了,卡在输入key的界面。1.63-17.2的keyGen出来的key 都不行,不知道为什么
2020-12-9 18:48
0
雪    币: 2322
活跃值: (8735)
能力值: ( LV2,RANK:15 )
在线值:
发帖
回帖
粉丝
6
琅環玉碎 试过了,卡在输入key的界面。1.63-17.2的keyGen出来的key 都不行,不知道为什么

2020-12-9 19:02
0
雪    币: 2322
活跃值: (8735)
能力值: ( LV2,RANK:15 )
在线值:
发帖
回帖
粉丝
7
琅環玉碎 试过了,卡在输入key的界面。1.63-17.2的keyGen出来的key 都不行,不知道为什么
私信一条20雪币,太贵。。
Loader和KeyGen:https://bbs.pediy.com/thread-260844-1.htm#1670577
2020.11.3的原包:https://bbs.pediy.com/thread-260844-1.htm#1671315
总之,善用搜索功能
2020-12-9 21:20
0
雪    币: 1636
活跃值: (653)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
8
FleTime 私信一条20雪币,太贵。。 Loader和KeyGen:https://bbs.pediy.com/thread-260844-1.htm#1670577 2020.11.3的原包:https:/ ...
谢谢大佬
2020-12-9 23:12
0
雪    币: 1981
活跃值: (206)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
这是什么班
2020-12-11 12:17
0
雪    币: 25
活跃值: (364)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10

楼主你好,可以帮忙分析一个m3u8的加密吗

这个网站他的视频中有的做了TS切片,有的没有

可以用Google Chrome的浏览器中开发者工具中的网络数据获取到m3u8的文件

可是不知道他是如何加密的

这是他的视频网址:https://www.ttgame.net/course/video/434

2021-7-23 12:27
0
游客
登录 | 注册 方可回帖
返回
//