built-in
unescape
Function
eval
Array
Object
Date
RegExp
indexOf
hasOwnProperty
decodeURIComponent encodeURI encodeURIComponent
Math 、round 、 random、parseInt 等强制转换
shift、pop、push、unshift
slice、splice、split、substring、substr、concat
String 、 fromCharCode、 charCodeAt
atob 、btoa、Uint8Array、 ArrayBuffer、 Int32Array、 Int16Array
setTimeout 、setInterval、 clearTimeout
- js加密,数组偏移等一些骚操作,就是通过push,unshift等一些列操作合成加密,如有一个数据表 [‘data’,‘data2’],那么正常来说[0]代表值就是"data",那么从服务端返回数据后,如[0,1] 进行数组偏移 +500 [500,501] ,然后,仅仅凭这个数组,根本不知道索引的数据表值是什么
- 自实现eval函数等都会用到,比如,将一个函数复制给一个变量c,那么
eval(c)就调用了函数 - 了解定时器,可能存在,定时更新cookie等操作,就得观察定时器函数
- 加密请求参数,url,等操作也是,需要调试看懂,可以通过非指纹built-in方法
-
unescape:解码方法ECMAScript v3 已从标准中删除了 unescape() 函数,并反对使用它,因此应该用 decodeURI() 和 decodeURIComponent() 取而代之
unescape('hello%20稳稳%21') -
Function:函数实例方法var fun = new Function("a", "return a") //前面是形参,后面是返回的内容 //等价于 function fun(a){ return a } -
eval:把字符串当做js代码执行,并且会执行一个虚拟机eval('alert("12312312")') //eval('debuger; alert("12312312")') -
Array:数组对象arr = new Array() -
Object:对象person = new Object() -
Date:内置时间方法Date() "Tue Jul 06 2021 22:33:02 GMT+0800 (中国标准时间)" a = new Date() // 实例化一个对象 Tue Jul 06 2021 22:33:09 GMT+0800 (中国标准时间) a.getDate() // 实例化对象后,可以使用对象的内置方法 6 -
RegExp:正则匹配的方法https://www.runoob.com/jsref/jsref-obj-regexp.html
常用 test()判断是否符合要求,返回True或者false exec()返回数组形式 match()返回第一个匹配对象//1、定义正则对象,qq邮箱 var re = /^\d{5,12}@qq\.com$/ //2、test true,false console.log(re.test("1243324@qq.com")) console.log(re.test("12d43324@qq.com")) var msg = "hello1,world2" var re = /[a-zA-Z]+/ console.log(re.exec(msg)) //字符串中也有方法支持正则,比如match var msg = "hello1,World2" // i忽略大小写,g全局 console.log(msg.match(/[a-z]+/ig)) -
indexof:会返回索引值indexOf() 方法可返回某个指定的字符串在字符串中首次出现的位置
indexOf() 方法可返回某个指定的字符串在字符串中首次出现的位置
数组使用arr = ['cookie', 'ck', 'cck'] arr.indexOf('cookie') //会返回cookie的索引值 0字符使用
var str="Hello world, welcome to the universe."; var n=str.indexOf("welcome"); //13 -
hasOwnProperty:检测一个属性是否是一个对象的自有属性function F(){ this.name = "自有属性" } F.prototype.name = "继承属性" var f = new F() f.hasOwnProperty("name") //True -
decodeURIComponent、encodeURI、encodeURIComponent:加密解密encode('a 2') // -> a%202 decodeURIComponent('a%202') // ->'a 2' -
Math:Math.random四舍五入Math.round取整保留Math.round(0.5) // -> 1 -
parseInt:数据类型转换,还有很多parseInt('1555') // -> 1555 parseInt(15.55) // -> 15 parseInt('15.55') // -> 15 -
Array:相关操作- unshift:在数组前面添加一个元素
- shift:删除数组内指定元素,若有多个相同的,默认删除第一个
- pop:删除数组最后一个元素,并返回这个元素
- concat:合并数组并返回,可以传参多个数组,没有去重功能
var arr = new Array() arr.push(4) arr.push(3) arr.push(2) arr.push(1) -->[4,3,2,1] arr2 = arr.concat(arr1, ar3) //合并数组,没有去重功能 -
String:字符串操作- 拆分:slice、splice、split (splice改变原数组,slice:不改变原数组)
- 查找:substring、substr
- 合并:concat
拆分
// slice() 提取字符串的某个部分并在新字符串中返回被提取的部分。 var str = "Apple, Banana, Mango"; var res = str.slice(7,13); //Banana // splice() 指定起始位,删除位置,插入数据 var arr = new Array(6) arr[0] = "George" arr[1] = "John" arr[2] = "Thomas" arr[3] = "James" arr[4] = "Adrew" arr[5] = "Martin" arr.splice(2,3,"William") // split() 方法用于把一个字符串分割成字符串数组 var str="How are you doing today?" console.log(str.split(" ")) //How,are,you,doing,today? console.log(str.split("")) // H,o,w, ,a,r,e, ,y,o,u, ,d,o,i,n,g, ,t,o,d,a,y,? console.log(str.split(" ",3)) // How,are,you查找
// substring() substring() 类似于 slice()。不同之处在于 substring() 无法接受负的索引。 var str = "Apple, Banana, Mango"; var res = str.substring(7,13);// Banana // substr() 类似于 slice()。不同之处在于第二个参数规定被提取部分的长度。 var str = "Apple, Banana, Mango"; var res = str.substr(7,6);//Banana合并
//concat() 连接两个或多个字符串 var text1 = "Hello"; var text2 = "World"; text3 = text1.concat(" ",text2); -
fromCharCodecharCodeAt:字符串与ascii码转换charCodeAt:把字符串转为ascii码 fromCharCode:把ascii码转变为字符串 -
atobbtoaUint8ArrayArrayBufferInt32ArrayInt16Array:与加密有关btoa -> binary to ascii //编码操作 atob -> ascii to binary //解码操作 -
setTimeout、setInterval、clearTimeout:定时器// setTimeout:延迟多少多少秒时间执行一次 // setInterval:按照时间间隔一直执行 // clearTimeout:清除定时器 setTimeout(function(){}, 500)
二、三元表达式:
js加密很多手段,会借助三元表达式,进行操作,让读的人非常困难
条件 ? 为正返回结果:为假返回结果
a > b ? c : d // a 大于 b 吗?大于的话返回c,反之 d
- 基本的使用
- 稍微加深
- 一般来算,三元表达式会多嵌套使用,就算俄罗斯套娃~~
二层嵌套 x = a > 10 ? 1 : a > 1 ? 2 : 3
三层嵌套 x = a > 10 ? 1 : a > 1 ? 2 : a > -5 ? 3:4
三层嵌套加赋值 a = a > 10 ? 1 : a > 1 ? 2 : a > -5 ? 3:4
三层嵌套加赋值加函数调用 错误情况1
function a(a){ a *= a};
a = a() > 10 ? 1 : a > 1 ? 2 : a > -5 ? 3:4
三层嵌套加赋值加函数正常调用 错误情况2
function a(a){ a *= a};
a = a(4) > 10 ? 1 : a > 1 ? 2 : a > -5 ? 3:4
三层嵌套加赋值加函数正常调用 正确情况
function a(a){ return a *= a};
a = a(4) > 10 ? 1 : a > 1 ? 2 : a > -5 ? 3:4
三、函数内的内置arguments参数
简单来说:
arguments 是一个对应于传递给函数的参数的类数组对象arguments 对象是所有(非箭头)函数中都可用的局部变量。你可以使用arguments
对象在函数中引用函数的参数。此对象包含传递给函数的每个参数,第一个参数在索引0处。例如,如果一个函数传递了三个参数,你可以以如下方式引用他们:arguments.callee:指向当前执行的函数(在 严格模式 下,第5版 ECMAScript (ES5) 禁止使用)
argunments.length:指向传递给当前函数的参数数量在
严格模式下,剩余参数、默认参数和解构赋值参数的存在不会改变 arguments对象的行为,但是在非严格模式下就有所不同了
- 这种加密情况,就是想混淆返回
- 其实ES6给了新的rest参数,用在函数最后,多余的参数以数组的形式交给变量rest,如果传入的参数未填满函数定义的参数,rest会是一个空数组,这种也能做手脚
function exm(a, b, ...rest) {
console.log('a = ' + a);
console.log('b = ' + b);
console.log(rest);
}
exm(1, 2, 3, 4, 5);
// 结果:
// a = 1
// b = 2
// Array [ 3, 4, 5 ]
exm(1);
// 结果:
// a = 1
// b = undefined
// Array []
四、位运算符和逻辑运算符
-
位运算符有 7 个,分为两类:
- 逻辑位运算符:位与(&)、位或(|)、位异或(^)、非位(~)
- 移位运算符:左移(<<)、右移(>>)、无符号右移(>>>)
1、位运算符


