Web入门-JS逆向

JS基础

Window对象成员:

1
2
3
4
5
6
7
8
9
10
11
12
13
document Document对象
histroy History对象
location Location对象
navigator Navigator对象
screen Screen对象
scrollBy() 按指定像素值滚动内容
scrollTo() 把内容滚到指定坐标
setInerval() 定时器
setTimeout() 延时器
alert() 警示框
prompt() 对话框
open() 打开新页面
close() 关闭页面

Document对象成员:

1
2
3
4
5
6
7
8
9
10
11
12
body <body>元素
cookie 当前cookie
domain 文档域名
lastModifid 文档最后修改日期时间
referrer 访问来源
title 文档标题
URL 当前URL
getElementById() 返回指定ID的引用对象
getElementsByName() 返回指定名称对象集合
getElementsByTagName() 返回指定标签名对象集合
open() 打开流接收输入输出
wrie() 向文档输入

Navigator对象成员:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
userAgent 用户代理
AppCodeName 浏览器代码名
AppName 浏览器名
AppVersion 浏览器版本
browserLanguage 浏览器语言
cookieEnabled 是否启用cookie布尔值
cpuclass 浏览器系统cpu等级
onLine 是否处于脱机模式
platform 浏览器操作系统平台
plugins 插件
webdriver 是否启用驱动
product 引擎名
hardwareConcurrency 硬件支持并发数
connection 网络信息
javaEnabled() 是否启用Java
taintEnabled() 是否启用数据污点

Location对象成员:

1
2
3
4
5
6
7
8
9
10
11
hash URL锚
host 当前主机名和端口号
hostname 当前主机名
href 当前URL
pathname 当前URL路径
port 当前URL端口号
protocol 当前URL协议
search 设置URL查询部分
assign() 加载新文档
reload() 重新加载文档
replace() 替换当前文档

Screen对象成员:

1
2
3
4
5
6
7
8
9
10
availHeight 屏幕高度
availWidth 屏幕宽度
bufferDepth 调色板比特深度
deviceXDPI 显示屏每英寸水平点数
deviceYDPI 显示屏每英寸垂直点数
fontSmoothingEnabled 是否启用字体平滑
height 显示屏高度
pixelDepth 显示屏分辨率
updateInterval 屏幕刷新率
width 显示屏高度

History对象:

1
2
3
4
length 浏览器历史列表中URL数量
back() 加载前一个URL
forward() 加载下一个URL
go() 加载某个具体页面

Console对象:

1
2
3
4
assert() 对输入的表达式断言
count() 统计代码被执行的次数
dir() 输出Dom节点
trace() 打印Js函数调用栈

常见触发事件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
onclick 用户单击
ondblclick 用户双击
onmove 对象移动
onmoveend 对象停止移动
onmovestart 对象开始移动
onkeydown 用户按下键盘
onkeyup 用户释放键盘
onload 页面或图像被完成加载
onselect 文本被选定
onblur 元素失去焦点
onchange HTML元素改变
onfocusin 元素将要被设置为焦点前
onehlp 用户按F1
onkeypress 用户按下字面键
onmousedown 任何鼠标按钮单击
onmousemove 用户鼠标划过
onmouseover 用户在某元素上移动鼠标
onmouseout 用户在某元素上移开鼠标
onmouseup 用户在某元素上释放鼠标按钮
onmousewheel 鼠标滚轮按钮旋转
onstop 用户单击停止按钮或离开页面
onactivate 对象设为活动元素
onreadystatechange 对象上发生对象属性更改
ondragend 用户拖拽操作结束后释放鼠标

常用绑定事件方法:

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
<!--行内绑定-->
<li>
<div onclick="xxx()">
点击
</div>
</li>

<!--动态绑定-->
<script>
var xx=document.getElementById('lx');
xx.onclick=function(){}
</script>

<!--事件监听-->
<script>
var xx=document.getElementById('lx');
xx.addEventListener('click'function(){})
</script>

