roysue 发表于 2021-9-7 16:06

大数据安全入门试炼2

- [习题牛刀小试: 找出Flag](#习题牛刀小试-找出flag)
- [题目 2021年6月份JS逆向第三题](#题目-2021年6月份js逆向第三题)



## 习题牛刀小试: 找出Flag

可见提示是 hook eval 那我们就试一下,那我们就用油猴脚本hook一下
```js
var _eval=eval;
eval=function (){
    console.log(arguments)
    return _eval(arguments)
   
}
```

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


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

额过分还有检测,那就上绝招,用代{过}{滤}理器hook一下eval函数
```js
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,看着好乱,我们就一个个的来看看它做了什么
```js
eval() === _0x5572a4(0x13d) ? window['$eval1'] = !![] : window = ![],
    Function(eval) === 'function\x20eval()\x20{\x20\x20}' ? window = !![] : window = ![];

```
```js
_0x5572a4(0x132)="toString"
_0x5572a4(0x13d)="function eval() { }"
_0x5572a4(0x137)="$eval1"
_0x5572a4(0x134)="prototype"
_0x5572a4(0x132)="toString"
_0x5572a4(0x136)="call"
_0x5572a4(0x131)="$eval2"
```
翻译一下就是
```js
eval["toString"]=="function eval() { }"?window['$eval1']=!![]:window['$eval1']=![]
Function['prototype']['toString']['call'](eval)==='function\x20eval()\x20{\x20\x20}'?window["$eval2"]=!![]:window["$eval2"]=![]
```
那这样就清晰了,蓝师傅监控了toString方法和原型链上的toString方法
那么我们hook掉这两个方法就好了,最后的代码如下
```js
    var _eval=eval;
eval=function (){
    console.log(arguments)
    return _eval(arguments)

}


eval.toString=function (){
    console.log(1111)
    return "function eval() { }"

}
Function.prototype.toString=function(){return "function eval() { }"}
```
接着刷新一下界面看一下

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

## 题目 2021年6月份JS逆向第三题
观察题目只有一个按钮点击后出现浏览器的设备指纹

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

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

在app.js中跟进去看一下
```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) + "&";
            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函数,跟踪进去
```js
var e = this.getfingerprint();
getfingerprint: function () {
    var e = []
      , t = e.push.bind(e);
    return .forEach(function (e) {
      for (var a in _()(window, e),
            e) {
            var n = e;
            n && "string" == typeof n && t(a + ":" + n)
      }
    }),
      e.join("###")
}
```
getfingerprint函数非常的简单,可以通过nodejs来模拟一下,尝试补出他的环境,如下图开始补环境

```js
let rawindexof = String.prototype.indexOf
String.prototype.indexOf = function (str) {
    var res = rawindexof.call(this, str)
    console.log(` "${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}] getOwnPropertyDescriptorpropKey [${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:直接用蓝师傅的环境真香哈),之前讲过就不多说了,接着我们遇到了我们的第一个错误_没定义

回到浏览器中查看一下_是个什么东西,发现到了下面这里,然后继续打断点跟踪
```js
var n = r && r.__esModule ? function() {
            return r.default
      }
```
查看一下r.default是什么,是一个属性删除函数,那么这一段的逻辑就是,在浏览器上删除不到这些属性,而在nodejs上能删除这些属性,那么其实_方法是无效的我们根本不需要这个删除方法,就把他删掉就好了

可以正常运行

最后打印一下这个匿名方法
```js
console.log((function () {
    var e = []
      , t = e.push.bind(e);
    return .forEach(function (e) {
      for (var a in e) {
            var n = e;
            n && "string" == typeof n && t(a + ":" + n)
      }
    }),
      e.join("###")
})());

```

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

通过了,可以看到蓝师傅的环境真好用
禁止AD

sam喵喵 发表于 2021-9-12 23:13

感谢分享,有没有大佬抽空写一篇有关油猴的专题文章,
带点源码之类的便于理解操作最好。

jmxhojp 发表于 2021-9-7 16:16

50加入?

推开世界的门 发表于 2021-9-7 17:01

不错不错不错

King6699 发表于 2021-9-7 18:31


不错不错不错

Wen198908 发表于 2021-9-9 17:18

挺牛逼的,感谢

linden007x 发表于 2021-9-9 21:04

看不懂,不影响喊66666666666666666666666666666666666666

3303232005 发表于 2021-9-10 16:48

牛逼666666

wf84674227 发表于 2021-9-10 23:08

好久没有来逛了,厉害厉害厉害!

tbloy 发表于 2021-9-13 01:43

来学习一下了。支持
页: [1] 2 3 4 5 6 7
查看完整版本: 大数据安全入门试炼2