2、逻辑运算符

3、jsfuck
https://www.jianshu.com/p/e7246218f424
false => ![]
true => !![]
undefined => [][[]]
NaN => +[![]]
0 => +[]
1 => +!+[]
2 => !+[]+!+[]
10 => [+!+[]]+[+[]]
Array => []
Number => +[]
String => []+[]
Boolean => ![]
Function => []["filter"]
eval => []["filter"]["constructor"]( CODE )()
window => []["filter"]["constructor"]("return this")()
那么有些混淆加密
+!+[]
1
a = 'abcd'
"abcd"
eval(a[+[]] + 'lert(111)')

五、js混淆,伪代码,操作都有哪些
那么通过文章,一、二、三、四小节可以引出以下(不完全)的混淆加密方法,骚操作
- 自执行函数嵌套执行 function(a, b){}(fn1,fn2)
- 变量名混淆:_0x319289 _$SW Oo0o00o0 a b c
- 函数名与不一致原因(1.构造函数、2. 重新赋值)
- 三元表达式嵌套
- 控制流平坦化
- 打包
- 魔改加密包
- 重构解释器
- 剩下后面文章
1. 自执行函数嵌套执行 function(a, b){}(fn1,fn2)
利用fn1,fn2两个函数的返回值当做a,b传入进去
2、变量名混淆
一般都不用管,直接分析也可以
可以通过AST,递归就能解决
3、函数名不一致(1.构造函数 2.重新复制)

