Javascript 作为一种用于网页交互的脚本语言而开发的,用于在网页上实现动态效果和用户交互。通过逆向,我们可以深入研究网页代码的安全性,并找出可能存在的问题。
consol 是 JavaScript 内的一个原生对象,内部存储的方法大部分都是在浏览器控制台输出一些内容,并且还提供了很多的辅助方法。
console 的功能主要在于控制台打印,它可以打印任何字符、对象、甚至 DOM 元素和系统信息
console.log( ) | info( ) | debug( ) | warn( ) | error( )
#直接打印字符,区别在于展示形态的不同
console.log('console.log');
console.info('console.info');
console.debug('console.debug');
console.warn('consolole.warn');
console.error('console.error');
可以将打印信息分类:
log() 与 info() 都对应 info,warn() 对应 warning,error() 对应 error,而 debug() 对应 verbose,因此建议在合适的场景使用合适的打印习惯,这样排查问题时也可以有针对性的筛选。
比如调试信息可以用 console.debug 仅在调试环境下输出,调试者即便开启了调试参数也不会影响正常 info 的查看,因为调试信息都输出在 verbose 中。
● %o — 对象
● %s — 字符串
● %d — 数字
如下所示,可通过占位符在一行中插入不同类型的值:
添加 CSS 样式
console.log('%c hello word','color:blue; font-size: 21px');
可以看出,console 支持输出复杂的内容,其输出能力堪比 HTML,但输入能力太弱,仅为字符串,因此采用了占位符 + 多入参修饰的设计模式解决这个问题。
console.dir()
按 JSON 模式输出。补充一句:console.log() 会自动判断类型,如果内容是 DOM 属性,则输出 DOM 树,但 console.dir 会强制以 JSON 模式输出,用在 DOM 对象时可强制转换为 JSON 输出。
for (let i=0; i < 11; i++){
clonse.log(i);
}
console.count()
count() 用来打印调用次数,一般用在循环或递归函数中。接收一个 label 参数以定制输出,默认直接输出 1 2 3 数字
console.memory
打印内存使用情况
1)解释型
2)弱类型
3)区分大小写
4)忽略换行和多余空格 (分号;代表语句结束)
在 retrun 和后面的表达式直接不能有换行
Javascript 会自动补全分号
return
true; 会解析成 return;true;
内部的JS:<script> JavaScript </script>
外部的JS:<script src="script.js" </script>
内联JS:<button onclick="createParagraph()"></button>
console.log("hello".length) //控制台输出内容(取字符串长度)
"hello".charAt(0) //得到字符串第一个字符
"hello".replace('h','a') //a替换为h 【a支持正则表达式】
"hello".toUpperCase() //转换为大写
&& 逻辑与 判断前后是否都为真
|| 逻辑或 判断前后是否有一个为真
!false = true !true = false
const pi = 3.14 //定义常量
var name = 111 //定义变量 没有作用域,如果在if里面,外部也可访问
let name = 222 //定义变量 有作用域,如果在if里面,则外部无法访问
变量可以更改,重新定义即可,常量不可改变
3+5=8 "3"+4+5=345 3+4+"5"=75
//如果开头为字符串,则全部转换为字符串 如果开头为整数型,则先相加,再转换
123=="123" 返回true 两个==会自动进行强制类型转换
123==="123" 返回false 三个===直接比较,比较数字和类型是否相等
if(条件){
语句
}else{
语句
}
while(条件){
语句
}
do(条件){
语句
}
for(var name=0;name<5;name++){
console.log(name)
}
条件 ? "yes" : "no" // 条件满足时返回yes,不满足返回no
switch(name){
case '1':
console.log('2')
case '2':
console.log('2')
default:
console.log('no')
}
对象:
var obj = new Object() //新建对象
var obj2 = {} //新建对象
obj = {
name:'xiaochen',
age:'20',
}
obj.name obj['name'] //两种调用方法
obj.name = "abc" //修改对象的值
obj.phone = "88888888" //添加对象的内容
数组:
var name = new Array() //新建数组
var name = [] //新建数组
name[0] = "xiaochen" //数组添加内容
name[5] = "20" //可直接在索引5的位置添加内容
name.push["sleep"] //在末尾添加sleep内容
name.pop() //从末尾删除一个
name.reverse() //把顺序改为倒序
name.shift() //删除第一个
name.unshift('lion') //在第一个位置添加
for(let i=0;i<a.length;i++){
console.log(a[i])
} //遍历数组:
for(let i in a){
console.log(a[i])
} //遍历数组 (如果索引有空值,则不输出,仅输出存在的值)
函数:
function add(a,b){
c = a+b
return c
}
add(1,2) //返回3
document.write('123') 当前页面输出内容
documnet.location 输出当前url
documnet.cookie 获取当前cookie
location.href='https://xz.aliyun.com/' URL跳转
有时候在触发提交表单的标签中会存在一个onClik属性,该属性的值正好是一个js函数。而这个函数往往就是我们要找的数据加密函数,我们只需要找到它定义的地方即可。Ps:如果需要调试,我们直接可以在控制台进行调试函数,这也就是前面所讲Console控制台和javascript的原因。
有了加密数据的方法名之后,再找一下该方法在那个js文件中定义,就可以定位到相关位置。
F12打开开发者工具,然后使用选择箭头选择目标标签,最后打开开发者工具Event Listeners面板。就能显示该标签对应的额事件了,只需要关注click点击事件。
ps:有时候标签是有绑定方法的,但看到Event Listeners面板却是空的。猜测是因为浏览器它没有加载完全所有的数据,导致无法分析出各个元素绑定的方法。这时我们可以进行将登录整个流程走一遍,多次刷新页面,甚至可以ctrl+s将网页保存到本地等操作,总之只为一个目的: 间接告诉浏览器赶紧将一些网页资源保存下来,以供Event Listeners分析出click事件对应的方法。
如果遇到的情况很糟糕,页面没有指定onClick方法,Event Listeners怎么操作都是空白一片,Visual Event也是半死不活的时候。这是我们就只能自己动手,丰衣足食了。当然我承认这种情况基本不可能发生。然而谁还没有个万一呢?
先将页面ctrl+s,保存起来。然后使用notepad++搜索保存目录下所有内容。这时我们就要考虑寻找搜索关键字了。搜索操作过程虽然有点繁琐,但很简单。这里我挑比较有意思的选择搜索关键字的思考跟大家分享一下。
例如:查看到源码中淘宝的登录按钮标签id值为J_SubmitStatic,于是我以#J_SubmitStatic作为关键字开始定位。
首选我们在定位的方法中打一个断点,然后在表单输入账号密码,最后点击提交。就可以进入调试模式了。进入调式模式,我们可以单步执行,梳理加密处理的每一步,找到相关的加密函数,编写脚本。
参数名称:enpassword
如果名字没有定位到js,那么class就可以定位到js
控制台下断点后再运行 按F10 F11进入
一个文件一个文件查看,一个文件全部定位的参数都下定点
选中b.val即可查看内容 为刚才提交的密码222222
加密完成后的内容为c.encrypt(b.val()),接着复制这段代码,我们自己构造一个函数,此时的b.val()就相当于我们提交的pwd
其中 a.result.modulus 和 a.result.publicExponent 就是从网页返回的值,我们去寻找这个值
寻找result,接着我们再去定义一个a数组
这个时候我们运行,发现RSAKey没有被定义,也就是说我们需要再去网页寻找加密的方法
选中j.RSAKey进入所在的代码块
可以看到定位到db函数,而db就是RSAKey的导出函数
选中最后一个 } 看最上方从哪里开始,全部复制,我们进行改写一下
提示没有,我们直接删除,结尾的括号也一样删除
再运行,我们发现c没有定义,我们也不需要c所以直接删除
我们直接调用RSAKey,把j删掉,因为上面我们已经修改定义了RSAKey=db
加载函数,即可看到加密后的值
登录地址:https://domain/
常见关键函数:entry() RSAKey(),加密字段参数 pwd
可以看到pwd直接进行的加密,我们可以直接拿来用
修改后,去寻找key_to_encode
接着去寻找encryptedString函数
改后发现缺少RSAKeyPair,发现这个参数也在刚才的js里面
我们直接把全部js复制,不调用的函数直接删掉
ok,解密成功