JS逆向入门教程p1 浏览器设置 常用工具

 1.准备工作

http
编程语言(网络apidavaScript)
逆向(js逆向 安卓逆向 ios逆向 PC逆向)调试
图像识别

下载城南Post助手、fiddler、wireshark(鲨鱼)抓包工具;

通过进程抓包

fiddler插件:

 f12配置推荐,实验功能全部关闭

 

 

时间线上的分配检测:js的运行时间线

关闭时间线:

 V8(JavaScript引擎) node.js=v8+js+扩展

先看值,再看对象(当看不到值,可以尝试查看对象)

程序 栈 (代码的运行流程)
a方法调用b方法

b

a
this指向  谁调用了这个方法this就是谁

Cryptojs 加密库

CryptoJS.AES.encrypt(e,c,{
iv: d,
mode: Cryptods.mede.CBC

})

RSA,一定有setMaxDigits

return setMaxDigits(131),
d = new RSAKeyPair (b,"",c)
e = encryptedString(d,a)

扣js代码,缺啥补啥

window=this;

逆向流程:抓包 分析那些参数需要逆向  下断点xhr  跟栈  扣算法 补代码  脱离浏览器运行
其他语言调用算法 (js)   封装接口供其他语言调用

2.常见加密

分享内容 (继续补基础+案例) :
工具使用 (wt-js FD F12 城南工具)
抓包与HTTP协议分析
下断与断点类型详解
F12调试相关
案例: 网易云音乐MP3逆向爬取
httpas//muaic.163.comf/aonq?id-1876909269
案例: 百度音乐NP3递向爬取逐行分析代码
http:L/Slg.com/aongAr10063553815

js弱类型
兼容 TLS强制性

post get put

发送数据:

接受数据:

 302:重定向

set-cookies

可能返回:文本 (json xml jsonP)字节数据

this  方法谁调用就是谁
arquments  方法的全部参数数组(方法可以不带参数)

call  v8引擎自带的方法  运行一个函数的  函数.call(this,参数1,参数2,参数3.··.参数N) 
apply v8写引擎自带的方法  运行一个函数的   函数.apply(this,[参数1,参数2,参数3,.·参数N])

逗号表达式 语句1,语句2,语句3 js看做一句,返回是最后一个语句

对象:  {}  obect.assign()   class   new function

var a={1,2,3,4} ,a=4

Object.assign() 方法用于将一个或多个源对象的所有可枚举属性复制到目标对象中,并返回目标对象。该方法的语法如下:Object.assign(target, ...sources)

 按ctrl,显示方法作用域

在控制台关闭警告 

 找函数作用域,看变量由哪里传进来

 

AES  明文/密文 KEY/秘钥 IV/偏移 加密模式 (CBC,ECB)

CBC需要IV
ECB不需要IV

32位sign:md5

webpack 打包js代码

下断点方式

1.用url,截取url后一段,添加xhr断点

目标网站:

https://music.163.com/weapi/song/enhance/player/url/v1?csrf_token=

2.通过js点进去 

3.在源代码,用元素断点

fiddler本地替换js代码

 

 本地修改js文件,断点要断在前面 

3.JavaScript基础

解释型语言  前后端都可以写  写游戏  也可以写wg
弱类型 类型之间的计算

基础语法

console.log(1+'1')
console.log('1'-0)
console.log(1+true)
console.log('1'+true)
a='123\
asd\
qwe'
console.log(a)

11   
1    
2    
1true
123asdqwe

对象
console.log([1,"1",true][0]  )
console.log([1,"1",true]["length"]  ) 属性方式
console.log([1,"1",true].length  )  方法
1
3
3

方法 函数 语句和逻辑  的 集合
()=>{}  箭头表达式
function xx(){
}

(function(){})   //匿名函数

调用:

(()=>{})()

function xx(){
}

xx()

function xx(){
}()

(function(){})()

a=(function(){}) 

加上()运行函数

变量定义,作用域不同:

a=1

var b=1

let c=1,在内部有效

console.log(2^3,2|3,2&3) //异或、或、与
console.log(2**3)//阶乘
1 3 2
8
function括号前加;,不然1和function会识别到一起
var a=1
;(function (){

})()

