新版红薯shield字段(1) --- unidgb补还境

文章目录

  • 前言
  • [定位java层 (hook request类)](#定位java层 (hook request类))
  • 定位so层
  • [unidbg 模拟执行](#unidbg 模拟执行)

前言

在还原这个字段之前,我先看了路飞学院的课程,初步了解unidbg。(不是推广,我觉得路飞的课讲得比较浅,达不到逆向就业的水平)

在网上找shield的相关文章时,我发现很多人都在使用unidbg的trace功能打印调用的代码,并且用unidbg打印寄存器。最重要的是,unidbg能实现汇编指令级别的hook,而frida只能实现函数级别的hook,遇到复杂一点的so算法就难以分析。

在分析某度加固的时候,frida这玩意一直断连,有时候运行一个脚本要重新加载好多次frida。 使用frida-stalker对某一个函数进行trace,我也执行了三次才将汇编代码完整打印下来

微信公众号同名。未经允许,禁止转载

如果嫌分析过程太长,最后有总结

定位java层 (hook request类)

hook "NewStringUTF",如果字段中存在XYAA, 则打印字段的调用栈

java 复制代码
[Pixel 3::小红书 ]-> 打印出的字符串: XYAAQAAwAAAAEAAABTAAAAUzUWEe0xG1IbD9/c+qCLOlKGmTtFa+lG438PfeFeRKhCzNW5zLc1GZ3w+rIOz8N5jph+2fc1EQxOFzTcYrzz2isx0uYEH2oxANALruvQwKOpkuzA
0xb4a6a5ff libxyass.so!0x245ff
0xe

java.lang.Throwable
        at com.xingin.shield.http.Native.intercept(Native Method)
        at com.xingin.shield.http.XhsHttpInterceptor.intercept(SourceFile:8)
        at okhttp3.internal.http.RealInterceptorChain.proceed(SourceFile:10)

执行结果

java 复制代码
function hook_newStr() {
  var symbols = Module.enumerateSymbolsSync("libart.so");
  var NewStringUTFAddress = null;
  for (var i = 0; i < symbols.length; i++) {
    var symbol = symbols[i];
    if (
      symbol.name.indexOf("NewStringUTF") >= 0 &&
      symbol.name.indexOf("CheckJNI") < 0
    ) {
      NewStringUTFAddress = symbol.address;
    }
  }
  if (NewStringUTFAddress != null) {
    Interceptor.attach(NewStringUTFAddress, {
      onEnter: function (args) {
        var CString = args[1].readCString();
        //根据密文特征去筛选我们想要的数据.

        //
        if (CString.indexOf("XYAAQ") != -1) {
          console.log("打印出的字符串:", CString);
          //打印调用堆栈
          console.log(
            Thread.backtrace(this.context, Backtracer.ACCURATE)
              .map(DebugSymbol.fromAddress)
              .join("\n") + "\n"
          );
          console.log(
            Java.use("android.util.Log").getStackTraceString(
              Java.use("java.lang.Throwable").$new()
            )
          );
        }
      },
    });
  }
}
hook_newStr();

在jadx里函数的声明如下:

java 复制代码
public static native Response intercept(Interceptor.Chain chain, long j60) throws IOException;

用frida hook 观察这个函数调用前和调用后的数据,观察是否生成sheild。 hook代码如下

js 复制代码
Java.perform(function () {
  let xxxHttpInterceptor = Java.use("com.xingin.shield.http.Native");
  xxxHttpInterceptor["intercept"].overload(
    "okhttp3.Interceptor$Chain",
    "long"
  ).implementation = function (chain, j2) {
    var request = chain.request();
    console.log("1111111111111111111111:", j2);
    var url = request.url().toString();
    console.log("url:", url);
    var headerString = request.headers().toString();
    console.log("调用函数前的请求头字段", headerString);
    console.log("1111111111111111111111");
    let result = this["intercept"](chain, j2);
    let resultResonseHeader = result.request().headers().toString();
    console.log("调用函数之后的请求头字段", resultResonseHeader);
    return result;
  };
});

代码运行结果:

cpp 复制代码
url: https://edith.xiaohongshu.com/api/push/badge/clear_v2?deviceId=09a9b1be-85ba-3cbe-8e71-06ad67760ad2
调用函数前的请求头字段 xy-direction: 93
X-B3-TraceId: 0505066e701c0e0f
x-xray-traceid: cd8bd7b00018c2644fb3ddb5e73ef5a0
xy-scene: fs=0&point=3019
x-legacy-did: 09a9b1be-85ba-3cbe-8e71-06ad67760ad2
x-legacy-fid: 176476455610a006500aeedc7aa3708a8be3031932d7
x-legacy-sid: session.1764773982217321578270
x-mini-gid: 7cde9a1712bc54f4e2ae3d76cedcd371ad7e14c947359ce37789292d
x-mini-sig: adeb8424258e7ad9ebc7db47838d60461860fb568ebd3cc318dc774cd8c82e88
x-mini-mua: eyJhIjoiRUNGQUFGMDEiLCJjIjoyMCwiayI6IjQyZmFkZWU1Njg0N2RlNTNhMDRjY2QwMjc3ZmNmODY2ZmVkYmVlNmViODdhN2NiNDgzZWJjYTYxNDdiMmQwNmMiLCJwIjoiYSIsInMiOiI0NjYxZTQ3NTkzNzljNzZmZWNmNTdhZDYxYTc1OTI5MGExN2YxNzI0ZTZhMzM0Nzc4NjAwNDM1MTc0NTQ5MzM3OWMzMGRmNzM0YzY3ZTc3NDlmMTI2Mzk4MjQ5ZGJhNzZlODdiN2MyMzg4M2ZjMmZhMDdmOWU3ZWE1ZDI1MjIzZiIsInQiOnsiYyI6MCwiZCI6MCwiZiI6MCwicyI6NDA5OCwidCI6MCwidHQiOltdfSwidSI6IjAwMDAwMDAwNGI0ZjkwN2EyMDc1YTViZDM4MzdiZGIyYTNlZjczYWEiLCJ2IjoiMi45LjQ5MyJ9.oiK0gpZTEferc_JrD_TiPIjJyIKgNGYPV2C0dypk23Zz89YGSXQ49kpob_mSb6z1Lc4CBqWB1OPqDJEQgYw9liISWJwwvkdg55eK6Z9t_nehCZlA-fO2wPS9woVGxol3oV9KH8Gl-AE36Ky3K2QMVxdM2rCTv6PKc4szyEbU_b-MiI63dFirTw_m50051h_MbIEffRxJuTInitYuoHfBzl7MeP7zcC4luwAOh8pyrapJDjucmUmP_fmZjNAdriKXGNkPF9uiFsZj8smKQJzSXkSmpHXe6tFjR2_UnJW8BlhfT7aArnjOWO0VP-a3X9B9GGuwjSKhjszuC-vPGGUD07ciBLmpz37ZJseXl6XDpNodnu3EK6FfGGdR7wV7_7RV6XLwU_q96HOQOeyxzpwY8D3wW3JDqbJJwCmdABQUOCVUBV3eC4_gGpnZ0NQTMy6LrdRiaWXQOCn-OSvKNGVwL9r-SzEeJvHbeOgTm1N60VBpbWMXmYHn1NGohwsKYLggw8-djH-z0rL91waZVJES7HZZYp58kk_BCh7TY2SsuUrUKWYyG4mPR9Bx7MOAv106XGe3a9xsA35L1OY8nkoGGhEY0Z2SBf00jdf4yi9i9rkrTS-0T4L_Vdcb-TLxQIlNSVI1KXVIoBeqeJ5RHS7Q6GDHC-SEjs8vct9KTUnNyQNW_WWwJkJgV4OYVvmA4k8Rxduwi0nwP0ubUGnvLsP3oUdFZjzC1krjvzO2WX21Zz2ZkWh3FNdgfIELDoMiQNpwsKMYfSTA4K8saWq2HRCNUOXfKb7aNAR5RA_LTSn52OE7Ohl-bdnvqWnf8BdG1-6vBQjNJvrEwdbstnvUIxI0LUq7gXB_M23vdkanWVxXk8Itbg_nL5bsuV1vUTf_5zdcYAz4I6NRzKApfwSix3YDvO9FJJLopPRA0PFPAgBD_jkN1wIsmOL8KJp-vHtWdjoHqEiruUWPFFBzueb6HepohmuwJOtZpr3s2wmUXvT0dScbQhfzYJ0Ir4aML-7xBwUyRn9ymqeJs8G0mi2iy9RX2gr-SB6PFIL6qjSAykgwTEtzhRQyTwHYbz6z-JWXg2wltBjT_ZUxlKmZuIs53IuMnMP6J11Dy-yGzBf2ZqquS_SHqumEhIW8zxlnYvrbxoXM1HeX9GVII9cTvESzfOr6dZ95ro3OORrihkHcBGv1E6iRKw24t0TsEbeApwvxC7qdSXT6qN4N7E1ARqMTAf4spYYtzWsclJj5SWk0vSbNnoENr32MDEvlVNqugDpwfiX-CBH35tyBYdOaHnpc1OxZ_n8zwlbX2dzc2UFNk3PxOoKuJDr575oyfzNJKHmidalI44JlOlleRTkGjT6CB4ozVszVX6-VbWIFbJHG_2pg8_8.
xy-common-params: fid=176476455610a006500aeedc7aa3708a8be3031932d7&gid=7cde9a1712bc54f4e2ae3d76cedcd371ad7e14c947359ce37789292d&device_model=phone&tz=Asia%2FShanghai&channel=YingYongBao&versionName=9.11.0&deviceId=09a9b1be-85ba-3cbe-8e71-06ad67760ad2&platform=android&sid=session.1764773982217321578270&identifier_flag=4&cpu_abi=armeabi-v7a&nqe_score=0&project_id=ECFAAF&x_trace_page_current=welcome_page&lang=zh-Hans&app_id=ECFAAF01&uis=light&teenager=0&active_ctry=&cpu_name=Qualcomm+Technologies%2C+Inc+SDM845&dlang=zh&data_ctry=CN&SUE=1&launch_id=1765628918&device_level=3&origin_channel=YingYongBao&overseas_channel=0&mlanguage=zh_cn&folder_type=none&auto_trans=0&t=1765628811&build=9110805&holder_ctry=CN&did=9d29cd0e55089e8e17beb8757715900b
User-Agent: Dalvik/2.1.0 (Linux; U; Android 9; Pixel 3 Build/PD1A.180720.030) Resolution/1080*2160 Version/9.11.0 Build/9110805 Device/(Google;Pixel 3) discover/9.11.0 NetType/WiFi
Referer: https://app.xhs.cn/


1111111111111111111111
调用函数之后的请求头字段 xy-direction: 93
X-B3-TraceId: f4f4b9547613080f
x-xray-traceid: cd8bd7afdf98c2633fa7d74afd95f050
xy-scene: fs=0&point=3019
x-legacy-did: 09a9b1be-85ba-3cbe-8e71-06ad67760ad2
x-legacy-fid: 176476455610a006500aeedc7aa3708a8be3031932d7
x-legacy-sid: session.1764773982217321578270
x-mini-gid: 7cde9a1712bc54f4e2ae3d76cedcd371ad7e14c947359ce37789292d
x-mini-s1: AA8AAAABCo8q8RuPvNsq3I+dgloICOWZH5sfCGHvaWqVNXWQmRMOWuMqx5T/OETaAtyRHFu4SpOdhUSZEgw=
x-mini-sig: a362dcc4e6dd7ec7c159ebb36c1fc9f73e5f0de713aa37a57c72682dafc10d85
x-mini-mua: eyJhIjoiRUNGQUFGMDEiLCJjIjoxOSwiayI6IjQyZmFkZWU1Njg0N2RlNTNhMDRjY2QwMjc3ZmNmODY2ZmVkYmVlNmViODdhN2NiNDgzZWJjYTYxNDdiMmQwNmMiLCJwIjoiYSIsInMiOiI0NjYxZTQ3NTkzNzljNzZmZWNmNTdhZDYxYTc1OTI5MGExN2YxNzI0ZTZhMzM0Nzc4NjAwNDM1MTc0NTQ5MzM3OWMzMGRmNzM0YzY3ZTc3NDlmMTI2Mzk4MjQ5ZGJhNzZlODdiN2MyMzg4M2ZjMmZhMDdmOWU3ZWE1ZDI1MjIzZiIsInQiOnsiYyI6MCwiZCI6MCwiZiI6MCwicyI6NDA5OCwidCI6MCwidHQiOltdfSwidSI6IjAwMDAwMDAwNGI0ZjkwN2EyMDc1YTViZDM4MzdiZGIyYTNlZjczYWEiLCJ2IjoiMi45LjQ5MyJ9.oiK0gpZTEferc_JrD_TiPIjJyIKgNGYPV2C0dypk23Zz89YGSXQ49kpob_mSb6z1Lc4CBqWB1OPqDJEQgYw9liISWJwwvkdg55eK6Z9t_nehCZlA-fO2wPS9woVGxol3oV9KH8Gl-AE36Ky3K2QMVxdM2rCTv6PKc4szyEbU_b-MiI63dFirTw_m50051h_MbIEffRxJuTInitYuoHfBzl7MeP7zcC4luwAOh8pyrapJDjucmUmP_fmZjNAdriKXGNkPF9uiFsZj8smKQJzSXkSmpHXe6tFjR2_UnJW8BlhfT7aArnjOWO0VP-a3X9B9GGuwjSKhjszuC-vPGGUD07ciBLmpz37ZJseXl6XDpNodnu3EK6FfGGdR7wV7_7RV6XLwU_q96HOQOeyxzpwY8D3wW3JDqbJJwCmdABQUOCVUBV3eC4_gGpnZ0NQTMy6LrdRiaWXQOCn-OSvKNGVwL9r-SzEeJvHbeOgTm1N60VBpbWMXmYHn1NGohwsKYLggw8-djH-z0rL91waZVJES7HZZYp58kk_BCh7TY2SsuUrUKWYyG4mPR9Bx7MOAv106XGe3a9xsA35L1OY8nkoGGhEY0Z2SBf00jdf4yi9i9rkrTS-0T4L_Vdcb-TLxQIlNSVI1KXVIoBeqeJ5RHS7Q6GDHC-SEjs8vct9KTUnNyQNW_WWwJkJgV4OYVvmA4k8Rxduwi0nwP0ubUGnvLsP3oUdFZjzC1krjvzO2WX21Zz2ZkWh3FNdgfIELDoMiQNpwsKMYfSTA4K8saWq2HRCNUOXfKb7aNAR5RA_LTSn52OE7Ohl-bdnvqWnf8BdG1-6vBQjNJvrEwdbstnvUIxI0LUq7gXB_M23vdkanWVxXk8Itbg_nL5bsuV1vUTf_5zdcYAz4I6NRzKApfwSix3YDvO9FJJLopPRA0PFPAgBD_jkN1wIsmOL8KJp-vHtWdjoHqEiruUWPFFBzueb6HepohmuwJOtZpr3s2wmUXvT0dScbQhfzYJ0Ir4aML-7xBwUyRn9ymqeJs8G0mi2iy9RX2gr-SB6PFIL6qjSAykgwTEtzhRQyTwHYbz6z-JWXg2wltBjT_ZUxlKmZuIs53IuMnMP6J11Dy-yGzBf2ZqquS_SHqumEhIW8zxlnYvrbxoXM1HeX9GVII9cTvESzfOr6dZ95ro3OORrihkHcBGv1E6iRKw24t0TsEbeApwvxC7qdSXT6qN4N7E1ARqMTAf4spYYtzWsclJj5SWk0vSbNnoENr32MDEvlVNqugDpwfiX-CBH35tyBYdOaHnpc1OxZ_n8zwlbX2dzc2UFNk3PxOoKuJDr575oyfzNJKHmidalI44JlOlleRTkGjT6CB4ozVszVX6-VbWIFbJHG_2pg8_8.
xy-common-params: fid=176476455610a006500aeedc7aa3708a8be3031932d7&gid=7cde9a1712bc54f4e2ae3d76cedcd371ad7e14c947359ce37789292d&device_model=phone&tz=Asia%2FShanghai&channel=YingYongBao&versionName=9.11.0&deviceId=09a9b1be-85ba-3cbe-8e71-06ad67760ad2&platform=android&sid=session.1764773982217321578270&identifier_flag=4&cpu_abi=armeabi-v7a&nqe_score=0&project_id=ECFAAF&x_trace_page_current=welcome_page&lang=zh-Hans&app_id=ECFAAF01&uis=light&teenager=0&active_ctry=&cpu_name=Qualcomm+Technologies%2C+Inc+SDM845&dlang=zh&data_ctry=CN&SUE=1&launch_id=1765628918&device_level=3&origin_channel=YingYongBao&overseas_channel=0&mlanguage=zh_cn&folder_type=none&auto_trans=0&t=1765628811&build=9110805&holder_ctry=CN&did=9d29cd0e55089e8e17beb8757715900b
User-Agent: Dalvik/2.1.0 (Linux; U; Android 9; Pixel 3 Build/PD1A.180720.030) Resolution/1080*2160 Version/9.11.0 Build/9110805 Device/(Google;Pixel 3) discover/9.11.0 NetType/WiFi
Referer: https://app.xhs.cn/
shield: XYAAQAAwAAAAEAAABTAAAAUzUWEe0xG1IbD9/c+qCLOlKGmTtFa+lG438PfeFeRKhCzNW5zLc1GZ3w+rIOz8N5jph+2fc1EQxOFzTcYrzz2isx0uYOPwf5N4FgHzrMVmNUyxZ0
xy-platform-info: platform=android&build=9110805&deviceId=09a9b1be-85ba-3cbe-8e71-06ad67760ad2

代码运行之后,添加shield与xy-platform-info字段

定位so层

根据调用堆栈,java最后调用intercept函数。用hook_RegisterNatives来查找intercept在so文件的位置。定位到在libxyass.so的0x23d55中

cpp 复制代码
.text:000245F8                 ADDEQ           R1, R5, #1
.text:000245FA                 MOV             R0, R4
.text:000245FC                 BLX             R3
.text:000245FE                 LDR             R4, [SP,#0x120+var_F8]
.text:00024600                 MOV             R10, R0
.text:00024602                 LDR             R0, [R4]
.text:00024604                 CBNZ            R0, loc_24636
.text:00024606                 MOVS            R0, #0x50 ; 'P'
.text:00024608                 BL              loc_D434

使用frida hook 0x23d55函数,结果函数没有调用。。。。 试一下使用unidbg trace

在使用unidbg trace之前,需要用unidbg完成函数模拟执行。

unidbg 模拟执行

java 复制代码
package com.demo;  
  
  
import com.github.unidbg.AndroidEmulator;  
import com.github.unidbg.Module;  
import com.github.unidbg.linux.android.AndroidEmulatorBuilder;  
import com.github.unidbg.linux.android.AndroidResolver;  
import com.github.unidbg.linux.android.dvm.*;  
import com.github.unidbg.memory.Memory;  
  
import java.io.File;  
  
public class XhsShield extends AbstractJni {  
    private static AndroidEmulator emulator;  
    private static Memory memory;  
    private static VM vm;  
    private static Module module;  
    public XhsShield(){  
        //1.初始化  
        emulator = AndroidEmulatorBuilder.for32Bit().setProcessName("com.che168.autotradercloud").build();  
  
        //2.设置内存对象  
        memory = emulator.getMemory();  
        // 3.设置安卓版本  
        memory.setLibraryResolver(new AndroidResolver(23));  
  
        //4. 创建虚拟机  
        vm = emulator.createDalvikVM(new File("apks/xhs/9.11.0.apk"));  
        vm.setJni(this);  // 补jni环境  
  
        //5. 加载so文件  
        DalvikModule dm = vm.loadLibrary(new File("apks/xhs/libxyass.so"),false);  
        dm.callJNI_OnLoad(emulator); // 动态注册  
  
        // 6 基于module访问so文件的成员  
        module = dm.getModule();  
    }  
  
    // 签名方法  
    public void intercept(){  
  
        // 找到java中的native类  
        DvmClass xhsNative = vm.resolveClass("com/xingin/shield/http/Native");  
        // 找到类的方法  
        String method = "intercept(Lokhttp3/Interceptor$Chain;J)Lokhttp3/Response;";  
        Long cptr = 1765721609L;  
  
        // 执行方法  
        // 第一个参数:设备对象  
        // 第二个参数: 方法  
        // 之后的参数:方法使用的参数  
        DvmObject<?> obj = xhsNative.callStaticJniMethodObject(  
                emulator,  
                method,  
                vm.resolveClass("okhttp3/Interceptor$Chain").newObject(null),  
                cptr  
        );  
  
        // DvmObject<?> result = obj;        
        System.out.println(obj);  
    }  
  
    public static void main(String[] args){  
        XhsShield xhsShield = new XhsShield();  
        xhsShield.intercept();  
    }  
}

开始补还境

1.writeLog

报错信息

复制代码
java.lang.UnsupportedOperationException: com/xingin/shield/http/ContextHolder->writeLog(I)V
	at com.github.unidbg.linux.android.dvm.AbstractJni.callStaticVoidMethodV(AbstractJni.java:708)

因为是打印日志的函数,不影响字段生成,所以不用补逻辑

java 复制代码
@Override  
public void callStaticVoidMethodV(BaseVM vm, DvmClass dvmClass, String signature, VaList vaList) {  
    switch (signature) {  
        case "com/xingin/shield/http/ContextHolder->writeLog(I)V" :{  
            // vm.resolveClass("com/xingin/shield/http/ShieldLogger").newObject(null);  
        }  
    }  //  super.callStaticVoidMethodV(vm, dvmClass, signature, vaList);  
}

2. 初始化函数

运行出现如下报错:Cannot invoke "com.github.unidbg.pointer.UnidbgPointer.toIntPeer()" because "jmethodID" is null

报错提示函数还未注册,[求助]某红薯x-mini-mua算法unidbg问题-Android安全-看雪论坛-安全社区|非营利性质技术交流社区 里解释这种情况缺少初始化操作的调用

xhs分析------shield字段 | Hexo 的这张图片捋清楚了函数的调用过程。于是模拟的时候可以先调用initalizeNative函数, 之后再调用initialize函数,最后调用intercepte函数

现在的代码变成这样,

java 复制代码
package com.xhs;  
    
public class XhsShield extends AbstractJni {  
    private static AndroidEmulator emulator;  
    private static Memory memory;  
    private static VM vm;  
    private static Module module;  
    private static DvmClass XhsNativeClass;  
    private static DvmObject XhsNativeObject;  
    private static  long cPtr;  
    
    public XhsShield(){  
    //1.初始化  
    emulator = AndroidEmulatorBuilder.for32Bit().setProcessName("com.che168.autotradercloud").build();  
  
    //2.设置内存对象  
    memory = emulator.getMemory();  
    // 3.设置安卓版本  
    memory.setLibraryResolver(new AndroidResolver(23));  
  
    //4. 创建虚拟机  
    vm = emulator.createDalvikVM(new File("apks/xhs/9.11.0.apk"));  
    vm.setJni(this);  // 补jni环境  
  
    //5. 加载so文件  
    DalvikModule dm = vm.loadLibrary(new File("apks/xhs/libxyass.so"),false);  
    dm.callJNI_OnLoad(emulator); // 动态注册  
  
    // 6 基于module访问so文件的成员  
    module = dm.getModule();  
  
    XhsNativeClass = vm.resolveClass("com/xingin/shield/http/Native");  
    XhsNativeObject = XhsNativeClass.newObject(null);  
}
    public void initializeNative(){  
        String method = "initializeNative()V";  
        XhsNativeClass.callStaticJniMethod(emulator,method);  
    }  
    // 初始化  
    public void initialize(){  
        XhsNativeClass = vm.resolveClass("com/xingin/shield/http/Native");  
        XhsNativeObject = XhsNativeClass.newObject(null);  
        cPtr = XhsNativeObject.callJniMethodLong(emulator, "initialize(Ljava/lang/String;)J", "main");  
        System.out.println("cPtr = " + cPtr);  
    }  
  
    // 签名方法  
    public void intercept(){  
  
        // 找到类的方法  
        String method = "intercept(Lokhttp3/Interceptor$Chain;J)Lokhttp3/Response;";  
  
        DvmObject<?> obj = XhsNativeClass.callStaticJniMethodObject(  
                emulator,  
                method,  
                vm.resolveClass("okhttp3/Interceptor$Chain").newObject(null),  
                cPtr  
        );  
  
        // DvmObject<?> result = obj;        System.out.println(obj);  
    }  
  
  
  public static void main(String[] args){  
    XhsShield xhsShield = new XhsShield();  
    xhsShield.initializeNative();  
    xhsShield.initialize();  
    xhsShield.intercept();  
}
    @Override  
    public void callStaticVoidMethodV(BaseVM vm, DvmClass dvmClass, String signature, VaList vaList) {  
        switch (signature) {  
            case "com/xingin/shield/http/ContextHolder->writeLog(I)V" :{  
                // vm.resolveClass("com/xingin/shield/http/ShieldLogger").newObject(null);  
            }  
        }      //  super.callStaticVoidMethodV(vm, dvmClass, signature, vaList);  
    }  
}

3. Charset的defaultCharset

报错如下

复制代码
[21:31:55 347]  WARN [com.github.unidbg.linux.ARM32SyscallHandler] (ARM32SyscallHandler:540) - handleInterrupt intno=2, NR=-1073744764, svcNumber=0x170, PC=unidbg@0xfffe0794, LR=RX@0x4001ebf7[libxyass.so]0x1ebf7, syscall=null
java.lang.UnsupportedOperationException: java/nio/charset/Charset->defaultCharset()Ljava/nio/charset/Charset;

按照报错补充代码就可以

java 复制代码
@Override  
public DvmObject<?> callStaticObjectMethodV(BaseVM vm, DvmClass dvmClass, String signature, VaList vaList) {  
    switch (signature) {  
        case "java/nio/charset/Charset->defaultCharset()Ljava/nio/charset/Charset;" :{  
            Charset defaultCharset = Charset.defaultCharset();  
            return ProxyDvmObject.createObject(vm, defaultCharset);  
        }  
  
    }    return super.callStaticObjectMethodV(vm, dvmClass, signature, vaList);  
}

4. 补充sDeviceId、sAppId

报错如下

复制代码
java.lang.UnsupportedOperationException: com/xingin/shield/http/ContextHolder->sDeviceId:Ljava/lang/String;
	at com.github.unidbg.linux.android.dvm.AbstractJni.getStaticObjectField(AbstractJni.java:103)

需要补充代码,用来获取ContextHolder类的sDeviceId属性。最简单的想法就是hook 得到结果

花一早上尝试使用java反射获取ContextHolder的sDeviceId的属性,打印结果为null。

最后使用[[objection]]的Wallbreaker插件,打印出sDeviceId

hook结果

复制代码
   /* static fields */                                                             
        static int sAppId; => -319115519
        static Context sContext; => [0x48e2]: com.xingin.xhs.app.XhsApplication@1b321ea
        static String sDeviceId; => 09a9b1be-85ba-3cbe-8e71-06ad67760ad2
        static boolean sJavaLogEnabled; => true

将hook结果补充到unidbg里

java 复制代码
@Override  
public int getStaticIntField(BaseVM vm, DvmClass dvmClass, String signature) {  
    switch (signature) {  
        case "com/xingin/shield/http/ContextHolder->sAppId:I": {  
            return -319115519;  
        }  
    }    return super.getStaticIntField(vm, dvmClass, signature);  
}  
  
@Override  
public DvmObject<?> getStaticObjectField(BaseVM vm, DvmClass dvmClass, String signature) {  
    switch (signature){  
        case "com/xingin/shield/http/ContextHolder->sDeviceId:Ljava/lang/String;" :{  
            return new StringObject(vm, "09a9b1be-85ba-3cbe-8e71-06ad67760ad2");  
        }  
  
    }    return super.getStaticObjectField(vm, dvmClass, signature);  
}

5. SharedPreferences补充

依旧查看报错信息

复制代码
java.lang.UnsupportedOperationException: android/content/Context->getSharedPreferences(Ljava/lang/String;I)Landroid/content/SharedPreferences;
	at com.github.unidbg.linux.android.dvm.AbstractJni.callObjectMethodV(AbstractJni.java:417)

这次缺少的是安卓类 ContextSharedPreferences。 因为安卓类的代码太多,如果使用复制源代码的方式补还境很麻烦。直接模拟代码

\[sharepreference\]\]介绍了sharepreference的基本概念。

先看程序访问了哪一个SharedPreferences文件。发现是s.xml

java 复制代码
@Override  
public DvmObject<?> callObjectMethodV(BaseVM vm, DvmObject<?> dvmObject, String signature, VaList vaList) {  
    switch (signature) {  
        case "android/content/Context->getSharedPreferences(Ljava/lang/String;I)Landroid/content/SharedPreferences;" :{  
            String sharedPreferencesFileName = vaList.getObjectArg(0).toString();  
            System.out.println("sharedPreferencesFileName:"+sharedPreferencesFileName);  
            return vm.resolveClass("android/content/SharedPreferences").newObject(sharedPreferencesFileName);  
        }  
    }    return super.callObjectMethodV(vm, dvmObject, signature, vaList);  
}

查看app下的s.xml文件,发现里面只有main_hmac键值对

补充代码逻辑和上面类似,假设main_hmac不变,返回已经生成的main_hmac就行

6.Base64Helper

报错信息

复制代码
java.lang.UnsupportedOperationException: com/xingin/shield/http/Base64Helper->decode(Ljava/lang/String;)[B
	at com.github.unidbg.linux.android.dvm.AbstractJni.callStaticObjectMethodV(AbstractJni.java:504)

用java自带的base64类完成解密即可

java 复制代码
case "com/xingin/shield/http/Base64Helper->decode(Ljava/lang/String;)[B" :{  
    String cipher = vaList.getObjectArg(0).toString();  
    return new ByteArray(vm, Base64.getMimeDecoder().decode(cipher));

7. request函数

接下来补充interpret函数的环境

报错信息

复制代码
java.lang.UnsupportedOperationException: okhttp3/Interceptor$Chain->request()Lokhttp3/Request;
	at com.github.unidbg.linux.android.dvm.AbstractJni.callObjectMethodV(AbstractJni.java:417)

定义一个chain对象,将其添加到代码里

java 复制代码
public class XhsShield extends AbstractJni {  
    private static AndroidEmulator emulator;  
    private static Memory memory;  
    private static VM vm;  
    private static Module module;  
    private static DvmClass XhsNativeClass;  
    private static DvmObject XhsNativeObject;  
    private static  long cPtr;  
    private static DvmObject chain = null;
    
    
      
public void intercept(){  
    chain =  vm.resolveClass("okhttp3/Interceptor$Chain").newObject(null);  
    // 找到类的方法  
    String method = "intercept(Lokhttp3/Interceptor$Chain;J)Lokhttp3/Response;";  
  
    DvmObject<?> response = XhsNativeClass.callStaticJniMethodObject(  
            emulator,  
            method,  
            chain,  
            cPtr  
    );

接下来补充okhttp的环境。下载okhttp , 最新的5.3.2版本有问题,所以使用老版本

xml 复制代码
<dependency>  
    <groupId>com.squareup.okhttp3</groupId>  
    <artifactId>okhttp</artifactId>  
    <version>4.9.0</version>  
</dependency>

这里设置idea的maven:打开下图的目录,将自动下载的三个多选框勾上

开始补充request函数

在构造函数中,为request变量赋值

返回构造好的request变量

java 复制代码
case "okhttp3/Interceptor$Chain->request()Lokhttp3/Request;" :{  
    return vm.resolveClass("okhttp3/Request").newObject(request);  
}

8. okhttp的其他环境

依旧按照报错信息补环境

复制代码
java.lang.UnsupportedOperationException: okhttp3/Request->url()Lokhttp3/HttpUrl;
	at com.github.unidbg.linux.android.dvm.AbstractJni.callObjectMethodV(AbstractJni.java:417)

其他函数逻辑是一样的,这里就直接给出代码了

java 复制代码
 case "okhttp3/Request->url()Lokhttp3/HttpUrl;" :{  
    return vm.resolveClass("okhttp3/HttpUrl").newObject(request.url());  
} case "okhttp3/HttpUrl->encodedPath()Ljava/lang/String;" :{  
    HttpUrl httpUrl = (HttpUrl) dvmObject.getValue();  
    return new StringObject(vm, httpUrl.encodedPath());  
} case "okhttp3/HttpUrl->encodedQuery()Ljava/lang/String;" :{  
    HttpUrl httpUrl = (HttpUrl) dvmObject.getValue();  
    return new StringObject(vm,httpUrl.encodedQuery());  
} case "okhttp3/Request->body()Lokhttp3/RequestBody;" :{  
    Request request = (Request) dvmObject.getValue();  
    return ProxyDvmObject.createObject(vm, request.body());  
} case "okhttp3/Request->headers()Lokhttp3/Headers;" :{  
    Request request = (Request) dvmObject.getValue();  
    return ProxyDvmObject.createObject(vm, request.headers());  
} case "okhttp3/Headers->name(I)Ljava/lang/String;":{  
    Headers headers = (Headers) dvmObject.getValue();  
    int arg1 = (int)vaList.getIntArg(0);  
    return new StringObject(vm, headers.name(arg1));  
} case "okhttp3/Headers->value(I)Ljava/lang/String;" :{  
    Headers headers = (Headers) dvmObject.getValue();  
    int arg1 = (int)vaList.getIntArg(0);  
    return new StringObject(vm, headers.value(arg1));  
}

9. okio

报错

复制代码
java.lang.UnsupportedOperationException: okio/Buffer-><init>()V
	at com.github.unidbg.linux.android.dvm.AbstractJni.newObjectV(AbstractJni.java:803)
java 复制代码
case "okio/Buffer-><init>()V" : {  
    return  dvmClass.newObject(new Buffer());  
}
复制代码
okio/Buffer->writeString(Ljava/lang/String;Ljava/nio/charset/Charset;)Lokio/Buffer;
	at com.github.unidbg.linux.android.dvm.AbstractJni.callObjectMethodV(AbstractJni.java:417)
java 复制代码
case "okio/Buffer->writeString(Ljava/lang/String;Ljava/nio/charset/Charset;)Lokio/Buffer;" :{  
    Buffer buffer = (Buffer) dvmObject.getValue();  
    String arg1 = vaList.getObjectArg(0).getValue().toString();  
    Charset arg2 = (Charset) vaList.getObjectArg(1).getValue();  
    return vm.resolveClass("okio/Buffer").newObject(buffer.writeString(arg1,arg2));  
}

还有其他需要补的环境

java 复制代码
case "okio/Buffer->clone()Lokio/Buffer;" :{  
    Buffer buffer = (Buffer) dvmObject.getValue();  
    return vm.resolveClass("okio/Buffer").newObject(buffer.clone());  
}

10 proceed

报错

复制代码
java.lang.NullPointerException: Cannot invoke "okhttp3.Interceptor$Chain.proceed(okhttp3.Request)" because "interceptor_chain" is null
	at com.xhs.XhsShield.callObjectMethodV(XhsShield.java:244)
	at com.github.unidbg.linux.android.dvm.AbstractJni.callObjectMethodV(AbstractJni.java:262)

这段代码用于发送请求,但是我们只需要关注shield生成,不需要发送请求数据

java 复制代码
case "okhttp3/Interceptor$Chain->proceed(Lokhttp3/Request;)Lokhttp3/Response;" :{  
    return vm.resolveClass("okhttp3/Response").newObject(null);  
}

11.状态码

java 复制代码
case "okhttp3/Response->code()I" :{  
    return 200;  
}

12. 打印shield

java 复制代码
public static void main(String[] args){  
    XhsShield xhsShield = new XhsShield();  
    xhsShield.initializeNative();  
    xhsShield.initialize();  
    xhsShield.intercept();  
    System.out.println("shield:"+ xhsShield.request.headers().get("shield"));  
}

打印结果是null

复制代码
sharedPreferencesFileName:"s"
key:"main_hmac"
defaultValue:""
cPtr = 1076277248
okhttp3.Response@62ddbd7e
shield:null

这是因为我们在补还境的时候,没有更新request属性。 导致打印的时候,使用的还是构造函数构造的request属性

在补环境的最后几步,我们会 Hook 到这样一个函数: "okhttp3/Request$Builder->build()Lokhttp3/Request;"。 在该函数执行之后,代码将继续调用 proceed(),从而完成网络请求的发送。所以build()函数就是最后返回request的位置。

java 复制代码
 case "okhttp3/Request$Builder->build()Lokhttp3/Request;" :{  
    Request.Builder requestObj_Builder = (Request.Builder) dvmObject.getValue();  
    Request resultRequest = requestObj_Builder.build();  
    request = resultRequest;  
    return vm.resolveClass("okhttp3/Request").newObject(resultRequest);  
}

运行结果

复制代码
sharedPreferencesFileName:"s"
key:"main_hmac"
defaultValue:""
cPtr = 1076277248
okhttp3.Response@62ddbd7e
shield:XYAAAAAwAAAAEAAABTAAAAUzUWEe0xG1IbD9/c+aCLOlKGmTtFa+lG438PfeFeRKhCzNW5zLc1GZ3w+rIOz8N5jph+2fc1EQxOFzTcYrzz2isx0uaV0XzforuR6ZR7O0hWI/e7

完整代码

java 复制代码
package com.xhs;  
  
  
import com.github.unidbg.AndroidEmulator;  
import com.github.unidbg.Module;  
import com.github.unidbg.linux.android.AndroidEmulatorBuilder;  
import com.github.unidbg.linux.android.AndroidResolver;  
import com.github.unidbg.linux.android.dvm.*;  
import com.github.unidbg.linux.android.dvm.array.ByteArray;  
import com.github.unidbg.linux.android.dvm.jni.ProxyDvmObject;  
import com.github.unidbg.memory.Memory;  
  
import java.io.File;  
import java.io.IOException;  
import java.nio.charset.Charset;  
import java.util.Base64;  
  
import okhttp3.*;  
import okio.Buffer;  
  
public class XhsShield extends AbstractJni {  
    private static AndroidEmulator emulator;  
    private static Memory memory;  
    private static VM vm;  
    private static Module module;  
    private static DvmClass XhsNativeClass;  
    private static DvmObject XhsNativeObject;  
    private static  long cPtr;  
    private static DvmObject chain = null;  
    private Request request;  
    private static String url;  
    public XhsShield(){  
        //1.初始化  
        emulator = AndroidEmulatorBuilder.for32Bit().setProcessName("com.che168.autotradercloud").build();  
  
        //2.设置内存对象  
        memory = emulator.getMemory();  
        // 3.设置安卓版本  
        memory.setLibraryResolver(new AndroidResolver(23));  
  
        //4. 创建虚拟机  
        vm = emulator.createDalvikVM(new File("apks/xhs/9.11.0.apk"));  
        vm.setJni(this);  // 补jni环境  
  
        //5. 加载so文件  
        DalvikModule dm = vm.loadLibrary(new File("apks/xhs/libxyass.so"),false);  
        dm.callJNI_OnLoad(emulator); // 动态注册  
  
        // 6 基于module访问so文件的成员  
        module = dm.getModule();  
  
        XhsNativeClass = vm.resolveClass("com/xingin/shield/http/Native");  
        XhsNativeObject = XhsNativeClass.newObject(null);  
        url = "https://edith.xiaohongshu.com/api/sns/v4/user/login/password?";  
        request = new Request.Builder()  
                .url(url)  
                .addHeader("xy-direction","99")  
                .addHeader("X-b3-traceId","afaf697d4a1a0e0f")  
                .addHeader("x-xray-traceid","cd722ebab5427376348604b9e41dd77d")  
                .addHeader("xy-scene","fs=0&point=-1")  
                .addHeader("x-legacy-did","09a9b1be-85ba-3cbe-8e71-06ad67760ad2")  
                .addHeader("x-legacy-fid","176476455610a006500aeedc7aa3708a8be3031932d7")  
                .addHeader("x-legacy-sid","session.1744300626655701629150")  
                .addHeader("x-mini-gid","7c0d68e8647a5438a2394bbad364c2bdf31b98794735944077bbfc55")  
                .addHeader("x-mini-s1","AC8AAAABw7ix0yQwSZbHfsTSRLmhLqg2ZlBEvg1RChKtfknNj4MlCHXkhCnmOPmKhVcyD73CaW60vx60csU=")  
                .addHeader("x-mini-sig","8612f4cc0cda7c3743973430d390d603c27a32f52cf5d75be3181aff61cbec57")  
                .addHeader("x-mini-mua","eyJhIjoiRUNGQUFGMDEiLCJjIjo0NywiayI6IjFiYjcyNmNmNGVkY2ZhYzdhYjcxODY4MWZjMGEwNjMyODlhZDVhN2M3YzA0NzA5ZTcyYjAyOWQyYWQ2NmI2NzYiLCJwIjoiYSIsInMiOiI0OWEyYWM0N2Q5OTIzMWFhMjdjZDYzYTMwNzFlMjAyZDk0OWQwNTQ3NDYwNDllNWIyMDAwYjBmZmE2OWU5ZDA2MTIxODA1MWVkMjhiMWNiNThmZjI1OGQzY2FmMmQ2OWU1NzAyYWZiNWY3MzRkZmJkZmM3YmJlMzcyZDY5MTdiYyIsInQiOnsiYyI6NDIsImQiOjIsImYiOjAsInMiOjQwOTgsInQiOjM5MDMyNDgsInR0IjpbMV19LCJ2IjoiMi45LjQ5MyJ9.piPax876l_Uzi3JLBE_LVR4mbEXCfUFOO_IE7eGf4a1e-Q4N6yvIFvokAc6yg03quMvk_xMgRKpSdg4c4AFoN6cuy4UzwjoJPzVRAS2ADlR3voF_xSDbc4pmdUMU36wDPzHDhadZTrCra_BAP6sxJvA7bk8gsO7BcTxKi168KORV9eII9b0WSCKFOPMtWTnyvkTrEdU4Ig7Xe7XrSJ4qNE4Mznd3i1hnO6Jca9kdS40ASw4XE9aw1ShQsWB0KnhL4GI18FsPMnYv8lmdDOPfwpm8XHf5jlHVjMJjNEq9ep2hKoD2ZVcl11Fw2WW_TeAPWfVmsy0KbZ1SUm3JIu0DDlh-Ods6axb2u9j2RjXKrME4uAShQjorQDMhFEP_2Ba1gpCWKZigvCvg3ib_4yNNAWAvaqQ_ROAUhKVZyNPKq4WFC8hSSfCSVSmc1tx4CeMYCv_vmCigzhxkXdUbz6-Mlj5CzAmUVXIwoG-3siN9QjrtN0lBeF3nVWCkgKt_rJ3iM93ezBAeVnDa8jqmbjtrJ-0_LUhgtebU3jiJWLIJQWolzKYRDP5cmrgsUwM0CwNWypp5B8XHEjRQ0PmpAmfnHYewSmHI2YSw_OiaCpQdu1dMTsPcfbAukG9y_X9JirLl9pej6bJY7j95nQPv71VT7Z8JPpri1V8nlwglGnKH_Fh7QHWk23tCwUhbz6eCTDlADtR8-eMDJNAyi8gKLmWIzPfqQ1ihdwvuJ-EQsYmbZNepdNpProRoNIWJM5xpOlCKrEwyOXxjmpg2lL4RhS7sgTYnFUX9WmWIR1BeR_xe9q7dhR0xI_5igza-bjppCqmU8Ece4ScaDtAP-esT9JTkOcmdi9g48FJMxbaGuq_PzRLRGpA06azEqJh-CCQuvHaFm2yPntXq76QMvs12hJzNc6B7IsFGTJokkW2uNWT_KYgVufS9T0BhrjXu0ZHYfx-gyhkvNXU52ZYyxAi-2uKPXdLYOuvFT1VluZlv0ufnRIxxRW-9okL1zxsYPAyRldtFciJNo-_axTMy-9gEDlaNMUhQhRGMMfO_bst11dFznUyfYQfHcusuNR30xpA95_Bb3q1sS6fFO5OwEFeY1l6vWhsORVKuPYmZMNmwG0OjDyXB-YEqNLxl7hGQ9nvrbYUA8tgOeeRMQ_hqzta69hAIPz7oCt2ey08ljVhKYlqTRx8PTUPfR2yJO3-sg4XPZK-f6UlL1NfScP8CvQdkXt_7X1DfDr765o0gjcuu0nr9zwO_J6bubgB3yLd6BsFLkLpY.")  
                .addHeader("xy-common-params","fid=176476455610a006500aeedc7aa3708a8be3031932d7&gid=&device_model=phone&tz=Asia%2FShanghai&channel=YingYongBao&versionName=9.11.0&deviceId=09a9b1be-85ba-3cbe-8e71-06ad67760ad2&platform=android&sid=&identifier_flag=4&cpu_abi=armeabi-v7a&nqe_score=91&project_id=ECFAAF&x_trace_page_current=&lang=zh-Hans&app_id=ECFAAF01&uis=light&teenager=0&active_ctry=&cpu_name=Qualcomm+Technologies%2C+Inc+SDM845&dlang=zh&data_ctry=CN&SUE=0&launch_id=1764767679&device_level=3&origin_channel=YingYongBao&overseas_channel=0&mlanguage=zh_cn&folder_type=none&auto_trans=0&t=1764767921&build=9110805&holder_ctry=CN&did=9d29cd0e55089e8e17beb8757715900b")  
                .addHeader("User-Agent","Dalvik/2.1.0 (Linux; U; Android 13; Pixel 4 XL Build/TP1A.221005.002.B2) Resolution/1440*3040 Version/8.77.0 Build/8770299 Device/(Google;Pixel 4 XL) discover/8.77.0 NetType/WiFi")  
                .addHeader("Referer","https://app.xhs.cn/")  
                .build();  
    }  
  
    public void initializeNative(){  
        String method = "initializeNative()V";  
        XhsNativeClass.callStaticJniMethod(emulator,method);  
    }  
    // 初始化  
    public void initialize(){  
  
        cPtr = XhsNativeObject.callJniMethodLong(emulator, "initialize(Ljava/lang/String;)J", "main");  
        System.out.println("cPtr = " + cPtr);  
    }  
  
    public void intercept(){  
        chain =  vm.resolveClass("okhttp3/Interceptor$Chain").newObject(null);  
        // 找到类的方法  
        String method = "intercept(Lokhttp3/Interceptor$Chain;J)Lokhttp3/Response;";  
  
        DvmObject<?> response = XhsNativeClass.callStaticJniMethodObject(  
                emulator,  
                method,  
                chain,  
                cPtr  
        );  
  
        // DvmObject<?> result = obj;        System.out.println(response);  
    }  
  
  
    public static void main(String[] args){  
        XhsShield xhsShield = new XhsShield();  
        xhsShield.initializeNative();  
        xhsShield.initialize();  
        xhsShield.intercept();  
        System.out.println("shield:"+ xhsShield.request.headers().get("shield"));  
    }  
  
    @Override  
    public int callIntMethodV(BaseVM vm, DvmObject<?> dvmObject, String signature, VaList vaList) {  
        switch (signature) {  
            case "okhttp3/Headers->size()I": {  
                Headers headers = (Headers) dvmObject.getValue();  
                return headers.size();  
            } case "okhttp3/Response->code()I" :{  
                return 200;  
            }  
        }        return super.callIntMethodV(vm, dvmObject, signature, vaList);  
    }  
  
    @Override  
    public DvmObject<?> newObjectV(BaseVM vm, DvmClass dvmClass, String signature, VaList vaList) {  
        switch (signature) {  
            case "okio/Buffer-><init>()V" : {  
                return  dvmClass.newObject(new Buffer());  
            }  
        }        return super.newObjectV(vm, dvmClass, signature, vaList);  
    }  
  
    @Override  
    public DvmObject<?> callStaticObjectMethodV(BaseVM vm, DvmClass dvmClass, String signature, VaList vaList) {  
        switch (signature) {  
            case "com/xingin/shield/http/Base64Helper->decode(Ljava/lang/String;)[B" :{  
                String cipher = vaList.getObjectArg(0).toString();  
                return new ByteArray(vm, Base64.getMimeDecoder().decode(cipher));  
            }case "java/nio/charset/Charset->defaultCharset()Ljava/nio/charset/Charset;" :{  
                Charset defaultCharset = Charset.defaultCharset();  
                return ProxyDvmObject.createObject(vm, defaultCharset);  
            }  
        }        return super.callStaticObjectMethodV(vm, dvmClass, signature, vaList);  
    }  
  
  
  
    @Override  
    public int getStaticIntField(BaseVM vm, DvmClass dvmClass, String signature) {  
        switch (signature) {  
            case "com/xingin/shield/http/ContextHolder->sAppId:I": {  
                return -319115519;  
            }  
        }        return super.getStaticIntField(vm, dvmClass, signature);  
    }  
  
    @Override  
    public DvmObject<?> getStaticObjectField(BaseVM vm, DvmClass dvmClass, String signature) {  
        switch (signature){  
            case "com/xingin/shield/http/ContextHolder->sDeviceId:Ljava/lang/String;" :{  
                return new StringObject(vm, "09a9b1be-85ba-3cbe-8e71-06ad67760ad2");  
            }  
  
        }        return super.getStaticObjectField(vm, dvmClass, signature);  
    }  
  
    @Override  
    public DvmObject<?> callObjectMethodV(BaseVM vm, DvmObject<?> dvmObject, String signature, VaList vaList) {  
        switch (signature) {  
            case "android/content/Context->getSharedPreferences(Ljava/lang/String;I)Landroid/content/SharedPreferences;": {  
                String sharedPreferencesFileName = vaList.getObjectArg(0).toString();  
                System.out.println("sharedPreferencesFileName:" + sharedPreferencesFileName);  
                return vm.resolveClass("android/content/SharedPreferences").newObject(sharedPreferencesFileName);  
            }  
            case "android/content/SharedPreferences->getString(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;": {  
                String key = vaList.getObjectArg(0).toString();  
                String defaultValue = vaList.getObjectArg(1).toString();  
  
                System.out.println("key:" + key);  
                System.out.println("defaultValue:" + defaultValue);  
                switch (key) {  
                    case "main_hmac": {  
                        return new StringObject(vm, "sN1QiRZkXPh88VBAWSUHBLLkVh7dWKE5cqJoWMqryy0KLi1rLzpDRoQLUQmUqmpp4QCRV1uX7HrWBmlmdgiqyAyJiPKE7Wqv/93mDZrGiQRHIBzvt8PmktASa8izEcM3");  
                    }  
                }                return new StringObject(vm, defaultValue);  
            }  
            case "okhttp3/Interceptor$Chain->request()Lokhttp3/Request;": {  
                return vm.resolveClass("okhttp3/Request").newObject(request);  
            }  
            case "okhttp3/Request->url()Lokhttp3/HttpUrl;": {  
                return vm.resolveClass("okhttp3/HttpUrl").newObject(request.url());  
            }  
            case "okhttp3/HttpUrl->encodedPath()Ljava/lang/String;": {  
                HttpUrl httpUrl = (HttpUrl) dvmObject.getValue();  
                return new StringObject(vm, httpUrl.encodedPath());  
            }  
            case "okhttp3/HttpUrl->encodedQuery()Ljava/lang/String;": {  
                HttpUrl httpUrl = (HttpUrl) dvmObject.getValue();  
                return new StringObject(vm, httpUrl.encodedQuery());  
            }  
            case "okhttp3/Request->body()Lokhttp3/RequestBody;": {  
                Request request = (Request) dvmObject.getValue();  
                return ProxyDvmObject.createObject(vm, request.body());  
            }  
            case "okhttp3/Request->headers()Lokhttp3/Headers;": {  
                Request request = (Request) dvmObject.getValue();  
                return ProxyDvmObject.createObject(vm, request.headers());  
            }  
            case "okio/Buffer->writeString(Ljava/lang/String;Ljava/nio/charset/Charset;)Lokio/Buffer;": {  
                Buffer buffer = (Buffer) dvmObject.getValue();  
                String arg1 = vaList.getObjectArg(0).getValue().toString();  
                Charset arg2 = (Charset) vaList.getObjectArg(1).getValue();  
                return vm.resolveClass("okio/Buffer").newObject(buffer.writeString(arg1, arg2));  
            }  
            case "okhttp3/Headers->name(I)Ljava/lang/String;": {  
                Headers headers = (Headers) dvmObject.getValue();  
                int arg1 = (int) vaList.getIntArg(0);  
                return new StringObject(vm, headers.name(arg1));  
            }  
            case "okhttp3/Headers->value(I)Ljava/lang/String;": {  
                Headers headers = (Headers) dvmObject.getValue();  
                int arg1 = (int) vaList.getIntArg(0);  
                return new StringObject(vm, headers.value(arg1));  
            }  
            case "okio/Buffer->clone()Lokio/Buffer;": {  
                Buffer buffer = (Buffer) dvmObject.getValue();  
                return vm.resolveClass("okio/Buffer").newObject(buffer.clone());  
            }  
            case "okhttp3/Request->newBuilder()Lokhttp3/Request$Builder;": {  
                Request requestObj_newBuilder = (Request) dvmObject.getValue();  
                return vm.resolveClass("okhttp3/Request$Builder").newObject(requestObj_newBuilder.newBuilder());  
            } case "okhttp3/Request$Builder->header(Ljava/lang/String;Ljava/lang/String;)Lokhttp3/Request$Builder;" :{  
                Request.Builder requestObj_Builder = (Request.Builder) dvmObject.getValue();  
                String arg0 = vaList.getObjectArg(0).getValue().toString();  
                String arg1 = vaList.getObjectArg(1).getValue().toString();  
                return vm.resolveClass("okhttp3/Request$Builder").newObject(requestObj_Builder.header(arg0,arg1));  
            } case "okhttp3/Request$Builder->build()Lokhttp3/Request;" :{  
                Request.Builder requestObj_Builder = (Request.Builder) dvmObject.getValue();  
                Request resultRequest = requestObj_Builder.build();  
                request = resultRequest;  
                return vm.resolveClass("okhttp3/Request").newObject(resultRequest);  
            } case "okhttp3/Interceptor$Chain->proceed(Lokhttp3/Request;)Lokhttp3/Response;" :{  
                return vm.resolveClass("okhttp3/Response").newObject(null);  
            }  
        }        return super.callObjectMethodV(vm, dvmObject, signature, vaList);  
    }  
  
  
  
    @Override  
    public void callStaticVoidMethodV(BaseVM vm, DvmClass dvmClass, String signature, VaList vaList) {  
        switch (signature) {  
            case "com/xingin/shield/http/ContextHolder->writeLog(I)V" :{  
                // vm.resolveClass("com/xingin/shield/http/ShieldLogger").newObject(null);  
            }  
        }      //  super.callStaticVoidMethodV(vm, dvmClass, signature, vaList);  
    }  
}

字段流程分析,在另一篇文章里

参考文章

c++的String

相关推荐
Jet_585 小时前
IDA Pro 远程调试指南:gdbserver / armlinux_server 全流程实战
安卓逆向·逆向工程·远程调试·gdbserver·ida pro·android 调试
Jet_5815 天前
[特殊字符] AndroidReverse101:100 天系统学习 Android 逆向工程(学习路线推荐)
安卓逆向·逆向工程·frida·android逆向·安全研究·apk逆向
泡泡以安1 个月前
【Android逆向工程】第3章:Java 字节码与 Smali 语法基础
android·java·安卓逆向
CC-NX3 个月前
移动终端安全:实验2-创建自签名证书对APP签名
安全·安卓逆向·签名校验
泡泡以安6 个月前
安卓高版本HTTPS抓包:终极解决方案
爬虫·https·安卓逆向·安卓抓包
染指11108 个月前
6.安卓逆向2-手机安装charles证书
安卓逆向·app逆向·app协议分析·安卓协议分析
染指11108 个月前
2.安卓逆向2-adb指令
安卓逆向·app逆向·app协议分析·apk逆向
染指11108 个月前
3.安卓逆向2-安卓文件目录
安卓逆向·app逆向·apk逆向
烬奇小云10 个月前
安卓7.0到11.0的更新变化(简单理解)
android·安卓逆向