那么如何确定呢,就通过 new c( 这样的方式去找函数入口,不一定找的到
4、三元表达式
前面提到了
5、流程平
6、打包
现在很多JavaScript代码的发展,很多都不是自己写的,都是用原生的,就是单纯的打包,提高运行速度,自带了一些混淆,
导致分析增加难度
7、控制流平坦化
将简单的流程复杂化,跳来跳去
简单的控制流:
- 常见if
- switch
程序自顶向下运行,执行的顺序很平坦,不会来回跳跃
function abc(){
a = 1;
a = a+1;
a = a + 123;
console.log(a);
}
undefined
abc() // 125

将简单的事情复杂化

8、 重构解释器
对js的内置的方法,进行了重改,国内网站很少见到
六、JS反爬原理
1、反爬虫设计要求
(风控爬虫,既一个用户不可能在一个小时内,访问上百万次,不同类型店铺)
反爬虫的两大基本要求和问题:
- 让浏览器正常访问
- 让爬虫脚本无法访问
- 不影响用户体验
- 能严重阻止爬虫工程师的编程难度
那么从爬虫,执行脚本程度要处理到发送请求,拿到数据
对于浏览器而言,就需要将请求响应后的数据,通过css+js渲染执行到浏览器显示,因此在这些部分就能做很多操作

2、JS反爬手段的特点
- cookie加密
翻页,或者一定条件,出现set-cookie操作,或者刷新cookie - 参数加密
翻页的时候url参数是变化的,url加密,每次fiddler重放攻击还不行,比如url拼接了一个奇怪的参数 - headers加密
明显反爬特点:sign safe,abcde 乱码等 fnesewq123
七、爬虫逆向方法论
本篇文章结合前面两篇文章
爬虫(js逆向)网络基础协议与抓包原理-chrome开发工具-fiddler抓包-重放攻击(1)
https://blog.csdn.net/weixin_44238683/article/details/118468491
爬虫(js逆向)js基础-函数进阶-原型链(prototype、proto、构造函数-this绑定对象(2)
https://blog.csdn.net/weixin_44238683/article/details/118503753
得出如下结论:
目标数据接口,进行重放攻击(重复请求)
- 重放攻击成功
- 成功,自行模拟其它参数再请求同一个,成功略过,
- 失败原因(IP检测、模拟请求参数格式错误、等等,后续完善此方法论)
- 一段时间内成功【是否请求url拼接的参数有变化,就要寻找加密参数,刷新cookie?headers中某个字段变化生成?XX参数等等】
- 重放攻击失败
- 寻找加密参数

本文转自 https://blog.csdn.net/weixin_44238683/article/details/118530864,如有侵权,请联系删除。