首页
社区
课程
招聘
[分享]某内容分享平台最新shield字段分析
发表于: 5天前 4567

[分享]某内容分享平台最新shield字段分析

5天前
4567

协议抓包

先看下协议
图片描述

unidbg算法分析

搭架子补的关键代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
...
@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(null);
        case "com/xingin/shield/http/ContextHolder->sDeviceId:Ljava/lang/String;":
            return new StringObject(vm, "0d7eee2c-5d77-3c26-99f8-a5a2c9e08aeb");
    }
    //throw new UnsupportedOperationException(signature);
    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->buildSourceStart()V":
            return;
        case "com/xingin/shield/http/ShieldLogger->buildSourceEnd()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->calculateStart()V":
            return;
        case "com/xingin/shield/http/ShieldLogger->calculateEnd()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) {
                    System.out.println(e);
                }
            }
            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 = vaList.getObjectArg(0).getValue().toString();
            return new ByteArray(vm, Base64.decodeBase64(input));
    }
    //throw new UnsupportedOperationException(signature);
 return super.callStaticObjectMethodV(vm, dvmClass, signature, vaList);
}
  
@Override
public int callIntMethodV(BaseVM vm, DvmObject dvmObject, String signature, VaList vaList) {
    if (signature.equals("okhttp3/Headers->size()I")) {
        Headers headers = (Headers) dvmObject.getValue();
        return headers.size();
    }
    if (signature.equals("okio/Buffer->read([B)I")) {
        Buffer buffer = (Buffer) dvmObject.getValue();
        return buffer.read((byte[]) vaList.getObjectArg(0).getValue());
    }
    if (signature.equals("okhttp3/Response->code()I")) {
        return 200;
    }
    return super.callIntMethodV(vm, dvmObject, signature, vaList);
}
  
