【JS逆向学习】有道翻译接口参数逆向

发布时间:2023年12月28日
逆向目标
  • 目标:有道翻译接口加密参数
  • 接口:https://dict.youdao.com/webtranslate
  • 加密参数:
    • sign: e3d8fa747713d6957db7cd2eedaa0d95
    • Cookie: OUTFOX_SEARCH_USER_ID=696102715@114.222.69.137; OUTFOX_SEARCH_USER_ID_NCOO=304412380.2597743
逆向过程
网络接口分析

在翻译页面输入文本,不用刷新就会翻译,因此推断是AJAX请求,F12打开开发者工具,选择XHR过滤AJAX请求,可以看到如下的POST请求:
在这里插入图片描述
加密参数如下:
在这里插入图片描述
当我们输入China后返回的翻译结果如下,数据是加密的:

Z21kD9ZK1ke6ugku2ccWu-MeDWh3z252xRTQv-wZ6jddVo3tJLe7gIXz4PyxGl73nSfLAADyElSjjvrYdCvEP4pfohVVEX1DxoI0yhm36ytQNvu-WLU94qULZQ72aml6kZ73SLZAuFYSDoo5DxD1CAD_gJoN2WmgoLKCbLnIEYzGOAyer1Jab7-s3V894sJs5T0PMYtKsruRiynDqxTpq17L4Jc3v4FYfzJpjS6tSLw343AhMilrI6zbTJTJ_L7429bntYH77EIX7ynVH3VeLEkEa_FpwAndfjS_1uXbq9vqWsfr0LlOxGegdmMZnPYhblwGSZxYvl9Od6f8bGucSAUDYVPoE3Iuj5zpiCSLmUlyxS3_WgM1MFvNV2D7oo5CZULO1inANGHfiYi61qHB5MI4BomG7ucNucRE277kAozj3I1nHTFtj9yrJvQ0PE07c9BeVncFwv2GfVZ-aKiccjPhtdWvaJmrhU1qLBpEDY28FSf52Hqcw5ThzcTmc1284dmZ8uaGCdWmjJcaHw4dZdce9mKQLMRPHanu_ro72WR3AMy3NKL4EVJmACWLsRmp2WOLAF8Zf5tY4x897gmMztmEJlaSI6cOFIverbBEbzK0H1Jq0AS5U4Zk_IF32aWrseq_uFMA5c2lJg3LD0bQoA==
加密参数分析

分析接口的启动器,可以看到一个xhr请求,我们直接点进去打上断点
在这里插入图片描述进去之后跟栈分析,就可以看到关键的加密代码:
在这里插入图片描述

function y(e) {
    return c.a.createHash("md5").update(e).digest()
}
function j(e) {
    return c.a.createHash("md5").update(e.toString()).digest("hex")
}
function k(e, t) {
    return j(`client=${u}&mysticTime=${e}&product=${d}&key=${t}`)
}
function E(e, t) {
    const o = (new Date).getTime();
    return {
        sign: k(o, e),
        client: u,
        product: d,
        appVersion: p,
        vendor: g,
        pointParam: m,
        mysticTime: o,
        keyfrom: b,
        mid: A,
        screen: h,
        model: f,
        network: v,
        abtest: O,
        yduuid: t || "abcdefg"
    }
}

分析这段加密代码:

  • d:固定字符串【fanyideskweb】
  • u:固定字符串【webfanyi】
  • e:固定字符串【fsdsogkndfokasodnaso】
  • t:13位时间戳【(new Date).getTime()】

直接使用 nodejs 里面的加密模块 CryptoJS 来进行 MD5 加密,改写 JS 如下:

const CryptoJS = require('crypto-js');

function sign(t) {
    let d = 'fanyideskweb', u = 'webfanyi', e = 'fsdsogkndfokasodnaso',
        signStr = `client=${d}&mysticTime=${t}&product=${u}&key=${e}`,
        sig = CryptoJS.MD5(signStr).toString();
    return sig;
}

返回的参数看起来像是一个base64的加密数据,推断他的解密逻辑应该先解密,然后使用JSON.parse进行格式化,可以直接控制台hook这个方法:

(function(){
	var parse_ = JSON.parse;
	JSON.parse = function(param){
		debugger;
		return parse_(param);
	}
})();

在这里插入图片描述
可以看到已经hook到了解密之后的结果,然后跟栈分析,发现解密方法

const a = Po["a"].decodeData(o, Wo["a"].state.text.decodeKey, Wo["a"].state.text.decodeIv)
                  , n = a ? JSON.parse(a) : {};
                0 === n.code ? e.success && t(e.success)(n) : e.fail && t(e.fail)(n)

在这里插入图片描述
继续跟栈进去decodeData,可以看到加密逻辑已经很清晰了,基本可以确定是AES加密了

(t,o,n)=>{
    if (!t)
        return null;
    const a = e.alloc(16, y(o))
      , i = e.alloc(16, y(n))
      , r = c.a.createDecipheriv("aes-128-cbc", a, i);
    let s = r.update(t, "base64", "utf-8");
    return s += r.final("utf-8"),
    s
}

在这里插入图片描述
直接使用 nodejs 里面的加密模块 crypto 来进行 AES 解密,改写 JS 如下:

const crypto = require('crypto');
function decrypt(decrypt_str) {
    const key = "ydsecret://query/key/B*RGygVywfNBwpmBaZg*WT7SIOUP2T0C9WHMZN39j^DAdaZhAnxvGcCY6VYFwnHl";
    const iv = "ydsecret://query/iv/C@lZe2YzHtZ2CYgaXKSVfsb7Y4QWHjITPPZ0nQp87fBeJ!Iv6v^6fvi2WN@bYpJ4";

    const key_md5 = crypto.createHash('md5').update(key, 'utf-8').digest();
    const iv_md5 = crypto.createHash('md5').update(iv, 'utf-8').digest();
    console.log('key_md5 = ', key_md5)
    console.log('iv_md5 = ', iv_md5)

    const decipher = crypto.createDecipheriv('aes-128-cbc', key_md5, iv_md5);

    let decrypted = decipher.update(decrypt_str, 'base64', 'utf8');
    decrypted += decipher.final('utf8');

    return JSON.parse(decrypted);
}

原创声明:未经许可,不得转载。
如有侵权,请联系作者删除删除。

文章来源:https://blog.csdn.net/andrew_wf/article/details/135263774
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。