AST反混淆|某练习平台混淆代码彻底还原及逆向请求

关注它,不迷路。       

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

一.目标地址

https://match.yuanrenxue.cn/match/2

二.代码还原

初次请求抓包,停止debugger位置:

31dc881ff756121b5ca6d1cd8564fc43.png

往上跟堆栈,看到混淆代码,将整个混淆代码保存下来:

daee11404d26904a197241f0e63cf070.png

分析得知,这是典型的ob混淆,使用星球里的插件先还原字符串:

https://t.zsxq.com/shQFg

字符串解密替换后:

f264a1c6e5ce14503fd8da71de7eb6b4.png

接下来就是后处理了,继续使用星球里的插件:

https://t.zsxq.com/G61wD

处理完毕后,发现更新了 cookie 值:

86592956eaac3b34f94d94f1f55f054f.png

 接下来就是删除垃圾代码,确保整个代码可以直接用起来。

三.分析和删除

  1. 最外层的自执行函数还原:

a77432ccc06072cd50fea678a94daaf8.png

代码可以很简单:

ExpressionStatement(path)
  {
    let {parentPath,node} = path;
    if (!parentPath.isProgram())
    {
      return;
    }
    let {expression} = path.node;
    if (types.isCallExpression(expression) && types.isFunctionExpression(expression.callee))
    {
      path.replaceWithMultiple(expression.callee.body.body);
    }
  },

2.接着看到这个函数:

3f168de9a4aefac270e6ef62bf987d07.png

分析可以后得知,它做了两件事,qz进行了赋值,try语句走的是catch分支,因此整个函数其实就是返回 navigator["vendorSub"],浏览器上是"".所以,可以将它引用的地方全部替换成"",代码也很容易:

TryStatement(path) {


    let { param, body } = path.node.handler;


    if (body.body.length == 1 && types.isReturnStatement(body.body[0])) {
      let functionParent = path.getFunctionParent();


      let binding = functionParent.scope.getBinding(functionParent.node.id.name);


      if (!binding) {
        return;
      }


      for (let referPath of binding.referencePaths) {
        let { parentPath } = referPath;


        if (parentPath.isCallExpression()) {
          parentPath.replaceWith(types.valueToNode(""));
        }
      }
      functionParent.remove();
    }
  },

 3.上一步看到了 qz 被赋值了,因此在它引用的地方:

81db4ccb714ccfcd138ce9a75cdd532f.png

代码会执行if分支,写个插件直接替换:

IfStatement(path) {
    let { test, consequent, alternate } = path.node;
    if (test.name == "qz") {
      path.replaceWithMultiple(consequent.body);
    }
  },

4.删除与加密无关的函数调用,有两处,分别是:

372e7deffad62a71b4e2962076ffc3c0.png

和:

e004c693c1272115fc3e976c7fccd107.png

代码如下:

CallExpression(path) {
    if (path.node.callee.name == "setInterval") {
      path.remove();
      return;
    }
    if (types.isMemberExpression(path.node.callee)) {
      let { object, property } = path.node.callee;
      if (types.isIdentifier(object, { "name": "location" }) && types.isStringLiteral(property, { "value": "reload" })) {
        path.remove();
      }
    }


  },

5.改造加密函数,使之可以直接调用。

改造前:

function _0x3e163b(_0x24b4ad, _0x12406a) {
    document["cookie"] = "m" + "" + "=" + _0x59d4f4(_0x24b4ad) + "|" + _0x24b4ad + "; path=/";
  }

改造后:

function _0x3e163b(_0x24b4ad, _0x12406a) {
   cookie = "m" + "" + "=" + _0x59d4f4(_0x24b4ad) + "|" + _0x24b4ad + "; path=/";
   return cookie;
  }

插件代码:

AssignmentExpression(path) {
    let { parentPath, node, scope } = path;
    if (!parentPath.isExpressionStatement()) {
      return;
    }
    let { left, operator, right } = node;
    if (types.isMemberExpression(left)) {
      let { object, property } = left;
      if (types.isIdentifier(object, { "name": "document" }) && types.isStringLiteral(property, { "value": "cookie" })) {
        path.node.left = types.Identifier(property.value);
        parentPath.insertAfter(types.ReturnStatement(path.node.left));
      }
    }
  },

经过上面的处理以后,整个混淆代码可以直接运行起来。

四.请求代码

分析得知,第一个实参是13位的时间戳,第二个参数没有用到,写下Python代码:

import time
import execjs
import requests


session = requests.Session()


session.headers = {
    "User-Agent": "yuanrenxue.project",
    }
 
 
