记某APP登录逆向解密过程
字数 1142 2025-08-22 12:23:13

APP登录逆向解密过程教学文档

1. 逆向分析准备

1.1 环境搭建

  • 测试设备:安装目标APP到测试机
  • 抓包工具:Burp Suite配置
    • 电脑端配置BP代理端口
    • 手机端设置代理与电脑同网络
  • 反编译工具:JADX用于反编译APK
  • 动态分析工具:Frida用于Hook验证

1.2 基本流程

  1. 安装目标APP到测试设备
  2. 抓取登录请求包
  3. 识别加密字段
  4. 反编译APP分析代码
  5. 定位关键加密方法
  6. Hook验证加密逻辑
  7. 还原加密算法

2. 密码加密逆向分析

2.1 定位密码加密位置

  • 搜索关键字:login/login.ashx
  • 定位到UserModel接口下的SecurityUtil.encodeMD5(str3)

2.2 MD5加密验证

  • 代码分析:
    SecurityUtil.encodeMD5(passwordString)
    
  • Python验证:
    import hashlib
    md5 = hashlib.md5()
    md5.update(b"123456")
    print(md5.hexdigest())  # e10adc3949ba59abbe56e057f20f883e
    
  • 通过对比抓包数据确认是标准MD5加密

2.3 Frida Hook验证

Java.perform(function() {
    var SecurityUtil = Java.use("com.example.app.util.SecurityUtil");
    SecurityUtil.encodeMD5.implementation = function(str) {
        console.log("MD5 input: " + str);
        var result = this.encodeMD5(str);
        console.log("MD5 output: " + result);
        return result;
    };
});

3. 签名(_sign)逆向分析

3.1 定位签名生成位置

  • 搜索关键字:_sign
  • 关键类:SignManager
  • 关键方法:signByType

3.2 签名生成逻辑

  1. 固定前缀字符串:W@oC!AH_6Ew1f6%8
  2. 拼接请求参数(按字典序排序)
  3. 再次拼接固定后缀字符串
  4. 对拼接结果进行MD5加密
  5. 结果转为大写

3.3 Python实现

import hashlib

def generate_sign(data_dict):
    data = "W@oC!AH_6Ew1f6%8"
    # 按key排序拼接
    result = "".join(["{}{}".format(key, data_dict[key]) 
                     for key in sorted(data_dict.keys())])
    un_sign_string = f"{data}{result}{data}"
    sign = hashlib.md5(un_sign_string.encode()).hexdigest().upper()
    return sign

4. UDID加密分析

4.1 UDID组成

getIMEI(context) + "|" + System.nanoTime() + "|" + SPUtils.getDeviceId()

4.2 IMEI获取逻辑

  1. 首先尝试从SharedPreferences读取
  2. 若不存在则通过系统API获取:
    ((TelephonyManager)context.getSystemService("phone")).getDeviceId()
    
  3. 若获取失败则使用WIFI MAC地址生成UUID
  4. 最终回退到随机UUID

4.3 3DES加密过程

  • 加密方法:SecurityUtil.encode3Des
  • 关键参数:
    • Key: appapiche168comappapiche168comap (前24字节有效)
    • IV: appapich
    • 模式: CBC

4.4 Python实现

from Crypto.Cipher import DES3
import base64

def encrypt_3des(plaintext):
    BS = 8
    pad = lambda s: s + (BS - len(s) % BS) * chr(BS - len(s) % BS)
    
    key = b'appapiche168comappapiche168comap'[0:24]
    iv = b'appapich'
    
    cipher = DES3.new(key, DES3.MODE_CBC, iv)
    padded_text = pad(plaintext).encode('utf-8')
    encrypted = cipher.encrypt(padded_text)
    return base64.b64encode(encrypted).decode()

5. 完整登录请求构造

5.1 请求参数示例

params = {
    "_appid": "atc.android",
    "appversion": "3.37.0",
    "channelid": "csy",
    "pwd": md5("123456"),  # e10adc3949ba59abbe56e057f20f883e
    "udid": encrypt_3des("IMEI|nanoTime|deviceId"),
    "username": "13111111111"
}

5.2 签名生成

sign = generate_sign(params)
params["_sign"] = sign

6. 关键Hook点总结

6.1 MD5加密Hook

Java.use("com.example.app.util.SecurityUtil")
    .encodeMD5.implementation = function(str) {
        // 打印输入输出
        return this.encodeMD5(str);
    };

6.2 签名生成Hook

Java.use("com.example.app.manager.SignManager")
    .signByType.implementation = function(type, map) {
        // 打印输入参数
        var result = this.signByType(type, map);
        // 打印签名结果
        return result;
    };

6.3 3DES加密Hook

