0x01 背景
前段时间玩个游戏《问道》手游,玩几天没意思想卖号,卖号期间有个游戏里边的角色,私信:“想通过其他渠道交易,平台太慢了。”
于是加上QQ联系方式就有了这篇水文~,如图:
根据“道友”提供的信息,访问到网站如图:
0x02 打击违法犯罪
经过分析,网站属实是诈骗网站(如:网易游戏的logo),初步分析漏洞挺多,但点到为止没做过多操作。(感兴趣的大佬可以搞一下试试,有结果可以私聊一起交流!)
0x03 跳转流程及前端解密
其实漏洞都比较简单,不太感兴趣,比较好奇他是怎么跳转的。
百度搜索到的网址:
https://www.girzi.cn/show/h1vIO.html (日本地区的网站,初步分析是黑灰产攻击后植入了黑页)
跳转后的网址:
http://kkmm.j1tj7z1.buzz
1)分析返回源码
请求https://www.girzi.cn/show/h1vIO.html
抓包获取,如下源码:
<script>
var __encode ='jsjiami.com',_a={}, _0xb483=["_decode","http://www.sojson.com/javascriptobfuscator.html"];(function(_0xd642x1){_0xd642x1[_0xb483[0]]= _0xb483[1]})(_a);var __Oxf777f=["0","1","2","3","4","5","6","7","8","9","a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z","A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z","(",")","","join","map","split","undefined","log","\u5220\u9664","\u7248\u672C\u53F7\uFF0Cjs\u4F1A\u5B9A","\u671F\u5F39\u7A97\uFF0C","\u8FD8\u8BF7\u652F\u6301\u6211\u4EEC\u7684\u5DE5\u4F5C","jsjia","mi.com"];function rOyeokH(_0xe722x2){let _0xe722x3={"9":__Oxf777f[0x0],"c":__Oxf777f[0x1],"e":__Oxf777f[0x2],"(":__Oxf777f[0x3],"s":__Oxf777f[0x4],"W":__Oxf777f[0x5],"Z":__Oxf777f[0x6],"y":__Oxf777f[0x7],"i":__Oxf777f[0x8],"C":__Oxf777f[0x9],"o":__Oxf777f[0xa],"2":__Oxf777f[0xb],"B":__Oxf777f[0xc],"U":__Oxf777f[0xd],"F":__Oxf777f[0xe],"I":__Oxf777f[0xf],"D":__Oxf777f[0x10],"R":__Oxf777f[0x11],"8":__Oxf777f[0x12],"O":__Oxf777f[0x13],"X":__Oxf777f[0x14],"t":__Oxf777f[0x15],"a":__Oxf777f[0x16],"J":__Oxf777f[0x17],"g":__Oxf777f[0x18],"p":__Oxf777f[0x19],"h":__Oxf777f[0x1a],"3":__Oxf777f[0x1b],"r":__Oxf777f[0x1c],"T":__Oxf777f[0x1d],"v":__Oxf777f[0x1e],"k":__Oxf777f[0x1f],"V":__Oxf777f[0x20],"Y":__Oxf777f[0x21],"E":__Oxf777f[0x22],"P":__Oxf777f[0x23],"6":__Oxf777f[0x24],"M":__Oxf777f[0x25],"G":__Oxf777f[0x26],"1":__Oxf777f[0x27],"L":__Oxf777f[0x28],"q":__Oxf777f[0x29],"z":__Oxf777f[0x2a],"7":__Oxf777f[0x2b],"4":__Oxf777f[0x2c],"A":__Oxf777f[0x2d],"f":__Oxf777f[0x2e],"b":__Oxf777f[0x2f],"5":__Oxf777f[0x30],"d":__Oxf777f[0x31],"u":__Oxf777f[0x32],"N":__Oxf777f[0x33],"K":__Oxf777f[0x34],"0":__Oxf777f[0x35],"w":__Oxf777f[0x36],"j":__Oxf777f[0x37],"H":__Oxf777f[0x38],"x":__Oxf777f[0x39],"m":__Oxf777f[0x3a],"S":__Oxf777f[0x3b],"Q":__Oxf777f[0x3c],"l":__Oxf777f[0x3d],")":__Oxf777f[0x3e],"n":__Oxf777f[0x3f]};return _0xe722x2[__Oxf777f[0x43]](__Oxf777f[0x40])[__Oxf777f[0x42]](function(_0xe722x4){return _0xe722x3[_0xe722x4]!== undefined?_0xe722x3[_0xe722x4]:_0xe722x4})[__Oxf777f[0x41]](__Oxf777f[0x40])} new Function(rOyeokH("V8JUgV.tgBoT8gJ.R3FI =\"RTTp:\/\/XXaa.OcTOyPc.2vPP\""))();(function(_0xe722x5,_0xe722x4,_0xe722x6,_0xe722x7,_0xe722x8,_0xe722x9){_0xe722x9= __Oxf777f[0x44];_0xe722x7= function(_0xe722xa){if( typeof alert!== _0xe722x9){alert(_0xe722xa)};if( typeof console!== _0xe722x9){console[__Oxf777f[0x45]](_0xe722xa)}};_0xe722x6= function(_0xe722xb,_0xe722x5){return _0xe722xb+ _0xe722x5};_0xe722x8= _0xe722x6(__Oxf777f[0x46],_0xe722x6(_0xe722x6(__Oxf777f[0x47],__Oxf777f[0x48]),__Oxf777f[0x49]));try{_0xe722x5= __encode;if(!( typeof _0xe722x5!== _0xe722x9&& _0xe722x5=== _0xe722x6(__Oxf777f[0x4a],__Oxf777f[0x4b]))){_0xe722x7(_0xe722x8)}}catch(e){_0xe722x7(_0xe722x8)}})({})
</script>
2)返回包格式化
为了方便分析,对js文件进行了格式化,得到如下代码:
<script>
var __encode = 'jsjiami.com',
_a = {},
_0xb483 = ["_decode", "http://www.sojson.com/javascriptobfuscator.html"];
(function(_0xd642x1) {
_0xd642x1[_0xb483[0]] = _0xb483[1]
})(_a);
var __Oxf777f = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "(", ")", "", "join", "map", "split", "undefined", "log", "删除", "版本号,js会定", "期弹窗,", "还请支持我们的工作", "jsjia", "mi.com"];
function rOyeokH(_0xe722x2) {
let _0xe722x3 = {
"9": __Oxf777f[0x0],
"c": __Oxf777f[0x1],
"e": __Oxf777f[0x2],
"(": __Oxf777f[0x3],
"s": __Oxf777f[0x4],
"W": __Oxf777f[0x5],
"Z": __Oxf777f[0x6],
"y": __Oxf777f[0x7],
"i": __Oxf777f[0x8],
"C": __Oxf777f[0x9],
"o": __Oxf777f[0xa],
"2": __Oxf777f[0xb],
"B": __Oxf777f[0xc],
"U": __Oxf777f[0xd],
"F": __Oxf777f[0xe],
"I": __Oxf777f[0xf],
"D": __Oxf777f[0x10],
"R": __Oxf777f[0x11],
"8": __Oxf777f[0x12],
"O": __Oxf777f[0x13],
"X": __Oxf777f[0x14],
"t": __Oxf777f[0x15],
"a": __Oxf777f[0x16],
"J": __Oxf777f[0x17],
"g": __Oxf777f[0x18],
"p": __Oxf777f[0x19],
"h": __Oxf777f[0x1a],
"3": __Oxf777f[0x1b],
"r": __Oxf777f[0x1c],
"T": __Oxf777f[0x1d],
"v": __Oxf777f[0x1e],
"k": __Oxf777f[0x1f],
"V": __Oxf777f[0x20],
"Y": __Oxf777f[0x21],
"E": __Oxf777f[0x22],
"P": __Oxf777f[0x23],
"6": __Oxf777f[0x24],
"M": __Oxf777f[0x25],
"G": __Oxf777f[0x26],
"1": __Oxf777f[0x27],
"L": __Oxf777f[0x28],
"q": __Oxf777f[0x29],
"z": __Oxf777f[0x2a],
"7": __Oxf777f[0x2b],
"4": __Oxf777f[0x2c],
"A": __Oxf777f[0x2d],
"f": __Oxf777f[0x2e],
"b": __Oxf777f[0x2f],
"5": __Oxf777f[0x30],
"d": __Oxf777f[0x31],
"u": __Oxf777f[0x32],
"N": __Oxf777f[0x33],
"K": __Oxf777f[0x34],
"0": __Oxf777f[0x35],
"w": __Oxf777f[0x36],
"j": __Oxf777f[0x37],
"H": __Oxf777f[0x38],
"x": __Oxf777f[0x39],
"m": __Oxf777f[0x3a],
"S": __Oxf777f[0x3b],
"Q": __Oxf777f[0x3c],
"l": __Oxf777f[0x3d],
")": __Oxf777f[0x3e],
"n": __Oxf777f[0x3f]
};
return _0xe722x2[__Oxf777f[0x43]](__Oxf777f[0x40])[__Oxf777f[0x42]](function(_0xe722x4) {
return _0xe722x3[_0xe722x4] !== undefined ? _0xe722x3[_0xe722x4] : _0xe722x4
})[__Oxf777f[0x41]](__Oxf777f[0x40])
}
new Function(rOyeokH("V8JUgV.tgBoT8gJ.R3FI =\"RTTp:\/\/XXaa.OcTOyPc.2vPP\""))();
(function(_0xe722x5, _0xe722x4, _0xe722x6, _0xe722x7, _0xe722x8, _0xe722x9) {
_0xe722x9 = __Oxf777f[0x44];
_0xe722x7 = function(_0xe722xa) {
if (typeof alert !== _0xe722x9) {
alert(_0xe722xa)
};
if (typeof console !== _0xe722x9) {
console[__Oxf777f[0x45]](_0xe722xa)
}
};
_0xe722x6 = function(_0xe722xb, _0xe722x5) {
return _0xe722xb + _0xe722x5
};
_0xe722x8 = _0xe722x6(__Oxf777f[0x46], _0xe722x6(_0xe722x6(__Oxf777f[0x47], __Oxf777f[0x48]), __Oxf777f[0x49]));
try {
_0xe722x5 = __encode;
if (!(typeof _0xe722x5 !== _0xe722x9 && _0xe722x5 === _0xe722x6(__Oxf777f[0x4a], __Oxf777f[0x4b]))) {
_0xe722x7(_0xe722x8)
}
} catch (e) {
_0xe722x7(_0xe722x8)
}
})({})
</script>
通过16进制转10进制[0x1]=>[1]、[0x2]=>[2],循环输出上文let _0xe722x3 中__Oxf777f[0x0]
字典对应关系,如下:
<script>
var __encode = 'jsjiami.com',
_a = {},
_0xb483 = ["_decode", "http://www.sojson.com/javascriptobfuscator.html"];
(function(_0xd642x1) {
_0xd642x1[_0xb483[0]] = _0xb483[1]
})(_a);
var __Oxf777f = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "(", ")", "", "join", "map", "split", "undefined", "log", "删除", "版本号,js会定", "期弹窗,", "还请支持我们的工作", "jsjia", "mi.com"];
var test = [__Oxf777f[0x0],
__Oxf777f[0x1],
__Oxf777f[0x2],
__Oxf777f[0x3],
__Oxf777f[0x4],
__Oxf777f[0x5],
__Oxf777f[0x6],
__Oxf777f[0x7],
__Oxf777f[0x8],
__Oxf777f[0x9],
__Oxf777f[0xa],
__Oxf777f[0xb],
__Oxf777f[0xc],
__Oxf777f[0xd],
__Oxf777f[0xe],
__Oxf777f[0xf],
__Oxf777f[0x10],
__Oxf777f[0x11],
__Oxf777f[0x12],
__Oxf777f[0x13],
__Oxf777f[0x14],
__Oxf777f[0x15],
__Oxf777f[0x16],
__Oxf777f[0x17],
__Oxf777f[0x18],
__Oxf777f[0x19],
__Oxf777f[0x1a],
__Oxf777f[0x1b],
__Oxf777f[0x1c],
__Oxf777f[0x1d],
__Oxf777f[0x1e],
__Oxf777f[0x1f],
__Oxf777f[0x20],
__Oxf777f[0x21],
__Oxf777f[0x22],
__Oxf777f[0x23],
__Oxf777f[0x24],
__Oxf777f[0x25],
__Oxf777f[0x26],
__Oxf777f[0x27],
__Oxf777f[0x28],
__Oxf777f[0x29],
__Oxf777f[0x2a],
__Oxf777f[0x2b],
__Oxf777f[0x2c],
__Oxf777f[0x2d],
__Oxf777f[0x2e],
__Oxf777f[0x2f],
__Oxf777f[0x30],
__Oxf777f[0x31],
__Oxf777f[0x32],
__Oxf777f[0x33],
__Oxf777f[0x34],
__Oxf777f[0x35],
__Oxf777f[0x36],
__Oxf777f[0x37],
__Oxf777f[0x38],
__Oxf777f[0x39],
__Oxf777f[0x3a],
__Oxf777f[0x3b],
__Oxf777f[0x3c],
__Oxf777f[0x3d],
__Oxf777f[0x3e],
__Oxf777f[0x3f]]
for (let index = 0; index < test.length; index++) {
console.log(test[index]);
}
</script>
结果如下:
function rOyeokH(_0xe722x2) {
let _0xe722x3 = {
"9":"0",
"c":"1",
"e":"2",
"(":"3",
"s":"4",
"W":"5",
"Z":"6",
"y":"7",
"i":"8",
"C":"9",
"o":"a",
"2":"b",
"B":"c",
"U":"d",
"F":"e",
"I":"f",
"D":"g",
"R":"h",
"8":"i",
"O":"j",
"X":"k",
"t":"l",
"a":"m",
"J":"n",
"g":"o",
"p":"p",
"h":"q",
"3":"r",
"r":"s",
"T":"t",
"v":"u",
"k":"v",
"V":"w",
"Y":"x",
"E":"y",
"P":"z",
"6":"A",
"M":"B",
"G":"C",
"1":"D",
"L":"E",
"q":"F",
"z":"G",
"7":"H",
"4":"I",
"A":"J",
"f":"K",
"b":"L",
"5":"M",
"d":"N",
"u":"O",
"N":"P",
"K":"Q",
"0":"R",
"w":"S",
"j":"T",
"H":"U",
"x":"V",
"m":"W",
"S":"X",
"Q":"Y",
"l":"Z",
")":"(",
"n":")"
};
进一步转换分析下文代码:
return _0xe722x2[__Oxf777f[0x43]](__Oxf777f[0x40])[__Oxf777f[0x42]](function(_0xe722x4) {
return _0xe722x3[_0xe722x4] !== undefined ? _0xe722x3[_0xe722x4] : _0xe722x4
})[__Oxf777f[0x41]](__Oxf777f[0x40])
转换后得出,如下代码段:
return _0xe722x2['split']()['map'](function(_0xe722x4) {
return arr[_0xe722x4] !== undefined ? arr[_0xe722x4] : _0xe722x4
})['join']()
PS: 知识点
由于在JavaScript中,.join('')
和['join']()
虽然看起来不同,但它们实际上是等效的,都是用于字符串拼接的方法。
.join('')
是数组对象的方法,它将数组中的所有元素连接成一个字符串,并使用指定的分隔符将它们分隔开。在这种情况下,使用空字符串''
作为分隔符,意味着没有任何字符在元素之间进行分隔,相当于将所有元素直接拼接在一起形成一个字符串。
['join']()
是通过数组对象的属性访问方式来调用join
方法。在JavaScript中,函数也是对象,因此可以通过属性访问方式来调用函数。这种方式在访问对象的属性时是很常见的,可以使用点号(.
)或者方括号([]
)来访问对象的属性。
在这种情况下,['join']()
与.join('')
是完全等效的,它们都调用了数组对象的join
方法,并传递了一个空字符串作为参数。因此,它们的结果都是将数组中的所有元素拼接成一个字符串,且没有元素之间的分隔符。
以下是一个示例,演示了.join('')
和['join']()
的等效性:
var arr = ['H', 'e', 'l', 'l', 'o'];
var result1 = arr.join(''); // 使用 .join('') 方法
console.log(result1); // 输出 "Hello"
var result2 = arr['join'](); // 使用 ['join']() 属性访问方式
console.log(result2); // 输出 "Hello"
无论是使用.
还是[]
来访问对象的属性,都可以达到相同的效果。选择使用哪种方式主要取决于个人的编码风格和偏好。
根据这一特性,上文中代码则转化为如下形式:
return _0xe722x2['split']()['map'](function(_0xe722x4) {
return arr[_0xe722x4] !== undefined ? arr[_0xe722x4] : _0xe722x4
})['join']()
return _0xe722x2.split('').map(function(_0xe722x4) {
return charMap[_0xe722x4] !== undefined ? charMap[_0xe722x4] : _0xe722x4;
}).join('');
继续往下分析,
new Function(
rOyeokH("V8JUgV.tgBoT8gJ.R3FI =\"RTTp:\/\/XXaa.OcTOyPc.2vPP\"")
)();
V8JUgV.tgBoT8gJ.R3FI =\"RTTp:\/\/XXaa.OcTOyPc.2vPP\"
则为上文rOyeokH
函数中参数_0xe722x2
,则_0xe722x2.split…可修改为:
var encodedString = "V8JUgV.tgBoT8gJ.R3FI =\"RTTp:\/\/XXaa.OcTOyPc.2vPP\"";
encodedString.split('').map(function(_0xe722x4) {
return charMap[_0xe722x4] !== undefined ? charMap[_0xe722x4] : _0xe722x4;
}).join('');
接下来代码就比较好理解了。
上文则是定义了一个变量 encodedString
,其中包含编码后的字符串。然后,使用 .split('')
将字符串拆分为单个字符的数组。接下来,使用 .map()
遍历数组中的每个字符,并对每个字符执行一个函数操作。
charMap
则为一个字符映射表,其中存储了字符的解码对应关系。对于数组中的每个字符 _0xe722x4
,它检查 charMap
对象中是否存在对应的解码字符。如果存在,就使用解码字符替换原字符;如果不存在,就保持原字符不变。
最后,使用 .join('')
将数组中的字符重新连接成一个字符串。
进一步构造代码,如下:
<script>
function decodeString(encodedString) {
let charMap = {
'9': '0',
'c': '1',
'e': '2',
'(': '3',
's': '4',
'W': '5',
'Z': '6',
'y': '7',
'i': '8',
'C': '9',
'o': 'a',
'2': 'b',
'B': 'c',
'U': 'd',
'F': 'e',
'I': 'f',
'D': 'g',
'R': 'h',
'8': 'i',
'O': 'j',
'X': 'k',
't': 'l',
'a': 'm',
'J': 'n',
'g': 'o',
'p': 'p',
'h': 'q',
'3': 'r',
'r': 's',
'T': 't',
'v': 'u',
'k': 'v',
'V': 'w',
'Y': 'x',
'E': 'y',
'P': 'z',
'6': 'A',
'M': 'B',
'G': 'C',
'1': 'D',
'L': 'E',
'q': 'F',
'z': 'G',
'7': 'H',
'4': 'I',
'A': 'J',
'f': 'K',
'b': 'L',
'5': 'M',
'd': 'N',
'u': 'O',
'N': 'P',
'K': 'Q',
'0': 'R',
'w': 'S',
'j': 'T',
'H': 'U',
'x': 'V',
'm': 'W',
'S': 'X',
'Q': 'Y',
'l': 'Z',
')': '(',
'n': ')'
};
return encodedString.split('').map(function(char) {
return charMap[char] !== undefined ? charMap[char] : char;
}).join('');
}
var decodedUrl = decodeString("V8JUgV.tgBoT8gJ.R3FI =\"RTTp:\/\/XXaa.OcTOyPc.2vPP\"");
console.log(decodedUrl)
</script>
执行测试,得出代码含义:
window.location.href ="http://kkmm.j1tj7z1.buzz"
到此,就分析结束了。
顺便吐槽一下:这个骗子也是没带脑子,本人游戏ID:゛Securityゞ