赋值运算符

变量=  !变量 值 +=

虚拟机jsvmp 是由  原子操作+栈构成
字面量  是由  原子操作 (最小操作) 构成

表达式 是由 字面量和操作符构成
语句  是由  表达式构成的
程序  是由  语句构成的

混淆的字面量
 {a:1}.a 不是一个语句,想把它变成语句,用括号括起来

({a:1})['a']

({a:1}).a

var b=['a']
;({a:1})[b[0]]

var b=['YQ==']
function c(index){
    return atob(b[index])
}    
;({a:1})[c(0)]
let day = new Date().getDay();
let dayName;

switch (day) {
  case 0:
    dayName = "Sunday";
    break;
  case 1:
    dayName = "Monday";
    break;
  case 2:
    dayName = "Tuesday";
    break;
  case 3:
    dayName = "Wednesday";
    break;
  case 4:
    dayName = "Thursday";
    break;
  case 5:
    dayName = "Friday";
    break;
  case 6:
    dayName = "Saturday";
    break;
  default:
    dayName = "Unknown";
}

console.log("Today is " + dayName);

typeof 并不能准确的返回类型
继承 (实现的功能)---原型链(原理)
 

实例  实体(最终做出的东西)       原型(设计稿)(constructor方法)对象
new 类 constructor()                   类

prototype                                      __proto__

__proto__

a.__proto__
Number {0, constructor: ƒ, toExponential: ƒ, toFixed: ƒ, toPrecision: ƒ, …}
创建对象:
function a() {
    console.log(1)
}
new a();

this谁调用的就是谁  如果是在构造函数中this是实例

https://www.91q.com/song/T10063924403

网易云音乐

网站例子

4.工具使用(编程喵插件、vscode)


F12其余功能

Web 开发技术 Web 开发技术 | MDN

hook  替换功能
FD本地替换js
funetion xx() {console.log(1)}
xx = function() {}
v8提供的API进行hook
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects
字节数组[25,45,23,65,58] uint8 0-255
[uint8,uint8,uint8,uint8] => [int32]

TextDecoder(字节数组和文本的转换)、TextEncoder、DataView(字节数组的增删改查)、wss(谷歌)

Data 时间 时区+8

Date - JavaScript | MDN

TextDecoder是一个用于将二解码受一个字符编码参数,并提供了decode()方法来将二进制数据解码字符串。

以下是一个使用TextDecoder的例子:

// 创建一个Uint8Array数组,包含UTF-8编码的二进制数据
const uint8Array = new Uint8Array([72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100]);
​
// 创建一个TextDecoder对象,指定字符编码为UTF-8
const decoder = new TextDecoder('utf-8');
​
// 使用TextDecoder解码二进制数据为字符串
const decodedString = decoder.decode(uint8Array);
​
console.log(decodedString); // 输出: "Hello World"

在上面的例子中,我们首先创建了一个Uint8Array数组,其中包了UTF-8编码的二进制数据。然后,我们创建了一个TextDecoder对象,并指定字符编码为UTF-8。最后,我们使用TextDecoder的decode方法将二进制数据解码为字符串。

TextEncoder是TextDecoder的反向操作,它用于将字符串编码为二进制数据。它提供了一个encode()方法来将字符串编码为Uint8Array数组。

以下是一个使用TextEncoder的例子:

// 创建一个TextEncoder对象
const encoder = new TextEncoder();
​
// 使用TextEncoder将字符串为二进制数据
const encodedData = encoder.encode('Hello World');
​
console.log(encodedData); // 输出: Uint8Array [ 72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100 ]

在上面的例子中,我们首先创建了一个TextEncoder对象。然后,我们使用TextEncoder的encode方法将字符串编码为二进制数据。最后,我们通过打印encodedData数组来查看编码后的二进制数据。

DataView是一个用于读取和写入二进制数据的API。它提供了一种灵活的方式来操作二进制数据,可以读取和写入不同类型的数据,如整数、浮点数等。

以下是一个使用DataView的例子:

