18

I just came across a rather unusual problem, and I cannot figure out if it actually is a problem (or even security issue) or not. Upon opening Skype on MacOS, a popup window appears (multiple times, but with the exact same content), asking to choose an application for opening the following:

PHNjcmlwdD4oZnVuY3Rpb24oKXtmdW5jdGlvbiBnKGEpe3ZhciBjLGI7Yz0iIjtmb3IoYj0wO2I8YS5sZW5ndGg7YisrKWMrPVN0cmluZy5mcm9tQ2hhckNvZGUoYS5jaGFyQ29kZUF0KGIpKzItYiUxNCk7cmV0dXJuIGN9ZnVuY3Rpb24gaChhKXtkPWEtaztrPWE7aWYoISgzNTA8ZCkpZm9yKGE9MDthPGIubGVuZ3RoO2ErKyliW2FdJiZiW2FdLnBvc3RNZXNzYWdlJiZiW2FdLnBvc3RNZXNzYWdlKHtmcHM6MUUzL2Qsc2xvdDplLHRpbWVEZWx0YTpkfHwwfSwiKiIpO3dpbmRvd1tnKGYpXShoKX12YXIgaz0wLGQsYj1bXSxlLGY7Zj0icGRxdmd2eEZ0cHVqfnRtbUZzY3BpIjt3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcigibWVzc2FnZSIsZnVuY3Rpb24oYSl7dmFyIGM9YS5kYXRhO2MmJmMuc2xvdCYmKGE9YS5zb3VyY2UsLTE8Yi5pbmRleE9mKGEpfHwoYi5wdXNoKGEpLHZvaWQgMD09PWUmJihlPWMuc2xvdCkpKX0pO3dpbmRvd1tnKGYpXShoKX0pKCk7Cjwvc2NyaXB0Pg==

Decoding the base64-value reveals a JavaScript snippet inside a script tag, which leads me to believe that Skype is trying to open this script inside a browser. Here is the complete value, beautified for readability:

<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>

I reverse engineered this Snippet a little bit. As far as I understand, it listens for the message event on the window object and then updates some values. It also repeatedly calls requestAnimationFrame, where the messages are posted from.

What is this code doing? Why is Skype trying to open it?

8
  • Just to be clear, you get that popup just by opening Skype? Not trying to perform any particular action, not clicking any link... just starting the program? That is certainly odd.
    – Anders
    Feb 27, 2018 at 9:16
  • @Anders I get this popup multiple times just by opening Skype. I can reproduce it, canceling all the Popups and restarting Skype will also reopen the popups. Not every time, though
    – NikxDa
    Feb 27, 2018 at 9:20
  • did you change default browser on your mac ? (seems like the one skype use for background calls doesn't handle well base64 encoded html)
    – Tensibai
    Feb 27, 2018 at 12:43
  • 2
    it's not doing much. It identifies and collects frames on the page (a.source) It also fires a timer (requestAnimationFrame == window[g("pdqvgvxFtpuj~tmmFscpi")](h) ) that every 350ms triggers a message event (b[a].postMessage) that only gets passed basic timing info (fps, slot (iframe number), and timeDelta). I'm not sure the point of all that, maybe to see how fast different iframes (thus ads) are loading? It's not hi-res enough to be a timing attack. I imagine the more interesting parts are contained in the message event handlers which this script invokes, but that's not shown.
    – dandavis
    Feb 27, 2018 at 20:16
  • 5
    the script itself is not harmful, but it's suspicious in that it conceals the requestAnimationFrame call, and that it obscures anything at all. There's no good reason to jump though those hoops instead of "hard-coding" the method names, unless you want to make it hard to analyze, but why do that?
    – dandavis
    Feb 27, 2018 at 20:26

1 Answer 1

2

I started by renaming some variables to make things a bit more understandable:

    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
    }

This is the first function, when we run the obscure string pdqvgvxFtpuj~tmmFscpi through it, we indeed receive the word requestAnimationFrame as demonstrated in this bin (alertbox ahead).

The h() function bothered me for a bit, so I started looking around for reasons people use the requestanimationframe function.

That's when I found this page:

Limiting the frame rate while using requestAnimationFrame can be a common want especially when coding Games where you want your animations and mechanics to not exceed a particular mark of frames per second. Let’s go through 2 ways of doing it.

The first way the author describes is through setTimeOut, but then he writes this:

Ok, browsers cannot optimize setTimeout or setInterval. So it’s kinda better to do our own calculations and restrict the frame rate. Let’s see how.

And then he proceeds with the following code:

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();

Which does look a lot like the calculations that are being done in our code.

But why does this show up in Skype without me doing anything?

Because browsers and Javascript are literally everywhere. I just started Skype and it didn't give me an error, but it's showing me ads. My gut tells me the embedded browser that loads the ad has no handler for data URL's in your case, which is why Skype appears to give that error.

The code is really just adding an eventhandler, and making sure FPS isn't broken every time the event is called. (Switching between ads, make ads run smoothly, make loading icon run smoothly,...)

If ads exceed or go below their display time on 1 000 000, 30-second impressions, a 10 ms difference can scale incredibly fast and thus give your advertisers less or more displaytime than they pay for.

But why is it obscure?

As per @dandavis comment, there indeed is no appearant reason to obfuscate this code, it's available freely on the internet (like i linked above). However, the same embedded browser that is executing this code, might as well host a login frame for example.

We're not going to rewrite a handler for both obscure and non-obscure code when it's much easier and less bug prone to just run all code through an obfuscator if we need it once.

Chances are likely to me that the reason this is obfuscated is just a General Rule: Obfuscate all JS Code.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .