【JS逆向学习】快乐学堂登陆接口(自定义DES加密、ddddocr验证码识别)

news2024/11/24 3:30:05
逆向目标
  • 网址:https://www.91118.com/Passport/Account/Login
  • 接口:https://www.91118.com/passport/Account/LoginPost
  • 参数:
    • pass
    • r
逆向过程

输入手机号、密码、验证码 点击登陆,多试几次,然后观察并比较不通请求参数有哪些变化,其中 ckcode 是验证码
在这里插入图片描述

逆向分析

先使用关键词 pass 搜索,匹配项太多,直接从启动器入口进去跟栈分析
在这里插入图片描述
调试如下
在这里插入图片描述
可以发现参数 r就是一个随机值 Math.random()pass 跟栈进去如下
在这里插入图片描述
加解密的方法都有了

var _key = 'k1fsa01v';
var _iv = 'k1fsa01v';
function encryptByDES(message) {
    var keyHex = CryptoJS.enc.Utf8.parse(_key);
    var encrypted = CryptoJS.DES.encrypt(message, keyHex, {
        iv: CryptoJS.enc.Utf8.parse(_iv),
        mode: CryptoJS.mode.ECB,
        padding: CryptoJS.pad.Pkcs7
    });
    return encrypted.toString();
}
function decryptByDES(ciphertext) {
    var keyHex = CryptoJS.enc.Utf8.parse(_key);
    var decrypted = CryptoJS.DES.decrypt({
        ciphertext: CryptoJS.enc.Base64.parse(ciphertext)
    }, keyHex, {
        iv: CryptoJS.enc.Utf8.parse(_iv),
        mode: CryptoJS.mode.ECB,
        padding: CryptoJS.pad.Pkcs7
    });
    return decrypted.toString(CryptoJS.enc.Utf8);
}

看着像是 DES 对称加密,使用标准库 crypto-js 来加密看看结果是否一致


var CryptoJS = require("crypto-js");
// 定义加密密钥,使用Utf8编码解析密钥字符串
const SECRET_KEY = CryptoJS.enc.Utf8.parse("k1fsa01v");
// 定义加密向量IV,使用Utf8编码解析IV字符串
const SECRET_IV = CryptoJS.enc.Utf8.parse("k1fsa01v");

/**
 * 加密函数,接受一个数据参数,返回加密后的字符串
 * @param {string|object} data - 需要加密的数据,可以是字符串或对象
 * @returns {string} 加密后的数据字符串
 */
function encrypt(data) {
	// 如果数据是对象类型,则尝试将其转换为字符串
	if (typeof data === "object") {
		try {
			data = JSON.stringify(data);
		} catch (e) {
			// 如果转换过程中发生错误,打印错误信息并返回
			console.log(e);
			return;
		}
	}
	// 将数据转换为Utf8格式的密文
	const dataHex = CryptoJS.enc.Utf8.parse(data);
	// 使用AES算法加密数据
	const encrypted = CryptoJS.AES.encrypt(dataHex, SECRET_KEY, {
		iv: SECRET_IV,
		mode: CryptoJS.mode.CBC, // 使用CBC模式
		padding: CryptoJS.pad.Pkcs7, // 使用Pkcs7填充
	});
	// 返回加密后的密文字符串
	return encrypted.toString();
}

console.log(encrypt("a123456"));
// 输出如下
>> T6fdfWw2zktEch0jKSJkmA==

我们再看网站加密结果

encryptByDES("a123456")
// 输出如下
>> bb3mlkFBqqo=

很明显网站对加密做了改造,我们跟进去把整个加密扣出来
在这里插入图片描述
我们把整个文件的 js code 全部copy出来执行并打印 console.log(CryptoJS) 输出如下