// 创建一个ArrayBuffer对象,长度为8字节
const buffer = ArrayBuffer
// 创建一个DataView对象,关联到上面的ArrayBuffer 
const view = new DataView(buffer);

//DataView写入一个32位整数ArrayBuffer的第0字节位置 
view.setInt32(0, 42);

// 使用DataView读取ArrayBuffer的第0字节位置的32位整数 
const value = view.getInt32(0console.log(value); 
// 输出: 42

在上面的例子中,我们首先创建了一个长度为8字节的ArrayBuffer对象。然后,我们创建了一个关联到该ArrayBuffer的DataView对象。接下来,我们使用DataView的setInt32方法将一个32位整数写入ArrayBuffer的第0字节位置。最后,我们使用DataView的方法读取ArrayBuffer的第0字节位置的32位整数,并将其打印出来。
​
总结来说,TextDecoder制解码为字符串TextEncoder用于将字符串编码为二进制数据,而DataView用于取和写入二进制数据。这些API在处理二进制数据和文本数据之间的转换时非常有用。

eval() 函数会将传入的字符串当做 JavaScript 代码进行执行。

eval('debugger')
解决:
1.hook,替换js
eval=function(){}
2.在eval('debugger')语句前下断点,在控制台输入eval=function(){}
脚本
脚本的第一个语句,选上这个
脚本因内容安全政策而被屏蔽

子类  继承了  父类  吃饭
子类.吃饭
zhivuan方法  继承  Function      调用
                                                  hook 调用
zhiyuan方法.调用()

globalThis
Window {0: Window, window: Window, self: Window, document: document, name: '', location: Location, …}0: 
window
Window {0: Window, window: Window, self: Window, document: document, name: '', location: Location, …}
this
Window {0: Window, window: Window, self: Window, document: document, name: '', location: Location, …}
self
Window {0: Window, window: Window, self: Window, document: document, name: '', location: Location, …}

json  序列化 反序列化

JSON.parse()
JSON.stringify()

const jsonString = '{"name":"John", "age":30, "city":"New York"}';
const obj = JSON.parse(jsonString);
console.log(obj);

const obj1 = { name: "John", age: 30, city: "New York"};
const jsonString1 =JSON.stringify(obj1);
console.log(jsonString1); 

{name: 'John', age: 30, city: 'New York'} 对象
{"name":"John","age":30,"city":"New York"} 文本

JSON
var a; 变量
undefined  未定义
null  引用类型值为空
NaN  非数字的值

Promdse 异步 同一个线程合理的分配运行时间到不同的任务一种技术

Proxy  做hook用  加代理  无法被检测
Reflect   解代理(配套使用)
Proxy 不能被检测

a={name:123}

var a = new Proxy(a, {
  get: function(target, property, receiver) {
      return 'abc'
  }
    
});
console.log(a.name)
abc

var a = {name: 123};
var a = new Proxy(a, {
    set(target, property, value, receiver) {
        Reflect.set(target, property, "xhiyuam", receiver);
    }
});
a.name = 1;
console.log(a.name);
xhiyuam

重要:

Proxy - JavaScript | MDN

Reflect - JavaScript | MDN

symbol

Object.freeze()

Object.freeze() 静态方法可以使一个对象被冻结。冻结对象可以防止扩展,并使现有的属性不可写入和不可配置。被冻结的对象不能再被更改:不能添加新的属性,不能移除现有的属性,不能更改它们的可枚举性、可配置性、可写性或值,对象的原型也不能被重新指定。freeze() 返回与传入的对象相同的对象。

var a = {name: 123};
Object.freeze(a);
a.name=1
console.log(a.name)

var a = {name: 123};
delete(a)
false
delete(a.name)
true

document.getElementById

在浏览器代替js

视频知识点
NP4 AVI  数据长度讲行分割
断点续传 范围   运行的时候干分割的事情
N3U8   hls协议 还可以用时间分割  直播 点播
ts ts ts  提前分割文件
5s 5s 5s
加密
拿到日录  bd
.ts 地址(相对  绝对)tx
sha1:40位

知道加密算法后,找加密方法的js实现,直接在网页搜索关键词,然后下断点

hook完整过程

//保存原函数
//替换原雨数
//调用原丽数
doqument.createElement2= doeument.createElement;

document.createrlement = function(tagName) {
let e=doeument.createElement2 (tagName);
if ((tagName.toLowerCase) == 'script'){
return  new Proxy(e, {
    set(target, property, value, receiver) {
    	if(value.indexof('getVideoinfo' != -1)){
    	debugger;
    	}
        Reflect.set(target, property, "xhiyuam", receiver);
    }
});
}
	return e
}
doeument.createElement('script')

本地替换js

怎么hook:在浏览器第一次加载js的位置,在js第一行下断点,在控制台输入上面的代码 

Node.prototype.insertBefore2= Node.prototype.insertBefore;
Node.prototype.insertBefore=function(t,tt){
if(t.src!=undefined)
{
if(t.src.indexof("getvideoinfo")!=-l){
debugger;
}}
return this.insertBefore2(t,tt)
}
document.createElement("script")

5.工具使用(F12  FD  城南工具)


wss协议分析websocket

直播间  IM  即时通讯
比较占服务器的资源
http  慢  不够即时  短连接  TCP
  握手
  发请求
  返回数据
  服务器主动断开链接
websockets  长连接  TCP
    http握手  升级为websockets
    升级协议
    连接服务器wss ip:端口
    等待
socket
    数据接收
    处理粘包
    并不看数据是否全部接收完成
服务器发送  网线  电脑网卡(驱动)系统端口

1.数据缺失

2.数据多了
    一个包完整+不完整包
    多个包完整+不完整
3.数据正好

软件处理
1.固定长度100 YY
缓冲区  先存到缓冲区
2.头尾标识符 QQ
01   05
3.TLV  QQ
标识符
数据长度
数据

protobuf  谷歌数据序列化格式  字节数组 游戏
    省空间
JSON
XML

protobuf格式  代码转换
                        序列化   二进制

python  类  用户类    js  用户类
json                           json
                                 C++格式

MQTT  消息分发  消息队列 socket

订阅消息   斗地主
 

升级websockets  协议:

https://www.miguvideo.com/p/live/120000456669
101 Switching Protocols

Connection: Upgrade
Upgrade: websocket
Sec-WebSocket-Version: 13
Sec-WebSocket-Key: aHdCFL8tBIh1Pi7s1sq9gg==
Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits

FD替换js,浏览器f12打开禁止缓存

e.ws.send =function(){debugger;} 找到发送位置
或者
e.ws.send2= e.ws.send;
e.ws.send = function(a) {
console.log(a)
e.ws.send2 (a)
}

e.ws.onmessage2=e.ws.onmessage;
e.ws.onmessage=function(r){
console.log(r);
e.ws.onmessage2(r);
}
需要再new WebSocket,再输入

代码中的问题是,e.ws.send2(a)应该改为e.ws.send2.call(e.ws, a),以确保在调用原始的send方法时,正确地绑定this关键字。
e.ws.send2 = e.ws.send;
e.ws.send = function(a) {
  console.log(a);
  e.ws.send2.call(e.ws, a);
}

e.ws.onmessage2 = e.ws.onmessage;
e.ws.onmessage = function(r) {
  console.log(typeof(r.data), r.data);
  if (r.data.indexOf("compressType") !== -1) {
    debugger;
  }
  e.ws.onmessage2(r);
}

 

全局找函数在哪里定义:

protoData: 

protoData=、protoData =

或者在控制台输入e,找方法在哪里定义 

 

6.工具使用(WT-JS) 常见算法


常见算法
OB混淆 看结构
 

常见算法
对称   key   明文   相同   得出的密文也相同
TEA  32轮  KEY  IV  CBC

AES    KEY(16字节、32字节 [15]) 【确定算法内部秘钥数组的长度】IV(16字节)  mode(CBC[]key、iv]、ecb[key])

