首页 > 其他分享 >JS逆向——某道翻译

JS逆向——某道翻译

时间:2023-12-01 14:23:22浏览次数:27  
标签:逆向 return 某道 crypto js sign mysticTime var JS

文章中所有内容仅供学习交流,不可用于任何商业用途和非法用途,如有侵权,请联系作者立即删除!

  • 目标网站:aHR0cHM6Ly9mYW55aS55b3VkYW8uY29tL2luZGV4Lmh0bWwjLw==

一、定位接口

  • 使用Chrome浏览器,打开Network进行抓包
  • 输入要翻译的字符串:Hello World !

页面没有重新加载,初步判断是Ajax请求,我们看 Fetch/XHR请求,有两个请求

  

  • 分析接口 

   经过查看分析,key的请求返回内容中不是我们需要的信息,只剩下webtranslate返回的内容,但是返回的内容是一长串字符串,我们先看一下请求参数,然后再换个要翻译的内容,看看参数有哪些变化。

  • 参数对比

  两次请求参数对比,发现,只有i、sign、mysticTime三个参数发生了变化

  

  i:要翻译的字符串

  sign:加密字符串

  mysticTime:1701264377572,13位数字字符串,去掉后三位放入时间戳转换工具,发现就是时间戳

  • 寻找sign加密位置

  全局搜索sign:(小技巧),搜索的位置打上断点,逐个排除

  

  再次请求,返现断点这个位置暂停,发现mysticTime就是时间戳

  

  进入k(o, e)函数,看一下函数构造

  执行会发现,k(o, e)函数右进入了j(e)函数,进行了一些列跟MD5有关的操作,先把这些函数抠出来

  在看k(o, e)函数的传参,o是时间戳,e呢?

  通过堆栈不难发现t就是e,那这个值怎么生成的(我这里查看了很久都没找到),但是发现不管翻译的内容如何,这t的值是固定,我们可以写死。

  

所以抠出的JS代码如下图,我们调用输出一下:

