高中生

- 金币
- 595
- 好评
- 1
- 信誉
- 100
|
嗯,对方只呢个出几十元,太廉价,还是算了。直接发出来研究吧
apk也不想分析了,直接抓包
- POST https://api.gdvaluechain.com/api/member/login HTTP/1.1
- Accept-Encoding: gzip
- Authorization: Bearer
- Connection: Keep-Alive
- Content-Length: 344
- Content-Type: application/json
- Cookie: server_name_session=a8ff308697289d8e34c7554aa6d0b9cd
- Host: api.gdvaluechain.com
- encrypted: true
- user-agent: Mozilla/5.0 (Linux; Android 9; SM-S9280 Build/PQ3B.190801.10161937; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/91.0.4472.114 Mobile Safari/537.36 uni-app Html5Plus/1.0 (Immersed/24.0)
- enwagHRQ2PUrLkS7jCZNMt4FeIbK6UCGwk0Z1oWPgiOENfnzwMVxG970KbjGyeKpydKLZyc7bgWLbrqQecQMb/bG2CsJR1DJ5FnyjC9ndtrVUd+hBSDRBGZcJwpNQENFY93xKK4FwBNLyYic79On3GyI81ruHk9gQHkLcvPgINP/dCxwUoYTIUQ0VOzRbcdfY80cw3OItsHsT5xaFIpEYHN3aJUnjJFMhf6ZE3E+ZsLgZPr3zBEACL7Qi2ZVQXKQsnYsaiVy6OlYDjOzKhBEv/7GA48uAINGa1KEZ7xgUmYzOlOQuqtqPTd7MQSW/11aL/6xcx8Gg5sselW9xTUeRw==
复制代码
看这个请求就明白起码是base64吧。在看看长度,肯定不是对称算法。因为每次请求都不一样,所以怀疑是rsa算法。而且客户自己也说了是rsa算法。
rsa是没办法解密的,除非能拿到私钥
我们直接上工具,把内存数据拉下来看看
先导出证书看看,能不能找到rsa证书
遗憾,不是明文,还有函数。
那么,我们从其他方面入手,还是先查内存数据,我们输入的密码看看
有收货啊
我们换个关键词,查看下接口api看看 member/login
很好,我们除了发现了接口api以及请求数据外,最主要的是我们发现了js文件。
这个js文件我们抓包的时候没抓到,所以可以肯定是apk内部生成释放到本地或者内存中的
复制到code里自行查看
文档中阅读比较清晰。post请求,data:a
所以加密函数就是_i啊
在文档中继续搜索_i的定义处
内存数据里找到了
一眼看见rsa公钥
(很奇怪的是我们第一步导出公钥到时候竟然没导出到,看来我们的神器还需要继续优化)
那简单了,结合我们刚才内存数据中找到的加密前的数据构造,公钥也有了,直接构造模仿请求测试下就能真相大白啊
- import json
- import base64
- import math
- import urllib.parse
- import requests
- from Crypto.PublicKey import RSA
- from Crypto.Cipher import PKCS1_v1_5
- # ==========================================
- # 1. 配置部分
- # ==========================================
- # 目标 URL
- URL = "https://api.gdvaluechain.com/api/member/login"
- # 公钥 (从之前的 JS 代码中提取) 这里我就省略部分中啊哟内容了
- PUBLIC_KEY_STR = """MIIBIjANBgkqhkiG9x x xxxxxxxxxxxxxxxeD/wn1fQLCGXTAQaTvt1KNQ7vq9tA0WaKxq31oHVXcwWqftYjs1/qRl9P41TQwddKtoEk4+2LkrqM+6qObAfzUvH8V9TeEb5Yh9XqwoItR2XSTsBfiTt9NZ/zNRUsRlDXOCZNXU7xs44SA7xMttycqvd3ZvLk0RcpTM8mmnCvNQIDAQAB"""
- # 格式化公钥为 PEM 格式
- PEM_PUBLIC_KEY = f"-----BEGIN PUBLIC KEY-----\n{PUBLIC_KEY_STR}\n-----END PUBLIC KEY-----"
- # 我们请求的原始数据构造
- payload_data = {
- "mobile": "1327710x x xxx", //真实值隐藏下了
- "password": "123456aa",
- "version": "1.1.9"
- }
- # 请求头
- headers = {
- "Host": "api.gdvaluechain.com",
- "Connection": "Keep-Alive",
- "Accept-Encoding": "gzip",
- "Content-Type": "application/json",
- "encrypted": "true", # 【关键】告诉服务器这是加密数据
- "Authorization": "Bearer",
- "User-Agent": "Mozilla/5.0 (Linux; Android 9; SM-S9280 Build/PQ3B.190801.10161937; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/91.0.4472.114 Mobile Safari/537.36 uni-app Html5Plus/1.0 (Immersed/24.0)",
- "Cookie": "server_name_session=a8ff308697289d8e34c7554aa6d0b9cd"
- }
- # ==========================================
- # 2. 加密函数 (完全复刻 JS 逻辑)
- # ==========================================
- def encrypt_payload(data_dict):
- # 1. JSON 序列化 (去除空格,模拟 JSON.stringify)
- # JS: JSON.stringify(e.data)
- json_str = json.dumps(data_dict, separators=(',', ':'))
-
- # 2. URL 编码
- # JS: encodeURIComponent(e)
- # Python 的 urllib.parse.quote 默认会转义很多字符,需要指定 safe 列表来模拟 JS 的行为
- # JS 不转义的字符: A-Z a-z 0-9 - _ . ! ~ * ' ( )
- encoded_str = urllib.parse.quote(json_str, safe='~()*!.\'')
-
- # 3. 加载公钥
- key = RSA.importKey(PEM_PUBLIC_KEY)
- cipher = PKCS1_v1_5.new(key)
-
- # 4. 分段加密
- # JS 逻辑: 每次取 117 个字符
- chunk_size = 117
- encrypted_chunks = []
-
- length = len(encoded_str)
- # 计算分段数量
- num_chunks = math.ceil(length / chunk_size)
-
- print(f"[debug] 原始字符串: {json_str}")
- print(f"[debug] 编码后字符串: {encoded_str}")
-
- for i in range(num_chunks):
- start = i * chunk_size
- end = min((i + 1) * chunk_size, length)
- chunk = encoded_str[start:end]
-
- # RSA 加密 (需要转成 bytes)
- ciphertext = cipher.encrypt(chunk.encode('utf-8'))
-
- # 转 Base64
- b64_text = base64.b64encode(ciphertext).decode('utf-8')
- encrypted_chunks.append(b64_text)
-
- # 5. 拼接
- # JS: return a.join("$split$")
- return "$split$".join(encrypted_chunks)
- # ==========================================
- # 3. 发送请求
- # ==========================================
- # 执行加密
- final_body = encrypt_payload(payload_data)
- print(f"\n[debug] 生成的加密Body (前50字符): {final_body[:50]}...")
- print(f"[debug] Body总长度: {len(final_body)}")
- # 发送 POST 请求
- # 注意:虽然 Header 写的是 application/json,但根据抓包,实际发送的是纯文本 Base64 字符串,不是 JSON 对象
- try:
- response = requests.post(URL, headers=headers, data=final_body, verify=True) # verify=False 如果你没有SSL证书链
-
- print("\n" + "="*30)
- print(f"响应状态码: {response.status_code}")
- print("="*30)
- print("响应内容:")
- try:
- # 尝试解析响应 JSON
- print(json.dumps(response.json(), indent=4, ensure_ascii=False))
- except:
- print(response.text)
-
- except Exception as e:
- print(f"请求发生错误: {e}")
复制代码
看到这个结果就知道我们成功了。又一例从内存数据中直接分析逻辑的案例
|
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有账号?立即注册
x
-
查看全部评分
总评分:好评 +1
金币 +1
|