{
  lib: {
    Base: {
      extend: [Function: extend],
      create: [Function: create],
      init: [Function: init],
      mixIn: [Function: mixIn],
      clone: [Function: clone]
    },
    WordArray: {
      init: [Function: init],
      toString: [Function: toString],
      concat: [Function: concat],
      clamp: [Function: clamp],
      clone: [Function: clone],
      random: [Function: random],
      '$super': [Object]
    },
    BufferedBlockAlgorithm: {
      reset: [Function: reset],
      _append: [Function: _append],
      _process: [Function: _process],
      clone: [Function: clone],
      _minBufferSize: 0,
      init: [Function (anonymous)],
      '$super': [Object]
    },
    Hasher: {
      cfg: [Object],
      init: [Function: init],
      reset: [Function: reset],
      update: [Function: update],
      finalize: [Function: finalize],
      blockSize: 16,
      _createHelper: [Function: _createHelper],
      _createHmacHelper: [Function: _createHmacHelper],
      '$super': [Object]
    },
    Cipher: {
      cfg: [Object],
      createEncryptor: [Function: createEncryptor],
      createDecryptor: [Function: createDecryptor],
      init: [Function: init],
      reset: [Function: reset],
      process: [Function: process],
      finalize: [Function: finalize],
      keySize: 4,
      ivSize: 4,
      _ENC_XFORM_MODE: 1,
      _DEC_XFORM_MODE: 2,
      _createHelper: [Function: _createHelper],
      '$super': [Object]
    },
    StreamCipher: {
      _doFinalize: [Function: _doFinalize],
      blockSize: 1,
      init: [Function (anonymous)],
      '$super': [Object]
    },
    BlockCipherMode: {
      createEncryptor: [Function: createEncryptor],
      createDecryptor: [Function: createDecryptor],
      init: [Function: init],
      '$super': [Object]
    },
    BlockCipher: {
      cfg: [Object],
      reset: [Function: reset],
      _doProcessBlock: [Function: _doProcessBlock],
      _doFinalize: [Function: _doFinalize],
      blockSize: 4,
      init: [Function (anonymous)],
      '$super': [Object]
    },
    CipherParams: {
      init: [Function: init],
      toString: [Function: toString],
      '$super': [Object]
    },
    SerializableCipher: {
      cfg: [Object],
      encrypt: [Function: encrypt],
      decrypt: [Function: decrypt],
      _parse: [Function: _parse],
      init: [Function (anonymous)],
      '$super': [Object]
    },
    PasswordBasedCipher: {
      cfg: [Object],
      encrypt: [Function: encrypt],
      decrypt: [Function: decrypt],
      init: [Function (anonymous)],
      '$super': [Object]
    }
  },
  enc: {
    Hex: { stringify: [Function: stringify], parse: [Function: parse] },
    Latin1: { stringify: [Function: stringify], parse: [Function: parse] },
    Utf8: { stringify: [Function: stringify], parse: [Function: parse] },
    Base64: {
      stringify: [Function: stringify],
      parse: [Function: parse],
      _map: 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='
    }
  },
  algo: {
    MD5: {
      _doReset: [Function: _doReset],
      _doProcessBlock: [Function: _doProcessBlock],
      _doFinalize: [Function: _doFinalize],
      clone: [Function: clone],
      init: [Function (anonymous)],
      '$super': [Object]
    },
    EvpKDF: {
      cfg: [Object],
      init: [Function: init],
      compute: [Function: compute],
      '$super': [Object]
    },
    DES: {
      _doReset: [Function: _doReset],
      encryptBlock: [Function: encryptBlock],
      decryptBlock: [Function: decryptBlock],
      _doCryptBlock: [Function: _doCryptBlock],
      keySize: 2,
      ivSize: 2,
      blockSize: 2,
      init: [Function (anonymous)],
      '$super': [Object]
    },
    TripleDES: {
      _doReset: [Function: _doReset],
      encryptBlock: [Function: encryptBlock],
      decryptBlock: [Function: decryptBlock],
      keySize: 6,
      ivSize: 2,
      blockSize: 2,
      init: [Function (anonymous)],
      '$super': [Object]
    }
  },
  MD5: [Function (anonymous)],
  HmacMD5: [Function (anonymous)],
  EvpKDF: [Function (anonymous)],
  mode: {
    CBC: {
      init: [Function (anonymous)],
      '$super': [Object],
      Encryptor: [Object],
      Decryptor: [Object]
    }
  },
  pad: { Pkcs7: { pad: [Function: pad], unpad: [Function: unpad] } },
  format: {
    OpenSSL: { stringify: [Function: stringify], parse: [Function: parse] }
  },
  kdf: { OpenSSL: { execute: [Function: execute] } },
  DES: { encrypt: [Function: encrypt], decrypt: [Function: decrypt] },
  TripleDES: { encrypt: [Function: encrypt], decrypt: [Function: decrypt] }
}

