关注微信公众号:K哥爬虫,持续分享爬虫进阶、JS/安卓逆向等技术干货!

声明

本文章中所有内容仅供学习交流,抓包内容、敏感网址、数据接口均已做脱敏处理,严禁用于商业用途和非法用途,否则由此产生的一切后果均与作者无关,若有侵权,请联系我立即删除!

逆向目标

  • 目标:Ether Rock(一种数字货币)空投接口 AES256 加密分析
  • 主页:aHR0cHM6Ly9ldGhlcnJvY2submV0L2FpcmRyb3Av
  • 接口:aHR0cHM6Ly9ldGhlcnJvY2submV0L2FpcmRyb3Atc3VibWl0
  • 逆向参数:Form Data:content: U2FsdGVkX1/XnffSPZONOHb... key: jrwBwX2ll38bu/FFql+bAUYrRG8Ij...

逆向分析

来到空投页面,随便输入一个 ETH 钱包地址,点击提交,可抓包到提交接口,POST 请求,Form Data 里 content 和 key 参数均经过了加密处理,如下图所示:

老方法,尝试直接搜索,结果很多,不利于快速定位,XHR 断点,很容易定位到加密位置,如下图所示:

一步一步分析,首先定义了 content 对象:

var content={
address:$(this).find('input[name=address]').val(),
ref:$(this).find('input[name=ref]').val(),
uuid:uuid,
tz:tz,
tz_offset:tz_offset,
screen:window.screen.width+'x'+window.screen.height+'x'+window.screen.colorDepth,
user_agent:navigator.userAgent,
cpu:navigator.hardwareConcurrency,
lang:navigator.language||navigator.userLanguage,
};

address 是钱包地址,ref、uuid 为空,tz 是时区,tz_offset 是时区偏移量,即当前时区与格林尼治标准时间(GMT)的差,screen 是屏幕相关信息,user_agent 是浏览器信息,cpu 是处理器数量,lang 是语言。这些值除了 address 以外都可以固定。

接下来定义了一个 key:var key=random_string(36);,跟进 random_string() 方法,可以看到是进行了一些取随机值和幂运算,可以直接 copy 下来,如下图所示:

接着将定义的 content 和生成的 key 进行了一个叫做 AES256 的加密:content=AES256.encrypt(JSON.stringify(content),key); 这里 AES256 一般是指的密钥长度为 32 bytes(256 bit / 8)的 AES 加密,但是不要被名称迷惑,我们跟进去看看:

可以看到实际上是调用了 h.AES.encrypt() 方法,往上看这个 h,可以看到是引用了 node-cryptojs-aes,支持 AES 对称密钥加密,这里就比较简单了,我们在本地也直接引入这个库即可,至此,content 的加密方式就找到了。

接下来看 key 值,这个就更简单了,很明显用的是 jsencrypt 库,对原来生成的 36 位字符串的 key 进行了 RSA 加密,同样在本地直接引用库即可。

完整代码

GitHub 关注 K 哥爬虫,持续分享爬虫相关代码!欢迎 star !https://github.com/kgepachong/

以下只演示部分关键代码,不能直接运行! 完整代码仓库地址:https://github.com/kgepachong/crawler/

JavaScript 加密代码

