欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 文旅 > 文化 > reverse-android-淘最热点so

reverse-android-淘最热点so

2025/3/19 0:09:53 来源:https://blog.csdn.net/wuhualong1314/article/details/139745028  浏览:    关键词:reverse-android-淘最热点so

资源

1.  com.maihan.tredian  2021版 淘最热点  

2. 该 app 没有加壳 ,也没混淆。

登录抓包

POST: https://api.taozuiredian.com/api/v1/auth/login/sms

POST /api/v1/auth/login/sms HTTP/1.1
Content-Type: application/json
Connection: close
Charset: UTF-8
User-Agent: Dalvik/2.1.0 (Linux; U; Android 14; Pixel 6 Build/AP1A.240505.004)
Host: api.taozuiredian.com
Accept-Encoding: gzip
Content-Length: 566{"sign":"3c0bc27ca0e9a647f32f5e9751d0db63e38849b5","nonce":"8bfisg1718611936552","tzrd":"BwzXzSGFyiPstMIVuzTZb7LzTZzbXRJOFzpbQiIaT7ujUDo3\/3Itq4wx7VQB94J9yQcrD22YICXHDicUiOY8ggIARFsAfdxkYDBJCJN5ScgdFKnF1+ISjECffNemekpceZEtoWiE8Dw8qF5DYd\/RAGF7iNzRF3WoESa4CR2\/JzHhlwW4d8a2HNEPaNGcdwvomjmkQRh17mnDNufFD3YbHeoTId4Gz0h+IzLUuHCLgQFWoUK\/FPYa7epLPvJ0fi5U1wrV+FU+avqDNzGQVyeewhofZU5c511E0ITgSI27IrqBdCwvtpyW29F8T5dsHhmTrkKyJqs43AS\/fAapl7jYuzLz1+P7PPNEATv5y8GVTQJb+xYVZSVeyNpXmpSgkNIiSQVcRG8xw\/tAAOh6LpuZrx4Xay6OlulssTeYvnaAR1k=","timestamp":"1718611936","app_ver":"100"}

HTTP/1.1 400 Bad Request
Server: nginx
Date: Mon, 17 Jun 2024 08:12:03 GMT
Content-Type: application/json
Content-Length: 167
Cache-Control: no-cache, private
Access-Control-Allow-Origin: *
Vary: Origin
Connection: close{"code":1,"error":{"code":1,"ex_code":0,"exid":"9a16e02c3c1769177721bc0ece924941","message":"\u9a8c\u8bc1\u7801\u4e0d\u6b63\u786e","custom_params":[]},"success":false}

需要一下三个参数逆向:

sign: 3c0bc27ca0e9a647f32f5e9751d0db63e38849b5

nonce: 8bfisg1718611936552

tzrd: BwzXzSGFyiPstMIVuzTZb7LzTZzbXRJOFzpbQiIaT7ujUDo3\/3Itq4wx7VQB94J9yQcrD22YICXHDicUiOY8ggIARFsAfdxkYDBJCJN5ScgdFKnF1+ISjECffNemekpceZEtoWiE8Dw8qF5DYd\/RAGF7iNzRF3WoESa4CR2\/JzHhlwW4d8a2HNEPaNGcdwvomjmkQRh17mnDNufFD3YbHeoTId4Gz0h+IzLUuHCLgQFWoUK\/FPYa7epLPvJ0fi5U1wrV+FU+avqDNzGQVyeewhofZU5c511E0ITgSI27IrqBdCwvtpyW29F8T5dsHhmTrkKyJqs43AS\/fAapl7jYuzLz1+P7PPNEATv5y8GVTQJb+xYVZSVeyNpXmpSgkNIiSQVcRG8xw\/tAAOh6LpuZrx4Xay6OlulssTeYvnaAR1k=

java层分析

1. 搜索 login/sms

2. 搜索sign, tzrd 字段

可以定位到在 MhRequestUtil.a中

tzrd: Base64.encodeToString(AesUtil.b(jSONObject.toString().getBytes(), a.getBytes(), b.getBytes()), 2);

我们在hook 下 encodeToString ()看是不是这里。 encodeToString里面是个AES ,

String a = "AES/CBC/PKCS5Padding"; 从代码中可以看出 是 aes 自吐算法