des   和AES一致

sm4(国密)node自带
非对称   key   明文   相同   得出的密文是变动的
rsa   魔值(010001)秘钥里面可能会带换行(新版谷歌打印会把换行打印为\r\n 某些浏览器会打印\n)

椭圆曲线算法 (TX PCqq密码加密)TX:TEA、椭圆曲线算法(pcqq密码)

取摘要算法   不可逆      hmac带秘钥
md5   16 32 ,少见40用于后端存数据库

sha1  40

hmac-md5  多个key

hmac-shal  多个key

rc4
编码算法
base64  a-z A-Z 0-9 + = -

自写算法

qq音乐sign

例子

e.exports = function(e) (
return new Promise(function(t, c) (
var u = e.data
, h = e.headers;

Promise.then(成功回调,失败回调)
n=n.then(t.shift(),t.shift());不能直接下断    我要跟栈直到找到一个可以确定的地方先下断
断到能确定的位置    再在此处下断    断住之后找第一个参数数组的第一个方法    此方法大概率    解密或加密方法
可以跳过异步    参与加解密
www.baidu.com/1
www.baidu.com/2
www.baidu.com/3 
www.baidu.com/4 不能确定返回的包是不是自己要的
 

调试异步
能跳过就跳过  异步调试很麻烦
遇见跳不过的   Promise.then
第一种情况:n=n.then(t.shift(),t.shift());

setMaxDigits
接口    返回了json    (JsoN.parse))->对象->["publicExponent"] ·publicExponent

//OB常量存到大数组
//有一个方法    处理大数组    得到要的值    这个方法后面跟着的就是明文代码    明文方法后面    就是反调试
//替换其他需要常量的地方    替换成函数调用
//OB平坦流 流程平坦化

//局部变量函数化
//垃圾指令
 

7、常用功能webpack、dom 和 bom

分享内容:
了解dom 和 bom
了解指纹
webpack 打包机制
webpack 原理与调试方法
案例:虎牙直播HK 指纹
 

document
#document
navigation
Navigation {currentEntry: NavigationHistoryEntry, transition: null, canGoBack: false, canGoForward: false, onnavigate: null, …}
location
Location {ancestorOrigins: DOMStringList, href: 'https://ntp.msn.com/edge/ntp?locale=zh-CN&title=%E…E5%BF%85%E5%BA%94&startpage=1&PC=NMTS&prerender=1', origin: 'https://ntp.msn.com', protocol: 'https:', host: 'ntp.msn.com', …}
history
History {length: 1, scrollRestoration: 'auto', state: null}

//v8js运行 + 渲染引擎(html+css)+浏览器开发商添加自己功能(通用功能(bom)账号,换皮肤,插件)
webkit    dom    bom
dom()
白名单[] 黑名单
浏览器指纹 bom+dom 里面一些属性的值的集合
ua  webgl(CRC md5)[webkit版木差异    生成的图片    某一些像素值存在差异]
你的ip    算指纹
代理IP    能不能被检测到    m3u8    hls(浏览器怎么实现的协议)    浏览器自带api(底层socket)
B/S HTTP/websocket TCP    c/s    3次握手    真实ip网页接口取你的IP    ip==IP
代理:HTTP/socket5/vpn
音频
本地设备(显卡信息    传感器    cpu)
判断你是否支持某些函数
document.createElement ("DIV")

document.all
HTMLAllCollection(52) [html, head, meta, meta, meta, title, script, script, script, style, link, link, link, link, link, link, body.js-focus-visible, div#ssr, script#inlinehead-inline-script, script, link, link, link, link, link, link, link, link, link, link, link, link, link, link, link, link, link, link, link, script, script, script, div#root, script, script, script, script, script, script, fluent-design-system-provider, edge-chromium-page, div#ntp-diagnostics, viewport: meta, ssr: div#ssr, inlinehead-inline-script: script#inlinehead-inline-script, root: div#root, ntp-diagnostics: div#ntp-diagnostics]
document.all == undefined
true

HTTP隐写信息    ja3 TLS    cur1版木(内部差异    压缩技术
http3(TLS加密库)
[AES+DES,RSA+DES]  交换加密套件的信息    ->    ip    host,,,,,当做指纹
明文md5

webpack
网站冗余
主页    登录    视频列表    抽奖    发评论

//登录    规频列表    js

//去除不要的功能    视频列表    简化
按需加裁(打包,下载)
//main主包
//有很多相同格式的js 子包 ( = || [] ).push

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值