Skype 打开 base64 编码的 JavaScript。它有什么作用?

信息安全 恶意软件 javascript 逆向工程 Skype
2021-09-08 21:50:11

我刚刚遇到了一个相当不寻常的问题,我无法弄清楚它是否真的是一个问题(甚至是安全问题)。在 MacOS 上打开 Skype 时,会出现一个弹出窗口(多次,但内容完全相同),要求选择一个应用程序来打开以下内容:

==

解码 base64 值会显示脚本标签内的 JavaScript 片段,这让我相信 Skype 正试图在浏览器中打开此脚本。这是完整的值,为了便于阅读而美化了:

<script>
    (function() {
        function g(a) {
            var c, b;
            c = "";
            for (b = 0; b < a.length; b++) c += String.fromCharCode(a.charCodeAt(b) + 2 - b % 14);
            return c
        }

        function h(a) {
            d = a - k;
            k = a;
            if (!(350 < d))
                for (a = 0; a < b.length; a++) b[a] && b[a].postMessage && b[a].postMessage({
                    fps: 1E3 / d,
                    slot: e,
                    timeDelta: d || 0
                }, "*");
            window[g(f)](h)
        }
        var k = 0,
            d, b = [],
            e, f;
        f = "pdqvgvxFtpuj~tmmFscpi";
        window.addEventListener("message", function(a) {
            var c = a.data;
            c && c.slot && (a = a.source, -1 < b.indexOf(a) || (b.push(a), void 0 === e && (e = c.slot)))
        });
        window[g(f)](h)
    })();
</script>

我对这个片段进行了一点逆向工程。据我了解,它监听对象message上的事件window,然后更新一些值。它还反复调用requestAnimationFrame,从那里发布消息。

这段代码在做什么?为什么 Skype 试图打开它?

1个回答

我首先重命名了一些变量以使事情更容易理解:

    function obscurify(function_input) {
        var returnstring, local_counter;
        returnstring = "";          
        for (local_counter = 0; local_counter < function_input.length; local_counter++) 
        {
            returnstring += String.fromCharCode(function_input.charCodeAt(local_counter) + 2 - local_counter % 14);

        }

        return returnstring
    }

这是第一个函数,当我们pdqvgvxFtpuj~tmmFscpi通过它运行晦涩的字符串时,我们确实收到了这个 binrequestAnimationFrame中所示的单词(前面的警报框)。

这个h()功能让我有点困扰,所以我开始四处寻找人们使用这个requestanimationframe功能的原因。

那是我找到这个页面的时候:

在使用 requestAnimationFrame 时限制帧速率可能是一种常见的需求,尤其是在您希望动画和机制不超过每秒帧数的特定标记的游戏编码时。让我们通过 2 种方法来实现它。

作者描述的第一种方式是 through setTimeOut,但随后他写道:

好的,浏览器无法优化 setTimeout 或 setInterval。因此,最好自己进行计算并限制帧速率。让我们看看如何。

然后他继续执行以下代码:

var fps = 30;
var now;
var then = Date.now();
var interval = 1000/fps;
var delta;

function draw() {

    requestAnimationFrame(draw);

    now = Date.now();
    delta = now - then;

    if (delta > interval) {
        // update time stuffs

        // Just `then = now` is not enough.
        // Lets say we set fps at 10 which means
        // each frame must take 100ms
        // Now frame executes in 16ms (60fps) so
        // the loop iterates 7 times (16*7 = 112ms) until
        // delta > interval === true
        // Eventually this lowers down the FPS as
        // 112*10 = 1120ms (NOT 1000ms).
        // So we have to get rid of that extra 12ms
        // by subtracting delta (112) % interval (100).
        // Hope that makes sense.

        then = now - (delta % interval);

        // ... Code for Drawing the Frame ...
    }
}

draw();

这看起来很像我们代码中正在进行的计算。

但是为什么这会在我不做任何事情的情况下出现在 Skype 中?

因为浏览器和 Javascript 无处不在。我刚启动 Skype,它没有给我一个错误,但它向​​我展示了广告。我的直觉告诉我,加载广告的嵌入式浏览器在您的情况下没有数据 URL 的处理程序,这就是 Skype 似乎给出该错误的原因。

该代码实际上只是添加了一个事件处理程序,并确保每次调用事件时都不会破坏 FPS。(在广告之间切换,让广告流畅运行,让加载图标流畅运行,...)

如果广告在 1 000 000 次 30 秒的展示中超过或低于其显示时间,则 10 毫秒的差异会以惊人的速度扩展,从而为您的广告客户提供比他们支付的更少或更多的显示时间。

但为什么会晦涩难懂?

根据@dandavis 的评论,确实没有明显的理由来混淆这段代码,它可以在互联网上免费获得(就像我在上面链接的那样)。但是,执行此代码的同一个嵌入式浏览器也可能会托管一个登录框架。

我们不会为晦涩和非晦涩的代码重写处理程序,因为如果我们需要一次通过混淆器运行所有代码会更容易且不易出错。

在我看来,混淆的原因可能只是一般规则:混淆所有 JS 代码。