Java.perform(function(){var Base64 = Java.use('android.util.Base64');var String =Java.use('java.lang.String');// Base64.encodeToString(AesUtil.b(jSONObject.toString().getBytes(), a.getBytes(), b.getBytes()), 2);Base64.encodeToString.overload("[B","int").implementation =function(input,flag){console.log(' hook encodeToString.overloads("[B","int") ...' );console.log(getStackTrace());var data= this.encodeToString(input,flag);console.log('res data origin: ', data);console.log('res data string: ', String.$new(data));return data;}// public static byte[] b(byte[] bArr, byte[] bArr2, byte[] bArr3) throws Exception {var  AesUtil = Java.use('com.maihan.tredian.util.AesUtil');AesUtil.b.implementation= function(src,key,key2){ // key =PeMBjWOVbrMgElXO 写死 , key2: VTToNCiifIJ9c2coconsole.log(getStackTrace());console.log('src: ',src)console.log('key: ',key)console.log('key2: ',key2)var data= this.b(src,key,key2);console.log('res data origin: ', data);console.log('res data string: ', String.$new(data));return data;}function getStackTrace(){return Java.use('android.util.Log').getStackTraceString(Java.use("java.lang.Throwable").$new());}
})//frida -UF -l hook_sign_java.js

打印出:

src string:  {"imei2":"null","device_name":"google Pixel 6","code":"6465","imei1":"null","phone":"18051116656","device_udid":"47cba2e1a0c4aed30ddf6687e096ab84","device_id":"2fd841981ec9f6dbb162d6bf7f93de5e","channel":"official","system":"1","from":"app","mac":"02:00:00:00:00:00","os_ver_code":"34","android_id":"e3de5277cf5deadf"}key string:  PeMBjWOVbrMgElXOkey2 string:  VTToNCiifIJ9c2co

可以看出上面的  几个数据都是 定2量的。

tzrd= Base64(AES(src,key,key2))

sign: TreUtil.sign(a(map, false, false))

sign 是so里面:  System.loadLibrary("tre");

    public static native String sign(String str);

先hook jni 函数,是可以直接hoo的。


Java.perform(function(){// hook jni var TreUtil = Java.use('com.maihan.tredian.util.TreUtil');TreUtil.sign.implementation = function(args){log('hook TreUtil.sign...')log(getStackTrace());log(' TreUtil.sign str: ',args);var data= this.sign(args);log(' TreUtil.sign res data: ',data);return  data;}
})

主动调用