var t='fsdsogkndfokasodnaso';
var e=new Date().getTime()

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}`)
}
console.log(k(e,t))

  

  ReferenceError: u is not defined u未定义

  在继续打上断点看一下

  

  在JavaScript中``反引号为模板字符串,反引号包括的字符串中出现${}占位符的意思,相当于Python的f'{}'

  

  观察u的值,通过测试发现u的值和d的值也是固定,我们也可以写死

  

  再次运行代码,提示ReferenceError: c is not definedc未定义,我们看一下内容,明显是MD5加密,使用Python MD5或者Node.js的都行,这里我用Node.js的的,crypto代替c.a

  

var crypto = require('crypto');
var t='fsdsogkndfokasodnaso';
var u="fanyideskweb"
var d="webfanyi"
var e=new Date().getTime()

function j(e) {
   return crypto.createHash("md5").update(e.toString()).digest("hex")
}
function k(e, t) {
   return j(`client=${u}&mysticTime=${e}&product=${d}&key=${t}`)
}
console.log(k(e,t))

  再次运行,发现运行成功

  

  对比页面上的加密字符串(防止魔改MD5),发现跟页面上的加密字符串不一致

  

  在进行分析,组成加密字符串的时间戳一直再变动,所以生成的加密字符串不一致,那我们传入跟页面上一样的字符串在本地JS代码中测试一下

  

  

  

  这次生成的加密字符串一致了

  开始编写程序,请求接口看看返回的内容

  JS代码:

var crypto = require('crypto');
var u="fanyideskweb"
var d="webfanyi"

function j(e) {
   return crypto.createHash("md5").update(e.toString()).digest("hex")
}
function return_sign(e, t) {
   return j(`client=${u}&mysticTime=${e}&product=${d}&key=${t}`)
}

  Python代码

import time
import execjs
import requests

def get_sign(t):
   with open("1.js", "r", encoding='utf-8') as f:
       read_js = f.read()
   e = 'fsdsogkndfokasodnaso'
   sign = execjs.compile(read_js).call('return_sign', t,e)
   return sign

def get_web(str1, t):
   url = 'https://dict.youdao.com/webtranslate'
   header = {
       "Content-Type": "application/x-www-form-urlencoded",
       "Referer": "https://fanyi.youdao.com/index.html",
       "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36",
   }
   cookie={
       "OUTFOX_SEARCH_USER_ID_NCOO":"1880472979.5706484",
       "OUTFOX_SEARCH_USER_ID":"-320001268@240e:3b8:2e6b:8db0:7dde:588a:9908:d4bb"
   }
   sign = get_sign(t)
   data = {
       "i": str1,
       "from": "auto",
       "to": "",
       "dictResult": "true",
       "keyid": "webfanyi",
       "sign": sign,
       "client": "fanyideskweb",
       "product": "webfanyi",
       "appVersion": "1.0.0",
       "vendor": "web",
       "pointParam": "client,mysticTime,product",
       "mysticTime": t,
       "keyfrom": "fanyi.web",
       "mid": "1",
       "screen": "1",
       "model": "1",
       "network": "wifi",
       "abtest": "0",
       "yduuid": "abcdefg"
   }

   resp = requests.post(url, headers=header,cookies=cookie, data=data)
   print(resp.status_code)
   print(resp.text)

if __name__ == '__main__':
   str1 = 'Hello Wodeld !'
   t = time.time()
   get_web(str1, t)

  

  运行之后发现返回的加密的字符串

  

  在Ajax请求位置返回内容,也就是得到sign值之后,继续跟踪,寻找解密函数,会发执行完这里右侧a中就会出现翻译内容,确定解密函数位置

   

  进入解密函数,看一下执行逻辑,抠出代码

  

  对e.alloc跟踪,你会发现,这里出现Uint8Arry函数,还有一个图标

  

  点击这个图标,然后会弹出以下内容

  

  怎么看着像是内存呀,我们查查Uint8Arry的用法

   Uint8Arry数组类型表示一个 8 位无符号整型数组,创建时内容被初始化为 0。创建完后,可以以对象的方式或使用数组下标索引的方式引用数组中的元素

  我们用Node.jsBuffer.alloc代替

  进入y(o)函数,发现就是MD5函数,我们引入crypto包,代替c.a

  

  运行代码,

  运行后报错: 'gbk' codec can't decode byte 0xb7 in position 68: illegal multibyte sequenc

  execjs包编码问题在引入前修改一下编码:

import subprocess
from functools import partial
subprocess.Popen = partial(subprocess.Popen, encoding='utf-8')

  

  再次运行,得到正确结果

  

  完整1.js代码

var crypto = require('crypto');
var u="fanyideskweb"
var d="webfanyi"

function j(e) {
   return crypto.createHash("md5").update(e.toString()).digest("hex")
}
function return_sign(e, t) {
   return j(`client=${u}&mysticTime=${e}&product=${d}&key=${t}`)
}

  

  完整2.js代码

var crypto = require('crypto');

function return_text(t, o, n) {
   if (!t)
       return null;
   const a = Buffer.alloc(16, crypto.createHash("md5").update(o).digest())
       ,
       i = Buffer.alloc(16, crypto.createHash("md5").update(n).digest())
       , r = crypto.createDecipheriv("aes-128-cbc", a, i);
   let s = r.update(t, "base64", "utf-8");
   return s += r.final("utf-8"), s
}

  

  完整Python代码

import subprocess
from functools import partial
subprocess.Popen = partial(subprocess.Popen, encoding='utf-8')

import time
import execjs
import requests

def get_sign(t):
   with open("1.js", "r", encoding='utf-8') as f:
       read_js = f.read()
   e = 'fsdsogkndfokasodnaso'
   sign = execjs.compile(read_js).call('return_sign', t, e)
   return sign


def get_text(str1):
   with open("2.js", "r", encoding='utf-8') as f:
       read_js = f.read()
   o="ydsecret://query/key/B*RGygVywfNBwpmBaZg*WT7SIOUP2T0C9WHMZN39j^DAdaZhAnxvGcCY6VYFwnHl"
   n="ydsecret://query/iv/C@lZe2YzHtZ2CYgaXKSVfsb7Y4QWHjITPPZ0nQp87fBeJ!Iv6v^6fvi2WN@bYpJ4"
   str2 = execjs.compile(read_js).call('return_text', str1,o,n)
   return str2


def get_web(str1, t):
   url = 'https://dict.youdao.com/webtranslate'
   header = {
       "Content-Type": "application/x-www-form-urlencoded",
       "Referer": "https://fanyi.youdao.com/index.html",
       "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36",
   }
   cookie = {
       "OUTFOX_SEARCH_USER_ID_NCOO": "1880472979.5706484",
       "OUTFOX_SEARCH_USER_ID": "-320001268@240e:3b8:2e6b:8db0:7dde:588a:9908:d4bb"
   }
   sign = get_sign(t)
   data = {
       "i": str1,
       "from": "auto",
       "to": "",
       "dictResult": "true",
       "keyid": "webfanyi",
       "sign": sign,
       "client": "fanyideskweb",
       "product": "webfanyi",
       "appVersion": "1.0.0",
       "vendor": "web",
       "pointParam": "client,mysticTime,product",
       "mysticTime": t,
       "keyfrom": "fanyi.web",
       "mid": "1",
       "screen": "1",
       "model": "1",
       "network": "wifi",
       "abtest": "0",
       "yduuid": "abcdefg"
   }
   resp = requests.post(url, headers=header, cookies=cookie, data=data)
   if resp.status_code == 200:
       str3 = get_text(resp.text)
       print(str3)

if __name__ == '__main__':
   str1 = 'Hello World !'
   t = time.time()
   get_web(str1, t)

 End !!!

标签:逆向,return,某道,crypto,js,sign,mysticTime,var,JS
From: https://www.cnblogs.com/toddywang/p/17869565.html

相关文章

  • js中get请求参数含有特殊字符的处理
    在拼接参数的时候,使用 encodeURIComponent() 进行手动转义。varurl="xxxx?name="+encodeURIComponent("aaa&bbb")特殊特殊字符的含义:字符特殊字符的含义URL编码+URL中+号表示空格%2B空格URL中的空格可以用+号或者编码%20/分隔目录和子目录%2F?分隔......
  • JMeter的JSON提取器JSON Path一次性提取多个
    JMeter调用接口时,返回一串列表,后面需要列表里的多个参数如下面接口返回示例,我需要提取每个数组里的vpc_id,后面需要用到{"vpcs":[{"vpc_name":"vpc1","vpc_id":"1712289779223859200"},{&qu......
  • Golang中如何自定义时间类型进行xml、json的序列化/反序列化
    在日常开发工作中,我们进行会遇到将struct序列化json字符串以及将json字符串反序列化为struct的场景,大家也对此十分熟悉。最近工作中,遇到了需要将struct序列化xml字符串以及将xml字符串反序列化为struct的场景,对于普通类型的字段,比如int、string等类型,直接......
  • 前端学习-JavaScript学习-js基础-API01
    学习视频:黑马程序员视频链接DOM简介DOM简介DOM树:将HTML文档标签以树状形式表现出来DOM对象:每个标签都是DOM对象DOM核心思想:将网页内容当作对象处理DOM中最大的对象:document,其次是<html><!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><metan......
  • JSONObject参数顺序问题
    签名需要规定参数顺序不能错。一开始是这么写的JSONObjectparam=newJSONObject();param.put("idcard",user.getIdCard());param.put("mobile",user.getPhone());param.put("uid",user.getId());param.put("username",user.getName());期望得到的顺序应该......
  • web前端tips:js继承——寄生组合式继承
    上篇文章给大家分享了js继承中的寄生式继承web前端tips:js继承——寄生式继承今天给大家分享一下js继承中的寄生组合式继承寄生组合式继承寄生组合式继承是一种结合了寄生式继承和组合式继承的方式,它的目标是减少组合式继承中多余的调用父类构造函数的开销。在组合式继承......
  • H50088:js动态生成html代码的三种形式
    1,//方案一O.TEMPLATE='<divclass="viewer-container">\<divclass="viewer-canvas"></div>\<divclass="viewer-footer">\<divclass="viewer-title&quo......
  • Jmeter接口自动化测试 —— Jmeter断言之Json断言
     json断言可以让我们很快的定位到响应数据中的某一字段,当然前提是响应数据是json格式的,所以如果响应数据为json格式的话,使用json断言还是相当方便的。还是以之前的接口举例Url:https://data.cma.cn/weatherGis/web/weather/weatherFcst/getCurrentConditionHTTPMethod:Po......
  • JS累加器
    假设您的数组如下:JavaScriptCode复制内容到剪贴板const array = [    { totalAmount: 100 },    { totalAmount: 200 },    { totalAmount: 300 },    { totalAmount: 150 }  ];   您可以使用Array.reduce()方法对每组totalAmount进行累......
  • Win7系统安装高版本node.js方法,node 16.x ,node 17.x(跳过安不了17),node 18.x,node 19.x 2
    随着前端框架的不断升级,node16.3.0的版本远远跟不上开发需要,导致win7无法安装高于16.3.0版本的node.js,经过不断的尝试和查找网上的帖子,终于解决了可以升级到19.x的nodejs了方法如下:(1)按照原来方式先升级到Nodejs16.3.0,先看我上次发的内容。地址:https://www.cnblogs.com/wuzexin/p......