大数据安全试炼2

习题牛刀小试: 找出Flag


可见提示是 hook eval 那我们就试一下,那我们就用油猴脚本hook一下

var _eval=eval;
eval=function (){
    console.log(arguments)
    return _eval(arguments)
    
}


报了一个错,不能在严格模式下运行这个脚本,那么我们就取消严格模式,并且在一开始就hook他的eval函数


出现了一个假答案,额...(哼恶趣味),输入假答案看看是啥

额过分还有检测,那就上绝招,用代理器hook一下eval函数

eval = new Proxy(eval,{
 apply(target, thisArg, argArray) {
  let result = Reflect.apply(target, thisArg, argArray)
  console.log(`function name is ${target.name}, thisArg is ${thisArg}, argArray is [${argArray}], result is ${result}.`)
  return result
 },
 construct(target, argArray, newTarget) {
  var result = Reflect.construct(target, argArray, newTarget)
  console.log(`construct function name is ${target.name}, argArray is [${argArray}], result is ${JSON.stringify(result)}.`)
  return result;
  
 }
 , get(target, p, receiver) {
  let res=Reflect.get(target, p, receiver);
  console.log(`get ${target.name} ${res}`)
  return res
 }
 ,set(target, p, value, receiver) {
  let res=Reflect.set(target, p, value, receiver);
  console.log(` set ${target.name} ${value}`)
  return res;
 }
})


让我看到了吧,调用了toString,跟进去看一下,打一个断点,f10开始

混淆了5555,看着好乱,我们就一个个的来看看它做了什么

 eval[_0x5572a4(0x132)]() === _0x5572a4(0x13d) ? window['$eval1'] = !![] : window[_0x5572a4(0x137)] = ![],
    Function[_0x5572a4(0x134)][_0x5572a4(0x132)][_0x5572a4(0x136)](eval) === 'function\x20eval()\x20{\x20[native\x20code]\x20}' ? window[_0x5572a4(0x131)] = !![] : window[_0x5572a4(0x131)] = ![];

_0x5572a4(0x132)="toString"
_0x5572a4(0x13d)="function eval() { [native code] }"
_0x5572a4(0x137)="$eval1"
_0x5572a4(0x134)="prototype"
_0x5572a4(0x132)="toString"
_0x5572a4(0x136)="call"
_0x5572a4(0x131)="$eval2"

翻译一下就是

eval["toString"]=="function eval() { [native code] }"?window['$eval1']=!![]:window['$eval1']=![]
Function['prototype']['toString']['call'](eval)==='function\x20eval()\x20{\x20[native\x20code]\x20}'?window["$eval2"]=!![]:window["$eval2"]=![]

那这样就清晰了,蓝师傅监控了toString方法和原型链上的toString方法
那么我们hook掉这两个方法就好了,最后的代码如下

    var _eval=eval;
eval=function (){
    console.log(arguments)
    return _eval(arguments)

}


eval.toString=function (){
    console.log(1111)
    return "function eval() { [native code] }"

}
Function.prototype.toString=function(){return "function eval() { [native code] }"}

接着刷新一下界面看一下

输入一下啊欢迎来到大数据安全技术学习JS课程,成功了

题目 2021年6月份JS逆向第三题

观察题目只有一个按钮点击后出现浏览器的设备指纹

查看网络请求看他有没有发包

有的那就说明是通过后端校验的,这是我们可以hook AJAX或者通过查看网络请求的调用栈来获得发包的内容,我们采用查看包的调用栈的方式来跟踪,

在app.js中跟进去看一下

