xuqi 发表于 2022-2-19 14:55

【2022春节红包】WEB题目

Web题:来试试WEB题吧,点击下方“立即申请”任务,即可获得本题地址。

小D最爱看的视频网站最近关站了,关站前他用 Fiddler 和 Web Archive 保存了一位主播的视频,但他发现存下来的文件无法播放。你能帮小D找回他的回忆吗?(.saz 与 .wacz 任选其一即可解题)

https://down.52pojie.cn/kFMiuT.7z | PassWord:UZFQq9BzpAG5

虽然说是web,但其实是misc题
解压查看文件类型:
52tube.saz:Zip archive data, at least v2.0 to extract, compression method=store
52tube.wacz: Zip archive data, at least v1.0 to extract, compression method=store

用Fiddler加载saz文件,找一些有用的信息
```r
https://52tube.mmxxii/hls/live.m3u8

#EXT-X-KEY:METHOD=AES-128,URI="key://live"


POST https://52tube.mmxxii/api/drm/
h=7b10311e6e310f0df068d9ede10475a8&id=live

byte[] arrOutput = { 0x08, 0xA5, 0xE6, 0xC2, 0xC2, 0x61, 0xA8, 0xAC, 0xB4, 0xD7, 0x9C, 0x49, 0xAF, 0x16, 0x0A, 0x3A, 0xDA, 0x4E, 0x5C, 0xEA, 0xE1, 0x6F, 0xED, 0x46, 0xEB, 0x6F, 0x49, 0x8C, 0x9B, 0x63, 0xD5, 0x3B };
```

保存了8个ts文件,是加密的,key和iv不太好找
把一开始的script.bundle.js保存下来搜一下,发现对 `/api/drm` 的处理可能有用,截取关键逻辑如下,大概就是把h参数和随机生成的字节做一些异或:
```r
        (() => {
                'use strict';
                var t = r(631);
                let e = '/api/ping/', i = '/api/drm/';
                function n(t) {
                        return [...new Uint8Array(t)].map(t => t.toString(16).padStart(2, '0')).join('');
                }
                function s(t, e) {
                        let r = new Uint8Array(t.length);
                        for (let i = 0; i < t.length; i++)
                                r = t ^ e;
                        return r;
                }
                class a extends t.DefaultConfig.loader {
                        constructor(t) {
                                super(t);
                                var r = this.load.bind(this);
                                this.load = function (t, a, o) {
                                        if (t && t.url.startsWith('key://')) {
                                                let r = t.url.substr(6);
                                                t.url = e;
                                                var l = o.onSuccess;
                                                o.onSuccess = function (t, e, a) {
                                                        (async function (t) {
                                                                let e = await async function () {
                                                                        let t = new Uint8Array(16);
                                                                        crypto.getRandomValues(t);
                                                                        let e = n(t.buffer) + Date.now() + Math.random();
                                                                        return new Uint8Array((await async function (t) {
                                                                                const e = new TextEncoder().encode(t);
                                                                                return await crypto.subtle.digest('SHA-256', e);
                                                                        }(e)).slice(0, 16));
                                                                }();
                                                                var r = new URLSearchParams();
                                                                r.append('h', n(e.buffer)), r.append('id', t);
                                                                var a = {
                                                                        method: 'POST',
                                                                        headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
                                                                        body: r
                                                                };
                                                                let o = await fetch(i, a), l = await o.arrayBuffer();
                                                                if (32 !== l.byteLength)
                                                                        throw new Error('Invalid response');
                                                                let u = new Uint8Array(l.slice(0, 16)), c = new Uint8Array(l.slice(16, 32));
                                                                return s(s(u, e), c);
                                                        }(r).then(t => {
                                                                l({ data: t.buffer }, e, a);
                                                        }));
                                                };
                                        }
                                        r(t, a, o);
                                };
                        }
                }
                var o = document.getElementById('video');
                if (t.isSupported()) {
                        var l = new t({ loader: a });
                        l.loadSource('./hls/live.m3u8'), l.attachMedia(o), l.on(t.Events.ERROR, function (t, e) {
                                e.type, e.details, e.fatal, alert('Video load failed!'), console.error(t, e);
                        });
                } else
                        alert("Your browser doesn't support HLS!");
        })();
```

python翻译逻辑如下:
```r
# coding:utf8

h_list = bytes.fromhex('7b10311e6e310f0df068d9ede10475a8')# IV

aa =

mid_result = []
for i in range(16):
    tmp = h_list ^ aa
    mid_result.append(tmp)
key = ''
for i in range(16):
    tmp = mid_result ^ aa
    key += f'{tmp:0>2x}'
print(key)

# a9fb8b364d3f4ae7afd00c28d571aaa9key
```

一开始并不知道哪个是key哪个是iv,只好都试一下,看看结果是否正确
CyberChef的AES_Decrypt还是很方便的,模式是AES-128-CBC
因为只有8个ts文件,就不写脚本了

解密之后看视频,发现flag在live_00003.ts视频里
flag{like_sub_52tube}

hx19930 发表于 2022-2-22 18:00

学到了{谢谢

Dunker 发表于 2022-3-15 01:00

确实厉害,谢谢大神

yyspawn 发表于 2022-3-15 06:09

页: [1]
查看完整版本: 【2022春节红包】WEB题目