当前位置:网站首页>X Book 6.97 shield unidbg calling method
X Book 6.97 shield unidbg calling method
2022-06-30 03:14:00 【Codeooo】
The previous article was taken off the shelf , Specially released xhs6.97 edition shield Generate analysis process .
shield-unidbg The way
jadx After decompiling :
The order in which the functions are called is initializeNative > initialize > intercept
Functions are heavily used JNI Method ,JNItrace It will greatly reduce our workload in this part , Forgot to say ,JNItrace It's based on Frida Framework of the Hook jni The library of methods ,https://github.com/chame1eon/jnitrace
jnitrace -l libbili.so tv.danmaku.bili --ignore-vm

Get the offset address of each function directly .
Where the template needs to be modified :
unidbg - 》 getStaticObjectField Method fill in your mobile phone deviceId
@Override
public DvmObject<?> getStaticObjectField(BaseVM vm, DvmClass dvmClass, String signature) {
switch (signature){
case "com/xingin/shield/http/ContextHolder->sLogger:Lcom/xingin/shield/http/ShieldLogger;":{
return vm.resolveClass("com/xingin/shield/http/ShieldLogger").newObject(signature);
}
case "com/xingin/shield/http/ContextHolder->sDeviceId:Ljava/lang/String;":{
return new StringObject(vm, "81e30ab8-2b81-33dd-8435-f9404554b4b5");
}
}
return super.getStaticObjectField(vm, dvmClass, signature);
}
unidbg - 》 callObjectMethodV Method fill in your little red book path s.xml In the value of the :

Or in the packet capture response header : lookup xy-ter-str

