某h软件-2

所需工具

  • 逍遥模拟器
  • lamda
  • jadx
  • frida
  • 一双手

抓包 #

软件有root检测和代理检测,这里不讲绕过。代理不要挂。 安装lamda:

set HTTPS_PROXY=127.0.0.1:7890
git clone https://github.com/rev1si0n/lamda.git

rev1si0n/lamda: ⚡️ Android reverse engineering & automation framework | 史上最强安卓抓包/逆向/HOOK & 云手机/远程桌面/自动化辅助框架,你的工作从未如此简单快捷。

下载lamda-server-x86_64.tar.gz 以及busybox-x86_64

先把模拟器的root打开

# 在你下载好的目录打开终端
adb push lamda-server-x86_64.tar.gz /data/local/tmp
adb push busybox-x86_64 /data/local/tmp


adb shell
# 以下命令都是在adb shell中执行的
su

chmod 755 /data/local/tmp/busybox-x86_64
cd /data

/data/local/tmp/busybox-x86_64 tar -xzf /data/local/tmp/lamda-server-x86_64.tar.gz

rm /data/local/tmp/lamda-server-x864.tar.gz
rm /data/local/tmp/busybox-x86_64

启动lamda

继续上一步结尾

cd /data/local/tmp/server/bin

sh launch.sh

启动完成 Pasted image 20231216130555

ctrl+D退出终端

在你的lamda目录里打开终端

cd tools
python startmitm.py localhost

启动app,记得关掉root再启动,已经可以抓包了

逆向 #

看看抓包

Pasted image 20231216152407

一眼盯帧,是有加密,那么,开始逆向吧 工具jadx,把apk拖进去

X-JSL-API-AUTH #

搜索大法好啊,ctrl+shift+F,直接找关键字 X-JSL-API-AUTH

只有一处

Pasted image 20231216152631

有,直接跟进去,v.a.a

String a = v.a.a(Z.h().u().getPath());

看到MD5关键字

Pasted image 20231216154541

参数基本一目了然

Pasted image 20231216154729

唯一有一个key参数,来自so层,右键这个函数,生成frida hook代码, Pasted image 20231216154806 frida hook不在此展开,多次hook易得key横不变,为 l8N2iooyp07M9IWa

易得脚本

X-TOKEN #

搜索,只有一个,按x,交叉引用,诶,找不到 Pasted image 20231216161614

但是,我们继续在上面能找到 f.a(com.niming.weipa.b.a.A, com.niming.weipa.utils.b.b(String.valueOf(jSONObject))); 一句

com.niming.weipa.b.a.A就是 X-TOKEN,后面是在加密那坨hashmap 看看加密,AES/ECB/PKCS7Padding,key还是同一个l8N2iooyp07M9IWa Pasted image 20231216162203

DATA #

直接去搜索data的话,肯定会有很多结果,注意到json中有一个handshake参数,大概是恒固定的,去搜索一下v20200429

只有一个结果,直接定位到加密

Pasted image 20231216162944

发现是使用的是和上面相同的加密方法 Pasted image 20231216163029

hook一下这个加密方法,看看都加密是些什么东西

右键这个方法,复制frida 方法,这里不再展开

邀请好友 #


from hashlib import md5
import time
import requests
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad, unpad
import base64,json
import random
MODE = AES.MODE_ECB
PAD_STYLE = 'pkcs7'
ENCODING = 'UTF-8'
key='l8N2iooyp07M9IWa'
url='http://apichlove.com'
def encrypt(plaintext: str, key: str) -> str:
    key_bytes = key.encode(ENCODING)
    cipher = AES.new(key_bytes, MODE)
    plaintext_bytes = plaintext.encode(ENCODING)
    plaintext_bytes_padded = pad(plaintext_bytes, AES.block_size, PAD_STYLE)
    ciphertext_bytes = cipher.encrypt(plaintext_bytes_padded)
    ciphertext_base64_bytes = base64.b64encode(ciphertext_bytes) 
    ciphertext = ciphertext_base64_bytes.decode(ENCODING)
    return ciphertext
