admin管理员组

文章数量:1586175

下载地址应用宝: https://a.app.qq/o/simple.jsp?pkgname=com.hw.okm

抓包看到请求体有 sign 参数 及响应是加密的状态

360壳加固脱壳并修复~
过root检测,该app有多方面检测root~
我们直接修改smali过掉~

java层循环检测root


我是直接将 public static final String COMMAND_SU = “su”;
更改为: public static final String COMMAND_SU = “zhihuijiance”;

已达到一个去除root检测的方案。

package com.hw.okm.g;


DispatchConstants.SIGN, 就是"sign"

那么就剩 s.a(s.a(sb.deleteCharAt(sb.length() - 1).toString()) + com.hw.okm.c.a.f11289d

sb.deleteCharAt(sb.length() - 1).toString()


盲猜 就是 参数加到sb 每个后面都会加 “&” 最后去掉最后那个 “&” 然后走s.a()方法

走完后 再 加上 f11289d 再走一遍MD5方法 也就是套两层md5

f11289d 是:

def md5_ersanli(data):
    _sign = ''
    for key, values in data.items():
        _sign += key + "=" + values + "&"

    encryptValue = bytes(_sign[:-1].encode("utf-8"))
    sign_encryption = hashlib.md5(encryptValue).hexdigest()

    f6967d = "qB5LB51bUHAjFBA4Bh3YQnoDRrC912KWumxLyDzvOojP6VBH6fAwoHE6w0t58H5MtEsQDpmeVUV2C5JOjCAa4kMp35R8aIZ4fWD6uD9iDvnUHH6XTKKF1KzoJ4ddA8w39I05Re7qQi9vDtpC8iSFEIrvgmo4b01WhcELvi3DIli0ik9O1AmkEvSXKJB0DXDc1nFrF4W5Gg3Vq3rcsabKR340uvcDaPuDcd2XC7771HX1U80Ed1pWQZtsAFDtVD5Y";
    encryptValue = bytes((sign_encryption + f6967d).encode("utf-8"))
    sign = hashlib.md5(encryptValue).hexdigest()

    return sign

frida走起:

# -*- coding: utf-8 -*-
# @Author  : Codeooo
# @Time    : 2021/11/18



import frida, sys



jscode ="""
Java.perform(function () {
    var utils = Java.use('com.hw.okm.g.a');
    utils.e.implementation = function () {
        console.log("======Hook Start...=========");
		send(arguments[0]);
        send(arguments[1]);
        send(arguments[2]);
        var map = arguments[2]
        for (var key in map) {
            console.log(key);
        }
		send("==========以上是返回值==========");
        console.log(this.e(arguments[0],arguments[1],arguments[2]));
        return this.e(arguments[0],arguments[1],arguments[2]);
    }
});
"""


res ="""
Java.perform(function () {
    var utils = Java.use('com.hw.okm.utils.s');
    utils.a.implementation = function () {
        console.log("======Hook Start...=========");
		send(arguments[0]);
		send("==========以上是返回值==========");
        console.log(this.a(arguments[0]));
        return this.a(arguments[0]);
    }
});
"""




def message(message, data):
    if message["type"] == 'send':
        print("[*] {0}".format(message['payload']))
    else:
        print(message)

process = frida.get_remote_device().attach('com.hw.okm')
# script= process.create_script(jscode)
script= process.create_script(res)
script.on("message", message)
script.load()
sys.stdin.read()


响应这块也进行了加密 :


我们请求下:

发现响应是这样的 ,看源码解密流程:



密钥找到了,那么第一个参数应该是刚刚响应加密那一串

package com.hw.okm.utils;

import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;

/* loaded from: classes2.dex */
public class a {

    /* renamed from: a  reason: collision with root package name */
    private static final char[] f12700a = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};

    /* renamed from: b  reason: collision with root package name */
    private static final char[] f12701b = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};

    /* renamed from: c  reason: collision with root package name */
    private static String f12702c = "utf-8";

    /* renamed from: d  reason: collision with root package name */
    private static String f12703d = "AES/ECB/PKCS5Padding";

    /* renamed from: e  reason: collision with root package name */
    private static String f12704e = "AES";

    public static byte[] a(CharSequence charSequence) {
        if (y.e(charSequence.toString())) {
            return null;
        }
        int length = charSequence.length();
        if ((length & 1) != 0) {
            charSequence = "0" + ((Object) charSequence);
            length = charSequence.length();
        }
        byte[] bArr = new byte[length >> 1];
        int i = 0;
        int i2 = 0;
        while (i < length) {
            int i3 = i + 1;
            i = i3 + 1;
            bArr[i2] = (byte) (((j(charSequence.charAt(i), i) << 4) | j(charSequence.charAt(i3), i3)) & 255);
            i2++;
        }
        return bArr;
    }

    public static String b(String str) {
        return c(str, com.hw.okm.c.a.f11288c);
    }

    public static String c(String str, String str2) {
        try {
            SecretKeySpec secretKeySpec = new SecretKeySpec(str2.getBytes(), f12704e);
            Cipher instance = Cipher.getInstance(f12703d);
            instance.init(2, secretKeySpec);
            return new String(instance.doFinal(a(str)), "UTF-8");
        } catch (Exception e2) {
            e2.printStackTrace();
            return null;
        }
    }

    protected static char[] d(byte[] bArr, char[] cArr) {
        int length = bArr.length;
        char[] cArr2 = new char[length << 1];
        int i = 0;
        for (int i2 = 0; i2 < length; i2++) {
            int i3 = i + 1;
            cArr2[i] = cArr[(bArr[i2] & 240) >>> 4];
            i = i3 + 1;
            cArr2[i3] = cArr[bArr[i2] & 15];
        }
        return cArr2;
    }

    public static String e(byte[] bArr) {
        return f(bArr, true);
    }

    public static String f(byte[] bArr, boolean z) {
        return g(bArr, z ? f12700a : f12701b);
    }

    protected static String g(byte[] bArr, char[] cArr) {
        return new String(d(bArr, cArr));
    }

    public static String h(String str) {
        return i(str, com.hw.okm.c.a.f11288c);
    }

    public static String i(String str, String str2) {
        try {
            SecretKeySpec secretKeySpec = new SecretKeySpec(str2.getBytes(), f12704e);
            Cipher instance = Cipher.getInstance(f12703d);
            byte[] bytes = str.getBytes(f12702c);
            instance.init(1, secretKeySpec);
            return e(instance.doFinal(bytes));
        } catch (Exception e2) {
            e2.printStackTrace();
            return null;
        }
    }

    private static int j(char c2, int i) {
        int digit = Character.digit(c2, 16);
        if (digit < 0) {
            return 0;
        }
        return digit;
    }
}