然后把具体加密的那段代码也拷贝过来执行

var _key = 'k1fsa01v';
var _iv = 'k1fsa01v';
function encryptByDES(message) {
    var keyHex = CryptoJS.enc.Utf8.parse(_key);
    var encrypted = CryptoJS.DES.encrypt(message, keyHex, {
        iv: CryptoJS.enc.Utf8.parse(_iv),
        mode: CryptoJS.mode.ECB,
        padding: CryptoJS.pad.Pkcs7
    });
    return encrypted.toString();
}
function decryptByDES(ciphertext) {
    var keyHex = CryptoJS.enc.Utf8.parse(_key);
    var decrypted = CryptoJS.DES.decrypt({
        ciphertext: CryptoJS.enc.Base64.parse(ciphertext)
    }, keyHex, {
        iv: CryptoJS.enc.Utf8.parse(_iv),
        mode: CryptoJS.mode.ECB,
        padding: CryptoJS.pad.Pkcs7
    });
    return decrypted.toString(CryptoJS.enc.Utf8);
}
console.log(encryptByDES('a123456'));

结果报错了:

(base) qin@wuanjuns-MacBook-Pro jsprojects % node test.js 
/Users/qin/dev/jsprojects/jsprojects/test.js:527
              var b = a.createEncryptor;
                        ^
TypeError: Cannot read properties of undefined (reading 'createEncryptor')

因为我们是全扣的代码,不存在少扣的问题,这个时候把这段代码拷贝到浏览器里执行发现正常输出了
在这里插入图片描述
大家回想一下在具体的加密代码那个页面是不是还有一段 html 代码,我们去看看是什么东西

(function () {
    document.write("<script language=\"javascript\" type=\"text/javascript\" src=\"//assets.91118.com/js/rollups/tripledes.js\"></script><script language=\"javascript\" type=\"text/javascript\" src=\"//assets.91118.com/js/components/mode-ecb.js\"></script>");
})();

代码比较简单,就是一个自执行函数,引入了两个 js scripttripledes.js就是定义 CryptoJS 的文件,我们看另外一个 mode-ecb.js 是什么

CryptoJS.mode.ECB = (function () {
    var ECB = CryptoJS.lib.BlockCipherMode.extend();

    ECB.Encryptor = ECB.extend({
        processBlock: function (words, offset) {
            this._cipher.encryptBlock(words, offset);
        }
    });

    ECB.Decryptor = ECB.extend({
        processBlock: function (words, offset) {
            this._cipher.decryptBlock(words, offset);
        }
    });

    return ECB;
}());

补充了 CryptoJSECB mode,我们在刚才代码中补上这段代码再执行结果如下

>> node test.js
>> bb3mlkFBqqo=

返回了正确的加密后的结果
另外,在接口请求参数中还有一个验证码参数 ckcode ,这个验证码是一个 img 元素,直接请求网址https://www.91118.com/Passport/Account/Login 并解析返回的 html 内容即可拿到 img 这里我门就不做赘述了,像这种简单的验证码推荐大家使用免费的验证码识别库 ddddocr(https://github.com/sml2h3/ddddocr),这里直接给出识别代码

# -*- coding: utf-8 -*-
import ddddocr

ocr = ddddocr.DdddOcr()

image = open("code.jpg", "rb").read()
result = ocr.classification(image)
print(result)

在这里插入图片描述
识别成功

逆向结果

到这里整个逆向过程就全部结束了,整个流程走下来就两点

  1. 扣代码——CryptoJS加密模块,尤其是后面那个 CryptoJS.mode.ECB,真的是很有迷惑性;
  2. 验证码识别——这个没有什么可讲的,直接上 ddddocr 硬怼就行了

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