hmac The results are in , In response , therefore hmac The server sends it to the client .
@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")){
System.out.println("getString :"+vaList.getObjectArg(0).getValue());
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");
}
}
}
case "okhttp3/Interceptor$Chain->request()Lokhttp3/Request;": {
DvmClass clazz = vm.resolveClass("okhttp3/Request");
return clazz.newObject(request);
}
case "okhttp3/Request->url()Lokhttp3/HttpUrl;": {
DvmClass clazz = vm.resolveClass("okhttp3/HttpUrl");
Request request = (Request) dvmObject.getValue();
return clazz.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 vm.resolveClass("okhttp3/RequestBody").newObject(request.body());
}
case "okhttp3/Request->headers()Lokhttp3/Headers;": {
Request request = (Request) dvmObject.getValue();
return vm.resolveClass("okhttp3/Headers").newObject(request.headers());
}
case "okio/Buffer->writeString(Ljava/lang/String;Ljava/nio/charset/Charset;)Lokio/Buffer;": {
System.out.println("write to my buffer:"+vaList.getObjectArg(0).getValue());
Buffer buffer = (Buffer) dvmObject.getValue();
buffer.writeString(vaList.getObjectArg(0).getValue().toString(), (Charset) vaList.getObjectArg(1).getValue());
return dvmObject;
}
case "okhttp3/Headers->name(I)Ljava/lang/String;": {
Headers headers = (Headers) dvmObject.getValue();
return new StringObject(vm, headers.name(vaList.getIntArg(0)));
}
case "okhttp3/Headers->value(I)Ljava/lang/String;": {
Headers headers = (Headers) dvmObject.getValue();
return new StringObject(vm, headers.value(vaList.getIntArg(0)));
}
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 request = (Request) dvmObject.getValue();
return vm.resolveClass("okhttp3/Request$Builder").newObject(request.newBuilder());
}
case "okhttp3/Request$Builder->header(Ljava/lang/String;Ljava/lang/String;)Lokhttp3/Request$Builder;": {
Request.Builder builder = (Request.Builder) dvmObject.getValue();
builder.header(vaList.getObjectArg(0).getValue().toString(), vaList.getObjectArg(1).getValue().toString());
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;": {
return vm.resolveClass("okhttp3/Response").newObject(null);
}
}
return super.callObjectMethodV(vm, dvmObject, signature, vaList);
}
Enclosed unidbg All source code :
Pay attention to the changes mentioned above :
package com.xhs6970181;
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 java.io.File;
import java.io.IOException;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;
public class xhs extends AbstractJni {
private final AndroidEmulator emulator;
private final VM vm;
private final Module module;
private Headers headers;
private Request request;
private String url;
xhs(){
emulator = AndroidEmulatorBuilder.for32Bit().setProcessName("com.xhs").build(); // Create simulator instance , To simulate 32 Bits or 64 position , Distinguish... Here
final Memory memory = emulator.getMemory(); // Memory operation interface of simulator
memory.setLibraryResolver(new AndroidResolver(23)); // Set system class library resolution
vm = emulator.createDalvikVM(new File("unidbg-android/src/test/resources/xhs69/xhs.apk"));
vm.setVerbose(true);
DalvikModule libcdm = vm.loadLibrary(new File("unidbg-android/src/main/resources/android/sdk23/lib/libc.so"), true);
// emulator.attach().addBreakPoint(libcdm.getModule().findSymbolByName("pthread_create").getAddress());
DalvikModule dm = vm.loadLibrary("shield", true);
vm.setJni(this);
module = dm.getModule();
System.out.println("call JNIOnLoad");
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=2b586458-dd63-3630-b79f-29b88a036ca7&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("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();
}
// The first initialization function
public void callinitializeNative(){
List<Object> list = new ArrayList<>(10);
list.add(vm.getJNIEnv()); // The first parameter is env
list.add(0); // The second parameter , The example method is jobject, The static method is jclazz, Directly fill in 0, Not usually used .
module.callFunction(emulator, 0x6c11d, list.toArray());
};
// The second initialization function
public long callinitialize(){
List<Object> list = new ArrayList<>(10);
list.add(vm.getJNIEnv()); // The first parameter is env
list.add(0); // The second parameter , The example method is jobject, The static method is jclazz, Directly fill in 0, Not usually used .
list.add(vm.addLocalObject(new StringObject(vm, "main")));
Number number = module.callFunction(emulator, 0x6b801, list.toArray())[0];
return number.longValue();
}
// Objective function
public void callintercept(long ptr){
List<Object> list = new ArrayList<>(10);
list.add(vm.getJNIEnv()); // The first parameter is env
list.add(0); // The second parameter , The example method is jobject, The static method is jclazz, Directly fill in 0, Not usually used .
DvmObject<?> chain = vm.resolveClass("okhttp3/Interceptor$Chain").newObject(null);
list.add(vm.addLocalObject(chain));
list.add(ptr);
module.callFunction(emulator, 0x6b9e9, list.toArray());
};
public static void main(String[] args) {
xhs test = new xhs();
test.callinitializeNative();
long ptr = test.callinitialize();
System.out.println("call intercept");
test.callintercept(ptr);
}
@Override
public DvmObject<?> getStaticObjectField(BaseVM vm, DvmClass dvmClass, String signature) {
switch (signature){
case "com/xingin/shield/http/ContextHolder->sLogger:Lcom/xingin/shield/http/ShieldLogger;":{
return vm.resolveClass("com/xingin/shield/http/ShieldLogger").newObject(signature);
}
case "com/xingin/shield/http/ContextHolder->sDeviceId:Ljava/lang/String;":{
return new StringObject(vm, "81e30ab8-2b81-33dd-8435-f9404554b4b5");
}
}
return super.getStaticObjectField(vm, dvmClass, signature);
}
@Override
public void callVoidMethodV(BaseVM vm, DvmObject<?> dvmObject, String signature, VaList vaList) {
switch (signature){
case "com/xingin/shield/http/ShieldLogger->nativeInitializeStart()V":{
return;
}
case "com/xingin/shield/http/ShieldLogger->nativeInitializeEnd()V": {
return;
}
case "com/xingin/shield/http/ShieldLogger->initializeStart()V": {
return;
}
case "com/xingin/shield/http/ShieldLogger->initializedEnd()V": {
return;
}
case "com/xingin/shield/http/ShieldLogger->buildSourceStart()V": {
return;
}
case "okhttp3/RequestBody->writeTo(Lokio/BufferedSink;)V": {
BufferedSink bufferedSink = (BufferedSink) vaList.getObjectArg(0).getValue();
RequestBody requestBody = (RequestBody) dvmObject.getValue();
if(requestBody != null){
try {
requestBody.writeTo(bufferedSink);
} catch (IOException e) {
e.printStackTrace();
}
}
return;
}
case "com/xingin/shield/http/ShieldLogger->buildSourceEnd()V": {
return;
}
case "com/xingin/shield/http/ShieldLogger->calculateStart()V": {
System.out.println("calculateStart —— Start calculating ");
return;
}
case "com/xingin/shield/http/ShieldLogger->calculateEnd()V": {
System.out.println("calculateEnd —— End calculation ");
return;
}
}
super.callVoidMethodV(vm, dvmObject, signature, vaList);
}
@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 input = (String) vaList.getObjectArg(0).getValue();
byte[] result = Base64.decodeBase64(input);
return new ByteArray(vm, result);
}
}
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 6970181;
}
}
return super.getIntField(vm, dvmObject, 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 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")){
System.out.println("getString :"+vaList.getObjectArg(0).getValue());
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");
}
}
}
case "okhttp3/Interceptor$Chain->request()Lokhttp3/Request;": {
DvmClass clazz = vm.resolveClass("okhttp3/Request");
return clazz.newObject(request);
}
case "okhttp3/Request->url()Lokhttp3/HttpUrl;": {
DvmClass clazz = vm.resolveClass("okhttp3/HttpUrl");
Request request = (Request) dvmObject.getValue();
return clazz.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 vm.resolveClass("okhttp3/RequestBody").newObject(request.body());
}
case "okhttp3/Request->headers()Lokhttp3/Headers;": {
Request request = (Request) dvmObject.getValue();
return vm.resolveClass("okhttp3/Headers").newObject(request.headers());
}
case "okio/Buffer->writeString(Ljava/lang/String;Ljava/nio/charset/Charset;)Lokio/Buffer;": {
System.out.println("write to my buffer:"+vaList.getObjectArg(0).getValue());
Buffer buffer = (Buffer) dvmObject.getValue();
buffer.writeString(vaList.getObjectArg(0).getValue().toString(), (Charset) vaList.getObjectArg(1).getValue());
return dvmObject;
}
case "okhttp3/Headers->name(I)Ljava/lang/String;": {
Headers headers = (Headers) dvmObject.getValue();
return new StringObject(vm, headers.name(vaList.getIntArg(0)));
}
case "okhttp3/Headers->value(I)Ljava/lang/String;": {
Headers headers = (Headers) dvmObject.getValue();
return new StringObject(vm, headers.value(vaList.getIntArg(0)));
}
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 request = (Request) dvmObject.getValue();
return vm.resolveClass("okhttp3/Request$Builder").newObject(request.newBuilder());
}
case "okhttp3/Request$Builder->header(Ljava/lang/String;Ljava/lang/String;)Lokhttp3/Request$Builder;": {
Request.Builder builder = (Request.Builder) dvmObject.getValue();
builder.header(vaList.getObjectArg(0).getValue().toString(), vaList.getObjectArg(1).getValue().toString());
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;": {
return vm.resolveClass("okhttp3/Response").newObject(null);
}
}
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();
return buffer.read((byte[]) vaList.getObjectArg(0).getValue());
}
return super.callIntMethodV(vm, dvmObject, signature, vaList);
}
}
…
Let's run it and see the result :