function randomString(N) {
if (!parseInt(N, 10)) N = 6;
var rs = Math.floor(Math.pow(36, N) * Math.random()).toString(36);
return (Math.pow(10, N) + rs).substr(-N);
} var h = require("node-cryptojs-aes").CryptoJS
, p = {
stringify: function (b) {
var e = h.enc.Hex.parse(b.salt.toString()).toString(h.enc.Latin1);
b = b.ciphertext.toString(h.enc.Latin1);
return h.enc.Latin1.parse("Salted__" + e + b).toString(h.enc.Base64)
},
parse: function (b) {
b = h.enc.Base64.parse(b).toString(h.enc.Latin1);
if ("Salted__" !== b.substr(0, 8))
throw Error("Error parsing salt");
var e = b.substr(8, 8);
b = b.substr(16);
return h.lib.CipherParams.create({
ciphertext: h.enc.Latin1.parse(b),
salt: h.enc.Latin1.parse(e)
})
}
}; var e = randomString(36); function getContent(address) {
var b = JSON.stringify({
"address": address,
"ref": "",
"uuid": "",
"tz": "Asia/Shanghai",
"tz_offset": 8,
"screen": "1920x1080x24",
"user_agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.81 Safari/537.36",
"cpu": 8,
"lang": "zh"
})
return h.AES.encrypt(b, e, {
format: p
}).toString()
} function getKey() {
JSEncrypt = require("jsencrypt")
var crypt = new JSEncrypt();
var pub = [
'-----BEGIN PUBLIC KEY-----',
'MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDVmYQhCYTnnkTPRMI5Ad3vfad9',
'lhjzOU92FZ3reUiN/vmqP/wC1DKKExYDsqa+w5xBP0AjGkfDWk3q4PlWu0UsBGZx',
'62Gvt0ds75u8FnmLv+ufMimF4962/9Lx7uyh9g1H3/ze5ZXscWYy3gtts9d2Ga0R',
'pl0X49Cz0JhYYicuGwIDAQAB',
'-----END PUBLIC KEY-----',
];
crypt.setPublicKey(pub.join('\n'));
key = crypt.encrypt(e);
return key
} function getContentAndKey(address) {
result = {
"key": getKey(),
"content": getContent(address)
}
return result
} // 测试样例
// console.log(getContentAndKey("xxxxxxxxxxxxxxxx"))

Python 代码

# ==================================
# --*-- coding: utf-8 --*--
# @Time : 2021-11-24
# @Author : 微信公众号:K哥爬虫
# @FileName: airdrop_submit.py
# @Software: PyCharm
# ================================== import execjs
import requests def get_content_and_key(address):
with open("get_content_and_key.js", encoding="utf-8") as f:
ether_rock_js = f.read()
content_and_key_dict = execjs.compile(ether_rock_js).call('getContentAndKey', address)
return content_and_key_dict def airdrop_submit(content_and_key_dict):
submit_url = "脱敏处理,完整代码关注 GitHub:https://github.com/kgepachong/crawler"
headers = {
"Accept": "text/html, */*; q=0.01",
"Accept-Language": "zh,zh-CN;q=0.9,en-US;q=0.8,en;q=0.7",
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.81 Safari/537.36",
"X-Requested-With": "XMLHttpRequest",
"Host": "脱敏处理,完整代码关注 GitHub:https://github.com/kgepachong/crawler",
"Origin": "脱敏处理,完整代码关注 GitHub:https://github.com/kgepachong/crawler",
}
data = {
"content": content_and_key_dict["content"],
"key": content_and_key_dict["key"]
}
response = requests.post(url=submit_url, data=data, headers=headers)
print(response.text) def main():
address = input("请输入ETH钱包地址领取空投: ")
content_and_key_dict = get_content_and_key(address)
airdrop_submit(content_and_key_dict) if __name__ == '__main__':
main()