看下源码

Over , 其实加密这块还比较简单都是标准的一些算法, 该app难点在于:

去除360加固,修改dex,并去除root检测,过掉反调试。

# -*- coding: utf-8 -*-
# @Author  : Codeooo
# @Time    : 2022/04/26


import re
import json
import time
import uuid
import hashlib
import requests
import binascii

from collections import OrderedDict
from Crypto.Cipher import AES


def md5_ersanli(data):
    _sign = ''
    for key, values in data.items():
        _sign += key + "=" + values + "&"

    encryptValue = bytes(_sign[:-1].encode("utf-8"))
    sign_encryption = hashlib.md5(encryptValue).hexdigest()

    f6967d = "qB5LB51bUHAjFBA4Bh3YQnoDRrC912KWumxLyDzvOojP6VBH6fAwoHE6w0t58H5MtEsQDpmeVUV2C5JOjCAa4kMp35R8aIZ4fWD6uD9iDvnUHH6XTKKF1KzoJ4ddA8w39I05Re7qQi9vDtpC8iSFEIrvgmo4b01WhcELvi3DIli0ik9O1AmkEvSXKJB0DXDc1nFrF4W5Gg3Vq3rcsabKR340uvcDaPuDcd2XC7771HX1U80Ed1pWQZtsAFDtVD5Y";
    encryptValue = bytes((sign_encryption + f6967d).encode("utf-8"))
    sign = hashlib.md5(encryptValue).hexdigest()

    return sign


def get_deviceId():
    return "".join(str(uuid.uuid4()).split("-"))


def decrypt(decrData, password='rFQJTvMFzm8MtBRy'):
    if isinstance(password, str):
        password = password.encode('utf8')

    cipher = AES.new(password, AES.MODE_ECB)
    plain_text = cipher.decrypt(binascii.a2b_hex(decrData))
    # print("plain_text", str(plain_text, 'utf-8').rstrip('\r'))
    # return plain_text.decode('utf8').rstrip('\0')
    return bytes.decode(plain_text).rstrip('\r')


def run():

    headers = {
        "User-Agent": "okm/7.2.5",
        "Host": "api.ersanli",
    }

    _area = "110101"

    post_data = OrderedDict()
    post_data["page"] = "1"
    post_data["size"] = "20"
    post_data["clientType"] = "3"
    post_data["deviceId"] = get_deviceId()
    post_data["appId"] = "1"
    post_data["appVersion"] = "7.2.5"
    post_data["osVersion"] = "7.2.5"
    post_data["timestamp"] = str(int(time.time()))
    post_data["nonce_str"] = str(uuid.uuid4())
    post_data["location"] = _area
    post_data["sign"] = md5_ersanli(post_data)

    url = 'https://api.ersanli/kilos/apis/news/'

    data = requests.post(url, headers=headers, data=post_data).json()
    print(data)

    decrypt_data = decrypt(data.get("dataJson"), 'rFQJTvMFzm8MtBRy')
    print(json.loads(re.findall(r'{.*}', decrypt_data, re.S)[0]))


if __name__ == '__main__':
    run()

本文标签: 二三里app