function call_sign(){Java.perform(function(){var TreUtil = Java.use('com.maihan.tredian.util.TreUtil');var res =TreUtil.sign('app_ver=100&nonce=x78b381718634336095&timestamp=1718634336&tzrd=BwzXzSGFyiPstMIVuzTZb7LzTZzbXRJOFzpbQiIaT7ujUDo3/3Itq4wx7VQB94J9sH6Br/+3ggTlKNhMMCwxI6jU4tNNGc3FdWH77BqPbj8Z3sr6GqVExUuEtetRWq25SWVEnXflbfjvJKBzOb2KAhNYCPx1NP700luPmXN8vRfplwvjHR5uPdw4Ek+X2hLDnq6nl7LM5OkLYEUxztD7ZaP9tWs+62Te35F/Gne+5Yv1XIn1MmoBpHKrgpprn6i/Bg+K29wqxYHPdj0B7bQKB+sUtQX6Jm1li8cKogRBfEZMQgLc1nbbqdr9yHvWdrfFGIGgVRRn6IZc0+UbUkVppXa0g0PRsbVZx+XREEB+LSBbWRYvF1HWmlMsutj4rxP/54/32j+zW9BAIkEN6Uh9T1IoJ/EI5xYF9gNmKdap1vQ=') //直接java方式主动调用 jni函数 也是可以的log(res)})
}

Hook 这个是可以拿到

 var MhRequestUtil = Java.use('com.maihan.tredian.net.MhRequestUtil');// public static String a(Map<String, String> map, boolean z, boolean z2) {// map: {nonce=v08rer1718617204105, tzrd=BwzXzSGFyiPstMIVuzTZb7LzTZzbXRJOFzpbQiIaT7ujUDo3/3Itq4wx7VQB94J9sH6Br/+3ggTlKNhMMCwxI6jU4tNNGc3FdWH77BqPbj/vF2YZf1INWi7KKGyEfahgGdD3G3I4mHOAx4Z96YwwDCeT0XfVarRvgvO3PYkw7/Yv7twVlbauY+aeUgNVm7dYNWzXn/4iVvu7vPLKw/mFBc2AEK17L8398+/mGp0QM9itquHM/0Jxo1Vd9MOlIulQ6XT/1bX3GMaYDnV6y2uLvqPZsaG2tG2TJoPPUD3b+tLP7Qn8XKQFU0w9hu04Osbkyc/LXdEva5R3c+CQGyYUdBZYV6fBatWAK58X4e4VOxmYuUrVY5U+jg/KG6wYuFZ7JpPpmzfD0t0p4YA84rp5K6H29+2xQueuEFbID0/T0do=, timestamp=1718617204, app_ver=100}MhRequestUtil.a.overload('java.util.Map', 'boolean', 'boolean').implementation = function(m,z,z2){log(' hook MhRequestUtil.a...' );log(m,z,z2);var hm = Java.cast(m,Java.use('java.util.HashMap'));log(hm.toString());var data= this.a(m,z,z2);log("res data: "+data)return data;}

从lib中找出 libtre.so 是32位的, 用 IDA 32位打开。 在 导出表里面.

需要手动消息第一个参数 JNIEnv *, 第二个 jclass 

nonce:  随机数

 private static String a() {Random random = new Random();StringBuffer stringBuffer = new StringBuffer();for (int i = 0; i < 6; i++) {stringBuffer.append("abcdefghijklmnopqrstuvwxyz0123456789".charAt(random.nextInt(36)));}return stringBuffer.toString() + System.currentTimeMillis();}

so层分析

unidbg 调用so

JNIclass: com.maihan.tredian.util.TreUtil

public static native String sign(String str);

frida hook java JNI 函数, 看输入输出就行。

静态方法
参数1:string 

返回值:  string

代码: 

新建包: com.maihan.tredian.util

新建类: TreUtil

package com.maihan.tredian.util;import com.alibaba.fastjson.util.IOUtils;
import com.github.unidbg.AndroidEmulator;
import com.github.unidbg.Module;
import com.github.unidbg.arm.backend.Unicorn2Factory;
import com.github.unidbg.linux.android.AndroidEmulatorBuilder;
import com.github.unidbg.linux.android.AndroidResolver;
import com.github.unidbg.linux.android.dvm.DalvikModule;
import com.github.unidbg.linux.android.dvm.DvmClass;
import com.github.unidbg.linux.android.dvm.StringObject;
import com.github.unidbg.linux.android.dvm.VM;
import com.github.unidbg.linux.android.dvm.array.ByteArray;
import com.github.unidbg.memory.Memory;import java.io.File;public class TreUtil {private final AndroidEmulator emulator;private final VM vm;private final Module module;private final DvmClass TreUtil;private final boolean logging;TreUtil(boolean logging) {this.logging = logging;emulator = AndroidEmulatorBuilder.for32Bit().setProcessName("com.pocket.snh48").addBackendFactory(new Unicorn2Factory(true)).build(); // 创建模拟器实例,要模拟32位或者64位,在这里区分final Memory memory = emulator.getMemory(); // 模拟器的内存操作接口memory.setLibraryResolver(new AndroidResolver(23)); // 设置系统类库解析vm = emulator.createDalvikVM(); // 创建Android虚拟机vm.setVerbose(logging); // 设置是否打印Jni调用细节DalvikModule dm = vm.loadLibrary(new File("unidbg-android/src/test/java/com/maihan/tredian/util/libtre.so"), false); // 加载libttEncrypt.so到unicorn虚拟内存,加载成功以后会默认调用init_array等函数dm.callJNI_OnLoad(emulator); // 手动执行JNI_OnLoad函数,一个 cpp 中可以有动态注册也可以静态注册module = dm.getModule(); // 加载好的libttEncrypt.so对应为一个模块TreUtil = vm.resolveClass("com/maihan/tredian/util/TreUtil");//原先在 app的路径}private void destroy() {IOUtils.close(emulator);if (logging) {System.out.println("destroy");}}public static void main(String[] args) throws Exception {TreUtil test = new TreUtil(true);String res = test.sign("app_ver=100&nonce=x78b381718634336095&timestamp=1718634336&tzrd=BwzXzSGFyiPstMIVuzTZb7LzTZzbXRJOFzpbQiIaT7ujUDo3/3Itq4wx7VQB94J9sH6Br/+3ggTlKNhMMCwxI6jU4tNNGc3FdWH77BqPbj8Z3sr6GqVExUuEtetRWq25SWVEnXflbfjvJKBzOb2KAhNYCPx1NP700luPmXN8vRfplwvjHR5uPdw4Ek+X2hLDnq6nl7LM5OkLYEUxztD7ZaP9tWs+62Te35F/Gne+5Yv1XIn1MmoBpHKrgpprn6i/Bg+K29wqxYHPdj0B7bQKB+sUtQX6Jm1li8cKogRBfEZMQgLc1nbbqdr9yHvWdrfFGIGgVRRn6IZc0+UbUkVppXa0g0PRsbVZx+XREEB+LSBbWRYvF1HWmlMsutj4rxP/54/32j+zW9BAIkEN6Uh9T1IoJ/EI5xYF9gNmKdap1vQ=");System.out.println(res);test.destroy();}private String sign(String src) {StringObject res = TreUtil.callStaticJniMethodObject(emulator, "sign(Ljava/lang/String;)Ljava/lang/String;", src); // 执行Jni方法return res.getValue();}}

算法还原

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词