文章目录
- 前言
- [定位java层 (hook request类)](#定位java层 (hook request类))
- 定位so层
- [unidbg 模拟执行](#unidbg 模拟执行)
-
- 1.writeLog
- [2. 初始化函数](#2. 初始化函数)
- [3. Charset的defaultCharset](#3. Charset的defaultCharset)
- [4. 补充sDeviceId、sAppId](#4. 补充sDeviceId、sAppId)
- [5. SharedPreferences补充](#5. SharedPreferences补充)
- 6.Base64Helper
- [7. request函数](#7. request函数)
- [8. okhttp的其他环境](#8. okhttp的其他环境)
- [9. okio](#9. okio)
- [10 proceed](#10 proceed)
- 11.状态码
- [12. 打印shield](#12. 打印shield)
- 完整代码
- 字段流程分析,在另一篇文章里
- 参考文章
前言
在还原这个字段之前,我先看了路飞学院的课程,初步了解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)
这次缺少的是安卓类 Context和SharedPreferences。 因为安卓类的代码太多,如果使用复制源代码的方式补还境很麻烦。直接模拟代码
\[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