this.fingerprint = this.$Encrypt.sign(e),
    p()({
        method: "post",
        url: "http://www.dtasecurity.cn:35555/subject3202106",
        data: {
            sign: this.fingerprint,
            fingerprint: window.btoa(e)
        },
        transformRequest: [function (e) {
            var t = "";
            for (var a in e)
                t += encodeURIComponent(a) + "=" + encodeURIComponent(e[a]) + "&";
            return t = t.substring(0, t.lastIndexOf("&"))
        }
        ],
        headers: {
            "Content-Type": "application/x-www-form-urlencoded"
        }

发包方式知道了,关键参数就是sign和fingerprint,先看一下sign是如何生成的,追踪进去this.$Encrypt.sign和e,e是明文的很容易就能看懂关键是sign函数我们继续跟踪

发现了md5字样菜猜测是md5算法,尝试一下,发现一模一样那么这里就是md5算法了


接着分析fingerprint也就是e是怎么来的,可以看到下面的这一行代码,那么就分析getfingerprint函数,跟踪进去

 var e = this.getfingerprint();
 getfingerprint: function () {
    var e = []
        , t = e.push.bind(e);
    return [navigator, location, history].forEach(function (e) {
        for (var a in _()(window, e),
            e) {
            var n = e[a];
            n && "string" == typeof n && t(a + ":" + n)
        }
    }),
        e.join("###")
}

getfingerprint函数非常的简单,可以通过nodejs来模拟一下,尝试补出他的环境,如下图开始补环境

let rawindexof = String.prototype.indexOf
String.prototype.indexOf = function (str) {
    var res = rawindexof.call(this, str)
    console.log(`[String] "${this}" is indexof "${str}", res is ${res}`)
    return res
}
let mydocument = {
    "head": {},
    "documentElement": {
        "getAttribute": function () {
        }
    },
    "readyState": "complete",
    "addEventListener": function () {
    },
    "createElement": function () {
        return {}
    },
    "getElementsByTagName": function (str) {
        console.log(str)
        if (str === "meta") {
            let metaRes = []
            metaRes["meta-pro"] = {
                "content": {
                    "length": 6
                }
            }
            return metaRes
        }
    }
}
let mynavigator = Object.create({
    "vendorSub": "",
    "productSub": "20030107",
    "vendor": "Google Inc.",
    "maxTouchPoints": 0,
    "userActivation": {},
    "doNotTrack": null,
    "geolocation": {},
    "connection": {},
    "plugins": {
        "0": {
            "0": {}
        },
        "1": {
            "0": {}
        },
        "2": {
            "0": {},
            "1": {}
        }
    },
    "mimeTypes": {
        "0": {},
        "1": {},
        "2": {},
        "3": {}
    },
    "webkitTemporaryStorage": {},
    "webkitPersistentStorage": {},
    "hardwareConcurrency": 4,
    "cookieEnabled": true,
    "appCodeName": "Mozilla",
    "appName": "Netscape",
    "appVersion": "5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.77 Safari/537.36",
    "platform": "Linux x86_64",
    "product": "Gecko",
    "userAgent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.77 Safari/537.36",
    "language": "zh",
    "languages": [
        "zh",
        "en-US",
        "en"
    ],
    "onLine": true,
    "webdriver": false,
    "scheduling": {},
    "mediaCapabilities": {},
    "permissions": {},
    "mediaSession": {}
});
let mysrceen = Object.create({
    height: 852,
    width: 1918,
    colorDepth: 24,
});
let mylocation = {
    "ancestorOrigins": {},
    "href": "http://www.dtasecurity.cn:11080/details?url=http%3A%2F%2Fwww.dtasecurity.cn%3A30080%2Fsubject%2F%23%2F202106subject3",
    "origin": "http://www.dtasecurity.cn:11080",
    "protocol": "http:",
    "host": "www.dtasecurity.cn:11080",
    "hostname": "www.dtasecurity.cn",
    "port": "11080",
    "pathname": "/details",
    "search": "?url=http%3A%2F%2Fwww.dtasecurity.cn%3A30080%2Fsubject%2F%23%2F202106subject3",
    "hash": ""
}
let myhistory = {
    "length": 4,
    "scrollRestoration": "manual",
    "state": {
        "key": "680.400"
    }
}

let mywindow = {
    XMLHttpRequest: function () {
    },
    sessionStorage: {},
    localStorage: {},
    navigator: mynavigator,
    scrollTo: function () {
    },
    addEventListener: function () {
    },
    attachEvent: function () {
    },
    screen: mysrceen,
    location: mylocation,
    chrome: {},
    document: mydocument,
};
let Image = function () {
};
let rawstringify = JSON.stringify;
JSON.stringify = function (Object) {
    if ((Object?.value ?? Object) === global) {
        return "global"
    } else {
        return rawstringify(Object)
    }
}

function checkproxy() {
    //Object.keys(window)
    window.a = {
        "b": {
            "c": {
                "d": 123
            }
        }
    }
    window.a.b.c.d = 456
    window.a.b
    window.btoa("123")
    window.atob.name
    "c" in window.a
    delete window.a.b
    Object.defineProperty(window, "b", {
        value: "bbb"
    })
    Object.getOwnPropertyDescriptor(window, "b")
    Object.getPrototypeOf(window)
    Object.setPrototypeOf(window, {"dta": "dta"})
    // for (let windowKey in window) {
    //     windowKey
    // }
    Object.preventExtensions(window)
    Object.isExtensible(window)
}

function getMethodHandler(WatchName) {
    let methodhandler = {
        apply(target, thisArg, argArray) {
            let result = Reflect.apply(target, thisArg, argArray)
            console.log(`[${WatchName}] apply function name is [${target.name}], argArray is [${argArray}], result is [${result}].`)
            return result
        },
        construct(target, argArray, newTarget) {
            var result = Reflect.construct(target, argArray, newTarget)
            console.log(`[${WatchName}] construct function name is [${target.name}], argArray is [${argArray}], result is [${JSON.stringify(result)}].`)
            return result;
        }
    }
    return methodhandler
}

function getObjhandler(WatchName) {
    let handler = {
        get(target, propKey, receiver) {
            let result = Reflect.get(target, propKey, receiver)
            if (result instanceof Object) {
                if (typeof result === "function") {
                    //console.log(`[${WatchName}] getting propKey is [${propKey}] , it is function`)
                    //return new Proxy(result,getMethodHandler(WatchName))
                } else {
                    console.log(`[${WatchName}] getting propKey is [${propKey}], result is [${JSON.stringify(result)}]`);
                }
                return new Proxy(result, getObjhandler(`${WatchName}.${propKey}`))
            }
            console.log(`[${WatchName}] getting propKey is [${propKey?.description ?? propKey}], result is [${result}]`);
            return result;
        },
        set(target, propKey, value, receiver) {
            if (value instanceof Object) {
                console.log(`[${WatchName}] setting propKey is [${propKey}], value is [${JSON.stringify(value)}]`);
            } else {
                console.log(`[${WatchName}] setting propKey is [${propKey}], value is [${value}]`);
            }
            return Reflect.set(target, propKey, value, receiver);
        },
        has(target, propKey) {
            var result = Reflect.has(target, propKey);
            console.log(`[${WatchName}] has propKey [${propKey}], result is [${result}]`)
            return result;
        },
        deleteProperty(target, propKey) {
            var result = Reflect.deleteProperty(target, propKey);
            console.log(`[${WatchName}] delete propKey [${propKey}], result is [${result}]`)
            return result;
        },
        getOwnPropertyDescriptor(target, propKey) {
            var result = Reflect.getOwnPropertyDescriptor(target, propKey);
            console.log(`[${WatchName}] getOwnPropertyDescriptor  propKey [${propKey}] result is [${JSON.stringify(result)}]`)
            return result;
        },
        defineProperty(target, propKey, attributes) {
            var result = Reflect.defineProperty(target, propKey, attributes);
            console.log(`[${WatchName}] defineProperty propKey [${propKey}] attributes is [${JSON.stringify(attributes)}], result is [${result}]`)
            return result
        },
        getPrototypeOf(target) {
            var result = Reflect.getPrototypeOf(target)
            console.log(`[${WatchName}] getPrototypeOf result is [${JSON.stringify(result)}]`)
            return result;
        },
        setPrototypeOf(target, proto) {
            console.log(`[${WatchName}] setPrototypeOf proto is [${JSON.stringify(proto)}]`)
            return Reflect.setPrototypeOf(target, proto);
        },
        preventExtensions(target) {
            console.log(`[${WatchName}] preventExtensions`)
            return Reflect.preventExtensions(target);
        },
        isExtensible(target) {
            var result = Reflect.isExtensible(target)
            console.log(`[${WatchName}] isExtensible, result is [${result}]`)
            return result;
        },
        ownKeys(target) {
            var result = Reflect.ownKeys(target)
            console.log(`[${WatchName}] invoke ownkeys, result is [${JSON.stringify(result)}]`)
            return result
        },
        apply(target, thisArg, argArray) {
            let result = Reflect.apply(target, thisArg, argArray)
            console.log(`[${WatchName}] apply function name is [${target.name}], argArray is [${argArray}], result is [${result}].`)
            return result
        },
        construct(target, argArray, newTarget) {
            var result = Reflect.construct(target, argArray, newTarget)
            console.log(`[${WatchName}] construct function name is [${target.name}], argArray is [${argArray}], result is [${JSON.stringify(result)}].`)
            return result;
        }
    }
    return handler;
}

const navigator = new Proxy(mynavigator, getObjhandler("navigator"));
const screen = new Proxy(mysrceen, getObjhandler("screen"));
const location = new Proxy(mylocation, getObjhandler("location"));
const document = new Proxy(mydocument, getObjhandler("document"));
const history = new Proxy(myhistory, getObjhandler("history"));
const window = new Proxy(Object.assign(global, mywindow), getObjhandler("window"));

//checkproxy()
module.exports = {
    window,
    navigator,
    screen,
    location,
    String,
    Image,
    document,
    history
}

(ps:直接用蓝师傅的环境真香哈),之前讲过就不多说了,接着我们遇到了我们的第一个错误_没定义

回到浏览器中查看一下_是个什么东西,发现到了下面这里,然后继续打断点跟踪

var n = r && r.__esModule ? function() {
            return r.default
        }

查看一下r.default是什么,是一个属性删除函数,那么这一段的逻辑就是,在浏览器上删除不到这些属性,而在nodejs上能删除这些属性,那么其实_方法是无效的我们根本不需要这个删除方法,就把他删掉就好了

可以正常运行

最后打印一下这个匿名方法

console.log((function () {
    var e = []
        , t = e.push.bind(e);
    return [navigator, location, history].forEach(function (e) {
        for (var a in e) {
            var n = e[a];
            n && "string" == typeof n && t(a + ":" + n)
        }
    }),
        e.join("###")
})());


复制上去访问一下看看能不能过

通过了,可以看到蓝师傅的环境真好用
有兴趣可以一起学习一下呀

posted on 2021-09-07 15:52  r0ysue  阅读(129)  评论(0编辑  收藏  举报