No problem ,shield Generated .
Partial exchange results :

…
边栏推荐
- The MariaDB database was found 12 hours late
- An article to get you started VIM
- Customize the buttons of jvxetable and the usage of $set under notes
- How does the trading platform for speculation in spot gold ensure capital security?
- Global and Chinese market for sensor screwdrivers 2022-2028: Research Report on technology, participants, trends, market size and share
- Intel hex, Motorola S-Record format detailed analysis
- 如何实现远程协同办公,收好这份攻略!
- 个人PC安装软件
- Mysql提取表字段中的字符串
- Wechat applet +php to realize authorized login operation
猜你喜欢

golang bilibili直播彈幕姬

发现mariadb数据库时间晚了12个小时

mysql 主从数据库同步失败的原因
![[live broadcast notes 0629] Concurrent Programming II: lock](/img/5c/42f5c9a9969b4d2bb950a7caac5555.png)
[live broadcast notes 0629] Concurrent Programming II: lock

Auto.js学习笔记16:按项目保存到手机上,不用每次都保存单个js文件,方便调试和打包

O & M (21) make winpe startup USB flash disk

C # basic learning (XIII) | breakpoint debugging

How to prevent duplicate submission under concurrent requests

自定义MVC的使用

Reasons for MySQL master-slave database synchronization failure
随机推荐
The Oracle main program is deleted, but the data is on another hard disk. Can I import the data again?
What is the concept of string in PHP
Shell counts all strings before the last occurrence of a string
[untitled]
Quick sort, cluster index, find the k-largest value in the data
数据库的下一个变革方向——云原生数据库
问题记录:fel_lib.c:26:10: fatal error: libusb.h: 没有那个文件或目录
C # basic learning (XIII) | breakpoint debugging
Hands on in-depth learning notes (XV) 4.1 Multilayer perceptron
OP diode limit swing
PHP two-dimensional array randomly fetches a random or fixed number of one-dimensional arrays
发现mariadb数据库时间晚了12个小时
Gulang bilibilibili Live Screen Jackie
Neo4j---性能优化
[QT] QMap使用详解
SQLite use
编译一个无导入表的DLL
Servlet面试题
Data set preparation and arrangement
Link garbled escape character