boss直聘zp_stoken逆向分析源码放送

1,923 阅读5分钟

1.前言

本分析过程仅供学习交流使用,切勿用于非法行为 因为前一篇文章感觉写的偏水,今天特定将整个流程重新梳理一遍,顺便开放一下源码 需要源码的关注公众号后加我微信

在这里插入图片描述

2.分析过程

2-1.寻找函数入口

在这里插入图片描述

code = (new ABC).z(seed, parseInt(ts) + (480 + (new Date).getTimezoneOffset()) * 60 * 1e3)
//这个就是函数入口
//(480 + (new Date).getTimezoneOffset()) * 60 * 1e3这一段等于0
//所以实际的函数入口就是
code = (new ABC).z(seed, parseInt(ts))

2-2.插桩暴露环境差异

插桩后在浏览器和本地运行即可看出差异

  • 插桩后浏览器端的运行效果 在这里插入图片描述
  • 插桩后本地编辑器运行的结果 在这里插入图片描述
有对nodejs的检测__filename,Buffer等等
在浏览器里面这个是undefined,而在nodejs里面这是个特定的模块

2-3.Js Proxy自吐环境

Js Proxy检测获取属性对象,走完这一步已经补完了60%左右的环境

window = new Proxy(window, {
    get: function (x, y) {
        console.log(y)
        return x[y]
    },
    set(target, p, value, receiver) {
        target[p] = value
    }
})

在这里插入图片描述

2-4.正则匹配可疑属性

Js proxy无法完全将window的属性全部获取,利用这个正则查看可疑代码,对相关对象做调试

.*\[.*\].*\(.*\)

在这里插入图片描述

2-5.hook 内置函数

因为zp_stoken是动态变化的,造成变化就是这个Math和Date对象 走到这里你已经成功了95%。

old_random=Math.random
Math.random=function(){
   console.log()
   debugger
   return old_random();
}

2-6.测试效果

通过这些操作后,以下就是补的环境,但是仍然不能实现百分之百成功,还需要操作一个细节 我们先看一下效果,会出现无法100%成功的尴尬局面,剩余补全部分请关注微信公众号获取 在这里插入图片描述