【JS 逆向百例】Ether Rock 空投接口 AES256 加密分析的更多相关文章

  1. JS逆向实战11——某金属集团动态cookie加密

    本文来自:来自: https://www.cnblogs.com/zichliang/ 目标网站 aHR0cDovL3d3dy50bm1nLmNvbS5jbi9pbmZvcm1hdGlvbi9pbmZ ...

  2. JS逆向实战13——某市公共资源交易中心Cookie混淆加密

    "本文地址:https://www.cnblogs.com/zichliang/p/17346860.html 目标网站 aHR0cDovL2xkZ2d6eS5obmxvdWRpLmdvdi ...

  3. 通过JS逆向ProtoBuf 反反爬思路分享

    前言 本文意在记录,在爬虫过程中,我首次遇到Protobuf时的一系列问题和解决问题的思路. 文章编写遵循当时工作的思路,优点:非常详细,缺点:文字冗长,描述不准确 protobuf用在前后端传输,在 ...

  4. Java设计模式百例 - 观察者模式

    观察者(Observer)模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象,主体对象的状态变化会通知所有观察者对象.观察者模式又叫做发布-订阅(Publish/Subscribe ...

  5. 网络爬虫之记一次js逆向解密经历

    1 引言 数月前写过某网站(请原谅我的掩耳盗铃)的爬虫,这两天需要重新采集一次,用的是scrapy-redis框架,本以为二次爬取可以轻松完成的,可没想到爬虫启动没几秒,出现了大堆的重试提示,心里顿时 ...

  6. 我去!爬虫遇到JS逆向AES加密反爬,哭了

    今天准备爬取网页时,遇到『JS逆向AES加密』反爬.比如这样的: 在发送请求获取数据时,需要用到参数params和encSecKey,但是这两个参数经过JS逆向AES加密而来. 既然遇到了这个情况,那 ...

  7. python爬虫之企某科技JS逆向

    python爬虫简单js逆向案例在学习时需要用到数据,学习了python爬虫知识,但是在用爬虫程序的时候就遇到了问题.具体如下,在查看请求数据时发现返回的数据是加密的信息,现将处理过程记录如下,以便大 ...

  8. python爬虫之JS逆向

    Python爬虫之JS逆向案例 由于在爬取数据时,遇到请求头限制属性为动态生成,现将解决方式整理如下: JS逆向有两种思路: 一种是整理出js文件在Python中直接使用execjs调用js文件(可见 ...

  9. JS逆向之补环境过瑞数详解

    JS逆向之补环境过瑞数详解 "瑞数" 是逆向路上的一座大山,是许多JS逆向者绕不开的一堵围墙,也是跳槽简历上的一个亮点,我们必须得在下次跳槽前攻克它!! 好在现在网上有很多讲解瑞数 ...

  10. JS逆向之浏览器补环境详解

    JS逆向之浏览器补环境详解 "补浏览器环境"是JS逆向者升职加薪的必备技能,也是工作中不可避免的操作. 为了让大家彻底搞懂 "补浏览器环境"的缘由及原理,本文将 ...

随机推荐

  1. Mac 修改文件默认打开方式

    Mac 播放 swf Flash文件 选中文件,Command+i 打开简介 不过文件图标还没变过来.重新下明天再看看

  2. 如何使用Java在Excel中添加动态数组公式?

    本文由葡萄城技术团队发布.转载请注明出处:葡萄城官网,葡萄城为开发者提供专业的开发工具.解决方案和服务,赋能开发者. 前言 动态数组公式是 Excel 引入的一项重要功能,它将 Excel 分为两种风 ...

  3. protobuf安装、编译和使用

    protobuf使用简单示例 一.安装 首先下载protobuf的安装包,我这里使用的是protobuf-cpp-3.21.5.tar.gz 解压安装包 tar -xzf protobuf-cpp-3 ...

  4. Java 21 新特性:Unnamed Patterns and Variables

    Java 21中除了推出JEP 445:Unnamed Classes and Instance Main Methods之外,还有另外一个预览功能:未命名模式和变量(Unnamed Patterns ...

  5. 30例 | 一文搞懂python日期时间处理

    前言 datetime是python的内置模块,用来处理日期和时间. 该模块常用的类有: 类名 功能说明 date 日期对象 time 时间对象 datetime 日期时间对象 timedelta 时 ...

  6. 函数计算 FC 3.0 发布,全面降价,最高幅度达93%,阶梯计费越用越便宜

    作为国内最早布局 Serverless 的云厂商之一,阿里云在 2017 年推出函数计算 FC,开发者只需编写代码并上传,函数计算就会自动准备好相应的计算资源,大幅简化开发运维过程.阿里云函数计算持续 ...

  7. 阿里云 X 森马 AIGC T恤设计大赛开启! 穿什么由你定,赢Airpods,作品定制联名T恤

    "关于宇宙,我所知道的最富诗意的事实之一就是, 我们身体中的每一个原子都曾经存在于某一颗爆发的恒星里. 组成你左手的原子和组成你右手的原子 很有可能来自不同的恒星, 而我们都是恒星的孩子, ...

  8. 【驱动】SPI驱动分析(七)-SPI驱动常用调试方法

    用户态 用户应用层使用spidev驱动的步骤如下: 打开SPI设备文件:用户可以通过打开/dev/spidevX.Y文件来访问SPI设备,其中X是SPI控制器的编号,Y是SPI设备的编号. 配置SPI ...

  9. 【调试】kprobes(一)基本概念

    简介 开发人员在内核或者模块的调试过程中,往往会需要要知道其中的一些函数有无被调用.何时被调用.执行是否正确以及函数的入参和返回值是什么等等. 比较简单的做法是在内核代码对应的函数中添加日志打印信息, ...

  10. vue-awesome-swiper swiper/dist/css/swiper.css 报not found错误

    解决办法删除package-lock.json文件写死package.json版本号  "vue-awesome-swiper": "^3.1.3", 删除no ...