url = "http://match.yuanrenxue.com/match/2"


r = session.get(url)


with open("2.js",'r') as fp:
    jscode = fp.read()


ctx = execjs.compile(jscode)


timestamp = str(int(time.time()*1000))


cookie = ctx.call("_0x3e163b",timestamp)




session.cookies.set("m",cookie[2:])


sum = 0
 
 
for i in range(1,2):
    api_url =f"http://match.yuanrenxue.com/api/match/2?page={i}"
    r = session.get(api_url)
    print (r.text)
    data = r.json()
    values = data["data"]
    for value in values:
        print (value)
        sum += value["value"]
 
 
print (sum)

请求结果:

cc34d00ddb7625ffbb815137b363b515.png

四.插件源码

完整源代码:

https://t.zsxq.com/kELKD

今天的分享就到这里,感谢阅读。

欢迎加入知识星球,学习更多AST和爬虫技巧。

b60e027c97eea805a363477943d30856.jpeg

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/752705.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Java常量、变量、成员内部类

文章目录 1.常量2.变量3.成员内部类4.变动 1.常量 实例常量:只用final修饰,是某个具体类的实例 静态常量:finalstatic修饰,属于类,所有实例共享同一个类常量 2.变量 实例变量(成员变量):定义在类内部但在…

【motan rpc 懒加载】异常

文章目录 升级版本解决问题我使用的有问题的版本配置懒加载错误的版本配置了懒加载 但是不生效 lazyInit"true" 启动不是懒加载 会报错一次官方回复 升级版本解决问题 <version.motan>1.2.1</version.motan><dependency><groupId>com.weibo…

Adobe Animate有必要学习AS3脚本吗?

AdobeAnimate软件已经慢慢的替代Flash系列软件在动画中的地位了&#xff0c;也越来越多的出现在各专业课中。不过还是以动画制作方面的教学为主。 Animate软件从入门到提高系列课程​http://www.bilibili.com/cheese/play/ss1826 也有不少同学知道从Flash系列开始&#xff0c;…

便携应急气象站设备—实时监测和记录气象数据

TH-BQX10便携应急气象站设备是一种高度集成、轻便易携的气象观测系统。它采用新型一体化结构设计&#xff0c;能够快速安装和拆卸&#xff0c;适用于各种复杂环境。通过集成多种气象传感器&#xff0c;该设备能够实时监测和记录温度、湿度、风向、风速、降雨量、气压等多种气象…

新手第一个漏洞复现:MS17-010(永恒之蓝)

文章目录 漏洞原理漏洞影响范围复现环境复现步骤 漏洞原理 漏洞出现在Windows SMB v1中的内核态函数srv!SrvOs2FeaListToNt在处理FEA&#xff08;File Extended Attributes&#xff09;转换时。该函数在将FEA list转换成NTFEA&#xff08;Windows NT FEA&#xff09;list前&am…

stm32学习笔记---TIM编码器接口(代码部分)编码器接口测速

目录 编码器接口的初始化步骤 Tim.h库函数 TIM_EncoderInterfaceConfig 代码实现 Encoder.c 初始化 三种输入模式的选择原则 获取编码器的增量值的函数 调整极性 闸门时间调整 Encoder.h main.c 声明&#xff1a;本专栏是本人跟着B站江科大的视频的学习过程中记录下…

文本分类-RNN-LSTM

1.前言 本节介绍RNN和LSTM&#xff0c;并采用它们在电影评论数据集上实现文本分类&#xff0c;会涉及以下几个知识点。 1. 词表构建&#xff1a;包括数据清洗&#xff0c;词频统计&#xff0c;词频截断&#xff0c;词表构建。 2. 预训练词向量应用&#xff1a;下载并加载Glove的…

Terraform基础概念一

Terraform基础概念一 1.Infrastructure-as-Code(IaC)概念1.1 IaC优势1.2 IaC工具1.3 IaC的两种方式 2.Terraform基础概念2.1 Terraform工作原理2.2 Terraform 工作流 3.总结 1.Infrastructure-as-Code(IaC)概念 基础设施即代码&#xff08;Infrastructure-as-Code&#xff0c;…

告别 “屎山” 代码,务必掌握这14 个 SpringBoot 优化小妙招

插&#xff1a; AI时代&#xff0c;程序员或多或少要了解些人工智能&#xff0c;前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家(前言 – 人工智能教程 ) 坚持不懈&#xff0c;越努力越幸运&#xff0c;大家…

flash-Attention2安装和使用