<!--JQuery-->
<script>
$("button").bind("click",function(){
$("p").slideToggle();
});
</script>

工具:http://cnlans.com/lx/tools

以下代码用于定位cookie的生成代码位置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
var code = function() {
var org = document.cookie._lookupSetter_('cookie');
document._defineSetter_("cookie", function(cookie) {
if (cookie.inDexOf('参数名') > -1)
debugger ;org = cookie;
});
document._defineGetter_("cookie", function() {
return org;
});
}
var script = document.createElement('script');
script.textContent = '(' + code + ')()';
(document.head || document.documentElement).appendChild(script);
script.parentNode.removeChild(script);

https://github.com/JSREI/ast-hook-for-js-RE 进行内存漫游。

webpack打包后的Js有webpack_require特征,可用https://github.com/1egoman/debundle 解包。针对打包后的Js文件有通用的函数导出方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
var lx;
!function(e){
var report={};
function o(n){
if(report[n])
return report[n].exports;
var t=report[n]={
i:n,
l:!1;
exports:{}
};
return e[n].call(t.exports,t,t.exports,o),t.l=!0,t.exports;
}
lx=0;
}({
//添加webpack模块
//"method":function(e){}
});
//调用模块函数
//var t=lx("method")

其他混淆:https://www.sojson.com/aaencode.htmlhttps://www.sojson.com/jjencode.htmlhttps://sojson.com/jsfuck.html等。

JsFuck的解码网站:http://codertab.com/JsUnFuck。

加密强度最难的一种为SoJson,JS文件开头有soJson.com.v5、jsjiami.com.v6等特征,网址:https://www.jsjiami.com/sojson.v5.html

大众点评等用隐写术将文本数据隐藏到图片中,如LSB隐写。

Javascript一些常见加密算法:

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
//Base64
var str1="lx";
var str2="bHg=";
var strToBase64=new Buffer(str1).toString('base64');
var base64ToStr=new Buffer(str2,'base64').toString();

//MD5
const CyryptoJs=require('crypto-js');
let password="lx123";
let encPwd=CryptoJs.MD5(password).toString(); //或换成SHA1
console.log(encPwd);

//HMAC-SHA256
const CryptoJs=require('crypto-js')
let key="key";
let text="lx";
let hast=CryptoJs.HmacSHA256(text,key);
let hashInHex=CryptoJs.enc.Hex.stringify(hash);
console.log(hashInHex);

//DES
const CryptoJs=require('crypto-js');
let password=CryptoJs.enc.Utf8.parse("123456");
let key=CryptoJs.enc.Utf8.parse("1234567");
cfg={
mode:CryptoJs.mode.ECB,
padding:CryptoJs.pad.Pkcs7
};
let encPwd=CryptoJs.DES.encrypt(password,key,cfg).toString();
decPwd=CryptoJs.DES.decrypt(encPwd,key,cfg).toString(CryptoJs.enc.Utf8);

//AES
let password="lx123";
let key="1234567890abcdef";
cfg={
mode:CryptoJs.mode.ECB,
padding:CryptoJs.pad.Pkcs7
}
let encPwd=CryptoJs.AES.encrypt(password,key,cfg).toString()

let key=CryptoJs.enc.Utf8.parse("1234567890abcdef");
cfg={
mode:CryptoJs.mode.ECB,
padding:CryptoJs.pad.Pkcs7
}
encPwd="+4X1GzDcLdd5yb3PiZLxdw==";
decPwd=CryptoJs.AES.decrypt(encPwd,key,cfg).toString(CryptoJs.enc.Utf8)
console.log(decPwd);

//RSA
window=global;
const JSEncrypt=require('jsencrypt');
publickey='公钥';
let jse=new JSEncrypt();
jse.setPublicKey(publickey);
var encStr=jse.encrypt('username');

privatekey='私钥';
jse.setPrivateKey(privatekey);
var Str=jse.decrypt(encStr);

