36氪文章揭秘

311 阅读2分钟

最近有粉丝老铁私信问我,能不能分析36氪文章下逆向,粉丝的要求必然要满足,这不就来了嘛

目标地址

www.36kr.com/p/218377088…

分析页面数据来源

打开控制台,随便搜索文章内容的关键字,提示没有搜索到 右键点击显示网页源代码 都是些js代码,并没有实际的文章内容 从上面测试来看,文章属于后台加密返回的,然后再通过js解密显示而来,我们的目标就是要找到返回的加密数据&js解密函数的地方

找到js解密的地方

输入decrypt(查询,点击文件进入 格式化代码 文件中搜索decrypt(,总共3个,在出现的位置都打上断点,刷新页面 断点成功进入到我们其中的一个 打印下oe的值 oe是个对象,state的内容是密文 这里解释下这段代码

//ne是经过efabccee-b754-4c utf-8编码得到的
var ne = ee.a.enc.Utf8.parse("efabccee-b754-4c");
//oe中state存放的值就是对应的密文
var re, oe = window.initialState || {};
//判断oe的字段isEncrypt是否为True,也就是是否加密,如果加密,则调用后面的解密函数
oe.isEncrypt && (oe = JSON.parse((re = window.initialState.state,
    //这里可以看出用的AES算法进行解密的
    ee.a.AES.decrypt(re, ne, {
        mode: ee.a.mode.ECB,
        padding: ee.a.pad.Pkcs7
    }).toString(ee.a.enc.Utf8).toString())));

到代码执行完解密函数的时候,我们可以看大oe的值已经变了,现在可以看到明文了

因为用的是AES算法,我们来看下这个算法是不是标准的

输出ee.a的值,看的出来这是一个算法包,里面各种算法包都有,这种情况下99.9%是标准算法,一般我们的前端人员也不会去改写

那就可以用标准的算法库来替换

var CryptoJS = require('crypto-js')
var ne = CryptoJS.enc.Utf8.parse("efabccee-b754-4c");

state = 'xxxxx'

function get_plain(message) {
    oe = JSON.parse((re = message,
    CryptoJS.AES.decrypt(re, ne, {
        mode: CryptoJS.mode.ECB,
        padding: CryptoJS.pad.Pkcs7
    }).toString(CryptoJS.enc.Utf8).toString()));

console.log(oe['articleDetail']['articleDetailData'])
    return oe
}

console.log(get_plain(state))

这里能够输出正确的明文信息

确定返回密文的位置

  1. 首先查了返回的XHR这几个接口,并没有对应的密文数据
  2. 因为明文是window.initialState中获取的,那我们就直接全局搜索这个关键字 在页面这里发现了,这个值是藏在页面中的,并不是特地接口返回的

python通用解析密文

可以通过python程序获取页面源码 通过xpath提取window.initialState,再通过正则表达式获取具体的值 python调用js,执行对应的解密方法,获取到明文数据