整理:抓包时,遇到JS—DES加密问题

前阵子,在奉命抓取某个网站的数据时,发现了一种前端JS加密校验DES—CBC模式。当时觉得头都大了,查了很多资料,瞎琢磨了一天,终于把它破解了,虽然方法愚蠢了点,但总算达到了目的。

JS的加密参数类似:uewZMOSGPb0Wu2KBbF5LxMcqMRzMjrAh8rGiJamd/MyKGoGRCoy4Awe7zRcO412qflhbUinG1f#2BBXlrIKGULSSU7hRYQQcJKp65YtKZH58CowbDIK7ROdFMQv3QrFqSj0pzihUkAijsgHG2UCsOE1AxkxemU/0Rd/iOw38ti0GDdexaaXsxxFnlrZrxZLzmK7zV7t0g50wblbL/TlWdv7mmPt2EiMwOAFhof7EbkPBfaw6vQ06YuKbHQQmvS24jQFw7eum6QUf9f5L2Cj5O7LGwhfNiBpcjEedpYUGJTkd6IwnKP/Z3XBKy8Ogib5zcmdcH#2B0wl1TXwotrsYzyaaWA==

好吧,确实是一段很长的密文

走个分析流程吧:

点击该网站内的查询按钮时,调用的是searchFlight这个方法:

 e.searchFlight = function() {
            var t = M(),
            n = t.replace(/\%/g, "#");
            x() && (E(), e.isBargain = !1, e.desc = n, e.pageData = T(), e.routerJson = k(), e.flights = null, e.$emit("$loading"), o.get("/pssweb/ota/flights", {
                params: {
                    //省略部分参数
                    desc: e.desc
                }
            }).success(function(t) {
                if (e.$emit("$loading-finish"), t.flihtProductList) {
                    var n = F(t.flihtProductList);
                    "OW" == e.pageData.flightWayType ? P(n) : L(n)
                }
            }).error(function() {
                e.$emit("$loading-finish")
            }))
        }

其中加密参数desc 产生的关系大概是 desc = e.desc = n = t = M();

根据M(),找到方法:

M = function() {  
            var e = (new born).getCiphertext();  
            return e  
        };  


以及下方的实现流程

window.mcArrs = [];
var m = "000215455";
window.mcArrps = [],
document.onkeypress = keypress,
document.onkeydown = keydown;
var mc = function() {
    jQuery && jQuery.mouseCollection.record(function(e) {
        var t = JSON.stringify(e.currentPoint);
        mcArrs.length < 5 ? mcArrs.push(t) : (mcArrs.shift(), mcArrs.push(t))
    })
}
function getScriptPaths() {
    m = "52D2841A3485DFFBCF2EA6A0515077CD";
    var e = document.scripts;
    return e = e[e.length - 1].src.substring(0, e[e.length - 1].src.lastIndexOf("/") + 1)
}
born.prototype = {
    getCiphertext: function() {
        return getParams()
    }
},

function getParams() {
    var e = {
        xy: mcArrs,
        fingerprint: (new referFingerprint).get()
    };
    mcArrs = [];
    var t = JSON.stringify(e),
    r = eq_u(t, m);
    return del_html_tags(r, "\\+", "%2B")
}
function eq_u(e, t) {
    var r = coypJsDk.enc.Utf8.parse(t),
    n = coypJsDk.DES.encrypt(e, r, {
        mode: coypJsDk.mode.CBC,
        padding: coypJsDk.pad.Nopk
    });
    return n.toString()
}

从以上代码已经很清晰地发现所有的加密参数, 此种js加密方式,是取得鼠标在一段时间内,经过屏幕的轨迹坐标,再借由DES加密组成一串密文。其中McArrs是鼠标轨迹坐标数组,fingerprint则是浏览器的身份(自己这么认为,啊哈哈!可以自己查询fingerprint.js了解一下),JSON.stringify就无需解释了。关键点是上方eq_u()方法的加密。

截止目前,我们所需要取到的数据便是McArrs以及fingerprint这两个参数,fingerprint可以随便取个浏览器生成,McArrs也可以利用js模拟鼠标轨迹生成。至于m这个参数,是从getScriptPaths()此方法取到的。

此时需要改动原JS,将不必要的代码去除,只留下相关加密js,然后利用Java代码(因为是利用HttpClient抓取的-_-)调用js生成加密参数即可。

给该修改后的JS添加方法:

function encryptByDESModeCBC(fingerid){  
    var t1 = Date.parse(new Date());   
    var t2 = parseInt(t1)+210;  
    var t3 = parseInt(t2)+230;   
      
    var x1 = Math.floor(Math.random()*40+30);  
    var x2 = Math.floor(Math.random()*40+30);  
    var x3 = Math.floor(Math.random()*40+30);  
      
    var y1 = Math.floor(Math.random()*40+30);  
    var y2 = Math.floor(Math.random()*40+30);  
    var y3 = Math.floor(Math.random()*40+30);  
      
    mcArrs.push("{\"x\\\":"+x1+",\\\"y\\\":"+y1+",\\\"t\\\":"+t1+"}");  
    mcArrs.push("{\"x\\\":"+x2+",\\\"y\\\":"+y2+",\\\"t\\\":"+t2+"}");  
    mcArrs.push("{\"x\\\":"+x3+",\\\"y\\\":"+y3+",\\\"t\\\":"+t3+"}");  
      
    var e = {  
        xy: mcArrs,  
        fingerprint: fingerid  
    };  
    mcArrs = [];  
    var message = stringify(e);  
    var m = eq_u(message,key);  
    return m;  
}
随机获取的x1,y1参数作为x,y坐标(选取三个 ),t1为时间戳,t2,t3的时间戳加上一些延时,达到仿真轨迹。fingerprintid 取谷歌浏览器的1814798975 (可以自己生成),利用后端JAVA代码调JS的方式:

public static String getDesc(){  
        String desc = "";  
        try {  
            ScriptEngineManager manager = new ScriptEngineManager();  
            ScriptEngine engine = manager.getEngineByName("javascript");  
            String path = FingerPrintUtil.class.getResource("/").getPath()+"service.js";  
            FileInputStream fileInputStream = new FileInputStream(new File(path));    
            Reader reader = new InputStreamReader(fileInputStream, "utf-8");    
              
            engine.eval(reader);     
      
            if(engine instanceof Invocable) {  
                Invocable invoke = (Invocable)engine;             
                desc = (String) invoke.invokeFunction("encryptByDESModeCBC", new Object[]{fingerid});  
  
            }     
            reader.close();  
            return desc;  
        } catch (FileNotFoundException e) {  
            logger.error(e.getMessage(),e);  
        } catch (ScriptException e) {  
            logger.error(e.getMessage(),e);  
        } catch (NoSuchMethodException e) {  
            logger.error(e.getMessage(),e);  
        } catch (IOException e) {  
            logger.error(e.getMessage(),e);  
        }  
        return "";  
    }

返回的desc,即是生成的密文,到这就可以进行下面的抓取工作了。

不过,不道德的开大量线程抓取数据,加大了对方服务器压力,真是罪该万死(---)。


评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值