醉后不知天在水,满船清梦压星河

无线debugger解决方法

  1. 浏览器debugger的原理和常见方法
(function() {var a = new Date(); debugger; return new Date() - a > 100;}())
  1. 解决方法
  • 禁用所有断点:==\>>,不能调试,适合静态分析网络请求。
  • 禁用某处断点:nerver pause none
  • 使用条件断点:false,使条件永不生效
  • 中间人工具替换特征字符串:使用fiddler、mitmproxy,修改函数
  • reres 替换本地修改过的文件:谷歌插件 reres ,在线替换js脚本
  • 重写关键函数:
    在函数声明之后,在console中重写关键函数
    或者根据堆栈找到入口函数,重写入口函数。与之相关的setInterval
    重写关键函数时,需要注意,是否需要在函数生效之前下断点,然后重写函数
Function.prototype.constructor = function(){}
//只有当下面这条语句为 true 时,在console写入上面这条语句才生效
(function(){}).constructor === Function

快速定位

  • 开发者工具全局搜索
    可以通过搜索特征参数名,或者请求url中的部分路径名。存在搜索不到的情况,当对方对js进行变量混淆,我们就搜索不到想要的结果。全局搜索不到怎么办?可以尝试查看发起者,或者下合适的断点,或尝试一些特殊hook

  • 断点调试

    • xhr断点:当某个请求含有设定的参数,就会停在该请求发起位置
    • dom断点:打上断点后,当该断点的元素属性发生变化,就会触发该断点
    • 事件监听器event:在elements页面右边有一个 event listeners,在source页面右下角也有一个event listeners面板,当发生某个特定事件,就会触发该事件断点。
  • hook技术
    当我们不知道从哪里下手时,或者大概猜测出加密方法时,可以使用hook技术对特定的属性和方法进行hook

使用execjs执行js

import execjs

with open('test.js','r') as f:
    content = f.read()
    ctx = execjs.compile(content)
    # call 方法可以传入两个参数 函数名,参数
    res = ctx.call('get_data')

print(res)

使用selenium执行js

由于execjs脱离浏览器环境,当执行的js脚本需要浏览器参数,需要手动替换。除此之外还可以直接使用selenium执行js脚本

from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait

options = webdriver.ChromeOptions()
options.add_argument('--headless')
options.add_argument('--disable-gpu')
options.add_argument('--ignore-certificate-errors')
browser = webdriver.Chrome(chrome_options=options)
wait = WebDriverWait(browser,10)

# 启动浏览器 获取网页源代码
mainUrl = ''
browser.get(mainUrl)
result = browser.execute_script('javascript 代码')

使用node开发api接口

  1. 通过nodejs写一个RPC(远程调用)服务,然后调用js。
  2. express基本使用方法

使用express开发一个api接口,供爬虫调用。扣好的js为单独的一个脚本,在该脚本最后添加

// 导出该方法,供其他模块使用
module.exports = {
    // 需要调用的方法
    encode
};

再新建一个关于express脚本,搭建服务

var express = require('express');
var app = express();
// 定义一个变量接收js模块导出的函数
var getData = require('./22.js');

app.get('/music', function(req, res) {
    // 接收所有参数
    // let text = JSON.stringify(req.query);
    let keyword = req.param('keyword');
    let text = 'text='+keyword+'&page=1&type=migu'
    // 调用加密函数
    data = getData.encode(text);
    res.send(data);
});

app.listen(3000);

使用pyppeteer执行js

from pyppeteer import launch
import asyncio

async def run():
    browser = await launch({"headless":True})
    page = await browser.newPage()
    await page.goto('http://www.dianping.com/shop/113089020')
    script = """
        const run=function(){
            return _token
        }
        run()
    """
    text = await page.evaluate(script)

    print(text)
    return text

if __name__ == '__main__':
    loop = asyncio.get_event_loop()
    loop.run_until_complete(run())
# 在页面加载前执行js,通常用于修改浏览器属性,如navigator属性
# 采集页面时的用法
result = awit page.evaluateOnNewDocument(js,*data)

颜文字混淆

  • 复制颜文字代码,在console中运行。如果报错,直接点击vm(由eval或者Function计算产生)。如果不出错,将最后一个表情删除,然后运行。或者替换为 toString。
  • 根据堆栈查看 颜文字请求 上一个请求

([,],(,),!,+)混淆

  • 代码最后如果存在(),直接运行,或者删除()
  • 代码最后不存在(),将最后一个()里的代码拿出来单独运行,很可能使用eval函数包裹该代码块

eval

eval函数的参数是一段js代码字符串,这段字符串可能经过packer打包处理,解决方法,使用console.log输出eval括号内的代码,即可得到原函数。

chrome浏览器工具

  • toggle javascript:开关浏览器js渲染

  • tampermonkey:js函数注入工具,hook

  • editthiscookie:编辑页面cookie

  • reres :该插件可以替换js文件
    使用方法:https://github.com/annnhan/ReRes

    If URL match栏,可以使用正则匹配,或者直接填写js文件地址
    Response栏,填写的是映射的响应地址。使用本地地址的方式是file:///E:/index.js,使用线上地址的方式是http://localhost:3000/xxx/index.js

aes对称加密

  1. 秘钥:支持三种长度的秘钥 128位,192位,256位,长度越长性能越差安全性越高
  2. 填充:为什么要填充?由于aes加密是分组加密,如果每组128bit,最后一组不足128bit,那么就需要对该组明文块进行填充,下面是常见填充方式
    • nopadding:不做填充,它要求明文的长度是128的整数倍
    • zeropadding:用0进行填充,但不推荐,如果明文最后一个也是0,就会解密出错
    • pkcs7padding:推荐使用。用缺少字节数作为数值,对明文进行填充
  3. 工作模式
    • ECB模式:是最简单的模式,该模式下,每一个明文块的加密都是完全独立,互不干涉。
      优点,可以进行并行计算,性能高。
      缺点,相同的明文加密后会得到相同的密文
    • CBC模式:初始向量IV。每一个明文块都要和前一个密文块进行异或操作,得到该明文块的密文块,第一个明文块就和初始向量IV进行异或
      安全性提高,但是性能下降
  4. 使用node实现
var CryptoJS = require('crypto-js');

function get_aes_decrypt(pwd,key){
    // 秘钥 json格式化
    var pwd = JSON.stringify(pwd);
    // 加密的数据转化成 128位
    var _key = CryptoJS.enc.Utf8.parse(key);
    var encryptedData = CryptoJS.AES.encrypt(pwd,_key,{
        mode:CryptoJS.mode.ECB,
        padding:CryptoJS.pad.Pkcs7
    });
    return encryptedData.ciphertext.toString();
}

var data = get_aes_decrypt({"o00o0o00o0o0o0":"eval0514undefined"},'e03163e36a107c9b');
console.log(data);
  1. 用python实现aes加密解密

js调试遇到的错误

  1. JavaScript heap out of memory
    有可能是代码反格式化,当我们格式化代码后运行,就会出现堆栈溢出或者内存不足
 // this['zIYQbj'] = function() {
 //     return 'newState'
 // };
 //FATAL ERROR: CALL_AND_RETRY_LAST Allocation failed - JavaScript heap out of memory
 this['zIYQbj'] = function() {return 'newState'};

node导入MD5

var cryptoJs = require('crypto-js');
var md5 = function(a){
    return cryptoJs.MD5(a).toString();
}

你可能感兴趣的:(醉后不知天在水,满船清梦压星河)