当前位置:网站首页>X书6.89版本shield-unidbg调用方式
X书6.89版本shield-unidbg调用方式
2022-06-30 03:03:00 【Codeooo】
之前文章被下架,特意发布下xhs6.89版本shield生成分析过程。
X书69版本shield生成过程传输门:
https://blog.csdn.net/weixin_38927522/article/details/125460805
本博客更新68版本代码:
version: 6.89.0.1
package com.xhs689;
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.memory.Memory;
import okhttp3.*;
import okio.Buffer;
import okio.BufferedSink;
import org.apache.commons.codec.binary.Base64;
import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import java.io.File;
import java.io.IOException;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;
public class XhsShield extends AbstractJni {
private final VM vm;
private final Module module;
private final AndroidEmulator emulator;
private Request request;
public static void main(String[] args) {
Logger.getLogger(DalvikVM.class).setLevel(Level.DEBUG);
Logger.getLogger(BaseVM.class).setLevel(Level.DEBUG);
XhsShield xhsShield = new XhsShield();
xhsShield.initializeNative();
long initialize = xhsShield.initialize();
System.out.println("initialize:" + initialize);
xhsShield.intercept(initialize);
}
XhsShield() {
emulator = AndroidEmulatorBuilder.for32Bit().build();
final Memory memory = emulator.getMemory();
memory.setLibraryResolver(new AndroidResolver(23));
vm = emulator.createDalvikVM(new File("unidbg-android/src/test/resources/xhs68/xhs_6_89_0_1.apk"));
vm.setVerbose(true); //打印虚拟器日志
vm.setJni(this);
// DalvikModule dm = vm.loadLibrary(new File("unidbg-android/src/test/resources/so/libshield.so"), true);
DalvikModule dm = vm.loadLibrary("shield", true);
module = dm.getModule();
dm.callJNI_OnLoad(emulator);
String url = "https://edith.xiaohongshu.com/api/sns/v3/user/info?user_id=5aae2cffb1da1410848cc29f";
request = new Request.Builder()
.url(url)
// .addHeader("x-b3-traceid", "9f9fb0630e150e0f")
// .addHeader("xy-common-params", "fid=162988201010e62257db56717f42068a3d56cc4cd8f1&device_fingerprint=20210621164233f1abe938f11f4371dad0e9cb3764ef0101e128bc882febd5&device_fingerprint1=20210621164233f1abe938f11f4371dad0e9cb3764ef0101e128bc882febd5&launch_id=1629940903&tz=Asia%2FShanghai&channel=PMgdt9803121&versionName=6.89.0.1&deviceId=26a42bc5-251e-3643-9dae-6fb99195d573&platform=android&sid=session.1629882581793303421285&identifier_flag=4&t=1629947848&project_id=ECFAAF&build=6890179&x_trace_page_current=note_detail_r10&lang=zh-Hans&app_id=ECFAAF01&uis=light")
.addHeader("xy-common-params", "deviceId=26a42bc5-251e-3643-9dae-6fb99195d573&identifier_flag=2&tz=Asia%2FShanghai&fid=16449101901012f8b5e741923e7c7d93279b1f4d24ee&app_id=ECFAAF01&device_fingerprint1=20180228185909b2e5364323077785b0315af9140e0d3801afbcb1c4756a33&uis=light&launch_id=1644910190&project_id=ECFAAF&device_fingerprint=20220215152949aaea5aa92aea9c2f049efe43f243b5ca0057c541252db372&versionName=6.89.0.1&platform=android&sid=session.1644911729731178944357&t=1644913238&build=6890179&x_trace_page_current=video_feed&lang=zh-Hans&channel=PMgdt9803121")
.addHeader("user-agent", "Dalvik/2.1.0 (Linux; U; Android 10; Redmi Note 8 MIUI/V12.0.2.0.QCOCNXM) Resolution/1080*2340 Version/6.89.0.1 Build/6890179 Device/(Xiaomi;Redmi Note 8) discover/6.89.0.1 NetType/WiFi")
.build();
}
// XYAAAAAQAAAAEAAABTAAAAUzUWEe0xG1IbD9/c+qCLOlKGmTtFa+lG43AGdeFXQ6RKxNGznuc1RJ36rehez8MpiJl+2aYxFQwYGGGIYL7x2Hlk1OGfvw85YVTtxhk/7jGHg2ER
public void initializeNative() {
List<Object> params = new ArrayList<>();
params.add(vm.getJNIEnv()); //第一个参数默认env
params.add(0); //第二个参数一般填0,一般用不到
module.callFunction(emulator, 0x94289, params.toArray());
}
public long initialize() {
List<Object> params = new ArrayList<>();
params.add(vm.getJNIEnv()); //第一个参数默认env
params.add(0); //第二个参数一般填0,一般用不到
params.add(vm.addLocalObject(new StringObject(vm, "main")));
Number number = module.callFunction(emulator, 0x937b1, params.toArray())[0];
return number.longValue();
}
public void intercept(long initialize) {
List<Object> params = new ArrayList<>();
params.add(vm.getJNIEnv()); //第一个参数默认env
params.add(0); //第二个参数一般填0,一般用不到
DvmObject<?> chain = vm.resolveClass("okhttp3/Interceptor$Chain").newObject(null);
params.add(vm.addLocalObject(chain));
params.add(initialize);
Number[] numbers = module.callFunction(emulator, 0x939d9, params.toArray());
Object result = vm.getObject(numbers[0].intValue()).getValue();
System.out.println(result);
}
@Override
public DvmObject<?> callStaticObjectMethodV(BaseVM vm, DvmClass dvmClass, String signature, VaList vaList) {
switch (signature) {
case "java/nio/charset/Charset->defaultCharset()Ljava/nio/charset/Charset;": {
return vm.resolveClass("java/nio/charset/Charset").newObject(Charset.defaultCharset());
}
case "com/xingin/shield/http/Base64Helper->decode(Ljava/lang/String;)[B": {
String param1 = (String) vaList.getObjectArg(0).getValue();
byte[] bytes = Base64.decodeBase64(param1);
return new ByteArray(vm, bytes);
}
}
return super.callStaticObjectMethodV(vm, dvmClass, signature, vaList);
}
@Override
public int getIntField(BaseVM vm, DvmObject<?> dvmObject, String signature) {
switch (signature) {
case "android/content/pm/PackageInfo->versionCode:I": {
return 6890179;
}
}
return super.getIntField(vm, dvmObject, 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, "81e30ab8-2b81-33dd-8435-f9404554b4b5");
return new StringObject(vm, "26a42bc5-251e-3643-9dae-6fb99195d573");
}
}
return super.getStaticObjectField(vm, dvmClass, signature);
}
@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 boolean getStaticBooleanField(BaseVM vm, DvmClass dvmClass, String signature) {
switch (signature) {
case "com/xingin/shield/http/ContextHolder->sExperiment:Z": {
return true;
}
}
return super.getStaticBooleanField(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;": {
return vm.resolveClass("android/content/SharedPreferences").newObject(vaList.getObjectArg(0));
}
case "android/content/SharedPreferences->getString(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;": {
if(((StringObject) dvmObject.getValue()).getValue().equals("s")) {
if (vaList.getObjectArg(0).getValue().equals("main")) {
return new StringObject(vm, "");
}
if (vaList.getObjectArg(0).getValue().equals("main_hmac")) {
// return new StringObject(vm, "a9+xPqTwWr7ua8QlDuTyLjvNTAszAxbIhBWeugeCNpcorLQJTUiH6JbLFDrW1cypknldr7izHSeoGQ1HzB6VAVu7iMG6FU1+bEt7/e+9cx6LmeDCOKSapcI9elpXr9ba");
return new StringObject(vm, "uNWJiReR82KLoznU3fiUS/tMBYt30zYAThV3GmPq+i/4FuHhniLg70K2AtA+yj4NnxvevnnLjD7AcS7AMS17M929yLlN63SLIflx0BkGZnAowfW4DfYmwRuoJbAIWhVc");
}
}
}
case "okhttp3/Interceptor$Chain->request()Lokhttp3/Request;": {
return vm.resolveClass("okhttp3/Request").newObject(request);
}
case "okhttp3/Request->url()Lokhttp3/HttpUrl;": {
Request tempRequest = (Request) dvmObject.getValue();
return vm.resolveClass("okhttp3/HttpUrl").newObject(tempRequest.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 tempRequest = (Request) dvmObject.getValue();
return vm.resolveClass("okhttp3/RequestBody").newObject(tempRequest.body());
}
case "okhttp3/Request->headers()Lokhttp3/Headers;": {
Request tempRequest = (Request) dvmObject.getValue();
return vm.resolveClass("okhttp3/Headers").newObject(tempRequest.headers());
}
case "okio/Buffer->writeString(Ljava/lang/String;Ljava/nio/charset/Charset;)Lokio/Buffer;": {
Buffer buffer = (Buffer) dvmObject.getValue();
String param1 = (String) vaList.getObjectArg(0).getValue();
Charset param2 = (Charset) vaList.getObjectArg(1).getValue();
buffer.writeString(param1, param2);
return dvmObject;
}
case "okhttp3/Headers->name(I)Ljava/lang/String;": {
Headers headers = (Headers) dvmObject.getValue();
int param1 = vaList.getIntArg(0);
return new StringObject(vm, headers.name(param1));
}
case "okhttp3/Headers->value(I)Ljava/lang/String;": {
Headers headers = (Headers) dvmObject.getValue();
int param1 = vaList.getIntArg(0);
return new StringObject(vm, headers.value(param1));
}
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 tempRequest = (Request) dvmObject.getValue();
return vm.resolveClass("okhttp3/Request$Builder").newObject(tempRequest.newBuilder());
}
case "okhttp3/Request$Builder->header(Ljava/lang/String;Ljava/lang/String;)Lokhttp3/Request$Builder;": {
Request.Builder builder = (Request.Builder) dvmObject.getValue();
String param1 = (String) vaList.getObjectArg(0).getValue();
String param2 = (String) vaList.getObjectArg(1).getValue();
System.out.println("*********************************");
System.out.println("key:" + param1);
System.out.println("value:" + param2);
System.out.println("*********************************");
builder.header(param1, param2);
return dvmObject;
}
case "okhttp3/Request$Builder->build()Lokhttp3/Request;": {
Request.Builder builder = (Request.Builder) dvmObject.getValue();
return vm.resolveClass("okhttp3/Request").newObject(builder.build());
}
case "okhttp3/Interceptor$Chain->proceed(Lokhttp3/Request;)Lokhttp3/Response;": {
Interceptor.Chain chain = (Interceptor.Chain) dvmObject.getValue();
if (chain == null) {
return vm.resolveClass("okhttp3/Response").newObject(null);
}
Request param1 = (Request) vaList.getObjectArg(0).getValue();
try {
return vm.resolveClass("okhttp3/Response").newObject(chain.proceed(param1));
} catch (IOException e) {
e.printStackTrace();
}
}
}
return super.callObjectMethodV(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 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;
}
case "okio/Buffer->read([B)I": {
Buffer buffer = (Buffer) dvmObject.getValue();
byte[] param1 = (byte[]) vaList.getObjectArg(0).getValue();
return buffer.read(param1);
}
}
return super.callIntMethodV(vm, dvmObject, signature, vaList);
}
@Override
public void callVoidMethodV(BaseVM vm, DvmObject<?> dvmObject, String signature, VaList vaList) {
switch (signature) {
case "okhttp3/RequestBody->writeTo(Lokio/BufferedSink;)V": {
RequestBody requestBody = (RequestBody) dvmObject.getValue();
if (requestBody != null) {
BufferedSink param1 = (BufferedSink) vaList.getObjectArg(0).getValue();
try {
requestBody.writeTo(param1);
} catch (IOException e) {
e.printStackTrace();
}
}
return;
}
}
super.callVoidMethodV(vm, dvmObject, signature, vaList);
}
}
我们运行下看生成结果:
其实小红书就是用的okhttp3发包请求,而且shield只是参数解密,
最重要的风控,数美无限滑块,登陆后的sid等才是关键。
边栏推荐
- Golang BiliBili live broadcast bullet screen
- 备忘一下es6的export/import和类继承的用法
- Three solutions to forced hibernation of corporate computers
- What is the concept of string in PHP
- Wechat applet +php to realize authorized login operation
- 正则全匹配:密码由8位以上数字,大小写字母,特殊字符组成
- oracle怎么设置密码复杂度及超时退出的功能
- Use of Arthas
- 快速排序、聚簇索引、寻找数据中第k大的值
- List of development tools
猜你喜欢