Java.use("com.example.app.util.SecurityUtil")
    .encode3Des.implementation = function(context, str) {
        // 打印明文和context信息
        var result = this.encode3Des(context, str);
        // 打印加密结果
        return result;
    };

7. 逆向技巧总结

  1. 关键字搜索:通过接口路径、参数名等快速定位关键代码
  2. 静态分析:结合反编译工具理清代码逻辑
  3. 动态验证:使用Frida Hook关键方法验证分析结果
  4. 算法还原:通过输入输出对比确认加密算法
  5. 参数追踪:对于依赖上下文(Context)的方法,注意参数来源
  6. JNI处理:对于so文件加密,可考虑Hook获取关键值而非直接逆向

8. 完整Python实现示例

import hashlib
from Crypto.Cipher import DES3
import base64

def md5_encrypt(text):
    return hashlib.md5(text.encode()).hexdigest()

def encrypt_3des(plaintext):
    BS = 8
    pad = lambda s: s + (BS - len(s) % BS) * chr(BS - len(s) % BS)
    key = b'appapiche168comappapiche168comap'[0:24]
    iv = b'appapich'
    cipher = DES3.new(key, DES3.MODE_CBC, iv)
    padded_text = pad(plaintext).encode('utf-8')
    encrypted = cipher.encrypt(padded_text)
    return base64.b64encode(encrypted).decode()

def generate_sign(data_dict):
    fixed_str = "W@oC!AH_6Ew1f6%8"
    sorted_params = "".join(f"{k}{v}" for k, v in sorted(data_dict.items()))
    sign_str = f"{fixed_str}{sorted_params}{fixed_str}"
    return md5_encrypt(sign_str).upper()

# 构造登录请求
login_params = {
    "_appid": "atc.android",
    "appversion": "3.37.0",
    "channelid": "csy",
    "pwd": md5_encrypt("123456"),
    "udid": encrypt_3des("cf15599b-5e93-3be5-a705-a39403227dfd|13359325995159|366586"),
    "username": "13111111111"
}

login_params["_sign"] = generate_sign(login_params)
print("Final login params:", login_params)

通过以上步骤,我们完整还原了APP登录过程中的各个加密环节,包括密码的MD5加密、UDID的3DES加密以及请求签名的生成逻辑。

APP登录逆向解密过程教学文档 1. 逆向分析准备 1.1 环境搭建 测试设备 :安装目标APP到测试机 抓包工具 :Burp Suite配置 电脑端配置BP代理端口 手机端设置代理与电脑同网络 反编译工具 :JADX用于反编译APK 动态分析工具 :Frida用于Hook验证 1.2 基本流程 安装目标APP到测试设备 抓取登录请求包 识别加密字段 反编译APP分析代码 定位关键加密方法 Hook验证加密逻辑 还原加密算法 2. 密码加密逆向分析 2.1 定位密码加密位置 搜索关键字: login/login.ashx 定位到 UserModel 接口下的 SecurityUtil.encodeMD5(str3) 2.2 MD5加密验证 代码分析: Python验证: 通过对比抓包数据确认是标准MD5加密 2.3 Frida Hook验证 3. 签名(_ sign)逆向分析 3.1 定位签名生成位置 搜索关键字: _sign 关键类: SignManager 关键方法: signByType 3.2 签名生成逻辑 固定前缀字符串: W@oC!AH_6Ew1f6%8 拼接请求参数(按字典序排序) 再次拼接固定后缀字符串 对拼接结果进行MD5加密 结果转为大写 3.3 Python实现 4. UDID加密分析 4.1 UDID组成 4.2 IMEI获取逻辑 首先尝试从SharedPreferences读取 若不存在则通过系统API获取: 若获取失败则使用WIFI MAC地址生成UUID 最终回退到随机UUID 4.3 3DES加密过程 加密方法: SecurityUtil.encode3Des 关键参数: Key: appapiche168comappapiche168comap (前24字节有效) IV: appapich 模式: CBC 4.4 Python实现 5. 完整登录请求构造 5.1 请求参数示例 5.2 签名生成 6. 关键Hook点总结 6.1 MD5加密Hook 6.2 签名生成Hook 6.3 3DES加密Hook 7. 逆向技巧总结 关键字搜索 :通过接口路径、参数名等快速定位关键代码 静态分析 :结合反编译工具理清代码逻辑 动态验证 :使用Frida Hook关键方法验证分析结果 算法还原 :通过输入输出对比确认加密算法 参数追踪 :对于依赖上下文(Context)的方法,注意参数来源 JNI处理 :对于so文件加密,可考虑Hook获取关键值而非直接逆向 8. 完整Python实现示例 通过以上步骤,我们完整还原了APP登录过程中的各个加密环节,包括密码的MD5加密、UDID的3DES加密以及请求签名的生成逻辑。