window = {
    document: {
        cookie: "",
        createElement: function (tag) {
            if (tag == "canvas") {
                return canvas
            } else if (tag == "caption") {
                return {
                    tagName: "CAPTION"
                }
            }

        },
        getElementById: function (a, b, c, d) {
            return false
        },
        getElementsByName: function (a, b, c, d) {
            return false
        },
        getElementsByTagName: function (a, b, c, d) {
            return false
        },
        getElementsByClassName: function (a, b, c, d) {
            return false
        },
        title: ""
    },
    moveBy: function () {
    },
    moveTo: function () {
    },
    open: function () {
    },
    dispatchEvent: function () {
        return true
    },
    screen: {
        availHeight: 824,
        availWidth: 1536
    },
    location: {
        host: "www.zhipin.com",
        hostname: "www.zhipin.com",
        href: "https://www.zhipin.com/c101280100-p100101/",
        origin: "https://www.zhipin.com",
        pathname: "/c101280100-p100101/",
        toString: function () {
            return "https://www.zhipin.com/"
        }
    },
    decodeURI: decodeURI,
    OfflineAudioContext: function () {
        this.createOscillator = function () {
            return {
                frequency: {
                    setValueAtTime: function () {
                    }
                },
                connect: function () {
                },
                start: function () {
                },
            }
        },
            this.createDynamicsCompressor = function () {
                return {
                    threshold: {
                        setValueAtTime: function () {
                        },
                    },
                    setValueAtTime: function () {
                    },
                    knee: {
                        setValueAtTime: function () {
                        },
                    },
                    ratio: {
                        setValueAtTime: function () {
                        },
                    },
                    reduction: {
                        setValueAtTime: function () {
                        },
                    },
                    attack: {
                        setValueAtTime: function () {
                        },
                    },
                    release: {
                        setValueAtTime: function () {
                        },
                    },
                    connect: function () {
                    },
                }
            },
            this.startRendering = function () {
            }
    },
    history: {
        "length": 2,
        "scrollRestoration": "auto",
        "state": null
    },
    // outerHeight: 824,
    // innerHeight: 150,
    // outerWidth: 1536,
    // innerWidth: 0,
    outerHeight: 28,
    innerHeight: 0,
    outerWidth: 160,
    innerWidth: 0,
    Math: Math,
    Date: Date,
    encodeURIComponent: encodeURIComponent,
    RegExp: RegExp,
    length: 0,
    ScreenOrientation: function () {
    },
    onmessage: null,
    performance: {},
    speechSynthesis: {
        paused: false,
        pending: false,
        speaking: false,
        getVoices: function () {
        },
        speak: function () {
        }
    },
    SourceBuffer: function () {
        return {
            mode: "",
            appendWindowStart: "",
            audioTracks: "",
            buffered: "",
            textTracks: "",
            toString: function () {
                return "function SourceBuffer() { [native code] }"
            }
        }
    },

    XMLHttpRequest: function () {
        return {
            readyState: "",
            response: "",
            responseText: "",
            responseURL: "",
            responseXML: "",
            statusText: "",
            toString: function () {
                return "function XMLHttpRequest() { [native code] }"
            }
        }
    },
    SpeechSynthesisUtterance: function () {

    },
    toString: function () {
        return "[object Window]"
    },

}
scrollBy = function () {

}
scrollBy.toString=function(){
    return "function scrollBy() { [native code] }"
}
window.scrollBy=scrollBy
scrollTo = function () {

}
scrollTo.toString=function(){
    return "function scrollTo() { [native code] }"
}
window.scrollTo=scrollTo
window.open.toString = function () {
    return "function open() { [native code] }"
}

OfflineAudioContext = window.OfflineAudioContext
canvas = {
    getContext: function () {
        return CanvasRenderingContext2D
    },
    toDataURL: function () {
        // 实际为canvas画布填充了图片
        return "data:image/png;base64,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"
    },
}
CanvasRenderingContext2D = {
    fillRect: function () {
    },
    fillText: function () {
    }
}
localStorage = {
    removeItem: function (key) {
        delete this[key]
    },
    getItem: function (key) {
        return this[key] ? this[key] : null;
    },
    setItem: function (key, value) {
        this[key] = "" + value;
    },
};
sessionStorage = {}
document = window.document
window.navigator = navigator = {
    cookieEnabled: true,
    language: "zh-CN",
    appCodeName: "Mozilla",
    appName: "Netscape",
    userAgent: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.61 Safari/537.36",
    appVersion: "5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.61 Safari/537.36"

}

window.sessionStorage = sessionStorage
window.localStorage = localStorage
setInterval = window.setInterval = function () {
    debugger;
}
setInterval.toString = function () {
    return "function setInterval() { [native code] }"
}
setTimeout = window.setTimeout = function () {

}
setTimeout.toString = function () {
    return "function setTimeout() { [native code] }"
}
clearTimeout = window.clearTimeout = function () {

}
clearTimeout.toString = function () {
    return "function clearTimeout() { [native code] }"
}
top = window.top = window
self = window.self = window
window.window = window
child_process = undefined;
closed = {
    __proto__: (1 >> 3 > 4)["__proto__"]
}
screenTop = {
    __proto__: (2)["__proto__"]
}
Function.prototype.toString = function () {
    return "function () { [native code] }";
}
Object.keys(window).forEach(property => {
    try {
        if (typeof global[property] === 'undefined') {
            global[property] = window[property];
        }
    } catch (e) {
        // console.log(e);
    }
});
global.window = window;
global = undefined;
global = window
process.argv = undefined;

最终效果

100%成功 在这里插入图片描述 剩余步骤请关注公众号获取 在这里插入图片描述