js逆向-逆向基础
js逆向-逆向基础
1.1 语法基础
Js调试相对方便,通常只需要chrome或者一些抓包工具、扩展插件,就能顺利的完成逆向分析。但是Js的弱类型和语法多样,各种闭包,逗号表达式等语法让代码可读性变得不如其他语言顺畅。所以需要学习一下基础语法。
- 基本数据类型
字符串 | String |
---|---|
数字 | Number |
布尔 | Boolean |
空值 | Null |
未定义 | Undefined |
独一无二的值 | Symbol |
- 引用数据类型
对象 | Object |
---|---|
数组 | Array |
函数 | Function |
- 语句标识符
在条件为true时重复执行 | do……while |
---|---|
在条件为true时执行 | while |
循环遍历 | for |
条件判断 | if……else |
根据情况执行代码块 | switch |
退出循环 | break |
异常捕获 | try……catch……finally |
抛出异常 | Throw |
声明固定值的变量 | const |
声明类 | class |
停止函数并返回 | return |
声明块作用域的变量 | let |
声明变量 | var |
断点调试 | debugger |
当前所属对象 | this |
- 算数运算符
加 | + |
---|---|
减 | - |
乘 | * |
除 | / |
取余 | % |
累加 | ++ |
递减 | – |
- 比较运算符
等于 | == |
---|---|
相等值或者相等类型 | === |
不等于 | != |
不相等值或者不相等类型 | !== |
大于 | > |
小于 | < |
大于等于 | >= |
小于等于 | <= |
在JavaScript中将数字存储为64位浮点数,但所有按位运算都以32位二进制数执行。在执行位运算之前,JavaScript将数字转换位32位有符号整数。执行按位操作后,结果将转换回64位JavaScript数。
Javascript 函数
JavaScript 中的函数是头等公民,不仅可以像变量一样使用它,同时它还具有十分强大的抽象能力
定义函数的 2 种方式
在JavaScript 中,定义函数的方式如下:
function abs(x) {
if (x >= 0) {
return x;
} else {
return -x;
}
}
上述 abs() 函数的定义如下:
- function 指出这是一个函数定义;
- abs 是函数的名称;
- (x) 括号内列出函数的参数,多个参数以,分隔;
- {……} 之间的代码是函数体,可以包含若干语句,甚至可以没有任何语句。
请注意,函数体内部的语句在执行时,一旦执行到 return 时,函数就执行完毕,并将结果返回。因此,函数内部通过条件判断和循环可以实现非常复杂的逻辑。
如果没有 return 语句,函数执行完毕后也会返回结果,只是结果为 undefined。
由于JavaScript的函数也是一个对象,上述定义的 abs()
函数实际上是一个函数对象,而函数名 abs
可以视为指向该函数的变量。
因此,第二种定义函数的方式如下:
var abs = function (x) {
if (x >= 0) {
return x;
} else {
return -x;
}
};
在这种方式下,function(x){……} 是一个匿名函数,它没有函数名。但是,这个匿名函数赋值给了变量 abs,所以,通过变量 abs 就可以调用该函数。
注意:上述两种定义 完全等价 ,第二种方式按照完整语法需要在函数体末尾加一个 ;,表示赋值语句结束。( 加不加都一样,如果按照语法完整性要求,需要加上)
调用函数时,按顺序传入参数即可:
abs(10); // 返回10
abs(-9); // 返回9
由于JavaScript 允许传入任意个参数而不影响调用,因此传入的参数比定义的参数多也没有问题,虽然函数内部并不需要这些参数:
abs(10, 'blablabla'); // 返回10
abs(-9, 'haha', 'hehe', null); // 返回9
传入的参数比定义的少也没有问题:
abs(); // 返回NaN
此时 abs(s) 函数的参数 x 将收到 undefined,计算结果为NaN。要避免收到undefined,可以对参数进行检查:
function abs(x) {
if (typeof x !== 'number') {
throw 'Not a number'; // 停止并抛出错误信息
}
if (x >= 0) {
return x;
} else {
return -x;
}
}
1.2 作用域
Js中有一个被称为作用域的特性。作用域是在运行时代码中的某些特定部分中变量、函数和对象的可访问性。换句话说,作用域决定了代码区块中变量和其他资源的可见性。作用域最大的用处就是隔离变量,不同作用域下同名变量不会有冲突。
Js的作用域分为三种:全局作用域、函数作用域、块级作用域。全局作用域可以让用户在任何位置进行调用,需要注意的是最外层函数和在最外层函数外面定义的变量拥有全局作用域,所有未定义直接赋值的变量会自动声明为拥有全局作用域,所有window对象的属性也拥有全局作用域。函数作用域也就是说只有在函数内部可以被访问,当然函数内部是可以访问全局作用域的。块级作用域则是在if和switch的条件语句或for和while的循环语句中,块级作用域可通过新增命令let和const声明,所声明的变量在指定的作用域外无法被访问。
1.3 窗口对象属性
我们总结了浏览器window的常见属性和方法。因为很多环境监测都是基于这些属性和方法的,在补环境前,需要了解window对象的常用属性和方法。
- Window
- Window对象表示浏览器当前打开的窗口。
Document对象 | document |
---|---|
History对象 | history |
Location对象 | location |
Navigator对象 | navigator |
Screen对象 | screen |
按照指定的像素值来滚动内容 | scrollBy() |
把内容滚动到指定的坐标 | scrollTo() |
定时器 | setInterval() |
延时器 | setTimeout() |
弹出警告框 | alert() |
弹出对话框 | prompt() |
打开新页面 | open() |
关闭页面 | close() |
- Document
- 载入浏览器的HTML文档。
<body>元素 | body |
---|---|
当前cookie | cookie |
文档域名 | domain |
文档最后修改日期和时间 | lastModified |
访问来源 | referrer |
文档标题 | title |
当前URL | URL |
返回指定id的引用对象 | getElementById() |
返回指定名称的对象集合 | getElementByName() |
返回指定标签名的对象集合 | getElementByTagName() |
打开流接收输入输出 | open() |
向文档输入 | write() |
- Navigator
- Navigator对象包含的属性描述了当前使用的浏览器,可以使用这些属性进行平台专用的配置。
用户代理 | userAgent |
---|---|
浏览器代码名 | AppCodeName |
浏览器名称 | AppName |
浏览器版本 | AppVersion |
浏览器语言 | browserLanguage |
指明是否启用cookie的布尔值 | cookieEnabled |
浏览器系统的cpu等级 | cpuClass |
是否处于脱机模式 | onLine |
浏览器的操作系统平台 | platform |
插件,所有嵌入式对象的引用 | plugins |
是否启用驱动 | webdriver |
引擎名 | product |
硬件支持并发数 | hardwareConcurrency |
网络信息 | connection |
是否启用java | javaEnabled() |
是否启用数据污点 | taintEnabled() |
- Location
- Location对象包含有关当前URL的信息
URL锚 | hash |
---|---|
当前主机名和端口号 | host |
当前主机名 | hostname |
当前URL | href |
当前URL的路径 | pathname |
当前URL的端口号 | port |
当前URL的协议 | protocol |
设置URL查询部分 | search |
加载新文件 | assign() |
重新加载文件 | reload() |
替换当前文档 | replace() |
- Screen
- 每个window对象的screen属性都引用一个Screen对象。Screen对象中存放着有关显示浏览器屏幕的信息。
屏幕高度 | avaiHeight |
---|---|
屏幕宽度 | availWidth |
调色版比特深度 | bufferDepth |
显示屏每英寸水平点数 | deviceXDPI |
显示屏每英寸垂直点数 | deviceYDPI |
是否启用字体平滑 | fontSmoothingEnabled |
显示屏高度 | height |
显示屏分辨率 | pixeIDepth |
屏幕刷新率 | updateInterval |
显示屏宽度 | width |
- History
- History对象包含用户在浏览器窗口中访问过的URL。
浏览器历史列表中的URL数量 | length |
---|---|
加载前一个URL | back() |
加载下一个URL | forward() |
加载某个具体页面 | go() |
window中还有很多属性和方法,这里就不再过多的描述,大家可以自行查看。
1.4 事件
HTML 事件是发生在 HTML 元素上的事情。
当在 HTML 页面中使用 JavaScript 时, JavaScript 可以触发这些事件。
HTML 事件可以是浏览器行为,也可以是用户行为。
以下是 HTML 事件的实例:
- HTML 页面完成加载
- HTML input 字段改变时
- HTML 按钮被点击
通常,当事件发生时,你可以做些事情。
在事件触发时 JavaScript 可以执行一些代码。
HTML 元素中可以添加事件属性,使用 JavaScript 代码来添加 HTML 元素。
事件可以用于处理表单验证,用户输入,用户行为及浏览器动作:
- 页面加载时触发事件
- 页面关闭时触发事件
- 用户点击按钮执行动作
- 验证用户输入内容的合法性
- 等等 …
可以使用多种方法来执行 JavaScript 事件代码:
- HTML 事件属性可以直接执行 JavaScript 代码
- HTML 事件属性可以调用 JavaScript 函数
- 你可以为 HTML 元素指定自己的事件处理程序
- 你可以阻止事件的发生。
- 等等 …
HTML事件
事件 | 描述 |
---|---|
onclick | 当用户单击HTML元素时触发 |
ondblclick | 当用户双击对象时触发 |
onmove | 当对象移动时触发 |
onmoveend | 当对象停止移动时触发 |
onmovestart | 当对象开始移动时触发 |
onkeydown | 当用户按下键盘按键时触发 |
onkeyup | 当用户释放键盘按键时触发 |
onload | 当某个页面或图像被完成加载 |
onselect | 当文本被选定 |
onblur | 当元素失去焦点 |
onchange | 当HTML元素改变时触发 |
onfocusin | 当元素将要被设置为焦点之前触发 |
onhelp | 当用户在按F1键时触发 |
onkeypress | 当用户按下字面键时触发 |
onmousedown | 当用户用任何鼠标按钮单击对象时触发 |
onmousemove | 当用户将鼠标划过对象时触发 |
onmouseover | 当用户从一个HTML元素上移动鼠标时触发 |
onmouseout | 当用户从一个HTML元素上移开鼠标时触发 |
onmouseup | 当用户在对象之上释放鼠标按钮时触发 |
onmousewheel | 当鼠标滚轮按钮旋转时触发 |
onstop | 当用户单击停止按钮或者离开页面时触发 |
onactivate | 当对象设置为活动元素时触发 |
onreadystatechange | 当在对象上发生对象属性更改时触发 |
ondragend | 当用户拖拽操作结束后释放鼠标时触发 |
接下来说一下HTMl中绑定事件的几种方法,分别是行内绑定、动态绑定、事件监听、bind和on绑定。
- 行内绑定是指把触发事件直接写到元素的标签中
<li>
<div onclick="xxx()">点击</div>
</li>
- 动态绑定是指先获取到dom元素,然后在元素上绑定事件
<script>
var xx = document.getElementById("lx");
xx.onclick = function(){}
</script>
- 事件监听主要通过addEventListener()方法来实现
<script>
var xx = document.getElementById("lx");
xx.addEventListener("click", function(){})
</script>
- bind()和on()绑定都是属于JQuery的事件绑定方法,bind()的事件函数只能针对已经存在的元素进行事件的设置
$("button").bind("click",function(){
$("p").slideToggle();
});
- on()支持对将要添加的新元素设置事件
$(document).ready(function(){
$("p").on("click", function(){});
});
还有live()和delegate()等事件绑定方法,目前并不常用。