前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >「JS 逆向百例」cnki 学术翻译 AES 加密分析

「JS 逆向百例」cnki 学术翻译 AES 加密分析

原创
作者头像
K哥爬虫
修改2021-11-18 18:02:39
1.7K0
修改2021-11-18 18:02:39
举报
文章被收录于专栏:Python 爬虫Python 爬虫

逆向目标

  • 目标:cnki 学术翻译 AES 加密
  • 主页:aHR0cHM6Ly9kaWN0LmNua2kubmV0L2luZGV4
  • 接口:aHR0cHM6Ly9kaWN0LmNua2kubmV0L2Z5enMtZnJvbnQtYXBpL3RyYW5zbGF0ZS9saXRlcmFsdHJhbnNsYXRpb24=
  • 逆向参数:Request Payload:words: "kufhG_UJw_k3Sfr3j0BLAA=="

逆向过程

本期逆向素材来源于K哥爬虫交流群里某位群友的求助,目标是 cnki 学术翻译,粉丝想实现两个功能:1、突破英文1000个字符的限制;2、逆向加密过程。

01.png
01.png

来到翻译首页,抓包定位到翻译接口,可以看到 Request Payload 里,待翻译文本会被加密处理,如下图所示:

02.png
02.png

这里如果直接搜索关键字 words,会发现结果非常多,不太好找,注意到 Payload 参数里还有个 translateType,那么就可以直接搜索 translateType,因为这两个参数一般都是挨着的,当然也可以使用 XHR 断点的方式来找,只不过麻烦一些,搜索结果都在 app.9fb42bb0.js 里,注意到最后一个结果里有 encrypto,加密的意思,基本上就是加密的地方了:

03.png
03.png

控制台打印一下 (0, h.encrypto)(this.inputWord),正是加密结果:

04.png
04.png

继续跟进一下 h.encrypto,很明显的 AES 加密,n = "4e87183cfd3a45fe",n 就是 key,模式 ECB,填充 Pkcs7,最后做了一些字符串的替换处理,如下图所示:

05.png
05.png

知道了加密算法,key 等关键参数,那么直接引用 crypto-js 模块来实现就 OK 了,JavaScript 代码如下:

代码语言:txt
复制
// 引用 crypto-js 加密模块
var CryptoJS = require('crypto-js')

function s(t) {
    var n = "4e87183cfd3a45fe"
    var e = {
        mode: CryptoJS.mode.ECB,
        padding: CryptoJS.pad.Pkcs7
    }
      , i = CryptoJS.enc.Utf8.parse(n)
      , s = CryptoJS.AES.encrypt(t, i, e)
      , r = s.toString().replace(/\//g, "_");
    return r = r.replace(/\+/g, "-"),
    r
}

console.log(s("测试"))

// kufhG_UJw_k3Sfr3j0BLAA==

使用 Python 翻译的一个小 demo:

代码语言:txt
复制
# ==================================
# --*-- coding: utf-8 --*--
# @Time    : 2021-11-05
# @Author  : 微信公众号:K哥爬虫
# @FileName: cnki.py
# @Software: PyCharm
# ==================================


import execjs
import requests


token_url = "https://dict.cnki.net/fyzs-front-api/getToken"
translation_api = "https://dict.cnki.net/fyzs-front-api/translate/literaltranslation"
UA = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.81 Safari/537.36"

session = requests.session()


def get_token():
    headers = {"User-Agent": UA}
    response = session.get(url=token_url, headers=headers).json()
    token = response["data"]
    return token


def get_encrypted_word(word):
    with open('cnki_encrypt.js', 'r', encoding='utf-8') as f:
        cnki_js = f.read()
    encrypted_word = execjs.compile(cnki_js).call('s', word)
    return encrypted_word


def get_translation_result(encrypted_word, token):
    payload = {
        "translateType": None,
        "words": encrypted_word
    }
    headers = {
        "Token": token,
        "User-Agent": UA
    }
    response = session.post(url=translation_api, headers=headers, json=payload).json()
    result = response["data"]["mResult"]
    return result


def main():
    word = input("请输入待翻译字符串: ")
    token = get_token()
    encrypted_word = get_encrypted_word(word)
    result = get_translation_result(encrypted_word, token)
    print("翻译结果为: ", result)


if __name__ == "__main__":
    main()

粉丝还有一个问题就是字符数限制问题,看能不能突破,实测英文限制1000字符,中文限制500字符,如下图所示:

06.png
06.png

这种限制其实大概率不仅仅是前端的限制,服务端应该也是有限制的,我们可以携带超过500字符的中文去请求一下,前面的字符是“测试1”,最后三个字符是“测试2”,此时已超过了500个字符,我们看到翻译结果里并没有出现 Test 2,所以想要翻译很多字符串,只能将其分割成几份来处理了。

07.png
07.png

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 逆向过程
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档