def decrypt(ciphertext: str, key: str) -> str:
    key_bytes = key.encode(ENCODING)
    decrypter = AES.new(key_bytes, MODE)
    ciphertext_base64_bytes = ciphertext.encode(ENCODING)
    ciphertext_bytes = base64.b64decode(ciphertext_base64_bytes)
    plaintext_bytes_padded = decrypter.decrypt(ciphertext_bytes)
    plaintext_bytes = unpad(plaintext_bytes_padded, AES.block_size, PAD_STYLE)
    plaintext = plaintext_bytes.decode(ENCODING)
    return plaintext
def x_t(url):
    a = []
    b = []
    # url = 'app/api/auth/login/device'
    v1 = str(int(time.time()))
    v2 = md5(v1.encode()).hexdigest()[:8]
    a.append('md5')
    a.append(key)
    a.append(v1)
    a.append(v2)
    a.append(url)
    v3 = '|'.join(a)
    v3 = md5(v3.encode()).hexdigest()
    b.append('md5')
    b.append(v1)
    b.append(v2)
    b.append(v3)
    return '|'.join(b)
def getRandom(randomlength=16):
    digits='0123456789'
    ascii_letters='abcdefghigklmnopqrstuvwxyz'
    str_list =[random.choice(digits +ascii_letters) for i in range(randomlength)]
    random_str =''.join(str_list)
    return random_str
def Token():
    device_id='b2ad30fc-0301-3d50-a97f-'+getRandom(12)
    data = json.dumps({"channel": "", "code": "", "device_no": device_id,"device_type": "A", "version": "1.0.0"})
    data={'data':encrypt(data,key),'handshake':'v20200429'}
    header = {'X-JSL-API-AUTH': x_t('/app/api/auth/login/device')}
    result = requests.post(url+'/app/api/auth/login/device', json=data, headers=header).json()
    msg=decrypt(result['data'],key)
    # print(msg)
    return json.loads(msg)['auth']['token'],device_id
def x_token(device_id,token):
    Json=json.dumps({"device_no":device_id,"device_type":"A","token":token,"version":"1.0.0"})
    return encrypt(Json,key)
def parent(code):
    token,device_id=Token()
    data={'data':encrypt(json.dumps({'code':code}),key),'handshake':'v20200429'}
    header={'X-JSL-API-AUTH':x_t('/app/api/user/bindcode'),'X-TOKEN':x_token(device_id=device_id,token=token)}
    result=requests.post(url+'/app/api/user/bindcode',json=data,headers=header).json()
    print(result)
    print(decrypt(result['data'],key))
    header['X-JSL-API-AUTH']=x_t('/app/api/user/info')
    # 你的X-TOKEN
    # header['X-TOKEN']='4LJnAngoza8TZIz2otKTe52PhqbrW8GULUYVUu87AjDKzXQWPzNCDiHTohcbTWRcJ5V+mdgxrLVskUbLae90njTJJk4bG8tqYcgDX/fhwwG0VkkB11CY0wLhlxPfSkfMSlqmArvVTbrJ7UiydzotGh9nUHVrBqxMbDy9+iuhq9pFmucuV1SRKd/1pGxDNI0UX9nA5mpYMfYih0N/vR3A6+AdHQASRqBpeXSfMj3M7fHY/5W4fj0esNHkw93KjsnWM2FJWdNCYrkZC3tHWipUqKTk7zvbx20zaWo/c78VuePh8OeiCV2Htt9ah8+MNvAu+o6TERNF13aavGJkxeptaZs/+PFbBa397NVD4zQ28QDhkuOthPwHbpvOL/cWm9rjoL7TH7BdKGqjbYzHTvUnpWHQtJhGTPXRdNdSklDv4UDW/nsKTVVcv1LQAU1Oo5EnMwfZF2wmTtIRMRTPIi9zYFVhTYlJeFroe2fWrl8H9afzxz+fP+tm5aGSa7Ll0RBitPmN364On3xaWrRIiYGvfYsqckb6+BRQyDMXI+nHUMOAR2EcT6U3BMUCN5VJnkX8atWL76jdqPlFZzS9zyo5yaeiNLnQzVYm9wxNPuzb9ZMgvRQ4TnXfBGE5t8BiE4jAPJczvQhvWseHNy3M3wCd5b7CavKAVznoovCoLaqJpRX+bOWnttUWMLqdYxBnweL3'
    # result=requests.post(url+'/app/api/user/info',data='{"handshake":"v20200429"}',headers=header).json()
    # print(json.loads(decrypt(result['data'],key))['vip_expired'])


# 邀请码
for i in range(5):
    parent('RWK6IF')