@Override
public DvmObject callObjectMethodV(BaseVM vm, DvmObject dvmObject, String signature, VaList vaList) {
    switch (signature) {
        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;":
            return new StringObject(vm, request.url().encodedPath());
        case "okhttp3/HttpUrl->encodedQuery()Ljava/lang/String;":
            if (request.url().encodedQuery() != null) {
                return new StringObject(vm, request.url().encodedQuery());
            }
            return new StringObject(vm, "");
        case "okhttp3/Request->body()Lokhttp3/RequestBody;":
            return vm.resolveClass("okhttp3/RequestBody").newObject(request.body());
        case "okhttp3/Request->headers()Lokhttp3/Headers;":
            return vm.resolveClass("okhttp3/Headers").newObject(request.headers());
        case "okio/Buffer->writeString(Ljava/lang/String;Ljava/nio/charset/Charset;)Lokio/Buffer;":
            Buffer buffer = (Buffer) dvmObject.getValue();
            buffer.writeString(vaList.getObjectArg(0).getValue().toString(), (Charset) vaList.getObjectArg(1).getValue());
            // return dvmObject;
            return ProxyDvmObject.createObject(vm,buffer);
        case "okio/Buffer->clone()Lokio/Buffer;":
            Buffer bufferc = (Buffer) dvmObject.getValue();
            return vm.resolveClass("okio/Buffer").newObject(bufferc.clone());
        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 headersValue = (Headers) dvmObject.getValue();
            return new StringObject(vm, headersValue.value(vaList.getIntArg(0)));
        case "okhttp3/Request$Builder->header(Ljava/lang/String;Ljava/lang/String;)Lokhttp3/Request$Builder;":
            okhttp3.Request.Builder builder = (okhttp3.Request.Builder)dvmObject.getValue();
            String para1 = (String)vaList.getObjectArg(0).getValue();
            String para2 = (String)vaList.getObjectArg(1).getValue();
            return vm.resolveClass("okhttp3/Request$Builder").newObject(builder.header(para1, para2));
        case "android/content/Context->getSharedPreferences(Ljava/lang/String;I)Landroid/content/SharedPreferences;":
            String xmlName =  vaList.getObjectArg(0).getValue().toString();
            System.out.println("xmlName : " + xmlName);
            return vm.resolveClass("android.content.SharedPreferences")
                    .newObject(null); //.newObject(vaList.getObjectArg(0).getValue().toString());
        case "android/content/SharedPreferences->getString(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;":
            String key = vaList.getObjectArg(0).getValue().toString();
            System.out.println("get key:"+key);
            switch (key){
                case "main":{
                    return new StringObject(vm, "");
                }
                case "main_hmac":{
                    return new StringObject(vm, "2s/EPZ9Xnk4cCZd5weXEd0DqcudY1yJwoQRV2cESN9+9HEVLiu6C72X5YfPYhiESrmuWLXe9U1BGSCIq7/DiMEWjsKmdlUEEbJGkmfTMN7xRJvuw2uqNpAewis/HKAQk");
                }
            }
        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->build()Lokhttp3/Request;":
            Request.Builder builderr = (Request.Builder) dvmObject.getValue();
            Request requestr = builderr.build();
            return vm.resolveClass("okhttp3/Request").newObject(requestr);
        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 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 newObjectV(BaseVM vm, DvmClass dvmClass, String signature, VaList vaList) {
    switch (signature){
        case "okio/Buffer->()V":
            return dvmClass.newObject(new Buffer());
    }
    return super.newObjectV(vm, dvmClass, signature, vaList);
}
  
public void call_initializeNative() {
    List<Object> params = new ArrayList<>();
    params.add(vm.getJNIEnv());
    params.add(0);
    Number number = module.callFunction(emulator, 0xbd8bc, params.toArray());
}
  
public long call_initialize() {
    List<Object> params = new ArrayList<>();
    params.add(vm.getJNIEnv());
    params.add(0);
    params.add(vm.addLocalObject(new StringObject(vm,"main")));
    Number number = module.callFunction(emulator, 0xbc3c8, params.toArray());
    return number.longValue();
}
  
public void call_intercept(long cPtr) {
    List<Object> params = new ArrayList<>();
    params.add(vm.getJNIEnv());
    params.add(0);
  
    DvmObject chain = vm.resolveClass("okhttp3/Interceptor$Chain").newObject(null);
    params.add(vm.addLocalObject(chain));
    params.add(cPtr);
    Number number = module.callFunction(emulator, 0xbc6b4, params.toArray());
    Object result = vm.getObject(number.intValue()).getValue();
}
  
public static void main(String[] args) {
    request = new Request.Builder()
            .url("e3eK9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6W2k6r3W2@1K9q4)9J5k6i4S2A6j5h3!0Z5L8$3&6Y4M7$3S2#2i4K6u0W2j5$3!0E0i4K6u0r3j5i4m8A6i4K6u0r3M7$3&6K6i4K6u0r3N6U0k6Q4x3V1k6E0k6i4y4K6j5h3N6W2i4K6u0r3k6r3g2@1k6h3y4@1")
            .addHeader("xy-direction", "49")
            .addHeader("xy-common-params","fid=1722182473106fc84899565e2acf00656ae05a78764b&device_fingerprint=2023122411004376bd379fe6f54e6dc5ca0b0cf8d24dd601dc85661f97571b&device_fingerprint1=2023122411004376bd379fe6f54e6dc5ca0b0cf8d24dd601dc85661f97571b&cpu_name=Qualcomm+Technologies%2C+Inc+SDM845&gid=7c7ea0a5b61c5590cec3770efa9cfec6e81b439947359eeb775b6fc4&device_model=phone&launch_id=1722617914&tz=Asia%2FShanghai&channel=Guanfang&versionName=8.42.0&overseas_channel=0&deviceId=0d7eee2c-5d77-3c26-99f8-a5a2c9e08aeb&platform=android&sid=session.1722182426050852896201&identifier_flag=4&t=1722617846&project_id=ECFAAF&build=8420294&x_trace_page_current=&lang=zh-Hans&app_id=ECFAAF01&uis=light&teenager=0")
            .build();
    fuckxhs fkxhs = new fuckxhs();
    fkxhs.call_initializeNative();
    long cPtr = fkxhs.call_initialize();
    fkxhs.call_intercept(cPtr);
}

运行起来后

1
2
3
4
5
6
7
8
9
10
11
JNIEnv->CallIntMethodV(okio.Buffer@5622fdf, read([B@7d9d1a19) => 0x302) was called from RX@0x40013d54[libshield.so]0x13d54
JNIEnv->GetByteArrayElements(false) => [B@7d9d1a19 was called from RX@0x40016048[libshield.so]0x16048
JNIEnv->CallIntMethodV(okio.Buffer@5622fdf, read([B@39c0f4a) => 0xffffffff) was called from RX@0x40013d54[libshield.so]0x13d54
JNIEnv->NewStringUTF("XYAAAAAQAAAAEAAABTAAAAUzUWEe0xG1IbD9/c+qCLOlKGmTtFa+lG434KfuFUTalCkYPly+NlH539q+dYz8N53st+2KtkGAwfFDSKN7Kh3CMx07Yvb5gnynhyIN/gbMnm9OPb") was called from RX@0x400bcf2c[libshield.so]0xbcf2c
JNIEnv->CallVoidMethodV(com.xingin.shield.http.ShieldLogger@5315b42e, calculateEnd()) was called from RX@0x40014354[libshield.so]0x14354
JNIEnv->CallObjectMethodV(okhttp3.Request@2b98378d, newBuilder() => okhttp3.Request$Builder@42e26948) was called from RX@0x40013bf4[libshield.so]0x13bf4
JNIEnv->CallObjectMethodV(okhttp3.Request$Builder@42e26948, header("shield", "XYAAAAAQAAAAEAAABTAAAAUzUWEe0xG1IbD9/c+qCLOlKGmTtFa+lG434KfuFUTalCkYPly+NlH539q+dYz8N53st+2KtkGAwfFDSKN7Kh3CMx07Yvb5gnynhyIN/gbMnm9OPb") => okhttp3.Request$Builder@57baeedf) was called from RX@0x40013bf4[libshield.so]0x13bf4
JNIEnv->CallObjectMethodV(okhttp3.Request$Builder@42e26948, header("xy-platform-info", "platform=android&build=8420294&deviceId=0d7eee2c-5d77-3c26-99f8-a5a2c9e08aeb") => okhttp3.Request$Builder@343f4d3d) was called from RX@0x40013bf4[libshield.so]0x13bf4
JNIEnv->CallObjectMethodV(okhttp3.Request$Builder@42e26948, build() => okhttp3.Request@53b32d7) was called from RX@0x40013bf4[libshield.so]0x13bf4
JNIEnv->CallObjectMethodV(okhttp3.Interceptor$Chain@4b9e13df, proceed(okhttp3.Request@53b32d7) => okhttp3.Response@5442a311) was called from RX@0x40013bf4[libshield.so]0x13bf4
JNIEnv->CallIntMethodV(okhttp3.Response@5442a311, code() => 0xc8) was called from RX@0x40013d54[libshield.so]0x13d54

从日志可以看出shield字段,我们挑最上面的“JNIEnv->NewStringUTF”的执行地址0xbcf2c开始定位debugger.addBreakPoint(module.base + 0xbcf2c)
图片描述
继续emulator.traceWrite(0x40461018,0x40461018+134)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
[23:37:28 675] Memory WRITE at 0x4046101a, data size = 8, data value = 0x4141514141414141, PC=RX@0x4028c1f8[libc.so]0x1c1f8, LR=RX@0x4009f0f0[libshield.so]0x9f0f0
[23:37:28 675] Memory WRITE at 0x40461022, data size = 8, data value = 0x5442414141454141, PC=RX@0x4028c1f8[libc.so]0x1c1f8, LR=RX@0x4009f0f0[libshield.so]0x9f0f0
[23:37:28 675] Memory WRITE at 0x40461022, data size = 8, data value = 0x5442414141454141, PC=RX@0x4028c220[libc.so]0x1c220, LR=RX@0x4009f0f0[libshield.so]0x9f0f0
[23:37:28 675] Memory WRITE at 0x4046102a, data size = 8, data value = 0x57557a5541414141, PC=RX@0x4028c220[libc.so]0x1c220, LR=RX@0x4009f0f0[libshield.so]0x9f0f0
[23:37:28 675] Memory WRITE at 0x40461032, data size = 8, data value = 0x6249314778306545, PC=RX@0x4028c224[libc.so]0x1c224, LR=RX@0x4009f0f0[libshield.so]0x9f0f0
[23:37:28 675] Memory WRITE at 0x4046103a, data size = 8, data value = 0x4c43712b632f3944, PC=RX@0x4028c224[libc.so]0x1c224, LR=RX@0x4009f0f0[libshield.so]0x9f0f0
[23:37:28 675] Memory WRITE at 0x40461042, data size = 8, data value = 0x4674546d474b6c4f, PC=RX@0x4028c228[libc.so]0x1c228, LR=RX@0x4009f0f0[libshield.so]0x9f0f0
[23:37:28 675] Memory WRITE at 0x4046104a, data size = 8, data value = 0x4b343334476c2b61, PC=RX@0x4028c228[libc.so]0x1c228, LR=RX@0x4009f0f0[libshield.so]0x9f0f0
[23:37:28 676] Memory WRITE at 0x40461052, data size = 8, data value = 0x436c615455467566, PC=RX@0x4028c22c[libc.so]0x1c22c, LR=RX@0x4009f0f0[libshield.so]0x9f0f0
[23:37:28 676] Memory WRITE at 0x4046105a, data size = 8, data value = 0x6c4e2b796c50596b, PC=RX@0x4028c22c[libc.so]0x1c22c, LR=RX@0x4009f0f0[libshield.so]0x9f0f0
[23:37:28 676] Memory WRITE at 0x40461062, data size = 8, data value = 0x59642b7139333548, PC=RX@0x4028c17c[libc.so]0x1c17c, LR=RX@0x4009f0f0[libshield.so]0x9f0f0
[23:37:28 676] Memory WRITE at 0x4046106a, data size = 8, data value = 0x2b747333354e387a, PC=RX@0x4028c17c[libc.so]0x1c17c, LR=RX@0x4009f0f0[libshield.so]0x9f0f0
[23:37:28 676] Memory WRITE at 0x40461072, data size = 8, data value = 0x667741476b744b32, PC=RX@0x4028c184[libc.so]0x1c184, LR=RX@0x4009f0f0[libshield.so]0x9f0f0
[23:37:28 676] Memory WRITE at 0x4046107a, data size = 8, data value = 0x684b374e4b534446, PC=RX@0x4028c184[libc.so]0x1c184, LR=RX@0x4009f0f0[libshield.so]0x9f0f0
[23:37:28 676] Memory WRITE at 0x40461082, data size = 8, data value = 0x76593730784d4333, PC=RX@0x4028c18c[libc.so]0x1c18c, LR=RX@0x4009f0f0[libshield.so]0x9f0f0
[23:37:28 676] Memory WRITE at 0x4046108a, data size = 8, data value = 0x79686e796e673562, PC=RX@0x4028c18c[libc.so]0x1c18c, LR=RX@0x4009f0f0[libshield.so]0x9f0f0
[23:37:28 676] Memory WRITE at 0x4046108e, data size = 8, data value = 0x672f4e4979686e79, PC=RX@0x4028c1a4[libc.so]0x1c1a4, LR=RX@0x4009f0f0[libshield.so]0x9f0f0
[23:37:28 676] Memory WRITE at 0x40461096, data size = 8, data value = 0x62504f396d6e4d62, PC=RX@0x4028c1a4[libc.so]0x1c1a4, LR=RX@0x4009f0f0[libshield.so]0x9f0f0
[23:37:28 676] Memory WRITE at 0x4046109e, data size = 1, data value = 0x00, PC=RX@0x4009f038[libshield.so]0x9f038, LR=RX@0x4009f120[libshield.so]0x9f120
[23:37:28 676] Memory WRITE at 0x40461018, data size = 2, data value = 0x5958, PC=RX@0x4028c1cc[libc.so]0x1c1cc, LR=RX@0x4009f78c[libshield.so]0x9f78c

根据地址定位到
图片描述
在此处下断点多调试几次,不难发现应该是memcpy函数
debugger.addBreakPoint(module.base+0x9f0e8)
图片描述
找到地址后继续trace一下emulator.traceWrite(0x4059a018,0x4059a018+134)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
[09:38:33 900] Memory WRITE at 0x4059a09d, data size = 1, data value = 0x00, PC=RX@0x4009d04c[libshield.so]0x9d04c, LR=RX@0x4009d030[libshield.so]0x9d030
[09:38:33 900] Memory WRITE at 0x4059a018, data size = 1, data value = 0x41, PC=RX@0x4004bfac[libshield.so]0x4bfac, LR=RX@0x40049b98[libshield.so]0x49b98
[09:38:33 900] Memory WRITE at 0x4059a01b, data size = 1, data value = 0x41, PC=RX@0x4004bfc4[libshield.so]0x4bfc4, LR=RX@0x40049b98[libshield.so]0x49b98
[09:38:33 900] Memory WRITE at 0x4059a019, data size = 1, data value = 0x41, PC=RX@0x4004bfc8[libshield.so]0x4bfc8, LR=RX@0x40049b98[libshield.so]0x49b98
[09:38:33 900] Memory WRITE at 0x4059a01a, data size = 1, data value = 0x41, PC=RX@0x4004bfcc[libshield.so]0x4bfcc, LR=RX@0x40049b98[libshield.so]0x49b98
[09:38:33 900] Memory WRITE at 0x4059a01c, data size = 1, data value = 0x41, PC=RX@0x4004bfac[libshield.so]0x4bfac, LR=RX@0x40049b98[libshield.so]0x49b98
[09:38:33 901] Memory WRITE at 0x4059a01f, data size = 1, data value = 0x41, PC=RX@0x4004bfc4[libshield.so]0x4bfc4, LR=RX@0x40049b98[libshield.so]0x49b98
[09:38:33 901] Memory WRITE at 0x4059a01d, data size = 1, data value = 0x51, PC=RX@0x4004bfc8[libshield.so]0x4bfc8, LR=RX@0x40049b98[libshield.so]0x49b98
...
[09:38:33 905] Memory WRITE at 0x4059a096, data size = 1, data value = 0x6e, PC=RX@0x4004bfcc[libshield.so]0x4bfcc, LR=RX@0x40049b98[libshield.so]0x49b98
[09:38:33 905] Memory WRITE at 0x4059a098, data size = 1, data value = 0x39, PC=RX@0x4004bfac[libshield.so]0x4bfac, LR=RX@0x40049b98[libshield.so]0x49b98
[09:38:33 905] Memory WRITE at 0x4059a09b, data size = 1, data value = 0x62, PC=RX@0x4004bfc4[libshield.so]0x4bfc4, LR=RX@0x40049b98[libshield.so]0x49b98
[09:38:33 905] Memory WRITE at 0x4059a099, data size = 1, data value = 0x4f, PC=RX@0x4004bfc8[libshield.so]0x4bfc8, LR=RX@0x40049b98[libshield.so]0x49b98
[09:38:33 905] Memory WRITE at 0x4059a09a, data size = 1, data value = 0x50, PC=RX@0x4004bfcc[libshield.so]0x4bfcc, LR=RX@0x40049b98[libshield.so]0x49b98
[09:38:33 906] Memory WRITE at 0x4059a09c, data size = 1, data value = 0x00, PC=RX@0x4004c080[libshield.so]0x4c080, LR=RX@0x40049b98[libshield.so]0x49b98
[09:38:33 906] Memory WRITE at 0x4059a09c, data size = 1, data value = 0x00, PC=RX@0x4009f038[libshield.so]0x9f038, LR=RX@0x40049bbc[libshield.so]0x49bbc

根据调用地址0x4bfac定位到函数sub_4BF44
图片描述
打断点看下表debugger.addBreakPoint(module.base + 0x4bfb0)
图片描述
标准的base64表,拿到网站换算一下
图片描述
能正确转换,继续往上分析下sub_4BF44的入参
图片描述
断点看一下入参情况 debugger.addBreakPoint(module.base + 0x49b94)
图片描述
继续emulator.traceWrite(0x40456098,0x40456098 + 99)分析下会发现也是memcpy,找到源地址后emulator.traceWrite(0x40593000,0x40593000 + 99)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
[08:42:02 756] Memory WRITE at 0x40593000, data size = 1, data value = 0x00, PC=RX@0x4004972c[libshield.so]0x4972c, LR=RX@0x400496e4[libshield.so]0x496e4
[08:42:02 756] Memory WRITE at 0x40593001, data size = 1, data value = 0x00, PC=RX@0x40049734[libshield.so]0x49734, LR=RX@0x400496e4[libshield.so]0x496e4
[08:42:02 756] Memory WRITE at 0x40593002, data size = 1, data value = 0x00, PC=RX@0x40049740[libshield.so]0x49740, LR=RX@0x400496e4[libshield.so]0x496e4
[08:42:02 756] Memory WRITE at 0x40593003, data size = 1, data value = 0x01, PC=RX@0x40049748[libshield.so]0x49748, LR=RX@0x400496e4[libshield.so]0x496e4
[08:42:02 756] Memory WRITE at 0x40593004, data size = 1, data value = 0x00, PC=RX@0x40049750[libshield.so]0x49750, LR=RX@0x400496e4[libshield.so]0x496e4
[08:42:02 756] Memory WRITE at 0x40593005, data size = 1, data value = 0x00, PC=RX@0x40049758[libshield.so]0x49758, LR=RX@0x400496e4[libshield.so]0x496e4
[08:42:02 756] Memory WRITE at 0x40593006, data size = 1, data value = 0x00, PC=RX@0x40049764[libshield.so]0x49764, LR=RX@0x400496e4[libshield.so]0x496e4
[08:42:02 756] Memory WRITE at 0x40593007, data size = 1, data value = 0x01, PC=RX@0x4004976c[libshield.so]0x4976c, LR=RX@0x400496e4[libshield.so]0x496e4
[08:42:02 756] Memory WRITE at 0x40593008, data size = 1, data value = 0x00, PC=RX@0x40049774[libshield.so]0x49774, LR=RX@0x400496e4[libshield.so]0x496e4
[08:42:02 756] Memory WRITE at 0x40593009, data size = 1, data value = 0x00, PC=RX@0x4004977c[libshield.so]0x4977c, LR=RX@0x400496e4[libshield.so]0x496e4
[08:42:02 756] Memory WRITE at 0x4059300a, data size = 1, data value = 0x00, PC=RX@0x40049788[libshield.so]0x49788, LR=RX@0x400496e4[libshield.so]0x496e4
[08:42:02 756] Memory WRITE at 0x4059300b, data size = 1, data value = 0x53, PC=RX@0x40049790[libshield.so]0x49790, LR=RX@0x400496e4[libshield.so]0x496e4
[08:42:02 756] Memory WRITE at 0x4059300c, data size = 1, data value = 0x00, PC=RX@0x40049798[libshield.so]0x49798, LR=RX@0x400496e4[libshield.so]0x496e4
[08:42:02 756] Memory WRITE at 0x4059300d, data size = 1, data value = 0x00, PC=RX@0x400497a0[libshield.so]0x497a0, LR=RX@0x400496e4[libshield.so]0x496e4
[08:42:02 756] Memory WRITE at 0x4059300e, data size = 1, data value = 0x00, PC=RX@0x400497ac[libshield.so]0x497ac, LR=RX@0x400496e4[libshield.so]0x496e4
[08:42:02 757] Memory WRITE at 0x4059300f, data size = 1, data value = 0x53, PC=RX@0x400497b4[libshield.so]0x497b4, LR=RX@0x400496e4[libshield.so]0x496e4
[08:42:02 757] Memory WRITE at 0x40593010, data size = 8, data value = 0x1b521b31ed111635, PC=RX@0x4028c220[libc.so]0x1c220, LR=RX@0x400497dc[libshield.so]0x497dc
[08:42:02 757] Memory WRITE at 0x40593018, data size = 8, data value = 0x523a8ba0fadcdf0f, PC=RX@0x4028c220[libc.so]0x1c220, LR=RX@0x400497dc[libshield.so]0x497dc
[08:42:02 757] Memory WRITE at 0x40593020, data size = 8, data value = 0xe346e96b453b9986, PC=RX@0x4028c224[libc.so]0x1c224, LR=RX@0x400497dc[libshield.so]0x497dc
[08:42:02 757] Memory WRITE at 0x40593028, data size = 8, data value = 0x42a94d54e17e0a7e, PC=RX@0x4028c224[libc.so]0x1c224, LR=RX@0x400497dc[libshield.so]0x497dc
[08:42:02 757] Memory WRITE at 0x40593030, data size = 8, data value = 0x9d1f65e3cbe58391, PC=RX@0x4028c228[libc.so]0x1c228, LR=RX@0x400497dc[libshield.so]0x497dc
[08:42:02 757] Memory WRITE at 0x40593038, data size = 8, data value = 0xde79c3cf58e7abfd, PC=RX@0x4028c228[libc.so]0x1c228, LR=RX@0x400497dc[libshield.so]0x497dc
[08:42:02 757] Memory WRITE at 0x40593040, data size = 8, data value = 0x1f0c1864abd87ecb, PC=RX@0x4028c22c[libc.so]0x1c22c, LR=RX@0x400497dc[libshield.so]0x497dc
[08:42:02 757] Memory WRITE at 0x40593048, data size = 8, data value = 0x23dca1b2378a3414, PC=RX@0x4028c22c[libc.so]0x1c22c, LR=RX@0x400497dc[libshield.so]0x497dc
[08:42:02 757] Memory WRITE at 0x40593050, data size = 8, data value = 0xca27986f2fb6d331, PC=RX@0x4028c18c[libc.so]0x1c18c, LR=RX@0x400497dc[libshield.so]0x497dc
[08:42:02 757] Memory WRITE at 0x40593058, data size = 8, data value = 0xe6c96ce0df207278, PC=RX@0x4028c18c[libc.so]0x1c18c, LR=RX@0x400497dc[libshield.so]0x497dc
[08:42:02 757] Memory WRITE at 0x40593053, data size = 8, data value = 0x207278ca27986f2f, PC=RX@0x4028c1a4[libc.so]0x1c1a4, LR=RX@0x400497dc[libshield.so]0x497dc
[08:42:02 757] Memory WRITE at 0x4059305b, data size = 8, data value = 0xdbe3f4e6c96ce0df, PC=RX@0x4028c1a4[libc.so]0x1c1a4, LR=RX@0x400497dc[libshield.so]0x497dc

可以明显看到数据分为两部分,先看第一部分

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
void __usercall sub_49650(__int64 *a1@, __int64 a2@)
{
  // [COLLAPSED LOCAL DECLARATIONS. PRESS KEYPAD CTRL-"+" TO EXPAND]
 
  v42 = *(_QWORD *)(_ReadStatusReg(ARM64_SYSREG(3, 3, 13, 0, 2)) + 40);
  v4 = *a1;
  v3 = (unsigned int *)a1[1];
  if ( v3 )
  {
    v5 = v3 + 2;
    if ( pthread_create_ptr )
    {
      do
        v6 = __ldaxr(v5);
      while ( __stlxr(v6 + 1, v5) );
    }
    else
    {
      ++*v5;
    }
  }
  v7 = *(_DWORD *)(v4 + 16);
  v8 = (int)(v7 + 16);
  if ( v8 < 0 )
    v9 = -1LL;
  else
    v9 = (int)(v7 + 16);
  v10 = (_BYTE *)sub_12490(v9);
  sub_129A0(v10, 0LL, v9);
  if ( v3 )
  {
    v11 = v3 + 2;
    if ( pthread_create_ptr )
    {
      do
        v12 = __ldaxr(v11);
      while ( __stlxr(v12 + 1, v11) );
    }
    else
    {
      ++*v11;
    }
  }
  if ( v7 <= 0xFFFFFFEF )
  {
    *v10 = *(_BYTE *)(v4 + 11); //赋值位置
    v10[1] = *(_WORD *)(v4 + 10);
    v10[2] = BYTE1(*(_DWORD *)(v4 + 8));
    v10[3] = *(_DWORD *)(v4 + 8);
    v10[4] = *(_BYTE *)(v4 + 15);
    v10[5] = *(_WORD *)(v4 + 14);
    v10[6] = BYTE1(*(_DWORD *)(v4 + 12));
    v10[7] = *(_DWORD *)(v4 + 12);
    v10[8] = *(_BYTE *)(v4 + 19);
    v10[9] = *(_WORD *)(v4 + 18);
    v10[10] = BYTE1(*(_DWORD *)(v4 + 16));
    v10[11] = *(_DWORD *)(v4 + 16);
    v10[12] = *(_BYTE *)(v4 + 23);
    v10[13] = *(_WORD *)(v4 + 22);
    v10[14] = BYTE1(*(_DWORD *)(v4 + 20));
    v10[15] = *(_DWORD *)(v4 + 20);
    if ( *(_DWORD *)(v4 + 16) + 16 <= (unsigned int)v8 )
...

可以很明显看到是a1中获取数据进行填充的,打断点看一下debugger.addBreakPoint(module.base+0x49650)
图片描述
取地址0x40453190
图片描述
trace跟踪一下emulator.traceWrite(0x40453196,40453196 + 16)

1
2
3
4
[23:30:45 903] Memory WRITE at 0x40453198, data size = 4, data value = 0x00000001, PC=RX@0x400492f0[libshield.so]0x492f0, LR=RX@0x400492ec[libshield.so]0x492ec
[23:30:45 903] Memory WRITE at 0x4045319c, data size = 4, data value = 0x00000001, PC=RX@0x400492f0[libshield.so]0x492f0, LR=RX@0x400492ec[libshield.so]0x492ec
[23:30:45 903] Memory WRITE at 0x404531a4, data size = 4, data value = 0x00000053, PC=RX@0x4004930c[libshield.so]0x4930c, LR=RX@0x400492ec[libshield.so]0x492ec
[23:30:45 920] Memory WRITE at 0x404531a0, data size = 4, data value = 0x00000053, PC=RX@0x40049574[libshield.so]0x49574, LR=RX@0x40049570[libshield.so]0x49570

根据地址定位下
图片描述
可以看到前八个字节固定为1,接着看下第一个0x53,断一下a1,debugger.addBreakPoint(module.base+0x4926c)
图片描述
v7 = *(_DWORD *)(*a1 + 20LL) + *(_DWORD *)(*a1 + 24LL) + *(_DWORD *)(*a1 + 28LL) + 24;
0x7+0x24+0x10+0x18=0x53
接着我们在继续trace一下emulator.traceWrite(0x4058e024,0x4058e024+9)

1
2
3
[00:18:21 012] Memory WRITE at 0x4058e024, data size = 4, data value = 0x00000007, PC=RX@0x40049138[libshield.so]0x49138, LR=RX@0x40049128[libshield.so]0x49128
[00:18:21 013] Memory WRITE at 0x4058e028, data size = 4, data value = 0x00000024, PC=RX@0x40049154[libshield.so]0x49154, LR=RX@0x40049140[libshield.so]0x49140
[00:18:21 013] Memory WRITE at 0x4058e02c, data size = 4, data value = 0x00000010, PC=RX@0x40049160[libshield.so]0x49160, LR=RX@0x4004915c[libshield.so]0x4915c

图片描述
断一下4908c后查看一下各个地址
*(_QWORD *)(*a2 - 24LL)
图片描述
*(_QWORD *)(*a5 - 24LL)
图片描述
很明显是build跟deviceid的长度,稍微修改下字符串,验证下就可以得出来
在看下0x10的来源,这个直接打开trace文件,根据汇编代码往上找就好
图片描述
trace一下emulator.traceWrite(0x40453120,0x40453120+4)

1
[10:06:27 070] Memory WRITE at 0x40453120, data size = 8, data value = 0x0000000000000010, PC=RX@0x4009ce2c[libshield.so]0x9ce2c, LR=RX@0x4009cdb4[libshield.so]0x9cdb4

根据trace文件定位一下
图片描述
可以看到w2是固定值0x10,传给函数0x9cd08,直接看下伪C代码更加明显一点
图片描述
现在接续看②剩下的83个字节,根据之前的trace日志可以定位到memcpy函数,继续emulator.traceWrite(0x4045e060,0x4045e060 + 83)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
[12:48:28 084] Memory WRITE at 0x4045e060, data size = 1, data value = 0x35, PC=RX@0x4005126c[libshield.so]0x5126c, LR=RX@0x40049570[libshield.so]0x49570
[12:48:28 085] Memory WRITE at 0x4045e061, data size = 1, data value = 0x16, PC=RX@0x400512ac[libshield.so]0x512ac, LR=RX@0x40049570[libshield.so]0x49570
[12:48:28 085] Memory WRITE at 0x4045e062, data size = 1, data value = 0x11, PC=RX@0x400512ec[libshield.so]0x512ec, LR=RX@0x40049570[libshield.so]0x49570
[12:48:28 085] Memory WRITE at 0x4045e063, data size = 1, data value = 0xed, PC=RX@0x4005132c[libshield.so]0x5132c, LR=RX@0x40049570[libshield.so]0x49570
[12:48:28 085] Memory WRITE at 0x4045e064, data size = 1, data value = 0x31, PC=RX@0x4005136c[libshield.so]0x5136c, LR=RX@0x40049570[libshield.so]0x49570
[12:48:28 085] Memory WRITE at 0x4045e065, data size = 1, data value = 0x1b, PC=RX@0x400513ac[libshield.so]0x513ac, LR=RX@0x40049570[libshield.so]0x49570
[12:48:28 085] Memory WRITE at 0x4045e066, data size = 1, data value = 0x52, PC=RX@0x400513ec[libshield.so]0x513ec, LR=RX@0x40049570[libshield.so]0x49570
[12:48:28 086] Memory WRITE at 0x4045e067, data size = 1, data value = 0x1b, PC=RX@0x40051424[libshield.so]0x51424, LR=RX@0x40049570[libshield.so]0x49570
...
[12:48:28 089] Memory WRITE at 0x4045e0ab, data size = 1, data value = 0xdf, PC=RX@0x4005132c[libshield.so]0x5132c, LR=RX@0x40049570[libshield.so]0x49570
[12:48:28 089] Memory WRITE at 0x4045e0ac, data size = 1, data value = 0xe0, PC=RX@0x4005136c[libshield.so]0x5136c, LR=RX@0x40049570[libshield.so]0x49570
[12:48:28 089] Memory WRITE at 0x4045e0ad, data size = 1, data value = 0x6c, PC=RX@0x400513ac[libshield.so]0x513ac, LR=RX@0x40049570[libshield.so]0x49570
[12:48:28 089] Memory WRITE at 0x4045e0ae, data size = 1, data value = 0xc9, PC=RX@0x400513ec[libshield.so]0x513ec, LR=RX@0x40049570[libshield.so]0x49570
[12:48:28 089] Memory WRITE at 0x4045e0af, data size = 1, data value = 0xe6, PC=RX@0x40051424[libshield.so]0x51424, LR=RX@0x40049570[libshield.so]0x49570
[12:48:28 089] Memory WRITE at 0x4045e0b0, data size = 1, data value = 0xf4, PC=RX@0x40051490[libshield.so]0x51490, LR=RX@0x40049570[libshield.so]0x49570
[12:48:28 089] Memory WRITE at 0x4045e0b1, data size = 1, data value = 0xe3, PC=RX@0x400514d8[libshield.so]0x514d8, LR=RX@0x40049570[libshield.so]0x49570
[12:48:28 090] Memory WRITE at 0x4045e0b2, data size = 1, data value = 0xdb, PC=RX@0x40051520[libshield.so]0x51520, LR=RX@0x40049570[libshield.so]0x49570

可以定位到sub_511E0函数,应为是伪c代码,没看到熟悉算法的明显特征,但是可以肯定的是算法的加密流程并不复杂,我们对着汇编代码译一下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
_DWORD *__fastcall sub_511E0(_DWORD *result, unsigned int a2, _BYTE *a3, _BYTE *a4)
...
  LODWORD(v5) = *result;                        // v5=result[0]=0 v6=result[1]=0
  LODWORD(v6) = result[1];
  if ( a2 >> 3 )
  {
    v7 = 8LL * (v4 - 1) + 8;                    // v7=0x50
    v8 = &a3[v7];
    v9 = -v4;
    out = a4;
    do
    {
      v11 = result + 2;                         // v11=&result[8]
      v12 = 4LL * (unsigned __int8)(v5 + 1);    // v12=4
      v13 = *(_DWORD *)((char *)result + v12 + 8);// v13=result[0xc]=0x2e
      ++v9;
      v14 = v13 + v6;                           // v14=result[0xc]=0x2e
      v15 = v14;                                // v15=v14<<2    //v15=result[0xc]<<2=0x2e<<2=0xb8
      v16 = result[v15 + 2];                    // v16=v11[v15]        //v16=v11[result[0xc]<<2]=result[8+0xb8]=result[0xc0]=0x68
      *(_DWORD *)((char *)v11 + v12) = v16;     // result[&result[8] + 4] = result[0xc] = 0x68
      v11[v15] = v13;                           // result[8+0xb8]=result[0xc0]=v13=0x2e
      v17 = (unsigned __int8)(v5 + 2);          // v17=v5<<2 = 0x8
      *out = *a3 ^ result[(unsigned __int8)(v16 + v13) + 2];// *out=*a3 ^ result[(v16 + v13) << 2] = *a3 ^ result[(0xb8 + 0x2e) << 2] = *a3 ^result[0x96 << 2] = 0x35
      LODWORD(v12) = result[v17 + 2];           // v12=result[8 + v17] // result[8 + 8] = result[0xf]=0xe
      v18 = v12 + v14;                          // v18= 0x2e +0xe = 0x3c
      v19 = v18;
      v20 = result[v19 + 2];                    // v20=result[8 + v19 << 2] //result[8 + 0x3c<<2]=result[8 + 0xf0]=0x37
      v11[v17] = v20;                           // result[8 + 8] = result[0xf] = 0x37
      v11[v19] = v12;                           // v11[v19]=result[8+v19<<2] //result[8+0xf0]=result[0xf8] = 0xe
      v21 = (unsigned __int8)(v5 + 3);
      out[1] = a3[1] ^ result[(unsigned __int8)(v20 + v12) + 2];
...

第一轮 result[0xc]与 result[0xc0]交换,第二轮 result[0xf]与 result[0xf0]交换,每一轮还有异或,result内存好像是256个字节
结合以上看上去就像RC4,result就是s盒,肯定还是需要往上找一下key的
图片描述
不难发现sub_51698就是RC4的初始化函数,qword_10B508应该就是key,找出来拿到网站试算一下
图片描述
分析完,继续看下sub_511e0的加密入参
图片描述
方便观看,我们拆分一下

1
2
3
4
5
1.   00 00 00 01
2.   EC FA AF 01 -->app_id
3.   00 00 00 02 00 00 00 07 00 00 00 24 00 00 00 10
4.   38 34 32 30 32 39 34 30 64 37 65 65 65 32 63 2D 35 64 37 37 2D 33 63 32 36 2D 39 39 66 38 2D 61 35 61 32 63 39 65 30 38 61 65 62 -->deviceId
5.   BA BE E4 F8 68 C3 E3 C9 4B 9B 57 81 B0 D7 14 60

①我们直接trace跟踪一下会发现是固定值,②很明显是app_id,③trace跟踪会发现02是固定值,07,24,10就是前面分析过的字符串长度跟固定值,④是deviceId,后面着重追下⑤
emulator.traceWrite(0x4045e043,0x4045e043 + 16)


[注意]看雪招聘,专注安全领域的专业人才平台!

最后于 5天前 被HandsomeBro编辑 ,原因:
收藏
免费 68
支持
分享
最新回复 (48)
雪    币: 1868
活跃值: (2740)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
.
5天前
0
雪    币: 118
活跃值: (1106)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
太好了
5天前
0
雪    币:
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
4
6
5天前
0
雪    币: 0
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
5
5天前
0
雪    币: 0
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
6
kk
5天前
0
雪    币: 50
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
7
包都抓不到 废了
5天前
0
雪    币: 4182
活跃值: (3939)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
6666
5天前
0
雪    币: 24
活跃值: (1220)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
666
5天前
0
雪    币: 20
活跃值: (1610)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
666
5天前
0
雪    币: 226
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
11
学习一下
5天前
0
雪    币: 1
活跃值: (360)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
12
6
5天前
0
雪    币: 14
活跃值: (369)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
13
666
5天前
0
雪    币: 206
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
14
666
5天前
0
雪    币: 3
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
15
6666
5天前
0
雪    币: 220
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
16
66666
5天前
0
雪    币: 90
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
17
6666666666666
5天前
0
雪    币: 188
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
18
6666666
5天前
0
雪    币: 1610
活跃值: (1204)
能力值: ( LV5,RANK:70 )
在线值:
发帖
回帖
粉丝
19
学习一下
4天前
0
雪    币: 335
活跃值: (3179)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
20
111
4天前
0
雪    币: 1777
活跃值: (1930)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
21
太好了
4天前
0
雪    币: 7397
活跃值: (22375)
能力值: ( LV12,RANK:550 )
在线值:
发帖
回帖
粉丝
22
看看
4天前
0
雪    币: 179
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
23
6666
4天前
0
雪    币: 375
活跃值: (2411)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
24
666
4天前
0
雪    币: 253
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
25
牛啊牛啊
4天前
1
游客
登录 | 注册 方可回帖
返回