flash-Attention2安装和使用 文章目录 flash-Attention2安装和使用写在前面解决方案 写在前面 就怕你不知道怎么查 pytorch、cuda 的版本 配置cuda&#xff1a;vim ~/.bashrc export CUDA_HOME/usr/local/cuda/ export PATH$PATH:$CUDA_HOME/bin export LD_LIBRARY_PATH$LD_LIB…

鉴源实验室·基于MQTT协议的模糊测试研究

作者 | 张渊策 上海控安可信软件创新研究院工控网络安全组 来源 | 鉴源实验室 社群 | 添加微信号“TICPShanghai”加入“上海控安51fusa安全社区” 随着物联网技术的快速发展&#xff0c;越来越多的设备加入到互联网中&#xff0c;形成了庞大的物联网系统。这些设备之间的通信…

【Sklearn-线性回归驯化】史上最为全面的预测分析的基石-线性回归大全

【Sklearn-驯化】史上最为全面的预测分析的基石-线性回归大全 本次修炼方法请往下查看 &#x1f308; 欢迎莅临我的个人主页 &#x1f448;这里是我工作、学习、实践 IT领域、真诚分享 踩坑集合&#xff0c;智慧小天地&#xff01; &#x1f387; 免费获取相关内容文档关注&…

Java8新特性stream的原理和使用

这是一种流式惰性计算&#xff0c;整体过程是&#xff1a; stream的使用也异常方便&#xff0c;可以对比如List、Set之类的对象进行流式计算&#xff0c;挑出最终想要的结果&#xff1a; List<Timestamp> laterTimes allRecords.stream().map(Record::getTime).filter…

电脑音频剪辑怎么操作?分享六个简单的音频剪辑技巧【常用】

音频剪辑的需求越来越多&#xff0c;大多数短视频中的音乐都是大家后期制作的&#xff0c;主要目的就就是让视频观看起来更有趣。音频剪辑的方法有很多&#xff0c;比较好用的可以借助第三方音频剪辑软件。操作简单&#xff0c;对没有任何剪辑经验的小白用户来说十分友好。 本文…

java简易计算器(多种方法)

parseDouble() 方法属于 java.lang.Double 类。它接收一个字符串参数&#xff0c;其中包含要转换的数字表示。如果字符串表示一个有效的 double&#xff0c;它将返回一个 double 值。 应用场景 parseDouble() 方法在以下场景中非常有用&#xff1a; 从用户输入中获取数字&a…

VUE大屏的开发过程(纯前端)

写在前面&#xff0c;博主是个在北京打拼的码农&#xff0c;工作多年做过各类项目&#xff0c;最近心血来潮在这儿写点东西&#xff0c;欢迎大家多多指教。 对于文章中出现的任何错误请大家批评指出&#xff0c;一定及时修改。有任何想要讨论和学习的问题可联系我&#xff1a;1…

2.4G无线通信芯片数据手册解读:Ci24R1南京中科微

今天&#xff0c;我非常荣幸地向您介绍这款引领行业潮流的2.4G射频芯片&#xff1a;Ci24R1。这款芯片&#xff0c;不仅是我们技术的结晶&#xff0c;更是未来无线通信的璀璨明星。 首先&#xff0c;让我们来谈谈Ci24R1的“速度”。2.4G射频芯片&#xff0c;凭借其卓越的数据传输…

Python基于逻辑回归分类模型、决策树分类模型、随机森林分类模型和XGBoost分类模型实现乳腺癌分类预测项目实战

说明&#xff1a;这是一个机器学习实战项目&#xff08;附带数据代码文档视频讲解&#xff09;&#xff0c;如需数据代码文档视频讲解可以直接到文章最后获取。 1.项目背景 在当今医疗健康领域&#xff0c;乳腺癌作为威胁女性健康的主要恶性肿瘤之一&#xff0c;其早期诊断与精…

OpenHarmony开发实战:HDF驱动开发流程

概述 HDF&#xff08;Hardware Driver Foundation&#xff09;驱动框架&#xff0c;为驱动开发者提供驱动框架能力&#xff0c;包括驱动加载、驱动服务管理、驱动消息机制和配置管理。并以组件化驱动模型作为核心设计思路&#xff0c;让驱动开发和部署更加规范&#xff0c;旨在…

Redis-Bitmap位图及其常用命令详解

1.Redis概述 2.Bitmap Bitmap 是 Redis 中的一种数据结构&#xff0c;用于表示位图&#xff08;bit array&#xff09;。 它通常用于处理大规模数据集中每个元素的状态&#xff0c;比如用户的在线/离线状态&#xff08;每个用户对应一个位&#xff0c;表示在线&#xff08;1&a…