网易云参数解析(多图)

网易云参数分析

工具:python3.6.6、火狐 、chrome、node.js

  • 网易云参数分析
  • 查找关键字定位到js文件
  • AES加密
  • 尝试发送
  • 结尾:

最近在学习linux相关的时候,突然有人叫我给他 做个下载网易云的程序,因为
不懂使用脚本,所以打算给他写成一个安卓app,其中在写搜索歌曲的界面时,突然想到,自动补全提示,所以就在网页做个分析,发现是post 两个参数encSecKey跟params,在网上我也参考了很多前辈的方法,但是网易好像有了些修改,在这里我会使用图片跟着教程一步一步解析
网易云参数解析(多图)_第1张图片

查找关键字定位到js文件

什么找我就不说了,我使用的两个浏览器,火狐跟chrome,为什么使用这两个,主要是火狐能够编辑重发,这一点我觉扽很好,不需要我们写代码调试,至于为什么用chrome,我的火狐好像配置问题,js调试断点不起作用

网易云参数解析(多图)_第2张图片

根据函数定位向上寻找函数d,并添加断点进行调试,可以发现d、e、f、g四个参数只有d是变化的,”{\”s\”:\”s\”,\”limit\”:\”8\”,\”csrf_token\”:\”\”}”(这是照抄我的程序上面的,我发送的数据是s,要求返回的是8,这也可以换成下载音乐的查询格式,或者是评论歌词都可以)还有下面的encSecKey的几个参数除了(e、f)也是固定值。

function d(d, e, f, g) {
    var h = {},
    i = a(16);
    return h.encText = b(d, g),
    h.encText = b(h.encText, i),
    h.encSecKey = c(i, e, f),
    h
    }

继续跟踪a函数可以定位到一个生成16位的随机数
有兴趣的同学可以使用node.js运行,但是这里就不需要了,先前我也是做了无用功,后经大佬点悟,用到参数 i 的就是params跟encSecKey的验证,只要固定死了了 i 那么,encSecKey也就是固定值了,但是我不敢肯定在服务端会不会有判断同一encSecKey访问而禁止IP。所以要是有大数的访问的话还是推荐使用encSecKey池

AES加密

一下子就解决了encSecKey跟i感觉也不是很难,继续。。。。
parm追踪到 b 函数进行两次运算,我们重新看一下参数,d是我们发送的数据,g是一常量,看看b函数到底做了什么

function b(a, b) {
var c = CryptoJS.enc.Utf8.parse(b),
d = CryptoJS.enc.Utf8.parse('0102030405060708'),
e = CryptoJS.enc.Utf8.parse(a),
f = CryptoJS.AES.encrypt(e, c, {
iv: d,
mode: CryptoJS.mode.CBC
});
return f.toString()
}

看到这里先不管前面几个运算是做什么,但是看到.mode.CBC 会不会有种熟悉的感觉?没错就是大名鼎鼎的AES的CBC,惊不惊喜意不意外,那么前面应该就是补位函数了,看函数的名字也越来越像了
我们先进行一下尝试,毕竟推断也只是推断,只有检验才是真理的唯一标准。

ps:关于crypto库的安装,还是自行解决,不会很难

from Crypto.Cipher import AES
import base64

#补全16的整数倍,要求bytes
def contentEndo(content):
    content=content.encode('utf-8')
    while len(content) % 16 != 0:
        content += '\0'.encode('utf-8')#以0补全
    return (content)
#进行AES加密
def AESencrypt(key, content):
    key = contentEndo(key)
    iv = b'0102030405060708'
    encryptor = AES.new(key, AES.MODE_CBC, iv)
    encrypt = encryptor.encrypt(content)
    encrypt = base64.b64encode(encrypt)
    return bytes.decode(encrypt)

content ="{\"s\":\"s\",\"limit\":\"8\",\"csrf_token\":\"\"}"
key = "0CoJUm6Qyw8W8jud"
content = contentEndo(content)
en =AESencrypt(key,content)
print(en)

得到的是,好像跟我们调试的有一点点不一样

f5Lcudct4ZaW6sHL3WNKrqGGzqLedMMO1DN2CDPnLFC55pGM7XlcfLr5RfVCzCai

网易云参数解析(多图)_第3张图片

不过至少成功了一半吧,将标准的加密串进行解密

def decrypt(text):
    key = "0CoJUm6Qyw8W8jud".encode('utf-8')
    cryptor = AES.new(key, AES.MODE_CBC, b'0102030405060708')
    text = base64.decodestring(text.encode('utf-8'))
    plain_text = cryptor.decrypt(text)
    print (plain_text)
b'{"s":"s","limit":"8","csrf_token":""}\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b'

网易云参数解析(多图)_第4张图片
原来补位字符是这样的啊,把\0换成\x0b,就得到正确的

只要在结合随机数i进行第二次加密就可以得到真正的param
但是同样的还是会出现加密串最后的有一点点不一样,同样通过解密得到补位的字符,因为加密后都是64位我就使用字符串拼接再进行加密

en =AESencrypt(key,content)+'\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10'

,还有一点,就是最后的需要进行URL转换



from Crypto.Cipher import AES
import urllib.parse
import base64


#补全16的整数倍,要求bytes
def contentEndo(content):
    content=content.encode('utf-8')
    while len(content) % 16 != 0:
        content += '\x0b'.encode('utf-8')#配合解密函数寻找补位字符
    return (content)

#进行AES加密
def AESencrypt(key, content):
    key = contentEndo(key)
    iv = b'0102030405060708'
    encryptor = AES.new(key, AES.MODE_CBC, iv)
    encrypt = encryptor.encrypt(content)
    encrypt = base64.b64encode(encrypt)
    return bytes.decode(encrypt)

def makeData():
    content ="{\"s\":\"s\",\"limit\":\"8\",\"csrf_token\":\"\"}"
    key = "0CoJUm6Qyw8W8jud"
    i="tCBHRuGjK2gndtne" #固定死,对应的encSecKey就是常量
    encSecKey = "2e3d379b236dffdf32409f066f6cc2f076ab0d713546ed0da7372c357755b0c364009ce41c093864788cb487f2b854d56b1ce06c2b62d79a718206b9e4b42122a82322f8b28c857f3cc99cb39de06fe5882cea5f49fed9684afcc1d5e22ea500ea18781f586b533e0bde357ac2ea87d4bc8c99f65d7fc0756d099f4bb2ce8d84"
    content = contentEndo(content)
    en =AESencrypt(key,content)+'\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10'
    param = AESencrypt(i,en.encode('utf-8'))
    param = urllib.parse.quote(param)
    param=param.replace("/","%2F")
    data = "params={}&encSecKey={}".format(param,encSecKey)
    return data

print (makeData())

尝试发送

运行程序
网易云参数解析(多图)_第5张图片

把结果拷贝下来打开火狐浏览器的开发者模式

网易云参数解析(多图)_第6张图片

把postdata粘贴进去,把请求头里面的一些参数删除Content-Length: XXX,看是不是正确的响应

网易云参数解析(多图)_第7张图片

结尾:

只是一个自动补全的传递参数,但是其他请求好像也会用到这两个参数,如果有需要只需要修改d参也就是代码中的

content = "{\"s\":\"s\",\"limit\":\"8\",\"csrf_token\":\"\"}"

通过调试断点看一下传输的格式是什么修改一下,再进行加密也可以得到答案

你可能感兴趣的:(爬虫)