具有RC反馈电路的正弦波振荡器(文氏桥振荡器+相移振荡器+双T振荡器)

2024-9-10&#xff0c;星期二&#xff0c;22:13&#xff0c;天气&#xff1a;雨&#xff0c;心情&#xff1a;晴。今天从下午开始淅淅沥沥一直在下雨&#xff0c;还好我有先见之明没骑自行车&#xff0c;但是我忘带伞了&#xff0c;属于说是有点脑子但是不多了&#xff0c;2333…

通信八股总结for普联

一.信息论 1.香农公式 1.1 香农公式的内容 &#xff1a;信道容量(bps) &#xff1a;信道带宽(Hz) &#xff1a;信噪比&#xff08;dB&#xff09;。 1.2 香农公式的意义 揭示了在有噪声的通信信道中&#xff0c;信息传输速率的理论上限。 可以通过改进编码或者调制技术来…

gradle 学习备忘

所学版本&#xff1a; Gradle User Manualhttps://docs.gradle.org/8.7/userguide/userguide.html?_gl1*1f2c50b*_gcl_au*NzQ2ODAwODgxLjE3MjMzNjI5Mzk.*_ga*NDY3MDM0MDIzLjE3MjMzNjI5NDA.*_ga_7W7NC6YNPT*MTcyNTk3NTU3OC4yLjEuMTcyNTk3NTY0MC42MC4wLjA. Android 官网文档&am…

第十九次CCF计算机软件能力认证题目解析(详细题解+代码+个人解读+持续跟新)

第一题 线性分类器 考虑一个简单的二分类问题——将二维平面上的点分为 A A A 和 B B B 两类。 训练数据包含 n n n 个点&#xff0c;其中第 i i i 个点&#xff08; 1 ≤ i ≤ n 1 ≤i ≤ n 1≤i≤n&#xff09;可以表示为一个三元组 ( x i , y i , t y p e i ) (x_i,y…

strncpy陷阱

最近遇到了一个strncpy的bug&#xff0c;他们居然说这不是bug&#xff0c;而我认为这是很严重的bug&#xff01; 相比于strcpy来说&#xff0c;strncpy具有更高的安全性&#xff0c;但是同时会带来一个问题&#xff0c;就是c字符串不会自动补’\0’。 废话不多说&#xff0c;…

使用Docker安装 Skywalking(单机版)

使用Docker安装 Skywalking&#xff08;单机版&#xff09; 文章目录 使用Docker安装 Skywalking&#xff08;单机版&#xff09;Skywalking 介绍Skywalking 安装 Skywalking 介绍 Skywalking官网 分布式系统的应用程序性能监视工具&#xff0c;专为微服务、云原生架构和基于容…

GPU相关的一些截图

GPU相关的一些截图

【树和二叉树的相关定义】概念

1.回顾与概览 2.什么是树型结构 3.树的&#xff08;递归&#xff09;定义与基本术语 3.1树的定义 注意&#xff1a;除了根结点以外&#xff0c;任何一个结点都有且仅有一个前驱 3.2树的其他表示方式 3.3树的基本术语 结点&#xff1a;数据元素以及指向子树的分支根结点:非空…

OpenMV——色块追踪

Python知识&#xff1a; 1.给Python的列表赋值&#xff1a; 定义一个元组时就是 元组a (1,2,…) 元组中可以只有一个元素&#xff0c;但是就必须要加一个 “ , ” 如 a (2,) 而列表的定义和元组类似&#xff0c;只是把()换成[]: #那么下面的colour_1 ~ 3属于元组&#xf…

【leetcode C++】动态规划

动态规划解题思路 1. 状态表示 dp表 里面的值所代表的含义&#xff08;1.根据题目要求得出 2.经验 题目要求 3.分析问题过程中&#xff0c;发现重要子问题&#xff09; 2. 状态转移方程 dp[i] 等于什么 3. 初始化 保证填表不越界 4. 填表顺序 为了填写该状态的时候&am…

02 Docker基本管理