Python实现为:

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
#Base64
import base64
print(base64.b64encode('lx'.encode()))
print(base64.b64decode('bHg='.encode()))

#MD5
import hashlib
m=hashlib.md5()
m.update(str.encode("utf8"))
m.hexdigest()

#HMAC-SHA356
import hmac,hashlib
key='key'.encode()
text='lx'.encode()
mac=hmac.new(key,text,hashlib.sha256)
mac.digest()
mac.hexdigest()

#DES
import binascii
from pyDes import des,CBC,PAD_PKCS5
def des_encrypt(secret_key,s):
iv=secret_key
k=des(secret_key,CBC,iv,pad=None)
en=k.encrypt(s,padmode=PAD_PCKS5)
return binascii.b2a_hex(en)
def des_decrypt(secret_key,s):
iv=secret_key
k=des(secret_key,CBC,iv,pad=None,padmode=PAD_PCKS5)
de=k.decrypt(binascii.a2b_hex(s),padmode=PAD_PKCS5)
return de
secret_str=des_encrypt('999','lx-message')
clear_str=des_decrypt('999',secret_str)

#AES
import base64
from Crypto.Cipher import AES
def add_to_16(value):
while len(value)%16!=0:
value+='\0'
return str.encode(value)
def encrypt(key,text):
aes=AES.new(add_to_16(key),AES.MODE_ECB)
encrypt_aes=aes.encrypt(add_to_16(text))
encrypted_text=str(base64.encodebytes(encrypt_aes),encoding='utf-8')
return encrypted_text
def decrypt(key,text):
aes=AES.new(add_to_16(key),AES.MODE_ECB)
base64_decrypted=base64.decodebytes(text.encode(encoding='utf-8'))
decrypted_text=str(aes.decrypt(base64_decrypted),encoding='utf-8').replace('\0','')
return decrypted_text

#RSA
import base64,rsa
from rsa import common
class RsaUtil(object):
PUBLIC_KEY_PATH='public_key.pem'
PRIVATE_KEY_PATH='private_key.pem'
def _init_(self,company_pub_file=PUBLIC_KEY_PATH,company_pri_file=PRIVATE_KEY_PATH):
if company_pub_file:
self.company_public_key=rsa.PublicKey.load_pkcs1_openssl_pem(open(company_pub_file).read())
if company_pri_file:
self.company_private_key=rsa.PrivateKey.load_pkcs1(open(company_pri_file).read())
def get_max_length(self,rsa_key,encrypt=True):
blocksize=common.byte_size(rsa_key.n)
reserve_size=11
if not encrypt:
reserve_size=0
maxlength=blocksize-reserve_size
return maxlength
def encrypt_by_pblic_key(self,message):
encrypt_result=b''
max_length=self.get_max_length(self.company_public_key)
while message:
input=message[:max_length]
message=message[max_length:]
out=rsa.encrypt(input,self.company_public_key)
encrypt_result+=out
encrypt_result=base64.b64decode(encrypt_result)
return encrypt_result
def decrypt_by_private_key(self,message):
decrypt_result=b""
max_length=self.get_max_length(self.company_private_key,False)
decrypt_message=base64.b64decode(message)
while decrypt_message:
input=decrypt_message[:max_length]
decrypt_message=decrypt_message[max_length:]
out=rsa.decrypt(input.self.company_private_key)
decrypt_result+=out
return decrypt_result
def sign_by_private_key(self,data):
signature=rsa.sign(str(data),priv_key=self.company_private_key,hash='SHA-1')
return base64.b64encode(signature)
def verify_by_public_key(self,message,signature):
signature=base64.b64decode(signature)
return rsa.verify(message,signature,self.company_public_key)

Python运行JS方法:

1
2
3
4
5
6
7
import execjs
js="""
function xxx(){
//...
}
"""
xvt_ant=execjs.compile(js).call('xxx')