首页
社区
课程
招聘
大数据安全试炼2
发表于: 2021-9-7 15:49 1191

大数据安全试炼2

2021-9-7 15:49
1191

<!-- @import "[TOC]" {cmd="toc" depthFrom=1 depthTo=6 orderedList=false} -->

 

<!-- code_chunk_output -->

<!-- /code_chunk_output -->

习题牛刀小试: 找出Flag


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

1
2
3
4
5
6
var _eval=eval;
eval=function (){
    console.log(arguments)
    return _eval(arguments)
 
}


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


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

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
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,看着好乱,我们就一个个的来看看它做了什么

1
2
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)] = ![];
1
2
3
4
5
6
7
_0x5572a4(0x132)="toString"
_0x5572a4(0x13d)="function eval() { [native code] }"
_0x5572a4(0x137)="$eval1"
_0x5572a4(0x134)="prototype"
_0x5572a4(0x132)="toString"
_0x5572a4(0x136)="call"
_0x5572a4(0x131)="$eval2"

翻译一下就是

1
2
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掉这两个方法就好了,最后的代码如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
    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中跟进去看一下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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函数,跟踪进去

1
2
3
4
5
6
7
8
9
10
11
12
13
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来模拟一下,尝试补出他的环境,如下图开始补环境

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
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:直接用蓝师傅的环境真香哈),之前讲过就不多说了,接着我们遇到了我们的第一个错误_没定义

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

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

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

可以正常运行

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

1
2
3
4
5
6
7
8
9
10
11
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("###")
})());


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

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


[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

收藏
免费 1
支持
分享
最新回复 (1)
雪    币: 1385
活跃值: (5609)
能力值: ( LV3,RANK:25 )
在线值:
发帖
回帖
粉丝
2
666666,第一个
2021-9-7 16:23
0
游客
登录 | 注册 方可回帖
返回
//