2.1 Docker镜像管理 2.1.1 案例&#xff1a;构建各类Docker镜像服务 2.1.2 案例环境 主机 操作系统 主机IP地址 服务器 Centos7.3x86-64 192.168.10.100 2.1.3 案例拓扑原理 通过 Dockerfile 创建常见应用镜像&#xff0c;Dockerfile 的构成如图 2.3 所示 图 2.1 Doc…

为什么说开放式耳机对耳朵更友好?性价比高的四款蓝牙耳机推荐

开放式耳机对耳朵更友好&#xff0c;主要体现在以下方面&#xff1a; 减少耳部闷热和潮湿&#xff1a;开放式耳机的开放结构&#xff0c;不会完全封闭耳朵&#xff0c;使得空气能够自由流通。这样可以有效减少因长时间佩戴导致的耳部闷热和潮湿情况。而耳部处于闷热潮湿的环境…

基于CNN-BiGUR的恶意域名检测方法

本文提出了一种基于 CNN 和 BiGRU 的恶意域名检测方法 CNN-BiGRU-Focal。利用卷积神经网络&#xff08;CNN&#xff09;提取域名字符的局部上下文特征。利用双向门控循环单元网络&#xff08;BiGRU&#xff09;捕捉域名字符序列的时间序列特征。同时&#xff0c;引入改进的 Foc…

十三、MySQL高级—读写分离(6)

&#x1f33b;&#x1f33b; 目录 一、Mycat 介绍1.1 是什么1.2 干什么的1.3 原理 二、安装启动2.1 解压缩文件拷贝到linux下 /usr/local/2.2 三个文件2.3 启动前先修改schema.xml&#xff08;配置&#xff09;2.4 再修改server.xml2.5 验证数据库访问情况2.6 启动程序2.7 启动…

Hive SQL子查询应用

目录 环境准备看如下链接 子查询 查询所有课程成绩均小于60分的学生的学号、姓名 查询没有学全所有课的学生的学号、姓名 解释: 没有学全所有课,也就是该学生选修的课程数 < 总的课程数。 查询出只选修了三门课程的全部学生的学号和姓名 环境准备看如下链接 环境准备h…

应用层 思维导图

绪论&#xff1a; ​“有志者自有千计万计&#xff0c;无志者只感千难万难。” 话不多说安全带系好&#xff0c;发车啦&#xff08;建议电脑观看&#xff09;。 思维导图能很好的帮助到我们去学习和理解记忆知识&#xff0c;当我们对一个知识有了一定的框架后就能有逻辑性的去…

关于我的阿里云服务器被入侵 - 分析报告

目录 引言一、事件概述1. 异地登陆2. 挖矿程序3. 密钥未注册4. 勒索病毒 二、问题分析1. 异地登陆2. 挖矿程序3. 密钥登录失效&#xff08;密钥未注册&#xff09;4. 勒索病毒 三、安全知识讲解1. 密钥登录 四、总结 引言 因为是第一次租云服务器&#xff0c;所以出现了很多的…

Clion配置ESP32开发,一文就够了

目录 1.下载ESP-IDF2.配置ESP32开发环境2.1方法1:Clion官方手册2.2方法2: 3.测试Clion开发ESP32的环境4.关于Clion的monitor无法正常运行的解决方法 我这里使用的CLiion版本是2023.2.1&#xff0c;网上激活方法有很多&#xff0c;这里就不赘述。 电脑是WIn11系统。 1.下载ESP-I…

无线感知会议系列【1】【增强无线感知应用的鲁棒性】

前言&#xff1a; 这个是2021年 泛在可信智能感知论坛&#xff0c;汤战勇 &#xff08;西北大学物联网研究院 )教授的 一个讲座《wireless signals like WiFi, RFID and (ultra) sound as a powerful modality for ubiquitous sensing》 参考连接&#xff1a; 4.见微知萌—…

02_硬件基础知识学习

通过上一课的学习&#xff0c;我们貌似成功的点亮了一个 LED 小灯&#xff0c;但是有一些知识大家还没彻底搞明白。单片机是根据硬件电路图的设计来编写代码的&#xff0c;所以我们不仅仅要学习编程知识&#xff0c;还要学习基本的硬件知识&#xff0c;这节课我们就要来穿插介绍…