HTA introductory basic tutorial | GUI interface of vbs script HTA concise tutorial, with complete course and interface beautification

Use of Arthas

Mysql表数据比较大情况下怎么修改添加字段

Idea remote debugging remote JVM debug

How to set password complexity and timeout exit function in Oracle

O & M (20) make and start USB flash disk and install win10

Heavy attack -- ue5's open source digital twin solution

自定义JvxeTable的按钮及备注下$set的用法

2. successfully solved bug:exception when publishing [Failed to connect and initialize SSH connection...

Distributed file storage system fastdfs hands on how to do it
随机推荐
发现mariadb数据库时间晚了12个小时
golang bilibili直播彈幕姬
Uniapp address translation latitude and longitude
Summary of PHP test sites encountered in CTF questions (I)
OP-diode-限制摆幅
Differences between comparable and comparator
SQLite use
正则全匹配:密码由8位以上数字,大小写字母,特殊字符组成
JS 互相引用的问题
中断操作:AbortController学习笔记
Raki's notes on reading paper: discontinuous named entity recognition as maximum clique discovery
外汇交易平台哪个好?有监管的资金就安全吗?
How to modify and add fields when MySQL table data is large
Azure developer news flash list of events of developers in June
通用分页(2)
2022 new test questions for safety management personnel of metal and nonmetal mines (small open pit quarries) and certificate examination for safety management personnel of metal and nonmetal mines (s
General paging (2)
(graph theory) connected component (template) + strongly connected component (template)
Raki's notes on reading paper: Leveraging type descriptions for zero shot named entity recognition and classification
Multi card server usage