├── ext_docs
├── 上报数据.pdf
├── 安全sdk-so6.3.80_保护.pdf
└── 安全sdk-so6.4.36_保护.pdf
├── libsg6.4.36
├── sub_2AC24.c
├── sub_32F44.c
├── sub_305BE.c
├── sub_2D1DA.c
├── sub_72080.c
├── sub_7B606.c
├── sub_9970.c
├── sub_30D60.c
├── sub_b7f6.c
├── sub_3026A.c
├── sub_7C10C.c
├── sub_9f1c.c
├── sub_32C46.c
├── sub_2B4BE.c
├── sub_301DE.c
├── sub_14FEE.c
├── put_unconditional_branch1.py
├── sub_7B86C.c
├── sub_77dbc.c
├── sub_2A01E.c
├── sub_7AFB6.c
├── sub_1511C.c
├── sub_E890.c
├── sub_73668.c
├── put_unconditional_branch.py
├── sub_7B93A.c
├── sub_9D82.c
├── jni_load.c
├── patches.py
├── sub_73e56.c
├── doCommandNative.c
├── sub_9a14.c
├── breaklist.idc
└── libsgmainso-6.4.36分析
├── README.md
├── .gitignore
├── libsg6.4.176
├── make_data.c
├── call_rc4.c
├── createGlobalBoolean_Integer_String.c
├── extends_vdata.c
├── create_vdata.c
├── decrypto.c
├── vdata.h
└── libsgmainso-6.4.176.txt
└── LICENSE
/ext_docs/上报数据.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/r0ysue/crack_libsgmain/HEAD/ext_docs/上报数据.pdf
--------------------------------------------------------------------------------
/ext_docs/安全sdk-so6.3.80_保护.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/r0ysue/crack_libsgmain/HEAD/ext_docs/安全sdk-so6.3.80_保护.pdf
--------------------------------------------------------------------------------
/ext_docs/安全sdk-so6.4.36_保护.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/r0ysue/crack_libsgmain/HEAD/ext_docs/安全sdk-so6.4.36_保护.pdf
--------------------------------------------------------------------------------
/libsg6.4.36/sub_2AC24.c:
--------------------------------------------------------------------------------
1 | signed int sub_2AC24(int a1)
2 | {
3 | int v1; // r4@1
4 |
5 | v1 = a1;
6 | if ( a1 )
7 | {
8 | pthread_mutex_lock(&plock);
9 | if ( !dword_B3FB9E0C )
10 | dword_B3FB9E0C = v1;
11 | pthread_mutex_unlock(&plock);
12 | }
13 | return 1;
14 | }
--------------------------------------------------------------------------------
/libsg6.4.36/sub_32F44.c:
--------------------------------------------------------------------------------
1 | int __fastcall sub_32F44(unsigned int a1)
2 | {
3 | unsigned int v1; // r4@1
4 | int v2; // r0@2
5 | int v3; // r4@4
6 |
7 | v1 = a1;
8 | pthread_mutex_lock((pthread_mutex_t *)&pthread_lock_0);
9 | if ( v1 <= 2 && (v2 = dword_8CE6C[v1]) != 0 && *(_DWORD *)(v2 + 4) )
10 | v3 = (*(int (**)(void))(v2 + 40))();
11 | else
12 | v3 = 0;
13 | pthread_mutex_unlock((pthread_mutex_t *)&pthread_lock_0);
14 | return v3;
15 | }
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # crack_libsgmain
2 | Reverse libsgmain
3 |
4 |
5 | 逆向libsgmain.so,它类似一个安全sdk,谁都可以集成, 我自己也可以集成, 所以测试其安全强度,对其进行逆向分析
6 |
7 | 不侵权吧, 如果涉及侵权请及时告知,我会马上删掉项目。
8 |
9 |
10 | 首先它没你想的那么简单, 那逆向时间完全随我心情; 我想起来就搞搞,想不搞了就放几天;
11 |
12 | 我会尽量多想一些办法去尝试逆向。
13 |
14 | 后续想起来什么在补充吧。
15 |
16 | 各版本目錄:
17 |
18 |
19 | libsgmain6.4.176
20 |
21 | libsgmain6.3.80
22 |
23 | libsgmain6.4.36
24 |
25 | ;ext_docs为早期的一些文档,可能存在错误或者过时,随便看看吧,还有很多文档
26 |
27 | 但不便公开!
28 |
29 | 難度 : 6.3.80 > 6.4.36 > 6.4.176
30 |
31 |
32 | 本人聲明:
33 | 該項目僅用於學習和交流目的,不能用於其他目的,否則後果自負;另外該項目所有權僅屬於我個人,你可以下載或者fork該項目,但不能用於其他目的(如發表文章、出書、投稿等),否則必究。
34 |
35 |
36 |
37 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Prerequisites
2 | *.d
3 |
4 | # Object files
5 | *.o
6 | *.ko
7 | *.obj
8 | *.elf
9 |
10 | # Linker output
11 | *.ilk
12 | *.map
13 | *.exp
14 |
15 | # Precompiled Headers
16 | *.gch
17 | *.pch
18 |
19 | # Libraries
20 | *.lib
21 | *.a
22 | *.la
23 | *.lo
24 |
25 | # Shared objects (inc. Windows DLLs)
26 | *.dll
27 | *.so
28 | *.so.*
29 | *.dylib
30 |
31 | # Executables
32 | *.exe
33 | *.out
34 | *.app
35 | *.i*86
36 | *.x86_64
37 | *.hex
38 |
39 | # Debug files
40 | *.dSYM/
41 | *.su
42 | *.idb
43 | *.pdb
44 |
45 | # Kernel Module Compile Results
46 | *.mod*
47 | *.cmd
48 | .tmp_versions/
49 | modules.order
50 | Module.symvers
51 | Mkfile.old
52 | dkms.conf
53 |
--------------------------------------------------------------------------------
/libsg6.4.36/sub_305BE.c:
--------------------------------------------------------------------------------
1 | int __fastcall sub_305BE(unsigned int a1, signed int a2)
2 | {
3 | unsigned int v2; // r5@1
4 | signed int v3; // r6@1
5 | int v4; // r4@2
6 | int v5; // r0@3
7 | int v6; // r0@5
8 |
9 | v2 = a1;
10 | v3 = a2;
11 | if ( a1 <= 2 )
12 | {
13 | v5 = goto_read_off_8AA50(a1, 9);
14 | v4 = v5;
15 | if ( !v5 || !*(_DWORD *)(v5 + 4) )
16 | {
17 | v6 = sub_2D228(v2);
18 | v4 = v6;
19 | if ( v6 && *(_DWORD *)(v6 + 4) )
20 | {
21 | sub_302C8(v6, v2, 9);
22 | }
23 | else if ( v3 >= 1 )
24 | {
25 | sub_304E4(v2, 0);
26 | }
27 | }
28 | }
29 | else
30 | {
31 | v4 = 0;
32 | }
33 | return v4;
34 | }
--------------------------------------------------------------------------------
/libsg6.4.36/sub_2D1DA.c:
--------------------------------------------------------------------------------
1 | int __fastcall sub_2D1DA(unsigned int a1, int a2)
2 | { // 參數1是jarray第一個值,參數2是程序傳遞下來的9
3 | int v2; // r5@1
4 | unsigned int v3; // r4@1
5 | int v4; // r8@1
6 | int v5; // r0@1
7 | int v6; // r6@1
8 | int v7; // r0@3
9 |
10 | v2 = a2;
11 | v3 = a1;
12 | v4 = goto_make_vdata6436(a1, a2);
13 | v5 = goto_read_off_8AA50(v3, v2);
14 | v6 = v5;
15 | if ( !v5 || !*(_DWORD *)(v5 + 4) )
16 | {
17 | goto_free_vdata(v5);
18 | v7 = sub_30D24(v4);
19 | v6 = v7;
20 | if ( v7 )
21 | {
22 | if ( *(_DWORD *)(v7 + 4) )
23 | sub_302C8(v7, v3, v2);
24 | }
25 | else
26 | {
27 | v6 = 0;
28 | }
29 | }
30 | goto_free_vdata(v4);
31 | return v6;
32 | }
--------------------------------------------------------------------------------
/libsg6.4.36/sub_72080.c:
--------------------------------------------------------------------------------
1 | void sub_72080(int a1, int a2, int a3, int a4, int a5, int a6, int a7, int a8, int a9)
2 | {
3 | int v9; // r1@4
4 | _JNIEnv *v10; // r4@0
5 | int v11; // r5@0
6 | int v12; // r7@0
7 | int v13; // r2@1
8 | int v14; // ST08_4@2
9 | int v15; // r1@2
10 | int v16; // r2@2
11 |
12 | *(_DWORD *)(v12 - 16) = a1;
13 | goto_decrypt_entry(a2 + 1, v11, a3);
14 | // "com/taobao/wireless/security/adapter/common/SPUtility2"
15 | if ( ((int (__fastcall *)(_JNIEnv *, int))v10->functions->FindClass)(v10, v11) )
16 | {
17 | v14 = ((int (__fastcall *)(_JNIEnv *))v10->functions->NewGlobalRef)(v10);
18 | *(_DWORD *)(v14 - 1275465542) = dyna_arg(v14, v15, v16);
19 | JUMPOUT(&goto_dynapc2);
20 | }
21 | dyna_arg(0, 0, v13);
22 | v9 = *(_DWORD *)(v12 - 16);
23 | JUMPOUT(__CS__, a9);
24 | }
--------------------------------------------------------------------------------
/libsg6.4.36/sub_7B606.c:
--------------------------------------------------------------------------------
1 | vstring *__fastcall create_vstring(vdata *a1)
2 | {
3 | vdata *v1; // r5@1
4 | vstring *v2; // r4@2
5 | vstring *result; // r0@2
6 | char *v4; // r8@3
7 | void *v5; // r0@4
8 | int v6; // r6@4
9 |
10 | v1 = a1;
11 | if ( !a1 )
12 | return 0;
13 | v2 = (vstring *)malloc(8u);
14 | result = 0;
15 | if ( v2 )
16 | {
17 | v2->str = 0;
18 | v2->len = 0;
19 | result = v2;
20 | v4 = (char *)v1->data_len;
21 | if ( v4 )
22 | {
23 | v5 = malloc((size_t)(v4 + 1));
24 | v6 = (int)v5;
25 | if ( v5 )
26 | {
27 | memset(v5, v4 + 1);
28 | v2->len = v6;
29 | _aeabi_memcpy(v6, v1->data, v4);
30 | v2->str = v4;
31 | return v2;
32 | }
33 | free(v2);
34 | return 0;
35 | }
36 | }
37 | return result;
38 | }
--------------------------------------------------------------------------------
/libsg6.4.36/sub_9970.c:
--------------------------------------------------------------------------------
1 | void sub_9970()
2 | {
3 | int v0; // r5@0
4 | int v1; // r6@0
5 | int v2; // r9@0
6 | int v3; // r1@1
7 | int v4; // r2@1
8 | int v5; // r3@1
9 | int v6; // r4@1
10 | int v7; // r1@2
11 | int v8; // r0@3
12 | int v9; // r0@3
13 | int v10; // ST04_4@3
14 |
15 | v6 = malloc(24);
16 | if ( !v6 )
17 | {
18 | sub_B3F31998(0, v3, v4, v5);
19 | v6 = v7;
20 | }
21 | ((void (__fastcall *)(int, signed int))memset0)(v6, 24);
22 | *(_DWORD *)v6 = v1;
23 | *(_DWORD *)(v6 + 4) = v2;
24 | v8 = time(0);
25 | v9 = srand48(v8);
26 | *(_QWORD *)(v6 + 8) = lrand48(v9);
27 | *(_DWORD *)(v6 + 16) = goto_create_tmp1vdata(0);
28 | (*(void (__cdecl **)(_DWORD, int))(*(_DWORD *)(v0 + 4) + 16))(*(_DWORD *)(v0 + 4), v6);
29 | v10 = *(_DWORD *)(*(_DWORD *)(v6 + 16) + 4);
30 | dyna_pc(2);
31 | JUMPOUT(5);
32 | }
--------------------------------------------------------------------------------
/libsg6.4.176/make_data.c:
--------------------------------------------------------------------------------
1 | vdata* make_data(vdata *old_vdata, char* databuf, int new_len)
2 | { // 创建数据
3 | // vdata结构相当于一个数据容器
4 | // 完成向容器中添加数据
5 |
6 | // 第一次执行示例
7 | // va = ma + 4 = 0;
8 | // vb = ma->data_mlen = 0x11
9 | // memcpy(r1, mb, 0x10); 第一次mb = "DcO/lcK+h?m3c*q@"
10 | // ma->data_len = data_mlen -1;
11 |
12 | if ( old_vdata && databuf && new_len >= 1 ) {
13 | old_data_len = old_vdata->data_len;
14 |
15 | if ( (int)(old_data_len + new_len) >= old_vdata->data_mlen ) {
16 |
17 | old_vdata = (vdata *)extend_vdata(old_vdata, new_len);
18 | if ( (int)old_vdata < 0 )
19 | return old_vdata;
20 | }
21 |
22 | memcpy((char *)old_vdata->data + old_data_len, databuf, new_len);
23 | old_vdata->data_len = (int)(old_vdata->data_len + new_len);
24 | }
25 | return old_vdata;
26 | }
--------------------------------------------------------------------------------
/libsg6.4.36/sub_30D60.c:
--------------------------------------------------------------------------------
1 | int sub_30D60(vdata_6436 *a1)
2 | {
3 | __int64 v1; // kr00_8@1
4 | int v2; // r5@1
5 | int v3; // r0@1
6 | int v4; // r4@1
7 | int v6; // [sp+4h] [bp-1Ch]@1
8 | int v7; // [sp+8h] [bp-18h]@1
9 | int v8; // [sp+Ch] [bp-14h]@1
10 | int v9; // [sp+10h] [bp-10h]@1
11 | int v10; // [sp+14h] [bp-Ch]@1
12 |
13 | v10 = *(_DWORD *)off_8AC00;
14 | v6 = 0;
15 | v1 = *(_QWORD *)&a1->data;
16 | v2 = geto_create_vdata32(a1->data, a1->data_len); // sub_7C258
17 | v7 = v2; // vdata32
18 | v8 = 1;
19 | v9 = 7;
20 | v3 = sub_73D90(); // 讀取90804的值到寄存器r0, 調試時為ACB3B600
21 | // v3 + 4 = 0x9df5, 最終是sub_9E30,即goto_docommand_native_inner
22 | v4 = (*(int (__fastcall **)(signed int, signed int, signed int, int *))(v3 + 4))(1, 21, 2, &v7);
23 | goto_callfree(v2);
24 | if ( *(_DWORD *)off_8AC00 != v10 )
25 | _stack_chk_fail(*(_DWORD *)off_8AC00 - v10, v10);
26 | return v4;
27 | }
--------------------------------------------------------------------------------
/libsg6.4.36/sub_b7f6.c:
--------------------------------------------------------------------------------
1 | signed int registerNatives(int a1, int a2)
2 | {
3 | _JNIEnv *v2; // r5@1
4 | void *v3; // r8@1
5 | signed int v4; // r0@1
6 | char v6; // [sp+7h] [bp-55h]@1
7 | char v7; // [sp+30h] [bp-2Ch]@1
8 | char *v8; // [sp+40h] [bp-1Ch]@1
9 | char *v9; // [sp+44h] [bp-18h]@1
10 | void (*v10)(); // [sp+48h] [bp-14h]@1
11 | int v11; // [sp+4Ch] [bp-10h]@1
12 |
13 | v2 = (_JNIEnv *)a1;
14 | v3 = (void *)a2;
15 | v11 = _stack_chk_guard;
16 | ((void (__fastcall *)(void *, char *, signed int))goto_dcrypto_entry)(&unk_B3EEEED9, &v7, 16);
17 | ((void (__fastcall *)(void *, char *, signed int))goto_dcrypto_entry)(&unk_B3EEEEEA, &v6, 41);
18 | v8 = &v7;
19 | v9 = &v6;
20 | v10 = sub_B3E7669C;
21 | v4 = v2->functions->RegisterNatives((JNIEnv *)v2, v3, (const JNINativeMethod *)&v8, 1);
22 | if ( _stack_chk_guard != v11 )
23 | sub_B3E6F13C(v4, _stack_chk_guard - v11);
24 | return v4 >> 31;
25 | }
--------------------------------------------------------------------------------
/libsg6.4.36/sub_3026A.c:
--------------------------------------------------------------------------------
1 | int __fastcall read_off_8AA50(unsigned int off, int index)
2 | {
3 | unsigned int v2; // r4@1
4 | int v3; // r5@1
5 | bool v4; // zf@2
6 | int v5; // r0@6
7 | int v6; // r4@8
8 |
9 | v2 = off;
10 | v3 = index;
11 | if ( off > 2 )
12 | goto LABEL_15;
13 | v4 = (index | 4) == 7;
14 | if ( (index | 4) != 7 )
15 | v4 = (index | 9) == 9;
16 | if ( v4 )
17 | {
18 | pthread_mutex_lock((pthread_mutex_t *)&pthread_lock);
19 | // 第一次計算off_8AA50[9] = 0xB3EF7E54 = 文件偏移8CE54
20 | // 第二次計算 [0xB3EF7E54 + 4] = 0
21 | // libsgmainso_6.4.36.so:B3EF7E58 DCD 0
22 | v5 = *(_DWORD *)(off_8AA50[index] + 4 * off);
23 | if ( v5 && *(_DWORD *)(v5 + 4) ) // 不成立
24 | v6 = (*(int (**)(void))(v5 + 40))();
25 | else
26 | v6 = 0; // 返回0
27 | pthread_mutex_unlock((pthread_mutex_t *)&pthread_lock);
28 | }
29 | else
30 | {
31 | LABEL_15:
32 | v6 = 0;
33 | }
34 | return v6;
35 | }
--------------------------------------------------------------------------------
/libsg6.4.176/call_rc4.c:
--------------------------------------------------------------------------------
1 | vdata* call_rc4(vdata *key, vdata *cryptedata)
2 | {
3 | int key_len; // r0@3
4 | vdata* decrypted_data; // r4@4
5 | char swapkey[264]; // [sp+0h] [bp-120h]@9
6 |
7 | if ( !key )
8 | goto exit1;
9 | if ( !key->data )
10 | goto exit1;
11 | key_len = key->data_len;
12 | if ( !key_len )
13 | goto exit1;
14 | decrypted_data = 0;
15 | if ( !cryptedata || key_len < 16 )
16 | goto exit;
17 | if ( !cryptedata->data || !cryptedata->data_len || (key->data_len = 16, (decrypted_data = create_vdata(cryptedata->data_len)) == 0) )
18 | {
19 | goto exit;
20 | }
21 | memset(swapkey, 0, 264); // 实际只用256,算法里面是swapkey+8开始的
22 | init_rc4key(swapkey, key->data, key->data_len);
23 | rc4_(swapkey, cryptedata->data_len, cryptedata->data, decrypted_data->data);
24 | if ( decrypted_data->data )
25 | decrypted_data->data_len = cryptedata->data_len;
26 |
27 | exit1:
28 | decrypted_data = 0;
29 | exit:
30 | return decrypted_data;
31 | }
--------------------------------------------------------------------------------
/libsg6.4.176/createGlobalBoolean_Integer_String.c:
--------------------------------------------------------------------------------
1 | int createGlobalBoolean_Integer_String(_JavaVM *a1)
2 | { // 对应源码
3 | _JNIEnv *env; // r0@1
4 | _JNIEnv *envf; // r4@1
5 | int v3; // r0@1
6 | int v4; // r0@1
7 | int v5; // r0@1
8 | int result; // r0@1
9 |
10 | javavm = (int)a1;
11 | env = (_JNIEnv *)getEnv(0);
12 | envf = env;
13 | v3 = ((int (*)(void))env->functions->FindClass)();
14 | global_jbooleanobj = ((int (__fastcall *)(_JNIEnv *, int))envf->functions->NewGlobalRef)(envf, v3);
15 | v4 = ((int (__fastcall *)(_JNIEnv *, const char *))envf->functions->FindClass)(envf, "java/lang/Integer");
16 | global_jintegerobj = ((int (__fastcall *)(_JNIEnv *, int))envf->functions->NewGlobalRef)(envf, v4);
17 | v5 = ((int (__fastcall *)(_JNIEnv *, const char *))envf->functions->FindClass)(envf, "java/lang/String");
18 | result = ((int (__fastcall *)(_DWORD, _DWORD))envf->functions->NewGlobalRef)(envf, v5);
19 | global_jstringobj = result;
20 | return result;
21 | }
22 |
--------------------------------------------------------------------------------
/libsg6.4.36/sub_7C10C.c:
--------------------------------------------------------------------------------
1 | struct vdata32_nest {
2 | void* nf1;
3 | void* nf2;
4 | void* nf3;
5 | void* nf4;
6 | };
7 |
8 | struct vdata32 {
9 | struct data* data128;
10 | int data_count;
11 | int chunk_size;
12 | void* f1; // goto_make_vdata32;
13 | struct vdata32_nest* nest;
14 | };
15 |
16 | vdata32 *create_vdata32()
17 | {
18 | vdata32 *v0; // r0@1
19 | vdata32 *v1; // r4@1
20 | struct data *v2; // r0@2
21 | struct data *v3; // r5@2
22 | vdata32_nest *v4; // r12@3
23 |
24 | v0 = (vdata32 *)malloc(0x20u);
25 | v1 = v0;
26 | if ( !v0 )
27 | return 0;
28 | memset(v0, 32);
29 | v2 = (struct data *)malloc(0x80u);
30 | v3 = v2;
31 | if ( !v2 )
32 | {
33 | free(v1);
34 | return 0;
35 | }
36 | memset(v2, 128);
37 | v4 = (vdata32_nest *)&v1->nest;
38 | v1->data128 = v3;
39 | v1->chunk_size = 128;
40 | v1->f1 = sub_7C180;
41 | v4->nf1 = sub_7C3C0;
42 | v4->nf2 = sub_7C280; // make_vdata32
43 | v4->nf3 = sub_7C43C;
44 | v4->nf4 = sub_7C49C;
45 | return v1;
46 | }
--------------------------------------------------------------------------------
/libsg6.4.36/sub_9f1c.c:
--------------------------------------------------------------------------------
1 | struct global_command_entry { // 記錄著生成和執行command的核心方法
2 | void* goto_make_command_entry; // 對應sub_9B3C; 生成command結構核心算法
3 | void* goto_do_command1; // // 對應sub_9d82; command_native_inner
4 | void* goto_do_command2; // 對應sub_9e7e; 和sub_9d82差不多
5 | };
6 |
7 | signed int make_global_command_ptr()
8 | {
9 | struct global_command_entry *v0; // r4@2
10 | signed int result; // r0@2
11 |
12 | if ( !get_global_command_entryptr() ) // 全局
13 | {
14 | v0 = (global_command_entry *)malloc(12);
15 | result = 0;
16 | if ( !v0 )
17 | return result;
18 | v0->goto_do_command1 = 0;
19 | v0->goto_make_command_entry = 0;
20 | gcommand_vdata1 = goto_create_tmp1vdata_(0); // 全局,記錄有關command結構指針
21 | gcommand_vdata2 = goto_create_tmp1vdata_(0); // 全局,記錄有關command結構指針
22 | v0->goto_make_command_entry = sub_B3E74A98;
23 | v0->goto_do_command1 = sub_B3E74DF4;
24 | v0->goto_do_command2 = sub_B3E74E48;
25 | set_global_command_entryptr(v0);
26 | }
27 | return 1;
28 | }
--------------------------------------------------------------------------------
/libsg6.4.36/sub_32C46.c:
--------------------------------------------------------------------------------
1 | int __fastcall sub_32C46(unsigned int a1)
2 | { // 第一個jarray的值,這裏為1
3 | unsigned int v1; // r6@1
4 | int v2; // r4@2
5 | int v3; // r2@3
6 | int v4; // r5@3
7 | int v5; // r0@4
8 | int v7; // r0@9
9 | int v8; // r8@9
10 | int v9; // r2@9
11 | int v10; // r0@9
12 | int v11; // r6@9
13 |
14 | v1 = a1;
15 | if ( a1 > 2 )
16 | return 0;
17 | v4 = sub_30590();
18 | if ( v4 || (sub_32CC8(0, v1, v3), (v4 = v5) != 0) && *(_DWORD *)(v5 + 4) )
19 | {
20 | v2 = (*(int (__fastcall **)(int))(v4 + 40))(v4);
21 | LABEL_7:
22 | goto_free_vdata(v4);
23 | return v2;
24 | }
25 | goto_free_vdata(v5);
26 | v2 = 0;
27 | v7 = sub_30240(v1, 0);
28 | v8 = v7;
29 | sub_32CC8(v7, v1, v9);
30 | v11 = v10;
31 | v4 = 0;
32 | if ( v10 )
33 | {
34 | if ( *(_DWORD *)(v10 + 4) )
35 | v2 = (*(int (__fastcall **)(int))(v10 + 40))(v10);
36 | else
37 | v2 = 0;
38 | v4 = v11;
39 | }
40 | if ( v8 )
41 | goto_free_vdata(v8);
42 | if ( v4 )
43 | goto LABEL_7;
44 | return v2;
45 | }
--------------------------------------------------------------------------------
/libsg6.4.36/sub_2B4BE.c:
--------------------------------------------------------------------------------
1 | int call_docommand_innerx()
2 | {
3 | int v0; // r4@1
4 | int v1; // r0@1
5 | const char *v2; // r5@1
6 | size_t v3; // r0@3
7 | void (__fastcall *v4)(int, const char *, size_t); // r6@4
8 | size_t v5; // r0@4
9 | int v7; // [sp+4h] [bp-14h]@1
10 | int v8; // [sp+8h] [bp-10h]@1
11 |
12 | v0 = 0;
13 | v8 = *(_DWORD *)off_8AC00;
14 | v7 = 0;
15 | sub_73D90(); // 保存著包含do_command_inner的結構
16 | // v1 + 4 指向的是do_command_inner的函數指針
17 | v2 = (const char *)(*(int (__fastcall **)(signed int, signed int, signed int, signed int))(v1 + 4))(1, 9, 2, 111);
18 | if ( v2 )
19 | { // 調試時返回0
20 | if ( *v2 && (v3 = strlen(v2), (v0 = goto_create_vadata(v3 + 1)) != 0) ) // 這裏應該包含一個解密,解密出一個結構
21 | {
22 | v4 = *(void (__fastcall **)(int, const char *, size_t))(v0 + 12);
23 | v5 = strlen(v2);
24 | v4(v0, v2, v5);
25 | }
26 | else
27 | {
28 | v0 = 0;
29 | }
30 | free((void *)v2);
31 | }
32 | if ( *(_DWORD *)off_8AC00 != v8 )
33 | _stack_chk_fail(*(_DWORD *)off_8AC00 - v8, v8);
34 | return v0;
35 | }
--------------------------------------------------------------------------------
/libsg6.4.36/sub_301DE.c:
--------------------------------------------------------------------------------
1 | vdata* sub_301DE(unsigned int a1, unsigned int a2)
2 | { // 參數1是jarray第一個值,參數2是程序傳遞下來的9
3 | unsigned __int8 v2; // cf@1
4 | char v3; // zf@1
5 | vdata *v4; // r4@1
6 | int *v5; // r0@6
7 | int v6; // r5@9
8 | int v7; // r0@9
9 | void (__fastcall *v8)(vdata *, int, int); // r6@9
10 | int v9; // r0@9
11 |
12 | v2 = a1 >= 2;
13 | v3 = a1 == 2;
14 | v4 = 0;
15 | if ( a1 <= 2 )
16 | {
17 | v2 = a2 >= 9;
18 | v3 = a2 == 9;
19 | }
20 | if ( !(!v3 & v2) )
21 | {
22 | if ( a1 == 2 )
23 | {
24 | v5 = (int *)&off_8A9F8; // off_8A9F8
25 | }
26 | else if ( a1 == 1 )
27 | {
28 | v5 = &off_8A9D0; // off_8A9D0
29 | }
30 | else
31 | {
32 | v5 = &off_8AA20; // off_8AA20
33 | }
34 | v6 = v5[a2]; // "d8b057995e905838"
35 | v7 = strlen(v5[a2]);
36 | v4 = (vdata *)goto_create_vdata(v7 + 1);
37 | v8 = (void (__fastcall *)(vdata *, int, int))v4->f1;
38 | v9 = strlen(v6);
39 | v8(v4, v6, v9); // make_vdata
40 | }
41 | return v4;
42 | }
--------------------------------------------------------------------------------
/libsg6.4.36/sub_14FEE.c:
--------------------------------------------------------------------------------
1 | int sub_14FEE(_JNIEnv *a1, int a2, int a3, int a4)
2 | {
3 | _JNIEnv *v4; // r4@1
4 | int v5; // r5@3
5 | const struct JNINativeInterface *v6; // r1@3
6 | int v7; // r2@3
7 | char v8; // r1@5
8 | int *v9; // r0@5
9 | int v11; // [sp+0h] [bp-8h]@0
10 | int v12; // [sp+4h] [bp-4h]@0
11 | int savedregs; // [sp+8h] [bp+0h]@0
12 | int savedregs_4; // [sp+Ch] [bp+4h]@0
13 |
14 | v4 = a1;
15 | if ( !a1 )
16 | {
17 | v8 = 0;
18 | v9 = &dword_B3EB5B04;
19 | LABEL_7:
20 | *(_BYTE *)v9 = v8;
21 | return 0;
22 | }
23 | if ( !(_BYTE)dword_B3EB5B04 )
24 | {
25 | v5 = 0;
26 | v6 = a1->functions;
27 | dword_B3EB5B0C = (int)a1->functions->GetFieldID;
28 | dword_B3EB5B1C = (int)v6->GetStaticFieldID;
29 | v7 = (int)v6->GetMethodID;
30 | dword_B3EB5B10 = (int)v6->GetMethodID;
31 | dword_B3EB5B20 = (int)v6->GetStaticMethodID;
32 | do
33 | sub_1511C((int)v4, v5++, v7, a4, v11, v12, savedregs, savedregs_4);
34 | while ( v5 != 9 );
35 | v8 = 1;
36 | v9 = &dword_B3EB5B04;
37 | goto LABEL_7;
38 | }
39 | return 0;
40 | }
--------------------------------------------------------------------------------
/libsg6.4.176/extends_vdata.c:
--------------------------------------------------------------------------------
1 | // 主要完成扩展vdata
2 | // @old_vdata 待扩展vdata结构
3 | // @extend_len 扩展长度
4 | int extend_vdata(vdata *old_vdata, int extend_len) {
5 | int newlen; // r1@3
6 | struct data *newdata; // r0@3
7 | int oldlen; // r6@4
8 | int result; // r0@4
9 |
10 | if ( old_vdata ) {
11 | if ( old_vdata->data ) {
12 | extendlen = extend_len + 100; // 扩展长度加100
13 | newlen = old_vdata->data_mlen + extendlen;
14 | newdata = relloc(old_vdata->data, newlen);
15 | if ( newdata ) {
16 | oldlen = old_vdata->data_mlen;
17 | old_vdata->data = (struct data *) newdata;
18 | memset(newdata + oldlen, 0, extendlen);
19 | old_vdata->data_mlen = extendlen + oldlen;
20 | return 0;
21 | }
22 | } else {
23 | if ( relen <= 100 )
24 | relen = 100;
25 | newdata = (struct data *) malloc(relen);
26 | if ( newdata ) {
27 | memset(newdata, 0, relen);
28 | old_vdata->data = newdata;
29 | old_vdata->data_len = 0;
30 | old_vdata->data_mlen = relen;
31 | return 0;
32 | }
33 | old_vdata->data = 0;
34 | }
35 | }
36 | return -1;
37 | }
--------------------------------------------------------------------------------
/libsg6.4.36/put_unconditional_branch1.py:
--------------------------------------------------------------------------------
1 | def put_unconditional_branch1(source, destination):
2 | offset = (destination - source - 4) >> 1
3 | if offset > 2097151 or offset < -2097152:
4 | raise RuntimeError("Invalid offset")
5 | if offset > 1023 or offset < -1024:
6 | instruction1 = 0xf000 | ((offset >> 11) & 0x7ff)
7 | instruction2 = 0xb800 | (offset & 0x7ff)
8 | PatchWord(source, instruction1)
9 | PatchWord(source + 2, instruction2)
10 | else:
11 | instruction = 0xe000 | (offset & 0x7ff)
12 | PatchWord(source, instruction)
13 |
14 | # ea = here()
15 | def patch1(ea):
16 | ea0 = ea
17 | if Word(ea) == 0xb503: #PUSH {R0,R1,LR}
18 | ea1 = ea + 6
19 | if Word(ea + 2) == 0xbf00: #NOP
20 | ea1 += 2
21 | offset = Dword(ea1)
22 | put_unconditional_branch1(ea, (ea1 + offset) & 0xffffffff)
23 | ea0 = ea1 - ea0
24 | else:
25 | print "Unable to detect first instruction"
26 |
27 | return ea0
28 |
29 |
30 | code_start = 0xb110 # JNI_OnLoad
31 | code_end = 0x886e0
32 | while (code_start <= code_end):
33 | flag = patch1(code_start)
34 | if (flag == 8) :
35 | code_start = code_start + 8
36 | else:
37 | code_start = code_start + 1
38 |
--------------------------------------------------------------------------------
/libsg6.4.176/create_vdata.c:
--------------------------------------------------------------------------------
1 | struct data {
2 | char* d; // 可变长数据
3 | };
4 |
5 | struct vdata{
6 | struct data* data;
7 | int data_len; // 前一次记录的内存大小
8 | int data_mlen; // 占总内存大小
9 | void* f1;
10 | void* f2;
11 | void* f3;
12 | void* f4;
13 | void* f5;
14 | void* f6;
15 | void* f7;
16 | void* f8;
17 | void* f9;
18 | void* f10; // f10 f11 = long long ,低四字节存放sub_B3BB1512,高四字节存放sub_B3BB1528
19 | void* f11;
20 | };
21 |
22 |
23 | struct vdata* create_vdata(int datalen) {
24 |
25 | if (data_len < 1) {
26 | return NULL;
27 | }
28 |
29 | struct vdata* vdata = malloc(56);
30 | if (vdata) {
31 | memset(vdata->data_len, 0, 52) // (char*) vdata + 4
32 | vdata->data = 0;
33 | vdata->data_mlen = datalen;
34 |
35 | struct vdata* data = malloc(datalen);
36 | if(data) {
37 | memset(data, 0, datalen);
38 | vdata->data_len = 0;
39 | vdata->data = data;
40 | vdata->f1 = make_data;
41 | vdata->f3 = extend_vdata;
42 | vdata->f4 = sub_B3BB13F4;
43 | vdata->f5 = sub_B3BB1412;
44 | vdata->f6 = sub_B3BB144A;
45 | vdata->f7 = sub_B3BB1468;
46 | vdata->f2 = sub_B3BB14D2;
47 | vdata->f8 = sub_B3BB14AC;
48 | vdata->f9 = sub_B3BB1500;
49 | vdata->f10 = sub_B3BB1512;
50 | vdata->f11 = sub_B3BB1528;
51 | }
52 | free(vdata);
53 | vdata = NULL;
54 | }
55 | return vdata;
56 | }
57 |
--------------------------------------------------------------------------------
/libsg6.4.36/sub_7B86C.c:
--------------------------------------------------------------------------------
1 | struct data {
2 | char* d;
3 | };
4 |
5 | struct tmp1_nest_struct {
6 | void* tmp1_nf1;
7 | void* tmp1_nf2;
8 | int len;
9 | };
10 |
11 | struct tmp1_vdata {
12 | struct data* datalist;
13 | int chunk_count;
14 | int chunk_size;
15 | void* tmp1_f1;
16 | void* tmp1_f2;
17 | void* tmp1_f3;
18 | struct tmp1_nest_struct tmp1_nest;
19 | };
20 |
21 | tmp1_vdata* sub_7B86C(signed int a1, int a2)
22 | { // create_tmp1_vdata, 第一次傳入0x20, 0
23 | signed int v2; // r5@1
24 | int v3; // r8@1
25 | tmp1_vdata *v4; // r0@2
26 | tmp1_vdata *v5; // r4@2
27 | struct data *v6; // r0@3
28 | struct data *v7; // r6@3
29 | tmp1_nest_struct *v8; // r0@4
30 |
31 | v2 = a1; // 傳入為0x20
32 | v3 = a2;
33 | if ( a1 < 1 )
34 | return 0;
35 | v4 = (tmp1_vdata *)malloc(0x24u);
36 | v5 = v4;
37 | if ( !v4 )
38 | return 0;
39 | memset(v4, 36);
40 | v6 = (struct data *)malloc(4 * v2); // 0x80 = 128
41 | v7 = v6;
42 | if ( !v6 )
43 | {
44 | free(v5);
45 | return 0;
46 | }
47 | memset(v6, 4 * v2);
48 | v5->data = v7;
49 | v5->chunk_count = 0;
50 | v5->chunk_size = v2;
51 | v5->tmp1_f1 = sub_7B8F8;
52 | v8 = &v5->tmp1_nest;
53 | v5->tmp1_f2 = sub_7B9B4;
54 | v5->tmp1_f3 = byte_7B9F5;
55 | v8->tmp1_nf1 = sub_7BA80;
56 | v8->tmp1_nf2 = sub_7BAF0;
57 | v8->len = v3;
58 | return v5;
59 | }
--------------------------------------------------------------------------------
/libsg6.4.36/sub_77dbc.c:
--------------------------------------------------------------------------------
1 | void sub77dbc(int a1, int a2, int a3) {
2 | int v3; // r0@5
3 | int v4; // r5@0
4 | int v5; // r6@0
5 | int v6; // lr@0
6 | _JNIEnv *v7; // r4@1
7 | int v8; // ST38_4@1
8 | int v9; // r1@1
9 | int v10; // r0@1
10 | int v11; // r1@1
11 | int v12; // r2@1
12 | int v13; // r0@2
13 | int v14; // ST18_4@2
14 | int v15; // r1@2
15 | int v16; // r2@2
16 | int v17; // r0@2
17 | int v18; // r1@2
18 | int v19; // r2@2
19 | char v20; // [sp+37h] [bp-45h]@1
20 | int v21; // [sp+6Ch] [bp-10h]@1
21 | _BYTE savedregs[24]; // [sp+7Ch] [bp+0h]@4
22 |
23 | v7 = (_JNIEnv *)a1;
24 | v8 = a1;
25 | dyna_arg(a1, a2, a3);
26 | dyna_arg(v8, v9, 16 * v5);
27 | v21 = **(_DWORD **)(16 * v4 - 1275462166);
28 | goto_decrypt_entry(v8 - 1275462161, &v20, 53);
29 | // "com/taobao/wireless/security/adapter/common/HttpUtil"
30 | v10 = ((int (__fastcall *)(_JNIEnv *, char *))v7->functions->FindClass)(v7, &v20);
31 | if ( v10 )
32 | {
33 | // 創建HttpUtil class
34 | v13 = ((int (__fastcall *)(_JNIEnv *, int))v7->functions->NewGlobalRef)(v7, v10);
35 | v14 = v13;
36 | v17 = dyna_arg(v13, v15, v16);
37 | *(_DWORD *)(v14 - 1275462080) = dyna_arg(v17, v18, v19);
38 | dyna_pc(2);
39 | JUMPOUT(3);
40 | }
41 | *(_DWORD *)&savedregs[4] = 0;
42 | *(_DWORD *)&savedregs[8] = v11;
43 | *(_DWORD *)&savedregs[12] = v6;
44 | dyna_arg(0, v11, v12);
45 | v3 = **(_DWORD **)(*(_DWORD *)&savedregs[4] - 1275462336);
46 | JUMPOUT(__CS__, *(_DWORD *)&savedregs[20]);
47 | }
--------------------------------------------------------------------------------
/libsg6.4.36/sub_2A01E.c:
--------------------------------------------------------------------------------
1 | int sub_2A01E(int a1, int a2)
2 | { // 參數1是第一個jarray的值,參數2不知道是啥,第一次傳0
3 | int v2; // r8@1
4 | int v3; // r5@2
5 | int v4; // r0@4
6 | int v5; // r6@4
7 | int v6; // r0@6
8 | int v7; // r0@6
9 | int v8; // r0@8
10 | int v9; // r4@10
11 | int v11; // [sp+4h] [bp-20h]@14
12 | int v12; // [sp+8h] [bp-1Ch]@14
13 | int v13; // [sp+Ch] [bp-18h]@14
14 | int v14; // [sp+10h] [bp-14h]@14
15 | int v15; // [sp+14h] [bp-10h]@1
16 |
17 | v2 = a2;
18 | v15 = *(_DWORD *)off_8AC00;
19 | if ( *(_DWORD *)(a1 + 4) )
20 | v3 = *(_DWORD *)a1;
21 | else
22 | v3 = sub_2AD20();
23 | v4 = sub_32C00(v3);
24 | v5 = v4;
25 | if ( v4 && *(_DWORD *)(v4 + 4) >= 32 )
26 | {
27 | v9 = sub_7B5D4(v4);
28 | goto LABEL_15;
29 | }
30 | v6 = goto_free_vdata(v4);
31 | v7 = sub_2B468(v6);
32 | v5 = v7;
33 | if ( !v7 || !*(_DWORD *)(v7 + 4) )
34 | {
35 | goto_free_vdata(v7);
36 | v8 = go_create_vadata(25);
37 | v5 = v8;
38 | if ( !v8 )
39 | {
40 | v9 = 0;
41 | v5 = 0;
42 | goto LABEL_14;
43 | }
44 | (*(void (**)(void))(v8 + 12))();
45 | if ( !*(_DWORD *)(v5 + 4) )
46 | {
47 | v9 = 0;
48 | goto LABEL_14;
49 | }
50 | }
51 | v9 = sub_7B5D4(v5);
52 | LABEL_14:
53 | v11 = v3;
54 | v12 = 0;
55 | v13 = 0;
56 | v14 = 1;
57 | sub_29E98(&v11, v2);
58 | LABEL_15:
59 | goto_free_vdata(v5);
60 | if ( *(_DWORD *)off_8AC00 != v15 )
61 | _stack_chk_fail(*(_DWORD *)off_8AC00 - v15, v15);
62 | return v9;
63 | }
--------------------------------------------------------------------------------
/libsg6.4.36/sub_7AFB6.c:
--------------------------------------------------------------------------------
1 | struct vdata_6436_nest {
2 | void* nf1;
3 | void* nf2;
4 | void* nf3;
5 | };
6 |
7 | struct vdata_6436 { // 對應版本6.4.36
8 | struct data* data;
9 | int data_len;
10 | int data_mlen; // = len + 1
11 | void* f1;
12 | void* f2;
13 | void* f3;
14 | void* f4;
15 | void* f5;
16 | void* f6;
17 | void* f7;
18 | void* f8;
19 | struct vdata_6436_nest* nest6436;
20 | };
21 |
22 | vdata_6436 *__fastcall create_vdata6436(signed int datalen)
23 | {
24 | int v1; // r5@1
25 | vdata_6436 *v2; // r4@2
26 | vdata_6436 *v3; // r6@2
27 | data *v4; // r6@3
28 | vdata_6436_nest *v5; // r3@4
29 |
30 | v1 = datalen;
31 | if ( datalen < 1 )
32 | goto LABEL_6;
33 | v2 = (vdata_6436 *)malloc(56);
34 | v3 = 0;
35 | if ( v2 )
36 | {
37 | memset(v2, 0, 56);
38 | v2->data_mlen = v1;
39 | v2->data = 0;
40 | v4 = (data *)malloc(v1);
41 | if ( v4 )
42 | {
43 | memset(v4, 0, v1);
44 | v2->data = v4;
45 | v2->data_len = 0;
46 | v2->f1 = &dword_B3EE5A5D;
47 | v2->f3 = sub_B3EE5AE0;
48 | v2->f4 = sub_B3EE5B7C;
49 | v2->f5 = sub_B3EE5BC8;
50 | v5 = (vdata_6436_nest *)&v2->nest6436;
51 | v2->f6 = sub_B3EE5C34;
52 | v2->f7 = sub_B3EE5C9C;
53 | v2->f8 = sub_B3EE5D0C;
54 | v2->f2 = &unk_B3EE5D75;
55 | v3 = v2;
56 | v5->nf1 = sub_B3EE5DE8;
57 | v5->nf2 = sub_B3EE5E38;
58 | v5->nf3 = sub_B3EE5E9C;
59 | return v3;
60 | }
61 | free(v2);
62 | LABEL_6:
63 | v3 = 0;
64 | }
65 | return v3;
66 | }
--------------------------------------------------------------------------------
/libsg6.4.36/sub_1511C.c:
--------------------------------------------------------------------------------
1 | int sub_1511C(_JNIEnv *a1, int a2, int a3)
2 | {
3 | int v4; // lr@0
4 | _JNIEnv *v5; // r11@1
5 | int v6; // r1@1
6 | int v7; // r4@1
7 | int v8; // r2@1
8 | int *v9; // r2@1
9 | _BYTE *v10; // r0@1
10 | int v11; // t1@1
11 | int v12; // r0@1
12 | int v13; // r1@1
13 | int v14; // r2@1
14 | int v15; // [sp-20h] [bp-38h]@1
15 | int v16; // [sp-1Ch] [bp-34h]@1
16 | _JNIEnv *v17; // [sp-14h] [bp-2Ch]@1
17 | int v18; // [sp-10h] [bp-28h]@1
18 | int v19; // [sp-Ch] [bp-24h]@1
19 | int v20; // [sp+4h] [bp-14h]@1
20 | _BYTE savedregs[24]; // [sp+18h] [bp+0h]@4
21 |
22 | v5 = a1;
23 | v17 = a1;
24 | v18 = a2;
25 | v19 = v4;
26 | dyna_arg(a1, a2, a3);
27 | v7 = v6;
28 | v15 = v6;
29 | v16 = v4;
30 | v9 = *(int **)(dyna_arg(v17, v6, v8) - 1276911288);
31 | v10 = *(_BYTE **)((char *)&v17[4 * v7 - 319227820] - 2);
32 | v20 = *v9;
33 | v11 = *v10;
34 | // 解密出"android/content/Context"
35 | goto_dcrypto_entry(v10 + 1, (char *)&v15 - (((_WORD)v11 + 8) & 0x1F8), v11 + 1);
36 | ((void (__fastcall *)(_JNIEnv *, char *))v5->functions->FindClass)(v5, (char *)&v15 - (((_WORD)v11 + 8) & 0x1F8));
37 | v12 = ((int (__fastcall *)(_JNIEnv *))goto_check_exception)(v5);
38 | if ( !v12 )
39 | {
40 | dyna_arg(0, v13, v14);
41 | dyna_pc(3);
42 | JUMPOUT(2);
43 | }
44 | *(_DWORD *)&savedregs[4] = v12;
45 | *(_DWORD *)&savedregs[8] = v13;
46 | *(_DWORD *)&savedregs[12] = v4;
47 | dyna_arg(v12, v13, v14);
48 | return **(_DWORD **)(*(_DWORD *)&savedregs[4] - 1276911362) - v20;
49 | }
--------------------------------------------------------------------------------
/libsg6.4.36/sub_E890.c:
--------------------------------------------------------------------------------
1 | int sub_E890(int a1, int a2, int a3, int a4)
2 | {
3 | _JNIEnv *v4; // r4@1
4 | int v5; // r3@1
5 | int v6; // r0@1
6 | int v7; // r5@1
7 | int v8; // r3@2
8 | int result; // r0@3
9 | int v10; // [sp+0h] [bp-70h]@1
10 | int v11; // [sp+4h] [bp-6Ch]@1
11 | int v12; // [sp+8h] [bp-68h]@1
12 | int v13; // [sp+Ch] [bp-64h]@1
13 | char v14; // [sp+4Ah] [bp-26h]@1
14 | int v15; // [sp+60h] [bp-10h]@1
15 |
16 | v4 = (_JNIEnv *)a1;
17 | v15 = *(_DWORD *)off_8AC00;
18 | // "(I)Ljava/lang/String;"
19 | goto_decrypt_entry((int)&unk_841F3, (int)&v14, 22, a4, v10, v11, v12, v13);
20 | // "com/taobao/wireless/security/adapter/datacollection/DeviceInfoCapturer"
21 | goto_decrypt_entry((int)&unk_8420A, (int)&v10 + 3, 71, v5, v10, v11, v12, v13);
22 | v6 = ((int (__fastcall *)(_JNIEnv *, char *))v4->functions->FindClass)(v4, (char *)&v10 + 3);
23 | v7 = v6;
24 | if ( v6 )
25 | {
26 | global_DeviceInfoCapturer_ref = ((int (__fastcall *)(_JNIEnv *, int))v4->functions->NewGlobalRef)(v4, v6);
27 | ((void (__fastcall *)(_JNIEnv *, int))v4->functions->DeleteLocalRef)(v4, v7);
28 | goto_decrypt_entry((int)&unk_84252, (int)(&v10 - 6), 19, v8, v10, v11, v12, v13);
29 | global_DeviceInfoCapturer_methodId = ((int (__fastcall *)(_JNIEnv *, int, int *, char *))v4->functions->GetStaticMethodID)(
30 | v4,
31 | dword_8CA98,
32 | &v10 - 6,
33 | &v14);
34 | }
35 | result = *(_DWORD *)off_8AC00 - v15;
36 | if ( *(_DWORD *)off_8AC00 != v15 )
37 | _stack_chk_fail(result, v15);
38 | return result;
39 | }
--------------------------------------------------------------------------------
/libsg6.4.36/sub_73668.c:
--------------------------------------------------------------------------------
1 | signed int __fastcall sub_73668(int a1, int a2, int a3, int a4)
2 | {
3 | signed int v4; // r5@1
4 | int v5; // r3@1
5 | _JNIEnv *v6; // r0@1
6 | _JNIEnv *v7; // r4@1
7 | int v8; // r0@2
8 | int v9; // r5@2
9 | int v10; // r3@3
10 | int v12; // [sp+0h] [bp-10h]@2
11 | int v13; // [sp+4h] [bp-Ch]@1
12 | int v14; // [sp+8h] [bp-8h]@2
13 | int v15; // [sp+Ch] [bp-4h]@2
14 |
15 | v4 = 0;
16 | goto_getenv(0, a2, a3, a4, *(_DWORD *)off_8AC00, v13);
17 | v7 = v6;
18 | if ( v6 )
19 | {
20 | call_decrypto_entry((int)&unk_860DC, (int)(&v12 - 14), 54, v5, v12, v13, v14, v15);
21 | // "com/taobao/wireless/security/adapter/umid/UmidAdapter"
22 | v8 = ((int (__fastcall *)(_JNIEnv *, int *))v7->functions->FindClass)(v7, &v12 - 14);
23 | v9 = v8;
24 | if ( v8 )
25 | {
26 | UmidAdapterRef = ((int (__fastcall *)(_JNIEnv *, int))v7->functions->NewGlobalRef)(v7, v8);
27 | ((void (__fastcall *)(_JNIEnv *, int))v7->functions->DeleteLocalRef)(v7, v9);
28 | call_decrypto_entry((int)&unk_86113, (int)(&v12 - 4), 16, v10, v12, v13, v14, v15);
29 | v4 = 1;
30 | // umidInitAdapter methodID
31 | umidInitAdapterMethodId = ((int (__fastcall *)(_JNIEnv *, int, int *, const char *))v7->functions->GetStaticMethodID)(
32 | v7,
33 | UmidAdapterRef,
34 | &v12 - 4,
35 | "(I)I");
36 | }
37 | else
38 | {
39 | v4 = 0;
40 | }
41 | }
42 | if ( *(_DWORD *)off_8AC00 != v12 )
43 | _stack_chk_fail(*(_DWORD *)off_8AC00 - v12, v12);
44 | return v4;
45 | }
--------------------------------------------------------------------------------
/libsg6.4.36/put_unconditional_branch.py:
--------------------------------------------------------------------------------
1 | from idaapi import *
2 | import idc
3 | import idautils
4 |
5 | def put_unconditional_branch(source, destination):
6 | offset = (destination - source - 4) >> 1
7 | if offset > 2097151 or offset < -2097152:
8 | raise RuntimeError("Invalid offset")
9 | if offset > 1023 or offset < -1024:
10 | instruction1 = 0xf000 | ((offset >> 11) & 0x7ff)
11 | instruction2 = 0xb800 | (offset & 0x7ff)
12 | patch_word(source, instruction1)
13 | patch_word(source + 2, instruction2)
14 | else:
15 | instruction = 0xe000 | (offset & 0x7ff)
16 | patch_word(source, instruction)
17 |
18 | ea = here()
19 | if Word(ea) == 0xb503: #PUSH {R0,R1,LR}
20 | ea1 = ea + 2
21 | if Word(ea1) == 0xbf00: #NOP
22 | ea1 += 2
23 | if GetOpType(ea1, 0) == 1 and GetOperandValue(ea1, 0) == 0 and GetOpType(ea1, 1) == 2:
24 | index = Dword(GetOperandValue(ea1, 1))
25 | print "index =", hex(index)
26 | ea1 += 2
27 | if GetOpType(ea1, 0) == 7:
28 | table = GetOperandValue(ea1, 0) + 4
29 | elif GetOpType(ea1, 1) == 2:
30 | table = GetOperandValue(ea1, 1) + 4
31 | else:
32 | print "Wrong operand type on", hex(ea1), "-", GetOpType(ea1, 0), GetOpType(ea1, 1)
33 | table = None
34 | if table is None:
35 | print "Unable to find table"
36 | else:
37 | print "table =", hex(table)
38 | offset = Dword(table + (index << 2))
39 | put_unconditional_branch(ea, table + offset)
40 | else:
41 | print "Unknown code", GetOpType(ea1, 0), GetOperandValue(ea1, 0), GetOpType(ea1, 1) == 2
42 | else:
43 | print "Unable to detect first instruction"
--------------------------------------------------------------------------------
/libsg6.4.36/sub_7B93A.c:
--------------------------------------------------------------------------------
1 | signed int __fastcall make_command_vdata(command_vdata *vdata, int index, $8bitstruct *a3)
2 | {
3 | command_vdata *gcommand_build_vdata; // r4@1
4 | $8bitstruct *first_8bitstr_ptr; // r9@1
5 | int v5; // r6@1
6 | signed int result; // r0@2
7 | int data_count; // r1@3
8 | int new_extend_data; // r0@5
9 | int data_size; // r8@6
10 | int v10; // r0@8
11 | int v11; // r2@8
12 |
13 | gcommand_build_vdata = vdata;
14 | first_8bitstr_ptr = a3;
15 | v5 = index;
16 | if ( !vdata )
17 | return 0;
18 | result = 0;
19 | if ( index < 0 )
20 | return result;
21 | data_count = gcommand_build_vdata->data_count;
22 | if ( data_count < v5 )
23 | return result;
24 | if ( data_count == gcommand_build_vdata->data_size )
25 | {
26 | new_extend_data = realloc(gcommand_build_vdata->datalist, 4 * data_count + 128);
27 | if ( new_extend_data )
28 | {
29 | gcommand_build_vdata->datalist = (struct data **)new_extend_data;
30 | data_size = gcommand_build_vdata->data_size;
31 | memset(new_extend_data + 4 * data_size, 128);
32 | gcommand_build_vdata->data_size = data_size + 32;
33 | data_count = gcommand_build_vdata->data_count;
34 | goto LABEL_7;
35 | }
36 | return 0;
37 | }
38 | LABEL_7:
39 | if ( data_count != v5 )
40 | { // 雖然這段代碼可能不會執行,但是感覺這段代碼明顯存在bug
41 | // 應該是while(v10) 可能永遠為true
42 | v10 = v5 - data_count;
43 | v11 = data_count;
44 | do
45 | {
46 | ++v10;
47 | gcommand_build_vdata->datalist[v11] = gcommand_build_vdata->datalist[v11 - 1];
48 | --v11;
49 | }
50 | while ( v10 );
51 | }
52 | gcommand_build_vdata->datalist[v5] = (struct data *) first_8bitstr_ptr;
53 | gcommand_build_vdata->data_count = data_count + 1;
54 | return 1;
55 | }
--------------------------------------------------------------------------------
/libsg6.4.36/sub_9D82.c:
--------------------------------------------------------------------------------
1 | int sub_9d82(int n1, int n2, int n3, int w, struct command_arg* arg, int* next_addr) {
2 | // arg 有時候是vdata32類型
3 | struct tmp1_vdata* vdata = &dword_8CA7C;
4 | if (w != 0) {
5 | vdata = &dword_8CA78;
6 | }
7 | // sub_9a14(tmp1_vdata, n1, n2, n3, w, 0)
8 | if(w != 0) {
9 | // create 8bitstruct 正序建立結構
10 | }
11 | // 最外層
12 | datalist = vdata->datalist;
13 |
14 | int i = 0;
15 | struct $8bitstruct* _8bitstruct = NULL;
16 | while(i < n1) {
17 | _8bitstruct = datalist[i]->d; // 取第一層8bitstruct指針
18 | int ra = _8bitstruct->command_arg1; // 第一層命令
19 | if (ra == n1) { // 第一層對比相等
20 | break;
21 | }
22 | i++;
23 | }
24 | // w不爲0,可能返回0x270F、0x26B0、0x26B1
25 | // 這裏暫不做分析
26 | if (_8bitstruct == NULL && w == 0) { // 沒找到的情況
27 | return 0x26b0;
28 | }
29 | //獲取第二層
30 | struct tmp1_vdata* vdata1 = _8bitstruct->vdata;
31 | int count = vdata1->data_count;
32 | i = 0;
33 | struct $24bitstruct _24bitstr = NULL;
34 | while(i < count) {
35 | _24bitstr = vdata1->datalist[i]->d;
36 | int rb = _24bitstr->command_arg2;
37 | if (rb = n2) { // 第二層對比
38 | break;
39 | }
40 | i++;
41 | }
42 | // w不爲0,可能返回0x270F、0x26B0、0x26B1
43 | // 這裏暫不做分析
44 | if(_24bitstr == NULL && w == 0) { // 沒找到的情況
45 | return 0x26b0;
46 | }
47 |
48 | // 獲取第三層
49 | struct tmp1_vdata* vdata2 = _24bitstr->vdata;
50 | count = vdata2->data_count;
51 | i = 0;
52 | struct $16bitstruct _16bitstr = NULL;
53 | while(i < count) {
54 | _16bitstr = vdata2->datalist[i]->d;
55 | int rc = _16bitstr->command_arg3;
56 | if(rc == n3) {
57 | int xor_addr = _16bitstr->xoraddr ^ _24bitstr->time;
58 | *next_addr = xor_addr;
59 | break;
60 | }
61 | i++;
62 | }
63 |
64 |
65 | typedef *func(void* void*) nfunc;
66 | nfunc nextf= (nfunc) next_addr;
67 | return nextf(command_arg, next_addr);
68 | }
--------------------------------------------------------------------------------
/libsg6.4.36/jni_load.c:
--------------------------------------------------------------------------------
1 | int __fastcall real_JNI_OnLoad(JavaVM *vm) {
2 | int result; // r0
3 | jclass clazz; // r0 MAPDST
4 | int v4; // r0
5 | JNIEnv *env; // r4
6 | int v6; // [sp-40h] [bp-5Ch]
7 | int v7; // [sp+Ch] [bp-10h]
8 | v7 = *(_DWORD *)off_8AC00;
9 | if ( !vm )
10 | goto LABEL_39;
11 | sub_7C4F4(); // 創建全局 jboolean, jinteger、jstring
12 | env = (JNIEnv *)sub_7C5B0(0); // 獲取env, goto_getenv()
13 | if ( !env )
14 | goto LABEL_39;
15 | v4 = sub_72CCC(); // goto_do_httpuitl
16 | sub_73634(v4); // goto_do_umidAdapter
17 | sub_73E24(&unk_83EA6, &v6, 49); // goto_decrypt_entry
18 | clazz = (jclass)((int (__fastcall *)(JNIEnv *, int *))(*env)->FindClass)(env, &v6);
19 | if ( clazz &&
20 | (sub_9EE4(), // goto_create_tmp1vdata_
21 | sub_71D68(env), // goto_do_SPUtility2
22 | sub_E7DC(env) >= 0 // 處理了DeviceInfoCapturer,pack_or_unpack_command
23 | && sub_69D68(env) >= 0 // 啥也沒乾
24 | && sub_197B4(env, clazz) >= 0 // 處理了DataReportJniBridgerer,pack_or_unpack_command
25 | && sub_E240(env, clazz) >= 0 // pack_or_unpack_command
26 | && sub_B8B0(env, clazz) >= 0 // pack_or_unpack_command
27 | && sub_5F0F4(env, clazz) >= 0 // pack_or_unpack_command
28 | && sub_70640(env, clazz) >= 0 // pack_or_unpack_command
29 | && sub_11F3C(env) >= 0 // 處理android相關類
30 | && sub_21C3C(env, clazz) >= 0 // pack_or_unpack_command
31 | && sub_2148C(env, clazz) >= 0 // pack_or_unpack_command
32 | && sub_210E0(env, clazz) >= 0 // pack_or_unpack_command
33 | && sub_41B58(env, clazz) >= 0 // pack_or_unpack_command
34 | && sub_27920(env, clazz) >= 0 // pack_or_unpack_command
35 | && sub_293E8(env, clazz) >= 0 // 處理ZipUtils、CallbackHelper和android相關類
36 | && sub_208F4(env, clazz) >= 0) ) // 處理UserTrackMethodJniBridge
37 | {
38 | result = (sub_B7B0(env, clazz) >> 31) | 0x10004; // 注冊doCommandNaitve
39 | } else {
40 | LABEL_39:
41 | result = -1;
42 | }
43 | return result;
44 | }
--------------------------------------------------------------------------------
/libsg6.4.36/patches.py:
--------------------------------------------------------------------------------
1 | patches = {}
2 | patches[0] = (0x00, 0xbf, 0x01, 0x48, 0x00, 0x68, 0x02, 0xe0)
3 | patches[1] = (0x00, 0xbf, 0x01, 0x49, 0x09, 0x68, 0x02, 0xe0)
4 | patches[2] = (0x00, 0xbf, 0x01, 0x4a, 0x12, 0x68, 0x02, 0xe0)
5 | patches[3] = (0x00, 0xbf, 0x01, 0x4b, 0x1b, 0x68, 0x02, 0xe0)
6 | patches[4] = (0x00, 0xbf, 0x01, 0x4c, 0x24, 0x68, 0x02, 0xe0)
7 | patches[5] = (0x00, 0xbf, 0x01, 0x4d, 0x2d, 0x68, 0x02, 0xe0)
8 | patches[8] = (0x00, 0xbf, 0xdf, 0xf8, 0x06, 0x80, 0xd8, 0xf8, 0x00, 0x80, 0x01, 0xe0)
9 | patches[9] = (0x00, 0xbf, 0xdf, 0xf8, 0x06, 0x90, 0xd9, 0xf8, 0x00, 0x90, 0x01, 0xe0)
10 | patches[10] = (0x00, 0xbf, 0xdf, 0xf8, 0x06, 0xa0, 0xda, 0xf8, 0x00, 0xa0, 0x01, 0xe0)
11 | patches[11] = (0x00, 0xbf, 0xdf, 0xf8, 0x06, 0xb0, 0xdb, 0xf8, 0x00, 0xb0, 0x01, 0xe0)
12 |
13 | ea = here()
14 |
15 | if (Word(ea) == 0xb082 #SUB SP, SP, #8
16 | and Word(ea + 2) == 0xb503): #PUSH {R0,R1,LR}
17 | if GetOpType(ea + 4, 0) == 7:
18 | pop = GetManyBytes(ea + 12, 4, 0)
19 | if ord(pop[1]) == 0xbc:
20 | register = -1
21 | r = Byte(ea + 12)
22 | for i in range(8):
23 | if r == (1 << i):
24 | register = i
25 | break
26 | if register == -1:
27 | print "Unable to detect register"
28 | else:
29 | address = Dword(ea + 8) + ea + 8
30 | for b in patches[register]:
31 | PatchByte(ea, b)
32 | ea += 1
33 | if ea % 4 != 0:
34 | ea += 2
35 | PatchDword(ea, address)
36 | elif ord(pop[:3]) == 0x4f85d:
37 | register = ord(pop[3]) >> 4
38 | if register in patches:
39 | address = Dword(ea + 8) + ea + 8
40 | for b in patches[register]:
41 | PatchByte(ea, b)
42 | ea += 1
43 | PatchDword(ea, address)
44 | else:
45 | print "POP instruction not found"
46 | else:
47 | print "Wrong operand type on +4:", GetOpType(ea + 4, 0)
48 | else:
49 | print "Unable to detect first instructions"
--------------------------------------------------------------------------------
/libsg6.4.176/decrypto.c:
--------------------------------------------------------------------------------
1 | struct dcryptdata {
2 | void* v;
3 | int caseno;
4 | void* v1;
5 | void* decryptdata_;
6 | struct vdata* key;
7 | struct vdata* cryptedata;
8 | }
9 |
10 | decryptdata_ 取值 820000 880000 890000
11 |
12 | int decrypto(struct dcryptdata* decryptdata_, int* a2) {
13 | // 传递两个参数 一个代表待解密结构体,一个代表返回码
14 | // 应该是解密算法
15 | // 内置n种解密算法
16 | // 如rc4
17 | // 解压缩等
18 | // 传递两个参数
19 | // 应该是解密算法
20 | // 内置n种解密算法
21 | // 如rc4
22 | // 解压缩等
23 | int caseno; // r1@3
24 | int result; // r0@4
25 |
26 | *a2 = 820000;
27 | if ( !decryptdata_ || !decryptdata_->cryptedata || (caseno = decryptdata_->caseno, (unsigned int)v5 > 0x1B) )
28 | {
29 | result = 0;
30 | *a2 = 890000;
31 | return result;
32 | }
33 | v3 = 880000;
34 | result = 0;
35 | switch ( caseno )
36 | {
37 | case 0x10u:
38 | case 0x11u:
39 | case 0x12u:
40 | result = ((int (__fastcall *)(void *))unk_A409A4F8)(decryptdata_->v);
41 | break;
42 | case 3u:
43 | result = ((int (__fastcall *)(struct vdata *, struct vdata *))call_rc4)(decryptdata_->key, decryptdata_->cryptedata);
44 | break;
45 | case 0x14u:
46 | result = ((int (__fastcall *)(void *, struct vdata *))call_uncompress)(decryptdata_->v, decryptdata_->cryptedata);
47 | break;
48 | case 0x15u:
49 | result = ((int (__fastcall *)(void *, struct vdata *, _DWORD *))unk_A409A998)(decryptdata_->v, decryptdata_->cryptedata, 820000);
50 | break;
51 | case 0x16u:
52 | result = ((int (__fastcall *)(struct vdata *))call_md5)(decryptdata_->cryptedata);
53 | break;
54 | case 0x17u:
55 | result = ((int (__fastcall *)(struct vdata *, struct vdata *))unk_A409AE54)(decryptdata_->key, decryptdata_->cryptedata);
56 | break;
57 | case 0x18u:
58 | result = ((int (__fastcall *)(struct vdata *))call_sha1)(decryptdata_->cryptedata);
59 | break;
60 | case 0x19u:
61 | result = ((int (__fastcall *)(struct vdata *))call_sha256)(decryptdata_->cryptedata);
62 | break;
63 | case 0x1Au:
64 | result = (int)sub_A409E338((int)decryptdata_->v, (int)decryptdata_->v1, (int)decryptdata_->cryptedata, v4);
65 | break;
66 | default:
67 | result = 0;
68 | *a2 = 880000;
69 | return result;
70 | }
71 |
72 | if ( result ) {
73 | result = 0;
74 | *a2 = 0;
75 | return result;
76 | }
77 |
78 | return 0;
79 | }
--------------------------------------------------------------------------------
/libsg6.4.36/sub_73e56.c:
--------------------------------------------------------------------------------
1 | int __fastcall decrypt_entry(int encdata, int decdata, int datalen)
2 | {
3 | int v3; // r10@1
4 | int v4; // r6@1
5 | int v5; // r5@1
6 | int v6; // r8@1
7 | vdata *v7; // r11@1
8 | vdata *v8; // r9@1
9 | int v9; // r4@4
10 | int v10; // r5@5
11 | int v11; // r0@5
12 | struct dcryptdata* v13; // [sp+0h] [bp-30h]@5
13 | int v14; // [sp+4h] [bp-2Ch]@5
14 | vdata *v15; // [sp+10h] [bp-20h]@5
15 | vdata *v16; // [sp+14h] [bp-1Ch]@5
16 | int v17; // [sp+1Ch] [bp-14h]@1
17 | int v18; // [sp+20h] [bp-10h]@1
18 |
19 | v3 = encdata;
20 | v4 = 0;
21 | v5 = datalen;
22 | v6 = decdata;
23 | v18 = _stack_chk_guard;
24 | v17 = 0;
25 | v7 = (vdata *)goto_create_vdata(17);
26 | v8 = (vdata *)goto_create_vdata(v5);
27 | if ( !v7 )
28 | {
29 | v9 = 0;
30 | goto LABEL_12;
31 | }
32 | // make_vdata 填充數據
33 | ((void (__fastcall *)(vdata *, const char *, signed int))v7->f1)(v7, "DcO/lcK+h?m3c*q@", 16);
34 | if ( !v8 )
35 | {
36 | LABEL_9:
37 | v4 = 0;
38 | goto LABEL_10;
39 | }
40 | v4 = 0;
41 | if ( !v3 )
42 | {
43 | LABEL_10:
44 | v9 = 0;
45 | goto LABEL_11;
46 | }
47 | v9 = 0;
48 | if ( v6 )
49 | {
50 | ((void (__fastcall *)(int, int))memset0)(v6, v5);
51 | v10 = v5 - 1;
52 | // make_vdata 填充數據
53 | ((void (__fastcall *)(vdata *, int, int))v8->f1)(v8, v3, v10);
54 | ((void (__fastcall *)(int *, signed int))memset0)(&v13, 20);
55 | v14 = 3;
56 | v15 = v7;
57 | v16 = v8;
58 | // 調用rc4解密
59 | // 解密出"com/taobao/wireless/security/adapter/common/HttpUtil"
60 | v11 = ((int (__fastcall *)(int *, int *))goto_dcrypto)(&v13, &v17);
61 | v9 = v11;
62 | if ( v11 )
63 | {
64 | if ( *(_DWORD *)(v11 + 4) != v10 )
65 | goto LABEL_19;
66 | // 拷貝到傳入的緩衝區
67 | ((void (__fastcall *)(int, _DWORD, int))memcpy)(v6, *(_DWORD *)v11, v10);
68 | v4 = *(_DWORD *)(v9 + 4);
69 | goto LABEL_11;
70 | }
71 | goto LABEL_9;
72 | }
73 | LABEL_11:
74 | while ( 1 )
75 | {
76 | ((void (__fastcall *)(vdata *))goto_free_vdata)(v7);
77 | LABEL_12:
78 | if ( v8 )
79 | ((void (__fastcall *)(vdata *))goto_free_vdata)(v8);
80 | if ( v9 )
81 | ((void (__fastcall *)(int))goto_free_vdata)(v9);
82 | if ( _stack_chk_guard == v18 )
83 | break;
84 | ((void (__fastcall *)(int))unk_B3F3113C)(_stack_chk_guard - v18);
85 | LABEL_19:
86 | v4 = 0;
87 | }
88 | return v4;
89 | }
--------------------------------------------------------------------------------
/libsg6.4.176/vdata.h:
--------------------------------------------------------------------------------
1 | struct data {
2 | char* d;
3 | };
4 |
5 | struct vdata_64176 { // 對應版本6.4.176
6 | struct data* data;
7 | int data_len;
8 | int data_mlen; // = len + 1
9 | void* f1;
10 | void* f2;
11 | void* f3;
12 | void* f4;
13 | void* f5;
14 | void* f6;
15 | void* f7;
16 | void* f8;
17 | void* f9;
18 | void* f10;
19 | void* f11;
20 | };
21 |
22 | struct vdata_6436_nest {
23 | void* nf1;
24 | void* nf2;
25 | void* nf3;
26 | };
27 |
28 | struct vdata_6436 { // 對應版本6.4.36
29 | struct data* data;
30 | int data_len;
31 | int data_mlen; // = len + 1
32 | void* f1;
33 | void* f2;
34 | void* f3;
35 | void* f4;
36 | void* f5;
37 | void* f6;
38 | void* f7;
39 | void* f8;
40 | struct vdata_6436_nest* nest;
41 | };
42 |
43 | struct dcryptdata {
44 | void* v;
45 | int caseno;
46 | void* v1;
47 | void* decryptdata_;
48 | struct vdata* key;
49 | struct vdata* cryptedata;
50 | };
51 |
52 | struct vdata32_nest {
53 | void* nf1;
54 | void* nf2;
55 | void* nf3;
56 | void* nf4;
57 | };
58 |
59 | struct vdata32 {
60 | struct data* data128;
61 | int data_count;
62 | int chunk_size;
63 | void* f1; // goto_make_vdata32;
64 | struct vdata32_nest* nest;
65 | };
66 |
67 | struct global_command_entry { // 記錄著生成和執行command的核心方法
68 | void* goto_make_command_entry; // 對應sub_9B3C
69 | void* goto_do_command1; // // 對應sub_9d82; command_native_inner
70 | void* goto_do_command2; // 對應sub_9e7e; 和sub_9d82差不多
71 | };
72 |
73 | struct command_nest {
74 | void* nf1;
75 | void* nf2;
76 | int len;
77 | };
78 |
79 | struct command_vdata {
80 | struct data** datalist; // 第一層$8bitstruct
81 | int data_count;
82 | int data_size;
83 | void* f1;
84 | void* f2; // make_vdata
85 | void* f3;
86 | struct command_nest* nest;
87 | };
88 |
89 | struct $8bitstruct { // 第一層結構
90 | int command_arg1; // command arg1
91 | struct command_vdata* vdata; // 指向第二層
92 | };
93 |
94 | struct $24bitstruct { // 第二層結構
95 | int command_arg1; // command arg1
96 | int command_arg2; // command arg2
97 | long time;
98 | int c; // (time >> 31)
99 | struct command_vdata* vdata; // 指向第三層
100 | int d; // 未知
101 | };
102 |
103 | struct $16bitstruct { // 第三層結構
104 | int command_arg1; // command arg1
105 | int command_arg2; // command arg2
106 | int command_arg3; // command arg3
107 | int xoraddr;
108 | };
109 |
110 | struct command_arg {
111 | int arg1;
112 | int arg2;
113 | int arg3;
114 | _JNIEnv* env;
115 | void* args;
116 | };
117 |
118 | struct vstring {
119 | int len;
120 | char* str;
121 | };
122 |
--------------------------------------------------------------------------------
/libsg6.4.36/doCommandNative.c:
--------------------------------------------------------------------------------
1 | int doCommandNative(JNIEnv *env, jobject obj, int command, jarray args)
2 | { // sub_B6F6
3 | int v5; // r5
4 | struc_2 *a5; // r6
5 | int v9; // r1
6 | int v11; // [sp+Ch] [bp-14h]
7 | int v12; // [sp+10h] [bp-10h]
8 | v5 = 0;
9 | v12 = *(_DWORD *)off_8AC00;
10 | v11 = 0;
11 | a5 = (struc_2 *)malloc(0x14u);
12 | if ( a5 )
13 | {
14 | a5->field_0 = 0;
15 | a5->field_4 = 0;
16 | a5->field_8 = 0;
17 | a5->field_C = 0;
18 | v9 = command % 10000 / 100;
19 | a5->field_0 = command / 10000;
20 | a5->field_4 = v9;
21 | a5->field_8 = command % 100;
22 | a5->field_C = env;
23 | a5->field_10 = args;
24 | v5 = goto_docommand_native_inner(command / 10000, v9, command % 100, 1, (int)a5, &v11);
25 | }
26 | free(v8);
27 | if ( !v5 && v22 )
28 | goto_throw_exception(v4, v22, (int)&byte_83ED7);
29 | if ( *(_DWORD *)off_8AC00 != v23 )
30 | _stack_chk_fail(*(_DWORD *)off_8AC00 - v23, v23);
31 | return v5;
32 | }
33 |
34 | 對著匯編逆向分析:
35 | struct command_arg {
36 | int arg1;
37 | int arg2;
38 | int arg3;
39 | JNIEnv* env;
40 | void* args;
41 | };
42 |
43 | int sub_B6F6(JNIEnv *env, jobject obj, int command, jarray args)
44 | { // doCommandNative
45 | int v4; // r8@1
46 | int v5; // r5@1
47 | int v6; // r9@1
48 | struct command_arg* v8; // r6@1
49 | int v17; // r0@2
50 | int v20; // r1@2
51 | int v22; // [sp+Ch] [bp-14h]@1
52 | int v23; // [sp+10h] [bp-10h]@1
53 |
54 | v4 = a1;
55 | v5 = 0;
56 | v6 = a4;
57 | _R4 = a3; // 10601
58 | v23 = *(_DWORD *)off_8AC00;
59 | v22 = 0;
60 | command_arg = (struct command_arg*) malloc(0x14u);
61 | if ( command_arg )
62 | {
63 | // 以一次調試爲例
64 | int _R4 = 12302; // command
65 | int _R0 = 0x68DB8BAD; // 68DB8BAD
66 | int _R2 = 0x51EB851F; // 51EB851F
67 |
68 | int r0 = _R0 * _R4; // 000013AE, SMMUL.W取高位
69 | int r3 = _R2 * _R4; // 00000F60, SMMUL.W取高位
70 | // (signed int)r0 >> 0xc) = (signed int) (13AE >> 0xc) = 00000001
71 | // r0 >> 31 = 0
72 | r0 = ((signed int)r0 >> 0xc) + (r0 >> 31); // 0x1, 參數1
73 | int r1 = _R4 - r0 * 10000 ; // 000008FE(2302)
74 | r1 = _R4 * r1; // 2E0, SMMUL.W取高位
75 | // ((signed int)r3 >> 5) = 0000007B(123)
76 | // (r3 >> 31) = 0
77 | r2 = _R4 - (((signed int)r3 >> 5) + (r3 >> 31)) * 100; // 2, 參數3
78 | r3 = (signed) r1 >> 5 = 00000017(23)
79 | r1 = r3 + (r1 >> 31) = 1; // 0x17, 參數2
80 |
81 | command_arg->arg1 = 1;
82 | command_arg->arg2 = 0x17;
83 | command_arg->arg3 = 2;
84 | command_arg->env = env;
85 | command_arg->args = args;
86 |
87 | v5 = sub_9D60(r0, r1, r2, 1, command_arg, v22);
88 | }
89 | free(command_arg);
90 | if ( !v5 && v22 )
91 | sub_7CF34(v4);
92 | if ( *(_DWORD *)off_8AC00 != v23 )
93 | _stack_chk_fail(*(_DWORD *)off_8AC00 - v23);
94 | return v5;
95 | }
96 |
97 | goto_docommand_native_inner
98 | sub_9D60->sub_9D82
99 | docommand_native_inner
--------------------------------------------------------------------------------
/libsg6.4.36/sub_9a14.c:
--------------------------------------------------------------------------------
1 | // w = 0代表查找, w = 1代表創建
2 | // n1, n2, n3 為command 三層索引
3 | // build_addr 正向時為被處理地址, 反向時為返回地址
4 | void* pack_or_unpack_command(command_vdata* g_build_vdata, int n1, int n2, int n3, w = 1, void* build_addr) {
5 |
6 | int data_count = g_build_vdata->data_count;
7 | int i = 0;
8 | if (data_count < 1) {
9 | if (w == 0) {
10 | return 0x26b0;
11 | }
12 |
13 | struct $8bitstruct* _8bitstruct = (struct $8bitstruct*) malloc(8); // B4E01130
14 | memset(_8bitstruct, 0, 8);
15 | _8bitstruct->command_arg1 = n1;
16 | // -> 7BB98
17 |
18 | // vdata = ACB4A3F8, datalist = ACB32980
19 | // vdata 初始化略; 默認data_size為120字節
20 | struct command_vdata* second_command_vdata = (struct command_vdata*) malloc(36);
21 |
22 | _8bitstruct->vdata = second_command_vdata;
23 | // make_command_vdata, 填充數據
24 | // 這裏僅僅執行了 vdata->datalist->d = _8bitstruct;
25 | // vdata->data_count++;
26 | g_build_vdata->f2(g_build_vdata, 0, _8bitstruct);
27 |
28 | if(second_command_vdata->data_count < 1) {
29 | if (w == NULL) {
30 | return 0x26B1;
31 | }
32 | // ACB12478
33 | struct $24bitstruct* _24bitstr = (struct $24bitstruct*) malloc(24);
34 | memset(_24bitstr, 0, 24);
35 | _24bitstr->command_arg1 = n1; // command arg1
36 | _24bitstr->command_arg2 = n2; // command arg2
37 | time_t seed;
38 | seed = time(NULL); // 5E58B699
39 | srand(seed);
40 | int random_time = (int) rand() >> 31; // 074D4C00
41 | int c = (int) random_time >> 31; // 0
42 | _24bitstr->time = random_time;
43 | _24bitstr->c = c;
44 | // 創建第三層command_vdata結構
45 | // vdata = ACB4A498; data = ACB32A00
46 | // vdata 初始化略
47 | struct command_vdata* third_command_vdata = (struct command_vdata*) malloc(36);
48 | _24bitstr->vdata = third_command_vdata;
49 | // 這裏僅僅執行了 vdata->datalist->d = _24bitstr;
50 | // vdata->data_count++;
51 | second_command_vdata->f2(second_command_vdata, _24bitstr); // make_command_vdata
52 | if (third_command_vdata->data_count < 1) {
53 | if (w == 0) {
54 | return 0x270F;
55 | }
56 | // ACB3B540
57 | struct $16bitstruct* _16bitstr = (struct $16bitstruct*) malloc(16);
58 | _16bitstr->command_arg1 = n1;
59 | _16bitstr->command_arg2 = n2;
60 | _16bitstr->command_arg3 = n3;
61 | // make_command_vdata, 填充數據
62 | // 這裏僅僅執行了 vdata->datalist->d = _16bitstr;
63 | // vdata->data_count++;
64 | third_command_vdata->f2(third_command_vdata, _16bitstr);// make_command_vdata
65 | // 異或加密地址存儲
66 | _16bitstr->xoraddr = _24bitstr->time ^ build_addr;
67 | return 0;
68 |
69 | } else {
70 | i = 0;
71 | while (i < third_command_vdata->data_count) {
72 | // 這裏後面在說
73 | }
74 | }
75 | } else {
76 | i = 0;
77 | while(i < second_command_vdata->data_count) {
78 | // 這裏後面在說
79 | }
80 |
81 | }
82 | } else {
83 | struct data** datalist = g_build_vdata->datalist;
84 | struct $8bitstruct* _8bitstr = NULL;
85 | for (int i = 0 ; i < g_build_vdata->data_count; i++) {
86 | _8bitstr = datalist[i];
87 | if(_8bitstr->command_arg1 == n1) {
88 | break;
89 | }
90 | }
91 | // 取第二層機構
92 | struct command_vdata* second_command_vdata = _8bitstr->vdata;
93 | if (second_command_vdata->data_count < 1 ) {
94 | return 0x26B1;
95 | }
96 |
97 | datalist = second_command_vdata->datalist;
98 | struct $24bitstruct* _24bitstr = NULL;
99 |
100 | for (int j = 0 ; j < second_command_vdata->data_count ; j++) {
101 | if((struct $24bitstruct*) datalist[i]->command_arg2 == n2) {
102 | _24bitstr = datalist[i];
103 | break;
104 | }
105 | }
106 |
107 | if (w == 0) {
108 | return ??;
109 | }
110 |
111 | if (_24bitstr == NULL) {
112 | _24bitstr = malloc(24);
113 | // 創建$24bitstruct 結構體
114 | // 創建third_command_vdata ACB4A4C0;同上
115 | // 更新second_command_vdata datalist同時data_count++等
116 | // ACB124C0 24bitstr,
117 | // 創建完后調用
118 | }
119 |
120 | // 取第三層
121 | struct $16bitstruct* _16bitstr = NULL;
122 | struct command_vdata* third_command_vdata = _24bitstr->vdata;
123 | if(third_command_vdata->data_count < 1) {
124 |
125 | }
126 |
127 | for (j = 0; j < third_command_vdata->data_count; j++) {
128 | if ((struct $16bitstruct*) third_command_vdata[j]->command_arg3 == n3) {
129 | _16bitstr = third_command_vdata[j];
130 | break;
131 | }
132 | }
133 |
134 | if (w == 0) {
135 | return ??;
136 | }
137 |
138 | if (_16bitstr == NULL) {
139 | _16bitstr = malloc(16);
140 | // ACB11F50
141 | // 創建$16bitstruct; 同上
142 | return 0;
143 | }
144 | }
145 | }
146 |
--------------------------------------------------------------------------------
/libsg6.4.36/breaklist.idc:
--------------------------------------------------------------------------------
1 | static main(void)
2 | { // 所有JNI_OnLoad 函數,以及我認爲重要的函數斷點
3 | auto bpt;
4 |
5 | auto libsgmain_base = 0;
6 | auto base = GetFirstModule();
7 | auto name = GetModuleName(base);
8 | auto size = GetModuleSize(base);
9 |
10 | while(1) {
11 | base = GetNextModule(base);
12 | name = GetModuleName(base);
13 | size = GetModuleSize(base);
14 | if (strstr (name, "libsgmainso-6.4.36.so") != -1) {
15 | libsgmain_base = base;
16 | Message("libsgmain_base = %x\n", libsgmain_base);
17 | break;
18 | }
19 | }
20 |
21 | bpt = Breakpoint();
22 | bpt.set_abs_bpt(libsgmain_base + 0x7B86C); // create_command_vdata
23 | Breakpoints.Add(bpt);
24 | Message("call create_command_vdata %x\n", (libsgmain_base + 0x7B86C));
25 |
26 | bpt = Breakpoint();
27 | bpt.set_abs_bpt(libsgmain_base + 0x73ed8); // goto_dcrypto
28 | Breakpoints.Add(bpt);
29 | Message("call goto_dcrypto %x\n", (libsgmain_base + 0x73ed8));
30 |
31 | bpt = Breakpoint();
32 | bpt.set_abs_bpt(libsgmain_base + 0x73eec); // memcpy
33 | Breakpoints.Add(bpt);
34 | Message("call memcpy %x\n", (libsgmain_base + 0x73eec));
35 |
36 | bpt = Breakpoint();
37 | bpt.set_abs_bpt(libsgmain_base + 0x9a14); // build_command
38 | Breakpoints.Add(bpt);
39 | Message("call build_command %x\n", (libsgmain_base + 0x9a14));
40 |
41 | bpt = Breakpoint();
42 | bpt.set_abs_bpt(libsgmain_base + 0x9D82); // do_command_native_inner
43 | Breakpoints.Add(bpt);
44 | Message("call memcpy %x\n", (libsgmain_base + 0x9D82));
45 |
46 |
47 | bpt = Breakpoint();
48 | bpt.set_abs_bpt(libsgmain_base + 0x7C4F4); // 創建全局objects
49 | Breakpoints.Add(bpt);
50 |
51 | bpt = Breakpoint();
52 | bpt.set_abs_bpt(libsgmain_base + 0x7C5B0); // goto_getEnv
53 | Breakpoints.Add(bpt);
54 |
55 | bpt = Breakpoint();
56 | bpt.set_abs_bpt(libsgmain_base + 0x72CCC); // goto_do_httpuitl
57 | Breakpoints.Add(bpt);
58 |
59 | bpt = Breakpoint();
60 | bpt.set_abs_bpt(libsgmain_base + 0x73634); // goto_do_umidAdapter
61 | Breakpoints.Add(bpt);
62 |
63 | bpt = Breakpoint();
64 | bpt.set_abs_bpt(libsgmain_base + 0x73E24); // goto_decrypt_entry
65 | Breakpoints.Add(bpt);
66 |
67 | bpt = Breakpoint();
68 | bpt.set_abs_bpt(libsgmain_base + 0xb534);
69 | Breakpoints.Add(bpt);
70 |
71 | bpt = Breakpoint();
72 | bpt.set_abs_bpt(libsgmain_base + 0xb538);
73 | Breakpoints.Add(bpt);
74 |
75 | bpt = Breakpoint();
76 | bpt.set_abs_bpt(libsgmain_base + 0x69D68);
77 | Breakpoints.Add(bpt);
78 |
79 | bpt = Breakpoint();
80 | bpt.set_abs_bpt(libsgmain_base + 0x197B4); // goto_do_DataReportJniBridgerer
81 | Breakpoints.Add(bpt);
82 |
83 | bpt = Breakpoint();
84 | bpt.set_abs_bpt(libsgmain_base + 0xE240);
85 | Breakpoints.Add(bpt);
86 |
87 | bpt = Breakpoint();
88 | bpt.set_abs_bpt(libsgmain_base + 0x9EE4);
89 | Breakpoints.Add(bpt);
90 |
91 | bpt = Breakpoint();
92 | bpt.set_abs_bpt(libsgmain_base + 0x71D68); // goto_do_SPUtility2
93 | Breakpoints.Add(bpt);
94 |
95 | bpt = Breakpoint();
96 | bpt.set_abs_bpt(libsgmain_base + 0xE7DC); // DeviceInfoCapturer
97 | Breakpoints.Add(bpt);
98 |
99 |
100 | bpt = Breakpoint();
101 | bpt.set_abs_bpt(libsgmain_base + 0xB8B0);
102 | Breakpoints.Add(bpt);
103 |
104 | bpt = Breakpoint();
105 | bpt.set_abs_bpt(libsgmain_base + 0x5F0F4);
106 | Breakpoints.Add(bpt);
107 |
108 | bpt = Breakpoint();
109 | bpt.set_abs_bpt(libsgmain_base + 0x70640);
110 | Breakpoints.Add(bpt);
111 |
112 | bpt = Breakpoint();
113 | bpt.set_abs_bpt(libsgmain_base + 0x11F3C); // android 原生類處理, context pm pkgmgr appinfo
114 | Breakpoints.Add(bpt);
115 |
116 |
117 | bpt = Breakpoint();
118 | bpt.set_abs_bpt(libsgmain_base + 0x21C3C);
119 | Breakpoints.Add(bpt);
120 |
121 | bpt = Breakpoint();
122 | bpt.set_abs_bpt(libsgmain_base + 0x2148C);
123 | Breakpoints.Add(bpt);
124 |
125 | bpt = Breakpoint();
126 | bpt.set_abs_bpt(libsgmain_base + 0x210E0);
127 | Breakpoints.Add(bpt);
128 |
129 | bpt = Breakpoint();
130 | bpt.set_abs_bpt(libsgmain_base + 0x41B58);
131 | Breakpoints.Add(bpt);
132 |
133 | bpt = Breakpoint();
134 | bpt.set_abs_bpt(libsgmain_base + 0x27920);
135 | Breakpoints.Add(bpt);
136 |
137 |
138 | bpt = Breakpoint();
139 | bpt.set_abs_bpt(libsgmain_base + 0x29918);
140 | Breakpoints.Add(bpt);
141 |
142 | bpt = Breakpoint();
143 | bpt.set_abs_bpt(libsgmain_base + 0x293E8); // unZip android pm appinfo
144 | Breakpoints.Add(bpt);
145 |
146 | bpt = Breakpoint();
147 | bpt.set_abs_bpt(libsgmain_base + 0x208F4); // do UserTrackMethodJniBridge
148 | Breakpoints.Add(bpt);
149 |
150 | bpt = Breakpoint();
151 | bpt.set_abs_bpt(libsgmain_base + 0xB7B0); // env->registerNatives
152 | Breakpoints.Add(bpt);
153 |
154 | bpt = Breakpoint();
155 | bpt.set_abs_bpt(libsgmain_base + 0xB69C); // doCommandNative
156 | Breakpoints.Add(bpt);
157 |
158 | bpt = Breakpoint();
159 | bpt.set_abs_bpt(libsgmain_base + 0x9D60); // goto_docommand_native_inner
160 | Breakpoints.Add(bpt);
161 |
162 | }
163 |
--------------------------------------------------------------------------------
/libsg6.4.176/libsgmainso-6.4.176.txt:
--------------------------------------------------------------------------------
1 | libsgmainso-6.4.176分析:
2 |
3 | libsgmain.so是一个apk,其中com.alibaba.wireless.security.mainplugin.SecurityGuardMainPlugin
4 | 类中加载真正的libsgmainso-6.4.176.so
5 |
6 |
7 | # libsgmain.so 被做了处理, section表失效
8 | 1、尝试修复,通过dynamic段信息进行section节修复,我修复了一个版本,不过有两三个节存在问题,特别是data,不过ida能加载。
9 | 2、可以通过010 editor把section 节个数设为0,这样ida可以通过段加载。
10 | 修复后可以静态先看看,我们可以发现此版本较libsgmainso-6.3.80版本变化挺大,libsgmainso-6.3.80版本里面的大量的跳转逻辑
11 | 不见了,可能是性能考虑吧, 觉得之前的版本比较恶心。
12 |
13 |
14 | # 有几种比较好的办法尝试逆向
15 | 1、尝试手动加载so,先逆向跑跑看
16 | 2、找一个集成该sdk的app,进行调试,注意最好这个app本身没什么防护,否则你要花特别多的时间在对抗app上。
17 | 3、同2,可以通过frida hook art::JNI::RegisterNatives(_JNIEnv *, _jclass *, JNINativeMethod const*, int) 把注册的
18 | doCommandNative对应的地址打印出来,然后通过加载地址和base计算得到文件偏移,静态看一看;libsgmainso-6.3.80版本
19 | 对应文件偏移的指令没法看,应该做了处理。
20 |
21 | # 加载段地址, 后面可能对不上,忘记这是第几次调试拷贝下来的了
22 | libsgmainso_6.4.176.so B3B25000 B3BD5000 R . X D . byte 00 public CODE 32 00 00
23 | libsgmainso_6.4.176.so B3BD5000 B3BD8000 R . . . . byte 00 public CONST 32 00 00
24 | libsgmainso_6.4.176.so B3BD8000 B3BF3000 R W . . . byte 00 public DATA 32 00 00
25 |
26 | # 分析:
27 | # init_array 没有逻辑
28 | 我手机linker调用init_array 导出函数 __dl__ZN6soinfo9CallArrayEPKcPPFvvEjb B6F97AC8
29 | 但该so没有init_array为空
30 |
31 |
32 | # call jni_onload
33 | ## 首先初始化了 三个全局jobject (Boolean, Integer, String)
34 |
35 | 首先肯定用了llvm混淆指令平坦化
36 |
37 | sub_8D194被我改名为createGlobalBoolean_Integer_String
38 | 详细见createGlobalBoolean_Integer_String.c
39 | r0 = javavm
40 | r1 = [stack]:BEBED5E8 DCD 0
41 | r2 = 0x10004
42 | r3 = art::CheckJII::GetEnv(_JavaVM *, void **, int)
43 | 调用GetEnv获取env
44 | static jint GetEnv(JavaVM* vm, void** env, jint version) {
45 | ScopedCheck sc(vm, true, __FUNCTION__);
46 | sc.Check(true, "vpI", vm);
47 | return CHECK_JNI_EXIT("I", BaseVm(vm)->GetEnv(vm, env, version));
48 | }
49 |
50 | 调用FindClass(env, "java/lang/Boolean")
51 | 调用NewGlobalRef(env, BooleanObj)并保存它
52 | 调用FindClass(env, "java/lang/Integer")
53 | 调用NewGlobalRef(env, Integer)并保存它
54 | 调用FindClass(env, "java/lang/String")
55 | 调用NewGlobalRef(env, String)并保存它
56 |
57 | # 拉了一块,后面在补
58 | libart.so:B4DD560E BLX R7 ; // 对应文件偏移1e660e
59 | //TODO 落下一点东西,操作一个栈变量,没细看
60 |
61 | [stack]:BEC335E0 DCD 0xA3FADAB9
62 | [stack]:BEC335E4 DCD 0x53
63 | [stack]:BEC335E8 DCD 0x22
64 | [stack]:BEC335EC DCD 0x9FEE1FCD
65 | [stack]:BEC335F0 DCD 1
66 | [stack]:BEC335F4 DCD 0xB4F7D200
67 | [stack]:BEC335F8 DCD 0xA3FD44EF
68 | [stack]:BEC335FC DCD 0xE8
69 | [stack]:BEC33600 DCD 0xD3
70 | [stack]:BEC33604 DCD 0x43
71 | [stack]:BEC33608 DCD 0xB4F53DC0
72 | [stack]:BEC3360C DCD 0
73 | [stack]:BEC33610 DCD 0xBEC33650
74 | [stack]:BEC33614 DCD 0xA3F373A7
75 | [stack]:BEC33618 DCD 0
76 | [stack]:BEC3361C DCD 0
77 | [stack]:BEC33620 DCD 0
78 | [stack]:BEC33624 DCD 0x9D
79 | [stack]:BEC33628 DCD 0x16
80 | [stack]:BEC3362C DCD 0x9FEE1FCD
81 | [stack]:BEC33630 DCD 0xB4F07800
82 | [stack]:BEC33634 DCD 0xB4F07800
83 | [stack]:BEC33638 DCD 0xBEC33870
84 | [stack]:BEC3363C DCD 0xBEC33860
85 | [stack]:BEC33640 DCD 0xB4EFCA64
86 | [stack]:BEC33644 DCD 0x43
87 | [stack]:BEC33648 DCD 0xB4EFDAE0
88 | [stack]:BEC3364C DCD 0
89 | [stack]:BEC33650 DCD 0xBEC336A0
90 | [stack]:BEC33654 DCD 0xB126976F
91 | [stack]:BEC33658 DCD 0xAFE00284
92 | [stack]:BEC3365C DCD 0xA3F372E9
93 | [stack]:BEC33660 DCD 0x27
94 | [stack]:BEC33664 DCD 0xB126A711
95 | [stack]:BEC33668 DCB 0xD3 ;
96 | [stack]:BEC33669 DCB 0xA6 ;
97 | [stack]:BEC3366A DCB 0x26 ; &
98 | [stack]:BEC3366B DCB 0xB1 ;
99 |
100 | libsgmainso_6.4.176.so:A3FAD9C4 BLX R2 = FindClass
101 | com/taobao/wireless/security/adapter/common/HttpUtil
102 | 调用art::CheckJNI::NewGlobalRef(_JNIEnv *, _jobject *)创建HttpUtil的NewGlobalRef
103 | 后续逻辑就没了,因为vm中没有该class
104 | 解密出字符串"sendSyncHttpGetRequestBridge"
105 | 調用env->getStaticMethodID
106 | 解密出數據"sendSyncHttpPostRequestBridge"
107 | 在解密出"downloadFileBridge"
108 |
109 |
110 | # 进入解密
111 | .text:000849B6 BL sub_8586C ; r0 = 0x84ab8
112 | .text:000849B6 ; r1 = 见下面,好像这个函数没有参数
113 | .text:000849B6 ; r2 = 0x35
114 | .text:000849B6 ; r3 = 0x53
115 |
116 |
117 | libsgmainso_6.4.176.so:B3BB15D0 (我给重命名为create_vdata(int len))
118 | .text:000858BE BL sub_8C5D0 ; r0 = 0x11
119 | .text:000858BE ; r1
120 | .text:000858BE ; r2 = 0x858b9
121 | .text:000858BE ; r3 = 0x5a
122 |
123 | debug014:ACC1CFC8 DCB 0 ; mallocA
124 | ma = malloc(0x38); // 56个字节大小的内存
125 | memset((char*) (ma + 4), 0, 0x34);
126 | debug120:A40082F8 DCB 0x6C ; l ; mallocb
127 | mb = malloc(0x11); // 传入大小
128 | memset(mb, 0, 0x11);
129 | ma = 0xA40082F8 = mb;
130 | ma + 0x4 = 0;
131 | ma + 0x8 = 0x11; // 即mb大小
132 | ma + 0xc = 0x8c34d; (一个函数起始地址)
133 | ma + 0x10 = 0x8c4d2;(一个函数起始地址)
134 | ma + 0x14 = 0x8c392;(一个函数起始地址)
135 | ma + 0x18 = 0x8c3f4;(一个函数起始地址)
136 | ma + 0x1c = 0x8c412(一个函数起始地址)
137 | ma + 0x20 = 0x8c44a
138 | ma + 0x24 = 0x8c468
139 | ma + 0x28 = 0x8c4ac
140 | ma + 0x2c = 0x8c500
141 | ma + 0x30 = 0x8c512
142 | ma + 0x34 = 0x8c528
143 | 对应结构体如下:
144 | struct data {
145 | char* d;
146 | };
147 |
148 | struct vdata{
149 | struct data* data;
150 | int data_len;
151 | int data_mlen; // = len + 1
152 | void* f1;
153 | void* f2;
154 | void* f3;
155 | void* f4;
156 | void* f5;
157 | void* f6;
158 | void* f7;
159 | void* f8;
160 | void* f9;
161 | void* f10;
162 | void* f11;
163 | };
164 |
165 | 跳转到跳转到0x858c2处继续执行
166 | ///////////////////////////////////////////////////////////////////////////////////////
167 | 后继续执行libsgmainso_6.4.176.so:B3BB15D0 create_vdata(我给重命名为create_vdata,见逆向代码create_vdata)
168 | debug024:AD3A1858 DCB 0 ; mmaloca
169 | mma
170 | debug024:AD3A1970 DCB 0 ; mmallocb
171 | mmb
172 | ////////////////////////////////////////////////////////////////////////////////////////
173 | libsgmainso_6.4.176.so:B3BAA91C BLX R3
174 | r0 = ma = debug014:ACC1CFC8 DCD 0xA40082F8 ; mallocA
175 | r1 = libsgmainso_6.4.176.so:B3BAAA48 aDcoLckHM3cQ DCB "DcO/lcK+h?m3c*q@",0
176 | r2 = 0x10
177 | blx rx = libsgmainso_6.4.176.so:B3BB134C sub_B3BB134C 被我重命名为 make_data
178 | 详细见make_data.c
179 | 第一次执行
180 | va = ma + 4 = 0;
181 | vb = ma + 8 = 0x11
182 | memcpy(mb, r1, 0x10); mb = "DcO/lcK+h?m3c*q@" // 分析是rc4的初始key
183 | ma + 4 = 0x10
184 |
185 | 对应调试内存
186 | debug014:ACC1CFC8 DCD 0xA40082F8 ; mallocA
187 | debug014:ACC1CFCC DCD 0x10
188 | debug014:ACC1CFD0 DCD 0x11
189 | debug014:ACC1CFD4 DCD 0xB3BB134D
190 | debug014:ACC1CFD8 DCD 0xB3BB14D3
191 | debug014:ACC1CFDC DCD 0xB3BB1393
192 | debug014:ACC1CFE0 DCD 0xB3BB13F5
193 | debug014:ACC1CFE4 DCD 0xB3BB1413
194 | debug014:ACC1CFE8 DCD 0xB3BB144B
195 | debug014:ACC1CFEC DCD 0xB3BB1469
196 | debug014:ACC1CFF0 DCD 0xB3BB14AD
197 | debug014:ACC1CFF4 DCD 0xB3BB1501
198 | debug014:ACC1CFF8 DCD 0xB3BB1513
199 | debug014:ACC1CFFC DCD 0xB3BB1529
200 | //////////////////////////////////////////////////////////////////////////////////////
201 | libsgmainso_6.4.176.so:B3BAA968 MOV R4, R1走到这里对应文件0x85968
202 | 对栈[stack]:BEC335A8 DCD memset,长度232个字节,memset(BEC335A8, 0x35, 0xe8)
203 | 对栈[stack]:BEC335A8 DCD memset,长度21个字节,memset(BEC335A8, 0, 0x15)
204 |
205 | 继续执行libsgmainso_6.4.176.so:B3BAA98A BLX R3,实际是跳转到make_data
206 | r0 = mma = debug024:AD3A1858 DCB 0x70 ; mmaloca
207 | ===========================================================================
208 | .text:00084AB9 DCD 0x3D21A7F9
209 | .text:00084ABD DCD 0x77FE3E8C
210 | .text:00084AC1 DCD 0x2ADB4018
211 | .text:00084AC5 DCD 0xF9C54AAD
212 | .text:00084AC9 DCD 0x547556A1
213 | .text:00084ACD DCD 0xA6C7BE23
214 | .text:00084AD1 DCD 0x8EEC357A
215 | .text:00084AD5 DCD 0x117405B2
216 | .text:00084AD9 DCD 0x6E7F5893
217 | .text:00084ADD DCD 0x9D4FE33A
218 | .text:00084AE1 DCD 0x6B7E0354
219 | .text:00084AE5 DCD 0xE35B1BFA
220 | .text:00084AE9 DCD 0xF902C1F8
221 | ==========================================================================
222 | r1 = libsgmainso_6.4.176.so:B3BA9AB9 loc_B3BA9AB8 ,对应文件偏移0x84AB9
223 | r2 = 0x34,52个字节
224 |
225 | va = ma + 4 = 0;
226 | vb = ma + 8 = 0x35
227 | memcpy(mb, r1, 0x10); mmb = B3BA9AB9
228 | ma + 4 = 0x34
229 |
230 | 对应测试内存
231 | debug024:AD3A1858 DCD 0xAD3A1970 ; mmaloca
232 | debug024:AD3A185C DCD 0x34
233 | debug024:AD3A1860 DCD 0x35
234 | debug024:AD3A1864 DCD 0xB3BB134D
235 | debug024:AD3A1868 DCD 0xB3BB14D3
236 | debug024:AD3A186C DCD 0xB3BB1393
237 | debug024:AD3A1870 DCD 0xB3BB13F5
238 | debug024:AD3A1874 DCD 0xB3BB1413
239 | debug024:AD3A1878 DCD 0xB3BB144B
240 | debug024:AD3A187C DCD 0xB3BB1469
241 | debug024:AD3A1880 DCD 0xB3BB14AD
242 | debug024:AD3A1884 DCD 0xB3BB1501
243 | debug024:AD3A1888 DCD 0xB3BB1513
244 | debug024:AD3A188C DCD 0xB3BB1529
245 |
246 | 继续进入.text:00074FEC sub_74FEC
247 | libsgmainso_6.4.176.so:B3BAA9A4 BL sub_B3B99FEC, 被我重命名为decrypto
248 | 详细见decrypto.c
249 | 传递两个参数(一个代表待解密结构体,一个代表返回码),应该是解密算法,内置n种解密算法如rc4、解压缩等
250 | r0 = BEC33560
251 | r1 = BEC3357C
252 |
253 | 先进入case 3:
254 | 被我重命名为call_rc4,详细见逆向的代码;
255 | 里面实际上就是调用了rc4算法解密,上面的mma数据(mma未被解密,而是重新拷贝一个结构体用于解密)
256 | r0 = ma = ACC1CFC8, r1 = mma = AD3A1858
257 |
258 | 首先创建vdatac拷贝mma数据内容
259 | debug120:A41BB158 DCB 0x20 ; vdatac
260 | debug120:A41BB120 DCB 0 ; decryptedata
261 | [stack]:BEC333F8 DCB 0 ; swapkey
262 | char buf[264];
263 | memset(buf, 0, 264); // 实际只用256,算法里面是buf+8开始的
264 | init_rc4key(swapkey, vdata->data, vata->data_len);
265 | rc4_(swapkey, cryptedata->data_len, cryptedata->data, decrypted_data->data);
266 | 解密后字符串
267 | com/taobao/wireless/security/adapter/umid/UmidAdapter
268 |
269 | 继续执行到
270 | libsgmainso_6.4.176.so:A40AA9D0 BX R10 = A40AA9E9
271 | 执行memcpy把解密字符串拷贝到栈上
272 | libsgmainso_6.4.176.so:A40AA9FC LDR R0, [SP,#8]
273 | libsgmainso_6.4.176.so:A40AA9FE BLX memcpy
274 | [stack]:BEC335A8 DCB 0
275 |
276 | 执行free把之前解密的数据释放掉
277 | libsgmainso_6.4.176.so:A40AAA06 BL free__
278 | 继续free掉之前的vdata结构体
279 |
280 | com/taobao/wireless/security/adapter/umid/UmidAdapter这个类也没有,又遇到上面提到的问题
281 | 調用env->findclass找到UmidAdapterClass,調用env->NewGlobalRef UmidAdapterRef
282 | 調用env->DeleteLocalRef, 刪除UmidAdapterClass,wtf?
283 | BL goto_decrypt_entry(, , 16)
284 | 解密出"umidInitAdapter"
285 | 調用env->getStaticMethodID(UmidAdapterRef, "umidInitAdapter")
286 | 繼續解密出"com/taobao/wireless/security/adapter/JNICLibrary"
287 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | GNU GENERAL PUBLIC LICENSE
2 | Version 3, 29 June 2007
3 |
4 | Copyright (C) 2007 Free Software Foundation, Inc.
5 | Everyone is permitted to copy and distribute verbatim copies
6 | of this license document, but changing it is not allowed.
7 |
8 | Preamble
9 |
10 | The GNU General Public License is a free, copyleft license for
11 | software and other kinds of works.
12 |
13 | The licenses for most software and other practical works are designed
14 | to take away your freedom to share and change the works. By contrast,
15 | the GNU General Public License is intended to guarantee your freedom to
16 | share and change all versions of a program--to make sure it remains free
17 | software for all its users. We, the Free Software Foundation, use the
18 | GNU General Public License for most of our software; it applies also to
19 | any other work released this way by its authors. You can apply it to
20 | your programs, too.
21 |
22 | When we speak of free software, we are referring to freedom, not
23 | price. Our General Public Licenses are designed to make sure that you
24 | have the freedom to distribute copies of free software (and charge for
25 | them if you wish), that you receive source code or can get it if you
26 | want it, that you can change the software or use pieces of it in new
27 | free programs, and that you know you can do these things.
28 |
29 | To protect your rights, we need to prevent others from denying you
30 | these rights or asking you to surrender the rights. Therefore, you have
31 | certain responsibilities if you distribute copies of the software, or if
32 | you modify it: responsibilities to respect the freedom of others.
33 |
34 | For example, if you distribute copies of such a program, whether
35 | gratis or for a fee, you must pass on to the recipients the same
36 | freedoms that you received. You must make sure that they, too, receive
37 | or can get the source code. And you must show them these terms so they
38 | know their rights.
39 |
40 | Developers that use the GNU GPL protect your rights with two steps:
41 | (1) assert copyright on the software, and (2) offer you this License
42 | giving you legal permission to copy, distribute and/or modify it.
43 |
44 | For the developers' and authors' protection, the GPL clearly explains
45 | that there is no warranty for this free software. For both users' and
46 | authors' sake, the GPL requires that modified versions be marked as
47 | changed, so that their problems will not be attributed erroneously to
48 | authors of previous versions.
49 |
50 | Some devices are designed to deny users access to install or run
51 | modified versions of the software inside them, although the manufacturer
52 | can do so. This is fundamentally incompatible with the aim of
53 | protecting users' freedom to change the software. The systematic
54 | pattern of such abuse occurs in the area of products for individuals to
55 | use, which is precisely where it is most unacceptable. Therefore, we
56 | have designed this version of the GPL to prohibit the practice for those
57 | products. If such problems arise substantially in other domains, we
58 | stand ready to extend this provision to those domains in future versions
59 | of the GPL, as needed to protect the freedom of users.
60 |
61 | Finally, every program is threatened constantly by software patents.
62 | States should not allow patents to restrict development and use of
63 | software on general-purpose computers, but in those that do, we wish to
64 | avoid the special danger that patents applied to a free program could
65 | make it effectively proprietary. To prevent this, the GPL assures that
66 | patents cannot be used to render the program non-free.
67 |
68 | The precise terms and conditions for copying, distribution and
69 | modification follow.
70 |
71 | TERMS AND CONDITIONS
72 |
73 | 0. Definitions.
74 |
75 | "This License" refers to version 3 of the GNU General Public License.
76 |
77 | "Copyright" also means copyright-like laws that apply to other kinds of
78 | works, such as semiconductor masks.
79 |
80 | "The Program" refers to any copyrightable work licensed under this
81 | License. Each licensee is addressed as "you". "Licensees" and
82 | "recipients" may be individuals or organizations.
83 |
84 | To "modify" a work means to copy from or adapt all or part of the work
85 | in a fashion requiring copyright permission, other than the making of an
86 | exact copy. The resulting work is called a "modified version" of the
87 | earlier work or a work "based on" the earlier work.
88 |
89 | A "covered work" means either the unmodified Program or a work based
90 | on the Program.
91 |
92 | To "propagate" a work means to do anything with it that, without
93 | permission, would make you directly or secondarily liable for
94 | infringement under applicable copyright law, except executing it on a
95 | computer or modifying a private copy. Propagation includes copying,
96 | distribution (with or without modification), making available to the
97 | public, and in some countries other activities as well.
98 |
99 | To "convey" a work means any kind of propagation that enables other
100 | parties to make or receive copies. Mere interaction with a user through
101 | a computer network, with no transfer of a copy, is not conveying.
102 |
103 | An interactive user interface displays "Appropriate Legal Notices"
104 | to the extent that it includes a convenient and prominently visible
105 | feature that (1) displays an appropriate copyright notice, and (2)
106 | tells the user that there is no warranty for the work (except to the
107 | extent that warranties are provided), that licensees may convey the
108 | work under this License, and how to view a copy of this License. If
109 | the interface presents a list of user commands or options, such as a
110 | menu, a prominent item in the list meets this criterion.
111 |
112 | 1. Source Code.
113 |
114 | The "source code" for a work means the preferred form of the work
115 | for making modifications to it. "Object code" means any non-source
116 | form of a work.
117 |
118 | A "Standard Interface" means an interface that either is an official
119 | standard defined by a recognized standards body, or, in the case of
120 | interfaces specified for a particular programming language, one that
121 | is widely used among developers working in that language.
122 |
123 | The "System Libraries" of an executable work include anything, other
124 | than the work as a whole, that (a) is included in the normal form of
125 | packaging a Major Component, but which is not part of that Major
126 | Component, and (b) serves only to enable use of the work with that
127 | Major Component, or to implement a Standard Interface for which an
128 | implementation is available to the public in source code form. A
129 | "Major Component", in this context, means a major essential component
130 | (kernel, window system, and so on) of the specific operating system
131 | (if any) on which the executable work runs, or a compiler used to
132 | produce the work, or an object code interpreter used to run it.
133 |
134 | The "Corresponding Source" for a work in object code form means all
135 | the source code needed to generate, install, and (for an executable
136 | work) run the object code and to modify the work, including scripts to
137 | control those activities. However, it does not include the work's
138 | System Libraries, or general-purpose tools or generally available free
139 | programs which are used unmodified in performing those activities but
140 | which are not part of the work. For example, Corresponding Source
141 | includes interface definition files associated with source files for
142 | the work, and the source code for shared libraries and dynamically
143 | linked subprograms that the work is specifically designed to require,
144 | such as by intimate data communication or control flow between those
145 | subprograms and other parts of the work.
146 |
147 | The Corresponding Source need not include anything that users
148 | can regenerate automatically from other parts of the Corresponding
149 | Source.
150 |
151 | The Corresponding Source for a work in source code form is that
152 | same work.
153 |
154 | 2. Basic Permissions.
155 |
156 | All rights granted under this License are granted for the term of
157 | copyright on the Program, and are irrevocable provided the stated
158 | conditions are met. This License explicitly affirms your unlimited
159 | permission to run the unmodified Program. The output from running a
160 | covered work is covered by this License only if the output, given its
161 | content, constitutes a covered work. This License acknowledges your
162 | rights of fair use or other equivalent, as provided by copyright law.
163 |
164 | You may make, run and propagate covered works that you do not
165 | convey, without conditions so long as your license otherwise remains
166 | in force. You may convey covered works to others for the sole purpose
167 | of having them make modifications exclusively for you, or provide you
168 | with facilities for running those works, provided that you comply with
169 | the terms of this License in conveying all material for which you do
170 | not control copyright. Those thus making or running the covered works
171 | for you must do so exclusively on your behalf, under your direction
172 | and control, on terms that prohibit them from making any copies of
173 | your copyrighted material outside their relationship with you.
174 |
175 | Conveying under any other circumstances is permitted solely under
176 | the conditions stated below. Sublicensing is not allowed; section 10
177 | makes it unnecessary.
178 |
179 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
180 |
181 | No covered work shall be deemed part of an effective technological
182 | measure under any applicable law fulfilling obligations under article
183 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or
184 | similar laws prohibiting or restricting circumvention of such
185 | measures.
186 |
187 | When you convey a covered work, you waive any legal power to forbid
188 | circumvention of technological measures to the extent such circumvention
189 | is effected by exercising rights under this License with respect to
190 | the covered work, and you disclaim any intention to limit operation or
191 | modification of the work as a means of enforcing, against the work's
192 | users, your or third parties' legal rights to forbid circumvention of
193 | technological measures.
194 |
195 | 4. Conveying Verbatim Copies.
196 |
197 | You may convey verbatim copies of the Program's source code as you
198 | receive it, in any medium, provided that you conspicuously and
199 | appropriately publish on each copy an appropriate copyright notice;
200 | keep intact all notices stating that this License and any
201 | non-permissive terms added in accord with section 7 apply to the code;
202 | keep intact all notices of the absence of any warranty; and give all
203 | recipients a copy of this License along with the Program.
204 |
205 | You may charge any price or no price for each copy that you convey,
206 | and you may offer support or warranty protection for a fee.
207 |
208 | 5. Conveying Modified Source Versions.
209 |
210 | You may convey a work based on the Program, or the modifications to
211 | produce it from the Program, in the form of source code under the
212 | terms of section 4, provided that you also meet all of these conditions:
213 |
214 | a) The work must carry prominent notices stating that you modified
215 | it, and giving a relevant date.
216 |
217 | b) The work must carry prominent notices stating that it is
218 | released under this License and any conditions added under section
219 | 7. This requirement modifies the requirement in section 4 to
220 | "keep intact all notices".
221 |
222 | c) You must license the entire work, as a whole, under this
223 | License to anyone who comes into possession of a copy. This
224 | License will therefore apply, along with any applicable section 7
225 | additional terms, to the whole of the work, and all its parts,
226 | regardless of how they are packaged. This License gives no
227 | permission to license the work in any other way, but it does not
228 | invalidate such permission if you have separately received it.
229 |
230 | d) If the work has interactive user interfaces, each must display
231 | Appropriate Legal Notices; however, if the Program has interactive
232 | interfaces that do not display Appropriate Legal Notices, your
233 | work need not make them do so.
234 |
235 | A compilation of a covered work with other separate and independent
236 | works, which are not by their nature extensions of the covered work,
237 | and which are not combined with it such as to form a larger program,
238 | in or on a volume of a storage or distribution medium, is called an
239 | "aggregate" if the compilation and its resulting copyright are not
240 | used to limit the access or legal rights of the compilation's users
241 | beyond what the individual works permit. Inclusion of a covered work
242 | in an aggregate does not cause this License to apply to the other
243 | parts of the aggregate.
244 |
245 | 6. Conveying Non-Source Forms.
246 |
247 | You may convey a covered work in object code form under the terms
248 | of sections 4 and 5, provided that you also convey the
249 | machine-readable Corresponding Source under the terms of this License,
250 | in one of these ways:
251 |
252 | a) Convey the object code in, or embodied in, a physical product
253 | (including a physical distribution medium), accompanied by the
254 | Corresponding Source fixed on a durable physical medium
255 | customarily used for software interchange.
256 |
257 | b) Convey the object code in, or embodied in, a physical product
258 | (including a physical distribution medium), accompanied by a
259 | written offer, valid for at least three years and valid for as
260 | long as you offer spare parts or customer support for that product
261 | model, to give anyone who possesses the object code either (1) a
262 | copy of the Corresponding Source for all the software in the
263 | product that is covered by this License, on a durable physical
264 | medium customarily used for software interchange, for a price no
265 | more than your reasonable cost of physically performing this
266 | conveying of source, or (2) access to copy the
267 | Corresponding Source from a network server at no charge.
268 |
269 | c) Convey individual copies of the object code with a copy of the
270 | written offer to provide the Corresponding Source. This
271 | alternative is allowed only occasionally and noncommercially, and
272 | only if you received the object code with such an offer, in accord
273 | with subsection 6b.
274 |
275 | d) Convey the object code by offering access from a designated
276 | place (gratis or for a charge), and offer equivalent access to the
277 | Corresponding Source in the same way through the same place at no
278 | further charge. You need not require recipients to copy the
279 | Corresponding Source along with the object code. If the place to
280 | copy the object code is a network server, the Corresponding Source
281 | may be on a different server (operated by you or a third party)
282 | that supports equivalent copying facilities, provided you maintain
283 | clear directions next to the object code saying where to find the
284 | Corresponding Source. Regardless of what server hosts the
285 | Corresponding Source, you remain obligated to ensure that it is
286 | available for as long as needed to satisfy these requirements.
287 |
288 | e) Convey the object code using peer-to-peer transmission, provided
289 | you inform other peers where the object code and Corresponding
290 | Source of the work are being offered to the general public at no
291 | charge under subsection 6d.
292 |
293 | A separable portion of the object code, whose source code is excluded
294 | from the Corresponding Source as a System Library, need not be
295 | included in conveying the object code work.
296 |
297 | A "User Product" is either (1) a "consumer product", which means any
298 | tangible personal property which is normally used for personal, family,
299 | or household purposes, or (2) anything designed or sold for incorporation
300 | into a dwelling. In determining whether a product is a consumer product,
301 | doubtful cases shall be resolved in favor of coverage. For a particular
302 | product received by a particular user, "normally used" refers to a
303 | typical or common use of that class of product, regardless of the status
304 | of the particular user or of the way in which the particular user
305 | actually uses, or expects or is expected to use, the product. A product
306 | is a consumer product regardless of whether the product has substantial
307 | commercial, industrial or non-consumer uses, unless such uses represent
308 | the only significant mode of use of the product.
309 |
310 | "Installation Information" for a User Product means any methods,
311 | procedures, authorization keys, or other information required to install
312 | and execute modified versions of a covered work in that User Product from
313 | a modified version of its Corresponding Source. The information must
314 | suffice to ensure that the continued functioning of the modified object
315 | code is in no case prevented or interfered with solely because
316 | modification has been made.
317 |
318 | If you convey an object code work under this section in, or with, or
319 | specifically for use in, a User Product, and the conveying occurs as
320 | part of a transaction in which the right of possession and use of the
321 | User Product is transferred to the recipient in perpetuity or for a
322 | fixed term (regardless of how the transaction is characterized), the
323 | Corresponding Source conveyed under this section must be accompanied
324 | by the Installation Information. But this requirement does not apply
325 | if neither you nor any third party retains the ability to install
326 | modified object code on the User Product (for example, the work has
327 | been installed in ROM).
328 |
329 | The requirement to provide Installation Information does not include a
330 | requirement to continue to provide support service, warranty, or updates
331 | for a work that has been modified or installed by the recipient, or for
332 | the User Product in which it has been modified or installed. Access to a
333 | network may be denied when the modification itself materially and
334 | adversely affects the operation of the network or violates the rules and
335 | protocols for communication across the network.
336 |
337 | Corresponding Source conveyed, and Installation Information provided,
338 | in accord with this section must be in a format that is publicly
339 | documented (and with an implementation available to the public in
340 | source code form), and must require no special password or key for
341 | unpacking, reading or copying.
342 |
343 | 7. Additional Terms.
344 |
345 | "Additional permissions" are terms that supplement the terms of this
346 | License by making exceptions from one or more of its conditions.
347 | Additional permissions that are applicable to the entire Program shall
348 | be treated as though they were included in this License, to the extent
349 | that they are valid under applicable law. If additional permissions
350 | apply only to part of the Program, that part may be used separately
351 | under those permissions, but the entire Program remains governed by
352 | this License without regard to the additional permissions.
353 |
354 | When you convey a copy of a covered work, you may at your option
355 | remove any additional permissions from that copy, or from any part of
356 | it. (Additional permissions may be written to require their own
357 | removal in certain cases when you modify the work.) You may place
358 | additional permissions on material, added by you to a covered work,
359 | for which you have or can give appropriate copyright permission.
360 |
361 | Notwithstanding any other provision of this License, for material you
362 | add to a covered work, you may (if authorized by the copyright holders of
363 | that material) supplement the terms of this License with terms:
364 |
365 | a) Disclaiming warranty or limiting liability differently from the
366 | terms of sections 15 and 16 of this License; or
367 |
368 | b) Requiring preservation of specified reasonable legal notices or
369 | author attributions in that material or in the Appropriate Legal
370 | Notices displayed by works containing it; or
371 |
372 | c) Prohibiting misrepresentation of the origin of that material, or
373 | requiring that modified versions of such material be marked in
374 | reasonable ways as different from the original version; or
375 |
376 | d) Limiting the use for publicity purposes of names of licensors or
377 | authors of the material; or
378 |
379 | e) Declining to grant rights under trademark law for use of some
380 | trade names, trademarks, or service marks; or
381 |
382 | f) Requiring indemnification of licensors and authors of that
383 | material by anyone who conveys the material (or modified versions of
384 | it) with contractual assumptions of liability to the recipient, for
385 | any liability that these contractual assumptions directly impose on
386 | those licensors and authors.
387 |
388 | All other non-permissive additional terms are considered "further
389 | restrictions" within the meaning of section 10. If the Program as you
390 | received it, or any part of it, contains a notice stating that it is
391 | governed by this License along with a term that is a further
392 | restriction, you may remove that term. If a license document contains
393 | a further restriction but permits relicensing or conveying under this
394 | License, you may add to a covered work material governed by the terms
395 | of that license document, provided that the further restriction does
396 | not survive such relicensing or conveying.
397 |
398 | If you add terms to a covered work in accord with this section, you
399 | must place, in the relevant source files, a statement of the
400 | additional terms that apply to those files, or a notice indicating
401 | where to find the applicable terms.
402 |
403 | Additional terms, permissive or non-permissive, may be stated in the
404 | form of a separately written license, or stated as exceptions;
405 | the above requirements apply either way.
406 |
407 | 8. Termination.
408 |
409 | You may not propagate or modify a covered work except as expressly
410 | provided under this License. Any attempt otherwise to propagate or
411 | modify it is void, and will automatically terminate your rights under
412 | this License (including any patent licenses granted under the third
413 | paragraph of section 11).
414 |
415 | However, if you cease all violation of this License, then your
416 | license from a particular copyright holder is reinstated (a)
417 | provisionally, unless and until the copyright holder explicitly and
418 | finally terminates your license, and (b) permanently, if the copyright
419 | holder fails to notify you of the violation by some reasonable means
420 | prior to 60 days after the cessation.
421 |
422 | Moreover, your license from a particular copyright holder is
423 | reinstated permanently if the copyright holder notifies you of the
424 | violation by some reasonable means, this is the first time you have
425 | received notice of violation of this License (for any work) from that
426 | copyright holder, and you cure the violation prior to 30 days after
427 | your receipt of the notice.
428 |
429 | Termination of your rights under this section does not terminate the
430 | licenses of parties who have received copies or rights from you under
431 | this License. If your rights have been terminated and not permanently
432 | reinstated, you do not qualify to receive new licenses for the same
433 | material under section 10.
434 |
435 | 9. Acceptance Not Required for Having Copies.
436 |
437 | You are not required to accept this License in order to receive or
438 | run a copy of the Program. Ancillary propagation of a covered work
439 | occurring solely as a consequence of using peer-to-peer transmission
440 | to receive a copy likewise does not require acceptance. However,
441 | nothing other than this License grants you permission to propagate or
442 | modify any covered work. These actions infringe copyright if you do
443 | not accept this License. Therefore, by modifying or propagating a
444 | covered work, you indicate your acceptance of this License to do so.
445 |
446 | 10. Automatic Licensing of Downstream Recipients.
447 |
448 | Each time you convey a covered work, the recipient automatically
449 | receives a license from the original licensors, to run, modify and
450 | propagate that work, subject to this License. You are not responsible
451 | for enforcing compliance by third parties with this License.
452 |
453 | An "entity transaction" is a transaction transferring control of an
454 | organization, or substantially all assets of one, or subdividing an
455 | organization, or merging organizations. If propagation of a covered
456 | work results from an entity transaction, each party to that
457 | transaction who receives a copy of the work also receives whatever
458 | licenses to the work the party's predecessor in interest had or could
459 | give under the previous paragraph, plus a right to possession of the
460 | Corresponding Source of the work from the predecessor in interest, if
461 | the predecessor has it or can get it with reasonable efforts.
462 |
463 | You may not impose any further restrictions on the exercise of the
464 | rights granted or affirmed under this License. For example, you may
465 | not impose a license fee, royalty, or other charge for exercise of
466 | rights granted under this License, and you may not initiate litigation
467 | (including a cross-claim or counterclaim in a lawsuit) alleging that
468 | any patent claim is infringed by making, using, selling, offering for
469 | sale, or importing the Program or any portion of it.
470 |
471 | 11. Patents.
472 |
473 | A "contributor" is a copyright holder who authorizes use under this
474 | License of the Program or a work on which the Program is based. The
475 | work thus licensed is called the contributor's "contributor version".
476 |
477 | A contributor's "essential patent claims" are all patent claims
478 | owned or controlled by the contributor, whether already acquired or
479 | hereafter acquired, that would be infringed by some manner, permitted
480 | by this License, of making, using, or selling its contributor version,
481 | but do not include claims that would be infringed only as a
482 | consequence of further modification of the contributor version. For
483 | purposes of this definition, "control" includes the right to grant
484 | patent sublicenses in a manner consistent with the requirements of
485 | this License.
486 |
487 | Each contributor grants you a non-exclusive, worldwide, royalty-free
488 | patent license under the contributor's essential patent claims, to
489 | make, use, sell, offer for sale, import and otherwise run, modify and
490 | propagate the contents of its contributor version.
491 |
492 | In the following three paragraphs, a "patent license" is any express
493 | agreement or commitment, however denominated, not to enforce a patent
494 | (such as an express permission to practice a patent or covenant not to
495 | sue for patent infringement). To "grant" such a patent license to a
496 | party means to make such an agreement or commitment not to enforce a
497 | patent against the party.
498 |
499 | If you convey a covered work, knowingly relying on a patent license,
500 | and the Corresponding Source of the work is not available for anyone
501 | to copy, free of charge and under the terms of this License, through a
502 | publicly available network server or other readily accessible means,
503 | then you must either (1) cause the Corresponding Source to be so
504 | available, or (2) arrange to deprive yourself of the benefit of the
505 | patent license for this particular work, or (3) arrange, in a manner
506 | consistent with the requirements of this License, to extend the patent
507 | license to downstream recipients. "Knowingly relying" means you have
508 | actual knowledge that, but for the patent license, your conveying the
509 | covered work in a country, or your recipient's use of the covered work
510 | in a country, would infringe one or more identifiable patents in that
511 | country that you have reason to believe are valid.
512 |
513 | If, pursuant to or in connection with a single transaction or
514 | arrangement, you convey, or propagate by procuring conveyance of, a
515 | covered work, and grant a patent license to some of the parties
516 | receiving the covered work authorizing them to use, propagate, modify
517 | or convey a specific copy of the covered work, then the patent license
518 | you grant is automatically extended to all recipients of the covered
519 | work and works based on it.
520 |
521 | A patent license is "discriminatory" if it does not include within
522 | the scope of its coverage, prohibits the exercise of, or is
523 | conditioned on the non-exercise of one or more of the rights that are
524 | specifically granted under this License. You may not convey a covered
525 | work if you are a party to an arrangement with a third party that is
526 | in the business of distributing software, under which you make payment
527 | to the third party based on the extent of your activity of conveying
528 | the work, and under which the third party grants, to any of the
529 | parties who would receive the covered work from you, a discriminatory
530 | patent license (a) in connection with copies of the covered work
531 | conveyed by you (or copies made from those copies), or (b) primarily
532 | for and in connection with specific products or compilations that
533 | contain the covered work, unless you entered into that arrangement,
534 | or that patent license was granted, prior to 28 March 2007.
535 |
536 | Nothing in this License shall be construed as excluding or limiting
537 | any implied license or other defenses to infringement that may
538 | otherwise be available to you under applicable patent law.
539 |
540 | 12. No Surrender of Others' Freedom.
541 |
542 | If conditions are imposed on you (whether by court order, agreement or
543 | otherwise) that contradict the conditions of this License, they do not
544 | excuse you from the conditions of this License. If you cannot convey a
545 | covered work so as to satisfy simultaneously your obligations under this
546 | License and any other pertinent obligations, then as a consequence you may
547 | not convey it at all. For example, if you agree to terms that obligate you
548 | to collect a royalty for further conveying from those to whom you convey
549 | the Program, the only way you could satisfy both those terms and this
550 | License would be to refrain entirely from conveying the Program.
551 |
552 | 13. Use with the GNU Affero General Public License.
553 |
554 | Notwithstanding any other provision of this License, you have
555 | permission to link or combine any covered work with a work licensed
556 | under version 3 of the GNU Affero General Public License into a single
557 | combined work, and to convey the resulting work. The terms of this
558 | License will continue to apply to the part which is the covered work,
559 | but the special requirements of the GNU Affero General Public License,
560 | section 13, concerning interaction through a network will apply to the
561 | combination as such.
562 |
563 | 14. Revised Versions of this License.
564 |
565 | The Free Software Foundation may publish revised and/or new versions of
566 | the GNU General Public License from time to time. Such new versions will
567 | be similar in spirit to the present version, but may differ in detail to
568 | address new problems or concerns.
569 |
570 | Each version is given a distinguishing version number. If the
571 | Program specifies that a certain numbered version of the GNU General
572 | Public License "or any later version" applies to it, you have the
573 | option of following the terms and conditions either of that numbered
574 | version or of any later version published by the Free Software
575 | Foundation. If the Program does not specify a version number of the
576 | GNU General Public License, you may choose any version ever published
577 | by the Free Software Foundation.
578 |
579 | If the Program specifies that a proxy can decide which future
580 | versions of the GNU General Public License can be used, that proxy's
581 | public statement of acceptance of a version permanently authorizes you
582 | to choose that version for the Program.
583 |
584 | Later license versions may give you additional or different
585 | permissions. However, no additional obligations are imposed on any
586 | author or copyright holder as a result of your choosing to follow a
587 | later version.
588 |
589 | 15. Disclaimer of Warranty.
590 |
591 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
592 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
593 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
594 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
595 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
596 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
597 | IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
598 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
599 |
600 | 16. Limitation of Liability.
601 |
602 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
603 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
604 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
605 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
606 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
607 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
608 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
609 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
610 | SUCH DAMAGES.
611 |
612 | 17. Interpretation of Sections 15 and 16.
613 |
614 | If the disclaimer of warranty and limitation of liability provided
615 | above cannot be given local legal effect according to their terms,
616 | reviewing courts shall apply local law that most closely approximates
617 | an absolute waiver of all civil liability in connection with the
618 | Program, unless a warranty or assumption of liability accompanies a
619 | copy of the Program in return for a fee.
620 |
621 | END OF TERMS AND CONDITIONS
622 |
623 | How to Apply These Terms to Your New Programs
624 |
625 | If you develop a new program, and you want it to be of the greatest
626 | possible use to the public, the best way to achieve this is to make it
627 | free software which everyone can redistribute and change under these terms.
628 |
629 | To do so, attach the following notices to the program. It is safest
630 | to attach them to the start of each source file to most effectively
631 | state the exclusion of warranty; and each file should have at least
632 | the "copyright" line and a pointer to where the full notice is found.
633 |
634 |
635 | Copyright (C)
636 |
637 | This program is free software: you can redistribute it and/or modify
638 | it under the terms of the GNU General Public License as published by
639 | the Free Software Foundation, either version 3 of the License, or
640 | (at your option) any later version.
641 |
642 | This program is distributed in the hope that it will be useful,
643 | but WITHOUT ANY WARRANTY; without even the implied warranty of
644 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
645 | GNU General Public License for more details.
646 |
647 | You should have received a copy of the GNU General Public License
648 | along with this program. If not, see .
649 |
650 | Also add information on how to contact you by electronic and paper mail.
651 |
652 | If the program does terminal interaction, make it output a short
653 | notice like this when it starts in an interactive mode:
654 |
655 | Copyright (C)
656 | This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
657 | This is free software, and you are welcome to redistribute it
658 | under certain conditions; type `show c' for details.
659 |
660 | The hypothetical commands `show w' and `show c' should show the appropriate
661 | parts of the General Public License. Of course, your program's commands
662 | might be different; for a GUI interface, you would use an "about box".
663 |
664 | You should also get your employer (if you work as a programmer) or school,
665 | if any, to sign a "copyright disclaimer" for the program, if necessary.
666 | For more information on this, and how to apply and follow the GNU GPL, see
667 | .
668 |
669 | The GNU General Public License does not permit incorporating your program
670 | into proprietary programs. If your program is a subroutine library, you
671 | may consider it more useful to permit linking proprietary applications with
672 | the library. If this is what you want to do, use the GNU Lesser General
673 | Public License instead of this License. But first, please read
674 | .
675 |
--------------------------------------------------------------------------------
/libsg6.4.36/libsgmainso-6.4.36分析:
--------------------------------------------------------------------------------
1 | libsgmainso-6.4.36邏輯分析
2 |
3 | //////////////////////////////////////////////////////////////
4 |
5 | 難點:
6 |
7 | 動態跳轉
8 | 動態生成參數,參數變形
9 | 函數隱藏(需要通過一個類似的梉跳過去,函數地址加密)
10 | 函數前面加一段垃圾代碼
11 | 字符串加密
12 | 部分關鍵代碼存在llvm混淆
13 | 垃圾代碼,靜態分析對抗,擾亂ida分析
14 | 多種加密算法
15 | 核心函數如進入到do_command_native的函數不是連續的,函數的連續性被記錄到一系列的
16 | 結構體中,下一個塊需要的獲取需要重新執行do_command_inner
17 |
18 |
19 | LOAD:0000B110 JNI_OnLoad
20 | LOAD:0000B110
21 | LOAD:0000B110 var_4 = -4
22 | LOAD:0000B110 07 B5 PUSH {R0-R2,LR}
23 | LOAD:0000B112 07 A1 ADR R1, 0xB130 // B130
24 | LOAD:0000B114 09 00 MOVS R1, R1
25 | LOAD:0000B116 05 39 SUBS R1, #5 // B130 - 0X5 = B12B
26 | LOAD:0000B118 00 00 MOVS R0, R0
27 | LOAD:0000B11A 08 00 MOVS R0, R1 // B12B
28 | LOAD:0000B11C 12 00 MOVS R2, R2
29 | LOAD:0000B11E 10 30 ADDS R0, #0x10 // B12B + 0X10 = B13B
30 | LOAD:0000B120 03 90 STR R0, [SP,#0xC] // SP + 0XC = R0 = B13B
31 | LOAD:0000B122 07 BD POP {R0-R2,PC} // PC = sp + 0xc = B13B, thumb指令跳转到0000B13A
32 |
33 | 执行完上述代码,r0,r1,r2,lr值不变,变的仅仅是pc,cpu会马上执行pc处的指令
34 |
35 | =================================================================================================
36 | 代码段共56处匹配这样的特征,想办法patch这样的逻辑
37 | patch 后
38 | LOAD:0000B110 JNI_OnLoad
39 | LOAD:0000B122 B loc_B13A
40 | ===================================================================================================
41 |
42 | 因为是thumb指令,地址起始奇数
43 | LOAD:0000B13A ; ---------------------------------------------------------------------------
44 | 特徵
45 | LOAD:0000B13A CODE16
46 | LOAD:0000B13A PUSH {R0,R1,LR}
47 | LOAD:0000B13C LDR R0, =8
48 | LOAD:0000B13E LDR R1, loc_B140 // 沒有意義, nop掉
49 | LOAD:0000B140
50 | LOAD:0000B140 loc_B140
51 | LOAD:0000B140 BLX sub_494C /// 分发器
52 | LOAD:0000B140 ; ---------------------------------------------------------------------------
53 | LOAD:0000B144 dword_B144 DCD 8
54 | -------------------------------------------------------------------------------------------
55 | 跳轉表,共40個跳轉, 計算pc時的纍加值:
56 | LOAD:0000B144
57 | LOAD:0000B144 ;第一個index = 8
58 | LOAD:0000B144 ; 找到8對應的偏移,它下一個index即下一個邏輯
59 | LOAD:0000B148 A8 00 00 00 DCD 0xA8 ; b1ec
60 | LOAD:0000B14C BC 00 00 00 DCD 0xBC ; b200
61 | LOAD:0000B150 CC 00 00 00 DCD 0xCC ; b120
62 | LOAD:0000B154 E0 00 00 00 DCD 0xE0 ; b224
63 | LOAD:0000B158 F0 00 00 00 DCD 0xF0 ; b234
64 | LOAD:0000B15C 00 01 00 00 DCD 0x100 ; b244
65 | LOAD:0000B160 10 01 00 00 DCD 0x110 ; b254
66 | LOAD:0000B164 20 01 00 00 DCD 0x120 ; b264 偏移為8,表值為0x120,第一個對應lr + off = b144 + 0x120
67 | LOAD:0000B168 34 01 00 00 DCD 0x134 ; b278
68 | LOAD:0000B16C 4C 01 00 00 DCD 0x14C ; b290
69 | LOAD:0000B170 68 01 00 00 DCD 0x168 ; b2ac
70 | LOAD:0000B174 7C 01 00 00 DCD 0x17C ; b2c0
71 | LOAD:0000B178 94 01 00 00 DCD 0x194 ; b2d8
72 | LOAD:0000B17C AC 01 00 00 DCD 0x1AC ; b2f0
73 | LOAD:0000B180 D4 01 00 00 DCD 0x1D4 ; b318
74 | LOAD:0000B184 EC 01 00 00 DCD 0x1EC ; b330
75 | LOAD:0000B188 08 02 00 00 DCD 0x208 ; b34c
76 | LOAD:0000B18C 24 02 00 00 DCD 0x224 ; b368
77 | LOAD:0000B190 40 02 00 00 DCD 0x240 ; b384
78 | LOAD:0000B194 68 02 00 00 DCD 0x268 ; b3ac
79 | LOAD:0000B198 7C 02 00 00 DCD 0x27C ; b3c0
80 | LOAD:0000B19C 90 02 00 00 DCD 0x290 ; b3d4
81 | LOAD:0000B1A0 A4 02 00 00 DCD 0x2A4 ; b3e0
82 | LOAD:0000B1A4 B8 02 00 00 DCD 0x2B8 ; b3fc
83 | LOAD:0000B1A8 CC 02 00 00 DCD 0x2CC ; b410
84 | LOAD:0000B1AC E0 02 00 00 DCD 0x2E0 ; b424
85 | LOAD:0000B1B0 FC 02 00 00 DCD 0x2FC ; b440
86 | LOAD:0000B1B4 10 03 00 00 DCD 0x310 ; b454
87 | LOAD:0000B1B8 24 03 00 00 DCD 0x324 ; b468
88 | LOAD:0000B1BC 3C 03 00 00 DCD 0x33C ; b480
89 | LOAD:0000B1C0 58 03 00 00 DCD 0x358 ; b49c
90 | LOAD:0000B1C4 6C 03 00 00 DCD 0x36C ; b4b0
91 | LOAD:0000B1C8 90 03 00 00 DCD 0x390 ; b4d4
92 | LOAD:0000B1CC AC 03 00 00 DCD 0x3AC ; b4f0
93 | LOAD:0000B1D0 C4 03 00 00 DCD 0x3C4 ; b508
94 | LOAD:0000B1D4 D8 03 00 00 DCD 0x3D8 ; b51c
95 | LOAD:0000B1D8 F0 03 00 00 DCD 0x3F0 ; b534
96 | LOAD:0000B1DC 14 04 00 00 DCD 0x414 ; b558
97 | LOAD:0000B1E0 28 04 00 00 DCD 0x428 ; b56c
98 | LOAD:0000B1E4 40 04 00 00 DCD 0x440 ; b584
99 | LOAD:0000B1E8 5C 04 00 00 DCD 0x45C ; b5a0
100 | -------------------------------------------------------------------------------------------------------------
101 | 以第一次跳轉為例:
102 | LOAD:0000494C sub_494C
103 | LOAD:0000494C arg_8 = 8
104 | LOAD:0000494C BIC R1, LR, #1 // LR = B144 , 最低一位清零 R1 还是B144
105 | //LOAD:0000B164 DCD 0x120
106 | LOAD:00004950 00 11 91 E7 LDR R1, [R1,R0,LSL#2] // R1 = [B144 + 0x8 << 2] = [B144 + 0X20] = [B164] = 0x120
107 | LOAD:00004954 ADD R1, R1, LR // R1 = B144 + 0x120 = B264
108 | LOAD:00004958 LDR LR, [SP,#8] // LR = B144
109 | LOAD:0000495C STR R1, [SP,#8] // B264
110 | LOAD:00004960 03 80 BD E8 LDMFD SP!, {R0,R1,PC} // R0 = [SP], R1 = [SP + 4], PC = [SP + 8] 跳转到B264
111 | 隨便列舉幾個跳轉:
112 | 1 = 0xb264
113 | 2 = 0x1511c
114 | 3 = 0x24764
115 | 4 = 0x5f2ac
116 | 5 = 0x71e70
117 | 6 = 0x72dbc
118 | 7 = 0x9a14
119 | ...
120 | ---------------------------------------------------------------------------------------------
121 | 其他混淆跳轉輔助指令特徵:
122 | LOAD:0000494C
123 | LOAD:0000494C ; =============== S U B R O U T I N E =======================================
124 | LOAD:0000494C
125 | LOAD:0000494C
126 | LOAD:0000494C dyna_pc ; CODE XREF: j_dyna_pcj
127 | LOAD:0000494C ; LOAD:loc_4C20p ...
128 | LOAD:0000494C
129 | LOAD:0000494C arg_8 = 8
130 | LOAD:0000494C
131 | LOAD:0000494C 01 10 CE E3 BIC R1, LR, #1
132 | LOAD:00004950 00 11 91 E7 LDR R1, [R1,R0,LSL#2] ; lr(最低位清零) + (r0 << 2)
133 | LOAD:00004954 0E 10 81 E0 ADD R1, R1, LR
134 | LOAD:00004958 08 E0 9D E5 LDR LR, [SP,#8]
135 | LOAD:0000495C 08 10 8D E5 STR R1, [SP,#8]
136 | LOAD:00004960 03 80 BD E8 LDMFD SP!, {R0,R1,PC} ; 1 = 0xb264
137 | LOAD:00004960 ; End of function dyna_pc ; 2 = 0x1511c
138 | LOAD:00004960 ; 3 = 0x24764
139 | LOAD:00004960 ; 4 = 0x5f2ac
140 | LOAD:00004960 ; 5 = 0x71e70
141 | LOAD:00004960 ; 6 = 0x72dbc
142 | LOAD:00004960 ; 7 = 0x9a14
143 | LOAD:00004960 ; ...
144 | LOAD:00004964
145 | LOAD:00004964 ; =============== S U B R O U T I N E =======================================
146 | LOAD:00004964
147 | LOAD:00004964 ; 完成pc = pc + 8
148 | LOAD:00004964 ; 待彈出寄存器值為 lr + [lr]
149 | LOAD:00004964 ; 目的是完成動態生成函數參數
150 | LOAD:00004964
151 | LOAD:00004964 dyna_mkarg ; CODE XREF: sub_4ADC:loc_4AE0j
152 | LOAD:00004964 ; LOAD:00004D16p ...
153 | LOAD:00004964
154 | LOAD:00004964 anonymous_0 = 0
155 | LOAD:00004964 arg_C = 0xC
156 | LOAD:00004964 arg_10 = 0x10
157 | LOAD:00004964
158 | LOAD:00004964 01 00 CE E3 BIC R0, LR, #1
159 | LOAD:00004968 00 10 90 E5 LDR R1, [R0]
160 | LOAD:0000496C 01 10 90 E7 LDR R1, [R0,R1]
161 | LOAD:00004970 04 E0 8E E2 ADD LR, LR, #4
162 | LOAD:00004974 0C E0 8D E5 STR LR, [SP,#0xC] ; pc = lr + 4 ,下一條指令処
163 | LOAD:00004978 10 10 8D E5 STR R1, [SP,#0x10] ; 後面pop 寄存器的值
164 | LOAD:0000497C 03 C0 BD E8 LDMFD SP!, {R0,R1,LR,PC} ; pc = pc + 8
165 | LOAD:0000497C
166 | LOAD:00004980
167 | LOAD:00004980 ; =============== S U B R O U T I N E =======================================
168 | LOAD:00004980
169 | LOAD:00004980
170 | LOAD:00004980 sub_4980 ; CODE XREF: sub_4ABC:loc_4AC0j
171 | LOAD:00004980
172 | LOAD:00004980 arg_8 = 8
173 | LOAD:00004980
174 | LOAD:00004980 01 10 CE E3 BIC R1, LR, #1
175 | LOAD:00004984 00 11 91 E7 LDR R1, [R1,R0,LSL#2]
176 | LOAD:00004988 81 00 8E E0 ADD R0, LR, R1,LSL#1
177 | LOAD:0000498C 08 E0 9D E5 LDR LR, [SP,#arg_8]
178 | LOAD:00004990 08 00 8D E5 STR R0, [SP,#arg_8]
179 | LOAD:00004994 03 80 BD E8 LDMFD SP!, {R0,R1,PC}
180 | LOAD:00004994 ; End of function sub_4980
181 | LOAD:00004994
182 | LOAD:00004998
183 | LOAD:00004998 ; =============== S U B R O U T I N E =======================================
184 | LOAD:00004998
185 | LOAD:00004998
186 | LOAD:00004998 sub_4998 ; CODE XREF: sub_4AC4:loc_4AC8j
187 | LOAD:00004998 ; LOAD:000098FCp ...
188 | LOAD:00004998
189 | LOAD:00004998 arg_8 = 8
190 | LOAD:00004998
191 | LOAD:00004998 01 00 CE E3 BIC R0, LR, #1
192 | LOAD:0000499C 00 10 90 E5 LDR R1, [R0]
193 | LOAD:000049A0 0E 10 81 E0 ADD R1, R1, LR
194 | LOAD:000049A4 08 E0 9D E5 LDR LR, [SP,#arg_8]
195 | LOAD:000049A8 08 10 8D E5 STR R1, [SP,#arg_8]
196 | LOAD:000049AC 03 80 BD E8 LDMFD SP!, {R0,R1,PC}
197 | LOAD:000049AC ; End of function sub_4998
198 | LOAD:000049AC
199 | LOAD:000049B0
200 | LOAD:000049B0 ; =============== S U B R O U T I N E =======================================
201 | LOAD:000049B0
202 | LOAD:000049B0
203 | LOAD:000049B0 sub_49B0
204 | LOAD:000049B0
205 | LOAD:000049B0 arg_C = 0xC
206 | LOAD:000049B0 arg_10 = 0x10
207 | LOAD:000049B0
208 | LOAD:000049B0 01 00 CE E3 BIC R0, LR, #1
209 | LOAD:000049B4 00 10 90 E5 LDR R1, [R0]
210 | LOAD:000049B8 00 10 81 E0 ADD R1, R1, R0
211 | LOAD:000049BC 04 E0 8E E2 ADD LR, LR, #4
212 | LOAD:000049C0 0C E0 8D E5 STR LR, [SP,#arg_C]
213 | LOAD:000049C4 10 10 8D E5 STR R1, [SP,#arg_10]
214 | LOAD:000049C8 03 C0 BD E8 LDMFD SP!, {R0,R1,LR,PC}
215 | LOAD:000049C8 ; End of function sub_49B0
216 | LOAD:000049C8
217 | LOAD:000049CC
218 | LOAD:000049CC ; =============== S U B R O U T I N E =======================================
219 | LOAD:000049CC
220 | LOAD:000049CC
221 | LOAD:000049CC sub_49CC
222 | LOAD:000049CC
223 | LOAD:000049CC var_4 = -4
224 | LOAD:000049CC
225 | LOAD:000049CC 03 40 2D E9 STMFD SP!, {R0,R1,LR}
226 | LOAD:000049D0 0E 10 A0 E1 MOV R1, LR
227 | LOAD:000049D4 A1 10 A0 E1 MOV R1, R1,LSR#1
228 | LOAD:000049D8 81 10 A0 E1 MOV R1, R1,LSL#1
229 | LOAD:000049DC 01 00 A0 E1 MOV R0, R1
230 | LOAD:000049E0 00 10 91 E5 LDR R1, [R1]
231 | LOAD:000049E4 00 10 81 E0 ADD R1, R1, R0
232 | LOAD:000049E8 00 10 91 E5 LDR R1, [R1]
233 | LOAD:000049EC 08 10 8D E5 STR R1, [SP,#0xC+var_4]
234 | LOAD:000049F0 04 E0 8E E2 ADD LR, LR, #4
235 | LOAD:000049F4 03 80 BD E8 LDMFD SP!, {R0,R1,PC}
236 | LOAD:000049F4 ; End of function sub_49CC
237 | LOAD:000049F4
238 | LOAD:000049F8
239 | LOAD:000049F8 ; =============== S U B R O U T I N E =======================================
240 | LOAD:000049F8
241 | LOAD:000049F8
242 | LOAD:000049F8 sub_49F8
243 | LOAD:000049F8
244 | LOAD:000049F8 arg_4 = 4
245 | LOAD:000049F8
246 | LOAD:000049F8 04 E0 9D E5 LDR LR, [SP,#arg_4]
247 | LOAD:000049FC 04 00 8D E5 STR R0, [SP,#arg_4]
248 | LOAD:00004A00 01 80 BD E8 LDMFD SP!, {R0,PC}
249 | LOAD:00004A00 ; End of function sub_49F8
250 | LOAD:00004A00
251 | LOAD:00004A04
252 | LOAD:00004A04 ; =============== S U B R O U T I N E =======================================
253 | LOAD:00004A04
254 | LOAD:00004A04
255 | LOAD:00004A04 sub_4A04
256 | LOAD:00004A04
257 | LOAD:00004A04 arg_C = 0xC
258 | LOAD:00004A04 arg_10 = 0x10
259 | LOAD:00004A04 arg_14 = 0x14
260 | LOAD:00004A04
261 | LOAD:00004A04 0E 10 A0 E1 MOV R1, LR
262 | LOAD:00004A08 A1 10 A0 E1 MOV R1, R1,LSR#1
263 | LOAD:00004A0C 81 10 A0 E1 MOV R1, R1,LSL#1
264 | LOAD:00004A10 01 00 A0 E1 MOV R0, R1
265 | LOAD:00004A14 00 10 91 E5 LDR R1, [R1]
266 | LOAD:00004A18 00 10 81 E0 ADD R1, R1, R0
267 | LOAD:00004A1C 00 00 91 E5 LDR R0, [R1]
268 | LOAD:00004A20 04 10 91 E5 LDR R1, [R1,#4]
269 | LOAD:00004A24 10 00 8D E5 STR R0, [SP,#arg_10]
270 | LOAD:00004A28 14 10 8D E5 STR R1, [SP,#arg_14]
271 | LOAD:00004A2C 04 E0 8E E2 ADD LR, LR, #4
272 | LOAD:00004A30 0C E0 8D E5 STR LR, [SP,#arg_C]
273 | LOAD:00004A34 03 40 BD E8 LDMFD SP!, {R0,R1,LR}
274 | LOAD:00004A38 04 F0 9D E4 LDR PC, [SP-0xC+arg_C],#4
275 | LOAD:00004A38 ; End of function sub_4A04
276 | LOAD:00004A38
277 | LOAD:00004A3C
278 | LOAD:00004A3C ; =============== S U B R O U T I N E =======================================
279 | LOAD:00004A3C
280 | LOAD:00004A3C
281 | LOAD:00004A3C sub_4A3C ; CODE XREF: sub_4AE4:loc_4AE8j
282 | LOAD:00004A3C
283 | LOAD:00004A3C var_8 = -8
284 | LOAD:00004A3C var_4 = -4
285 | LOAD:00004A3C arg_8 = 8
286 | LOAD:00004A3C
287 | LOAD:00004A3C 04 70 2D E5 STR R7, [SP,#-4]!
288 | LOAD:00004A40 00 70 0F E1 MRS R7, CPSR
289 | LOAD:00004A44 04 20 2D E5 STR R2, [SP,#-4]!
290 | LOAD:00004A48 01 10 CE E3 BIC R1, LR, #1
291 | LOAD:00004A4C 80 01 B1 E7 LDR R0, [R1,R0,LSL#3]!
292 | LOAD:00004A50 04 10 91 E5 LDR R1, [R1,#4]
293 | LOAD:00004A54 00 00 51 E3 CMP R1, #0
294 | LOAD:00004A58 0E 00 00 0A BEQ loc_4A98
295 | LOAD:00004A5C 01 00 11 E3 TST R1, #1
296 | LOAD:00004A60 7F 20 A0 13 MOVNE R2, #0x7F ; ''
297 | LOAD:00004A64 21 22 02 10 ANDNE R2, R2, R1,LSR#4
298 | LOAD:00004A68 02 00 40 10 SUBNE R0, R0, R2
299 | LOAD:00004A6C 02 00 11 E3 TST R1, #2
300 | LOAD:00004A70 7F 20 A0 13 MOVNE R2, #0x7F ; ''
301 | LOAD:00004A74 A1 25 02 10 ANDNE R2, R2, R1,LSR#11
302 | LOAD:00004A78 02 00 80 10 ADDNE R0, R0, R2
303 | LOAD:00004A7C 04 00 11 E3 TST R1, #4
304 | LOAD:00004A80 FF 20 A0 13 MOVNE R2, #0xFF
305 | LOAD:00004A84 21 29 02 10 ANDNE R2, R2, R1,LSR#18
306 | LOAD:00004A88 02 00 20 10 EORNE R0, R0, R2
307 | LOAD:00004A8C 01 2E A0 E1 MOV R2, R1,LSL#28
308 | LOAD:00004A90 C2 0F 20 E0 EOR R0, R0, R2,ASR#31
309 | LOAD:00004A94 21 0D 80 E0 ADD R0, R0, R1,LSR#26
310 | LOAD:00004A98
311 | LOAD:00004A98 loc_4A98 ; CODE XREF: sub_4A3C+1Cj
312 | LOAD:00004A98 0E 00 80 E0 ADD R0, R0, LR
313 | LOAD:00004A9C 04 20 9D E4 LDR R2, [SP],#4
314 | LOAD:00004AA0 07 F0 29 E1 MSR CPSR_cf, R7
315 | LOAD:00004AA4 04 70 9D E4 LDR R7, [SP],#4
316 | LOAD:00004AA8 08 E0 9D E5 LDR LR, [SP,#8]
317 | LOAD:00004AAC 08 00 8D E5 STR R0, [SP,#8]
318 | LOAD:00004AB0 03 80 BD E8 LDMFD SP!, {R0,R1,PC}
319 | LOAD:00004AB0 ; End of function sub_4A3C
320 |
321 | ----------------------------------------------------------------------------------------------
322 | 在拿一個調整表做例子:
323 | LOAD:00009884 01 48 LDR R0, =5
324 | LOAD:00009888 FB F7 60 E8 BLX dyna_pc
325 | LOAD:0000988C 05 00 00 00 dword_988C DCD 5
326 | LOAD:00009890 1C 00 00 00 DCD 0x1C
327 | LOAD:00009894 40 00 00 00 DCD 0x40
328 | LOAD:00009898 E4 00 00 00 DCD 0xE4
329 | LOAD:0000989C 3C 01 00 00 DCD 0x13C
330 | LOAD:000098A0 88 01 00 00 DCD 0x188
331 | LOAD:000098A4 08 02 00 00 DCD 0x208
332 | 同上,規律是dyna_pc + 4 (即下一條指令地址[是r0的值] + offset[0 - 5], 因爲表大小為9890 - 98A4 共5個),
333 | 因此證明一共5個跳轉經過這裏,經證明確實如此:
334 | Down j LOAD:000098C4 BL loc_9888
335 | Down j LOAD:00009966 BL loc_9888
336 | Down j LOAD:000099BE BL loc_9888
337 | Down j LOAD:00009A0C BL loc_9888
338 | Down j LOAD:00009A8A BL loc_9888
339 | -------------------------------------------------------------------------------------------
340 | sub_494C的特征,代码段中仅存在一处
341 | LOAD:0000B264 ; ---------------------------------------------------------------------------
342 | LOAD:0000B264 PUSH.W {R4-R8,LR}
343 | LOAD:0000B268 ADD R7, SP, #0xC
344 | LOAD:0000B26A PUSH {R0,R1,LR}
345 | LOAD:0000B26C LDR R0, =0x20
346 | LOAD:0000B26E BL loc_B140 // 又跳回了LOAD:0000B140 BLX sub_494C
347 | LOAD:0000B26E ; ---------------------------------------------------------------------------
348 | 可以看到并想象程序中有多种类似的跳转,
349 | 特征:
350 | PUSH {R0,R1,LR}
351 | LDR R0, =number
352 | NOP
353 | patch代码摘自网络,被放置在put_unconditional_branch.py文件中,
354 | 在B26A处执行patch脚本,运行结果如下:B26A处指令变成了B loc_B4B0
355 | LOAD:0000B264 ; ---------------------------------------------------------------------------
356 | LOAD:0000B264 2D E9 F0 41 PUSH.W {R4-R8,LR}
357 | LOAD:0000B268 03 AF ADD R7, SP, #0xC
358 | LOAD:0000B26A 21 E1 B loc_B4B0
359 | LOAD:0000B26C 01 48 LDR R0, =0x20
360 | LOAD:0000B26E FF F7 67 FF BL loc_B140
361 | LOAD:0000B26E ; ---------------------------------------------------------------------------
362 |
363 | LOAD:0000B4B0 ; ---------------------------------------------------------------------------
364 | LOAD:0000B4B0
365 | LOAD:0000B4B0 loc_B4B0
366 | LOAD:0000B4B0 82 B0 SUB SP, SP, #8
367 | LOAD:0000B4B2 82 B0 SUB SP, SP, #8 // 这段代码包含一个blx跳转,该跳转
368 | LOAD:0000B4B4 03 B5 PUSH {R0,R1,LR} // 仅仅是完成了跳到下一个指令的位置
369 | LOAD:0000B4B6 F9 F7 56 EA BLX sub_4964 // 并且计算出指定寄存器的值
370 | LOAD:0000B4BA EA 00 LSLS R2, R5, #3 // 这段类似代码都可以被patch掉
371 | LOAD:0000B4BC 00 00 MOVS R0, R0 //
372 | LOAD:0000B4BE 02 BC POP {R1} //
373 | LOAD:0000B4C0 00 28 CMP R0, #0 //
374 | LOAD:0000B4C2 79 44 ADD R1, PC //
375 | LOAD:0000B4C4 09 68 LDR R1, [R1]
376 | LOAD:0000B4C6 03 B5 PUSH {R0,R1,LR}
377 | LOAD:0000B4C8 01 48 LDR R0, =0x27
378 | LOAD:0000B4CA FF F7 39 FE BL loc_B140
379 | LOAD:0000B4CA ; ---------------------------------------------------------------------------
380 |
381 |
382 |
383 | sub_4964处指令只是完成了 PC = R1 = B5A4, LR = B4BE(它下一条指令处), R0, R1略
384 | LOAD:00004964 ; =============== S U B R O U T I N E =======================================
385 | LOAD:00004964
386 | LOAD:00004964
387 | LOAD:00004964 sub_4964
388 | LOAD:00004964
389 | LOAD:00004964
390 | LOAD:00004964 arg_C = 0xC
391 | LOAD:00004964 arg_10 = 0x10
392 | LOAD:00004964
393 | LOAD:00004964 01 00 CE E3 BIC R0, LR, #1 // LR最低位清零,最终R0仍为B4BA
394 | LOAD:00004968 00 10 90 E5 LDR R1, [R0] // R1 = [B4BA] = 0XEA
395 | LOAD:0000496C 01 10 90 E7 LDR R1, [R0,R1] // R1 = B4BA + 0XEA = B5A4
396 | LOAD:00004970 04 E0 8E E2 ADD LR, LR, #4 // B4BA + 4 = B4BE
397 | LOAD:00004974 0C E0 8D E5 STR LR, [SP,#0xC]
398 | LOAD:00004978 10 10 8D E5 STR R1, [SP,#0x10]
399 | LOAD:0000497C 03 C0 BD E8 LDMFD SP!, {R0,R1,LR,PC} // PC = B4BE(它下一条指令处)
400 | LOAD:0000497C ; End of function sub_4964
401 | LOAD:0000497C
402 | LOAD:00004980 ; ---------------------------------------------------------------------------
403 |
404 | 特征如下:
405 | SUB SP, SP, #8
406 | PUSH {R0,R1,LR}
407 | ....
408 | POP xxx
409 | 摘自网络的patch代码见patches.py文件,在B4B2处进行patch后代码变化如下:
410 | LOAD:0000B4B0 ; ---------------------------------------------------------------------------
411 | LOAD:0000B4B0
412 | LOAD:0000B4B0 loc_B4B0
413 | LOAD:0000B4B0 82 B0 SUB SP, SP, #8
414 | LOAD:0000B4B2 00 BF NOP
415 | LOAD:0000B4B4 01 49 LDR R1, =0xB5A4 // = 0x7F73A
416 | LOAD:0000B4B6 09 68 LDR R1, [R1]
417 | LOAD:0000B4B8 02 E0 B loc_B4C0
418 | LOAD:0000B4B8 ; ---------------------------------------------------------------------------
419 | LOAD:0000B4BA EA 00 word_B4BA DCW 0xEA
420 | LOAD:0000B4BC A4 B5 00 00 dword_B4BC DCD 0xB5A4
421 | LOAD:0000B4C0 ; ---------------------------------------------------------------------------
422 | LOAD:0000B4C0
423 | LOAD:0000B4C0 loc_B4C0 ; CODE XREF: LOAD:0000B4B8j
424 | LOAD:0000B4C0 00 28 CMP R0, #0
425 | LOAD:0000B4C2 79 44 ADD R1, PC // __stack_chk_guard
426 | LOAD:0000B4C4 09 68 LDR R1, [R1]
427 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
428 | 另一块类似代码,特征:
429 |
430 | LOAD:0007203C 03 B5 PUSH {R0,R1,LR}
431 | LOAD:0007203E 00 BF NOP
432 | LOAD:00072040 92 F7 AA EC BLX sub_4998
433 | LOAD:00072044 0C 00 MOVS R4, R1
434 | -------------------------------------------------------------------------------------------------------------------
435 |
436 | LOAD:00004998
437 | LOAD:00004998
438 | LOAD:00004998 sub_4998
439 | LOAD:00004998
440 | LOAD:00004998
441 | LOAD:00004998 arg_8 = 8
442 | LOAD:00004998
443 | LOAD:00004998 01 00 CE E3 BIC R0, LR, #1 // 对LR = 0x72044最低位清零,仍为72044
444 | LOAD:0000499C 00 10 90 E5 LDR R1, [R0] // 取R1 = [0x72044] = 0xc
445 | LOAD:000049A0 0E 10 81 E0 ADD R1, R1, LR // 对LR = 0x72044 + 0xc = 0x72050
446 | LOAD:000049A4 08 E0 9D E5 LDR LR, [SP,#8]
447 | LOAD:000049A8 08 10 8D E5 STR R1, [SP,#8]
448 | LOAD:000049AC 03 80 BD E8 LDMFD SP!, {R0,R1,PC} // PC = 0x72050
449 | LOAD:000049AC ; End of function sub_4998
450 |
451 | ----------------------------------------------------------------------------------------------------------------
452 | 摘自网络命名位put_unconditional_branch1.py文件patch 0x7203C。
453 |
454 | LOAD:0007203C B loc_72050
455 | LOAD:0007203E NOP
456 | LOAD:00072040 BLX sub_4998
457 | LOAD:00072044 MOVS R4, R1
458 | LOAD:00072046 MOVS R0, R0
459 |
460 | ---------------------------------------------------------------------------------------------------------------
461 | 另一種計算pc的特徵:
462 | LOAD:00009A50 FA F7 A2 EF BLX sub_4998
463 | LOAD:00009A50 ; ---------------------------------------------------------------------------
464 | LOAD:00009A54 7A FF FF FF DCD 0xFFFFFF7A
465 | LOAD:00009A58 ; ---------------------------------------------------------------------------
466 |
467 | sub_4998
468 | LOAD:00004998 arg_8 = 8
469 | LOAD:00004998
470 | LOAD:00004998 01 00 CE E3 BIC R0, LR, #1 // lr = 9A54
471 | LOAD:0000499C 00 10 90 E5 LDR R1, [R0] // 0xFFFFFF7A
472 | LOAD:000049A0 0E 10 81 E0 ADD R1, R1, LR // 0x9ace = 9A54 + 0x7a
473 | LOAD:000049A4 08 E0 9D E5 LDR LR, [SP,#8]
474 | LOAD:000049A8 08 10 8D E5 STR R1, [SP,#8]
475 | LOAD:000049AC 03 80 BD E8 LDMFD SP!, {R0,R1,PC} // 0x9ace
476 | 以上指令等價於下面僞代碼:
477 | bl (lr + [lr])
478 | ---------------------------------------------------------------------------------------------------------------
479 | 另一種計算pc的特徵:
480 | LOAD:00009BBC 00 F0 0C B8 B.W loc_9BD8
481 | LOAD:00009BC0 ; ---------------------------------------------------------------------------
482 |
483 |
484 | LOAD:00009BD8 loc_9BD8
485 | LOAD:00009BD8
486 | LOAD:00009BD8 71 46 MOV R1, LR // lr = 9BC0
487 | LOAD:00009BDA 02 A5 ADR R5, 0x9BE4
488 | LOAD:00009BDC 55 F8 21 10 LDR.W R1, [R5,R1,LSL#2] ; 30ae4 = 0xFE6B
489 | LOAD:00009BE0 29 44 ADD R1, R5 ; 19A4F
490 | LOAD:00009BE2 08 47 BX R1 // 動態跳轉
491 | LOAD:00009BE2 ; ---------------------------------------------------------------------------
492 | LOAD:00009BE4 DD FF FF FF DCD 0xFFFFFFDD
493 | LOAD:00009BE8 ; ---------------------------------------------------------------------------
494 |
495 | ---------------------------------------------------------------------------------------------------------------
496 | 另一種計算pc的特徵(同時動態計算寄存器值,參數動態生成):
497 | LOAD:00004D12 82 B0 SUB SP, SP, #8
498 | LOAD:00004D14 03 B5 PUSH {R0,R1,LR}
499 | LOAD:00004D16 FF F7 26 EE BLX sub_4964
500 | LOAD:00004D16 ; ---------------------------------------------------------------------------
501 | LOAD:00004D1A EE 31 00 00 DCD 0x31EE
502 | LOAD:00004D1E ; ---------------------------------------------------------------------------
503 | LOAD:00004D1E 01 BC POP {R0} // pop xxx,動態生成參數
504 |
505 | sub_4964
506 | LOAD:00004964 01 00 CE E3 BIC R0, LR, #1 // 4D1A
507 | LOAD:00004968 00 10 90 E5 LDR R1, [R0] // 0x31EE
508 | LOAD:0000496C 01 10 90 E7 LDR R1, [R0,R1] // r1 = [4D1A + 0x31EE] = [7f08] = 0x85ECC
509 | LOAD:00004970 04 E0 8E E2 ADD LR, LR, #4 // lr = 4D1E
510 | LOAD:00004974 0C E0 8D E5 STR LR, [SP,#0xC] // lr + 4 ,下一條指令処
511 | LOAD:00004978 10 10 8D E5 STR R1, [SP,#0x10] // 待彈出寄存器值0x85ECC
512 | LOAD:0000497C 03 C0 BD E8 LDMFD SP!, {R0,R1,LR,PC} // pc = pc + 8
513 | 等同於僞代碼:
514 | arg_addr = [lr + [lr]]
515 | r{0-3} = arg_addr
516 | ---------------------------------------------------------------------------------------------------------------
517 | 程序JNI_OnLoad邏輯:
518 | libsgmainso_6.4.36.so B3F2D000 B3FB6000 R . X D . byte 00 public CODE 32 00 00
519 | sp = BE903640 B1200284 debug038:B1200284
520 | 第一個動態pc:
521 | libsgmainso_6.4.36.so:B3F38140 BLX dyna_pc
522 | 動態arg:
523 | libsgmainso_6.4.36.so:B3F384B6 BLX dyna_arg
524 | libsgmainso_6.4.36.so:AFE80210 BL loc_AFEF14F4(重命名為goto_create_global_objs)
525 | sub_7C4F4(); // 創建全局 jboolean, jinteger、jstring
526 |
527 | 调试时跳过这里,否则可能崩溃
528 | LOAD:0000B584 71 F0 14 F8 BL goto_getenv(7C5B0)
529 | ---------------------------------------------------------------------------------------------------------------
530 | #sub_72CCC(),被重命名為goto_do_httpuitl
531 | 主要完成對com/taobao/wireless/security/adapter/common/HttpUtil的各種方法的查找
532 | 獲取對應的MethodId並保存
533 |
534 | sub77dbc(), 代码複合patch代码第二種特征,但是这里应该不被patch,被patch的地方
535 | 82 B0 SUB SP, SP, #8
536 | 03 B5 PUSH {R0,R1,LR}
537 | 91 F7 CC ED BLX dyna_arg
538 | 32 01 LSLS R2, R6, #4
539 | 00 00 MOVS R0, R0
540 | 01 BC POP {R0}
541 | 应该满足两个SUB SP, SP, #8指令,因此運行patch代碼,patch整個代碼段
542 | 會出錯,它會把{R0,R1,LR}指令patch成b xxxx導致運行失敗。
543 | sp = BE903620 AFE80111 libsgmainso_6.4.36.so:AFE80111
544 | BL sub_B3FA0E24(sub_73e24(),被重命名為goto_decrypt_entry)
545 | arg:B3FB2FA9, BE9035C3,0x35 // 參數1為加密數據緩存區,參數2是解密數據緩存區
546 | sub_B3FA0E56(sub_73e56, 被重命名為decrypt_entry),比較重要的函數涉及創建容器結構體和解密
547 | BL unk_B3FA7F78(goto_create_vdata)
548 | BL sub_B3FA7FB6(create_vdata)
549 | arg:vdata1,"DcO/lcK+h?m3c*q@",0x10
550 | //vdata1->make_vdata 填充數據
551 | libsgmainso_6.4.36.so:B3FA0E94 98 47 BLX R3(7AA5D)
552 | 拷貝"DcO/lcK+h?m3c*vaq@"到vdata1的data1中
553 |
554 | 第二次調用make_vdata,arg:vdata2,B3FB2FA9,52 // 參數2是數據緩存區
555 | 這次是把下面這52個字節拷貝到vdata2的data2中
556 | 0xF9,0xA7,0x21,0x3D,0x8C,0x3E,0xFE,0x77,0x18,0x40,0xDB,0x2A,
557 | 0xAD,0x4A,0xC5,0xF9,0xA1,0x56,0x75,0x54,0x23,0xBE,0xC7,0xA6,
558 | 0x7A,0x35,0xEC,0x8E,0xB2,5,0x74,0x11,0x93,0x58,0x7F,0x6E,0x3A,
559 | 0xE3,0x4F,0x9D,0x54,3,0x7E,0x6B,0xFA,0x1B,0x5B,0xE3,0xF8,0xC1,2,0xF9
560 | dcryptdata:BE903578
561 | memset(BE903578, 0, 20)
562 | arg:BE903578,BE903594,20,20
563 | // 進入解密函數,dcryptdata結構對應内存
564 | [stack]:BE903578 DCD 0
565 | [stack]:BE90357C DCD 3 ; caseno
566 | [stack]:BE903580 DCD 0
567 | [stack]:BE903584 DCD 0
568 | [stack]:BE903588 DCD 0xACC1C890 ; vdata1
569 | [stack]:BE90358C DCD 0xACC1C8C8 ; vdata2
570 | libsgmainso_6.4.36.so:B3FA0ED8 BL sub_B3F8E15C(重命名為goto_dcrypto)
571 | goto_dcrypto(dcryptdata, )
572 | 進入sub_611b4(被重命名為decrypto)進行解密,解密出:
573 | "com/taobao/wireless/security/adapter/common/HttpUtil"
574 | libsgmainso_6.4.36.so AFE75000 AFEFE000 R . X D . byte 00 public CODE 32 00 00
575 | 調用findclass查找該class,調用NewGlobalRef創建該類的ref
576 | arg: httputilref,
577 | bl sub_72d60()
578 | // 參數1加密數據,參數2為解密緩衝區,參數3為長度
579 | BL goto_decrypt_entry(encdata, decdata, len);
580 | BL goto_create_vdata
581 | memset (BE9035A0, 0, 0x1d)
582 | 拷貝加密數據到vdata2
583 | memset dcryptdata 結構BE903558
584 | BL goto_dcrypto, 解密出字符串"sendSyncHttpGetRequestBridge"
585 | 調用env->getStaticMethodID,75F247D8
586 | sub_72e54()
587 | 解密出數據"sendSyncHttpPostRequestBridge"
588 | 調用env->getStaticMethodID, 75F24828
589 | 在解密出"downloadFileBridge"
590 | 調用env->getStaticMethodID, 75F24788
591 | 調用env->DeleteLocalRef刪除httputilref
592 | 至此sub_72CCC()結束
593 | ---------------------------------------------------------------------------------------------------------------
594 | sub_73634()被重命名為goto_do_umidAdapter
595 | 主要完成對com/taobao/wireless/security/adapter/umid/UmidAdapter的方法的查找
596 | 並保存其MethodId
597 | sub_7366A()
598 | BL goto_decrypt_entry(,, 54)
599 | 解密出"com/taobao/wireless/security/adapter/umid/UmidAdapter"
600 | 調用env->findclass找到UmidAdapterClass 00100025,調用env->NewGlobalRef UmidAdapterRef
601 | 調用env->DeleteLocalRef, 刪除UmidAdapterClass
602 | BL goto_decrypt_entry(AFEFB113, BE9035B8, 16)
603 | 解密出"umidInitAdapter"
604 | 調用env->getStaticMethodID(UmidAdapterRef, "umidInitAdapter") 75F248C8
605 | sub_73634()結束
606 | ---------------------------------------------------------------------------------------------------------------
607 | sub_73E24() goto_decrypt_entry(AFEF8EA6, BE9035E8, 49)
608 | 解密出"com/taobao/wireless/security/adapter/JNICLibrary"
609 | libsgmainso_6.4.36.so B3F2D000 B3FB7000 R . X D . byte 00 public CODE 32 00 00
610 | 調用env->findclass查找JNICLibrary 00200025
611 | bl 9EE4
612 | sub_9ee4() 被重命名為goto_create_command_vdata,主要是調用sub_9F1C完成創建兩個大的結構體
613 | sub_9F1C() // make_global_command_ptr
614 | 首先讀取off_90804処的值是否為NULL(被重命名為global_command_entryptr
615 | 它保存著下面的global_command_entry結構的指針)
616 |
617 | struct global_command_entry { // 記錄著生成和執行command的核心方法
618 | void* goto_make_command_entry; // 對應sub_9B3C; 生成command結構核心算法
619 | void* goto_do_command1; // // 對應sub_9d82; command_native_inner
620 | void* goto_do_command2; // 對應sub_9e7e; 和sub_9d82差不多
621 | };
622 |
623 | ACC11F60 = malloc(12); // 這是個什麽結構體,暫且命名為tmp_vdata
624 | debug014:ACC11F60 DCD 0xB3F36A99 // 對應sub_9B3C; 生成command結構核心算法
625 | debug014:ACC11F64 DCD 0xB3F36DF5 // 對應sub_9d82; command_native_inner
626 | debug014:ACC11F68 DCD 0xB3F36E49 // 對應sub_9e7e; 和sub_9d82差不多
627 | sub_7B86C(32,0) // 重命名為create_command_vdata(int len, int w); // len表示結構體大小,w未知
628 | struct command_nest {
629 | void* nf1;
630 | void* nf2;
631 | int len;
632 | };
633 |
634 | struct command_vdata {
635 | struct data** datalist; // 第一層$8bitstruct
636 | int data_count;
637 | int data_size;
638 | void* f1;
639 | void* f2;
640 | void* f3;
641 | struct command_nest* nest;
642 | };
643 |
644 | ACC3A3D0 = malloc(36);
645 | 創建command_vdata結構體,對應内存結構:
646 | debug014:ACC3A3D0 DCD 0xACC49300 ; command_vdata1
647 | debug014:ACC3A3D4 DCD 0
648 | debug014:ACC3A3D8 DCD 0x20
649 | debug014:ACC3A3DC DCD 0xB3FA88F9
650 | debug014:ACC3A3E0 DCD 0xB3FA89B5
651 | debug014:ACC3A3E4 DCD 0xB3FA89F5
652 | debug014:ACC3A3E8 DCD 0xB3FA8A81
653 | debug014:ACC3A3EC DCD 0xB3FA8AF1
654 | debug014:ACC3A3F0 DCD 0
655 | 創建data結構體(chunk)
656 | ACC49300 = malloc(128);
657 | 創建第二個command_vdata結構體ACC3A3A8
658 | debug014:ACC3A3A8 DCD 0xACC49280 ; command_vdata2
659 | debug014:ACC3A3AC DCD 0
660 | debug014:ACC3A3B0 DCD 0x20
661 | debug014:ACC3A3B4 DCD 0xB3FA88F9
662 | debug014:ACC3A3B8 DCD 0xB3FA89B5
663 | debug014:ACC3A3BC DCD 0xB3FA89F5
664 | debug014:ACC3A3C0 DCD 0xB3FA8A81
665 | debug014:ACC3A3C4 DCD 0xB3FA8AF1
666 | debug014:ACC3A3C8 DCD 0
667 | 創建第二個data結構體ACC49280
668 | 然後把它倆存儲在以下地方:
669 | off_8CA7C g_search_command_vdata DCD 0xACC3A3D0, do_command 第四個參數為0,查找
670 | off_8CA78 gcommand_build_vdata DCD 0xACC3A3A8, do_command 第四個參數為1,生成
671 | 在off_90804処保存global_command_entry指針
672 | ---------------------------------------------------------------------------------------------------------------
673 | bl sub_71D68(),重命名為goto_do_SPUtility2
674 | 主要是查找com/taobao/wireless/security/adapter/common/SPUtility2的一些methoidID
675 | sub_73DD4()啥也沒乾
676 |
677 | sub_71E70只是用來構造參數
678 | sub_72080()
679 | 解密得到"com/taobao/wireless/security/adapter/common/SPUtility2"
680 | 調用env->findclass找到SPUtility2Class 00000029
681 | 調用env->NewGlobalRef創建SPUtility2Ref 001003DA
682 | sub_72134()
683 | 解密"readFromSPUnified"
684 | 調用env-getStaticMethodID, 75F26B48
685 | 解密"saveToFileUnifiedForNative"
686 | 調用env-getStaticMethodID, 75F26C88
687 | sub_720C8()
688 | 解密出 "removeFromSPUnifiedp"
689 | 調用env-getStaticMethodID, 75F26BE8
690 | sub_71FD0()
691 | 解密出"readSS"
692 | 解密出"writeSS",調用env-getStaticMethodID, 75F26D78
693 | sub_71EB0()
694 | 調用env-getStaticMethodID("readSS"), 75F26B98
695 | 解密出"read", "write"
696 | 調用env-getStaticMethodID("read"),75F26AF8
697 | 調用env-getStaticMethodID("write"),75F26D28
698 | ---------------------------------------------------------------------------------------------------------------
699 | sub_e7dc()
700 | sub_E890()
701 | 解密出"(I)Ljava/lang/String;"
702 | 解密出"com/taobao/wireless/security/adapter/datacollection/DeviceInfoCapturer"
703 | 調用findclass,0010002D,調用NewGlobalRef創建該類的ref 001003DE
704 | 調用DeleteLocalRef, 刪除本地DeviceInfoCapturer類的ref
705 | 解密出"doCommandForString"
706 | 調用env-getStaticMethodID("doCommandForString"),75F27048 存儲在off_8CA94処
707 | 存儲在以下位置:
708 | off_8CA94 global_DeviceInfoCapturer_methodId DCD 0x75F27048
709 | off_8CA98 global_DeviceInfoCapturer_ref DCD 0xB6F33E04
710 |
711 | #########################################################################################
712 | #sub_9B3C
713 | 這是一個重要的函數,每個command依賴的數據結構都需要經過它來生成
714 | 這個函數經過了llvm混淆,在不去掉llvm混淆時分析起來還是比較費勁的。
715 | command 最主要的參數是三個:
716 | command / 10000 ; // n1
717 | command % 10000 / 100 ; // n2
718 | command % 100 ; // n2
719 | 由此三個參數構成了三層結構(由外向内順序是n1->n2->n3),其中最終的加密后的地址保存在
720 | n3層結構中(只是異或加密),解密密匙保存在n2層結構中(是用time做種子生成的隨機數,
721 | 每次都不一樣,每個app可能都不一樣)。
722 |
723 | 每個command相關地址并不是函數的實際地址(是包含實際地址的封裝),是執行函數的一個入口(梉),
724 | 這個入口需要進一步做處理才能跳轉到實際函數的地址。
725 | 一個函數會被分成不同的塊,由n3層結構決定,例如:
726 | command(1, 17, 1) { // 隨便假設的
727 | stub2->do_command_parser->real_func_addr
728 | stub1->do_command_parser->real_func_addr
729 | stub3->do_command_parser->real_func_addr
730 | stub4->do_command_parser->real_func_addr
731 | }
732 | 在上面的分析中我們已經看到它生成了一個全局的command_entryptr,它記錄著生產command相關結構
733 | 和反向按結構找到梉的算法。
734 | 同時還生成了兩個gcommand_vdata1和gcommand_vdata2的n1第一層指針結構(分別為查找和生成時使用)
735 |
736 | 主要結構如下(僞定義):
737 |
738 | n1 -> first struct{8 bit: n2_addr, count} -> n2 -> second {24 bit: n3_addr, count} -> n3 ->
739 | third {16 bit: stub_addr, count}
740 |
741 | 無論是正向生成command相關結構,還是反向依賴參數查找結構都需要這三個參數
742 | 1、正向生成command相關結構,傳遞的參數是1
743 | 2、反向查找command相關結構,傳遞的參數是0
744 |
745 | #後續在酌情添加
746 | 開始分析:
747 | sub_9B3C() // goto_make_command_entry
748 | 以第一次分析爲例(我只記錄關鍵邏輯):
749 | [stack]:BE8915C8 DCD 0xB3E7B2B5 ; sp
750 | [stack]:BE8915CC DCD 0x100025
751 | sub_9B3C(1, 9, 1, 1, build_addr) ->
752 | // goto_build_or_unpack_command
753 | sub_9854(gcommand_build_vdata, 1, 9, 1, 1, ...) ->
754 |
755 | sub_9a14(gcommand_build_vdata, 1, 9, 1, 1, build_addr = 0xB3E7B2B5) // build_addr = 0x102B5
756 |
757 | struct $8bitstruct { // 第一層結構
758 | int command_arg1; // command arg1
759 | struct command_vdata* vdata; // 指向第二層
760 | };
761 |
762 | struct $24bitstruct { // 第二層結構
763 | int command_arg1; // command arg1
764 | int command_arg2; // command arg2
765 | long time;
766 | int c; // (time >> 31)
767 | struct command_vdata* vdata; // 指向第三層
768 | int d; // 未知
769 | };
770 |
771 | struct $16bitstruct { // 第三層結構
772 | int command_arg1; // command arg1
773 | int command_arg2; // command arg2
774 | int command_arg3; // command arg3
775 | int xoraddr;
776 | };
777 |
778 | // w = 0代表查找, w = 1代表創建
779 | // n1, n2, n3 為command 三層索引
780 | // build_addr 正向時為被處理地址, 反向時為返回地址
781 | void* sub_9a14(command_vdata* g_build_vdata, int n1, int n2, int n3, w = 1, void* build_addr) {
782 |
783 | int data_count = g_build_vdata->data_count;
784 | int i = 0;
785 | if (data_count < 1) {
786 | if (w == 0) {
787 | return 0x26b0;
788 | }
789 |
790 | struct $8bitstruct* _8bitstruct = (struct $8bitstruct*) malloc(8); // B4E01130
791 | memset(_8bitstruct, 0, 8);
792 | _8bitstruct->command_arg1 = n1;
793 | // -> 7BB98
794 |
795 | // vdata = ACB4A3F8, datalist = ACB32980
796 | // vdata 初始化略; 默認data_size為120字節
797 | struct command_vdata* second_command_vdata = (struct command_vdata*) malloc(36);
798 |
799 | _8bitstruct->vdata = second_command_vdata;
800 | // make_command_vdata, 填充數據
801 | // 這裏僅僅執行了 vdata->datalist->d = _8bitstruct;
802 | // vdata->data_count++;
803 | g_build_vdata->f2(g_build_vdata, 0, _8bitstruct);
804 |
805 | if(second_command_vdata->data_count < 1) {
806 | if (w == NULL) {
807 | return 0x26B1;
808 | }
809 | // ACB12478
810 | struct $24bitstruct* _24bitstr = (struct $24bitstruct*) malloc(24);
811 | memset(_24bitstr, 0, 24);
812 | _24bitstr->command_arg1 = n1; // command arg1
813 | _24bitstr->command_arg2 = n2; // command arg2
814 | time_t seed;
815 | seed = time(NULL); // 5E58B699
816 | srand(seed);
817 | int random_time = (int) rand() >> 31; // 074D4C00
818 | int c = (int) random_time >> 31; // 0
819 | _24bitstr->time = random_time;
820 | _24bitstr->c = c;
821 | // 創建第三層command_vdata結構
822 | // vdata = ACB4A498; data = ACB32A00
823 | // vdata 初始化略
824 | struct command_vdata* third_command_vdata = (struct command_vdata*) malloc(36);
825 | _24bitstr->vdata = third_command_vdata;
826 | // 這裏僅僅執行了 vdata->datalist->d = _24bitstr;
827 | // vdata->data_count++;
828 | second_command_vdata->f2(second_command_vdata, _24bitstr); // make_command_vdata
829 | if (third_command_vdata->data_count < 1) {
830 | if (w == 0) {
831 | return 0x270F;
832 | }
833 | // ACB3B540
834 | struct $16bitstruct* _16bitstr = (struct $16bitstruct*) malloc(16);
835 | _16bitstr->command_arg1 = n1;
836 | _16bitstr->command_arg2 = n2;
837 | _16bitstr->command_arg3 = n3;
838 | // make_command_vdata, 填充數據
839 | // 這裏僅僅執行了 vdata->datalist->d = _16bitstr;
840 | // vdata->data_count++;
841 | third_command_vdata->f2(third_command_vdata, _16bitstr);// make_command_vdata
842 | // 異或加密地址存儲
843 | _16bitstr->xoraddr = _24bitstr->time ^ build_addr;
844 | return 0;
845 |
846 | } else {
847 | i = 0;
848 | while (i < third_command_vdata->data_count) {
849 | // 這裏後面在說
850 | }
851 | }
852 | } else {
853 | i = 0;
854 | while(i < second_command_vdata->data_count) {
855 | // 這裏後面在說
856 | }
857 |
858 | }
859 | } else {
860 | struct data** datalist = g_build_vdata->datalist;
861 | struct $8bitstruct* _8bitstr = NULL;
862 | for (int i = 0 ; i < g_build_vdata->data_count; i++) {
863 | _8bitstr = datalist[i];
864 | if(_8bitstr->command_arg1 == n1) {
865 | break;
866 | }
867 | }
868 | // 取第二層機構
869 | struct command_vdata* second_command_vdata = _8bitstr->vdata;
870 | if (second_command_vdata->data_count < 1 ) {
871 | return 0x26B1;
872 | }
873 |
874 | datalist = second_command_vdata->datalist;
875 | struct $24bitstruct* _24bitstr = NULL;
876 |
877 | for (int j = 0 ; j < second_command_vdata->data_count ; j++) {
878 | if((struct $24bitstruct*) datalist[i]->command_arg2 == n2) {
879 | _24bitstr = datalist[i];
880 | break;
881 | }
882 | }
883 |
884 | if (w == 0) {
885 | return ??;
886 | }
887 |
888 | if (_24bitstr == NULL) {
889 | _24bitstr = malloc(24);
890 | // 創建$24bitstruct 結構體
891 | // 創建third_command_vdata ACB4A4C0;同上
892 | // 更新second_command_vdata datalist同時data_count++等
893 | // ACB124C0 24bitstr,
894 | // 創建完后調用
895 | }
896 |
897 | // 取第三層
898 | struct $16bitstruct* _16bitstr = NULL;
899 | struct command_vdata* third_command_vdata = _24bitstr->vdata;
900 | if(third_command_vdata->data_count < 1) {
901 |
902 | }
903 |
904 | for (j = 0; j < third_command_vdata->data_count; j++) {
905 | if ((struct $16bitstruct*) third_command_vdata[j]->command_arg3 == n3) {
906 | _16bitstr = third_command_vdata[j];
907 | break;
908 | }
909 | }
910 |
911 | if (w == 0) {
912 | return ??;
913 | }
914 |
915 | if (_16bitstr == NULL) {
916 | _16bitstr = malloc(16);
917 | // ACB11F50
918 | // 創建$16bitstruct; 同上
919 | return 0;
920 | }
921 | }
922 | }
923 |
924 | #########################################################################################
925 | ---------------------------------------------------------------------------------------------------------------
926 | sub_69D68() 啥也沒乾
927 | ---------------------------------------------------------------------------------------------------------------
928 | sub_197B4() 被重命名為goto_do_DataReportJniBridgerer
929 | 主要是處理com/taobao/wireless/security/adapter/datareport/DataReportJniBridgerer這個類的方法,同上
930 | sub_1990C()
931 | 解密出"com/taobao/wireless/security/adapter/datareport/DataReportJniBridgerer"
932 | 調用findclass, 0000002D
933 | 調用NewGlobalRef創建該類的ref 001003E2
934 | sub_19998()
935 | 下面忘記下斷點了,丟失信息了
936 | 解密出"sendReportBridge", 調用getStaticMethodID, 忘記記錄了
937 | 解密出 "accsAvaiableBridge", 調用getStaticMethodID, 忘記記錄了
938 | 解密出"()I" , 調用getStaticMethodID, 忘記記錄了
939 | 解密出"registerAccsListnerBridge"
940 | 解密出"()I" , 調用getStaticMethodID, 忘記記錄了
941 | 他們被分別保存在off_8CB80起始的地址処
942 | sub_73D90() 讀取global_command_entry指針的值
943 | 繼續調用sub_9b3c(1, 0xb, 0x34, 1, build_addr = B3E84725 = 0x19725) 詳細分析見上面
944 | ---------------------------------------------------------------------------------------------------------------
945 | sub_E240()
946 | sub_e280()
947 | 又sub_9B3C(1, 7, 1, 1, build_addr = 0xB3E791D5 = off_E1D5)同上, 不在繼續分析
948 | ---------------------------------------------------------------------------------------------------------------
949 | sub_B8B0()
950 | 繼續調用sub_9B3C(1, 1, 1, 1, build_addr = 0xB3E76921 = off_B921) 同上略
951 | 繼續調用sub_9B3C(1, 1, 2, 1, build_addr = 0xB3E76FD9 = off_BFD9) 同上略
952 | ---------------------------------------------------------------------------------------------------------------
953 | sub_5F0F4()
954 | sub_5F11E()
955 | sub_9B3C() 同上略
956 | ---------------------------------------------------------------------------------------------------------------
957 | sub_5F0F4(env, clazz)
958 | sub_9B3C() 同上略
959 | sub_9B3C() 同上略
960 | ---------------------------------------------------------------------------------------------------------------
961 | sub_70640(env, clazz)
962 | sub_9B3C() 同上略
963 | sub_9B3C() 同上略
964 | ---------------------------------------------------------------------------------------------------------------
965 | sub_11F3C(env)
966 | sub_14FEE()
967 | sub_1511C(),中間很多調用findclass和調用都略
968 | 解密出"android/content/Context",調用findclass
969 | sub_151A4()
970 | 解密出"getPackageManager","()Landroid/content/pm/PackageManager;"
971 | 調用getStaticMethodID 70FC7458
972 | 解密出"getContentResolver", "()Landroid/content/ContentResolver;"
973 | 調用getStaticMethodID 70FC7458
974 | 解密出"getSystemService","(Ljava/lang/String;)Ljava/lang/Object;"
975 | 調用getStaticMethodID 70FC7BA8
976 | 解密出"WIFI_SERVICE","Ljava/lang/String;"
977 | 調用GetStaticFieldID 70FC66E8
978 | 調用NewGlobalRef創建該類的ref 001003E6
979 | 調用DeleteLocalRef刪除該類本地ref
980 | 解密出"android/content/pm/PackageManager", "getPackageInfo",,調用findclass
981 | "(Ljava/lang/String;I)Landroid/content/pm/PackageInfo;"
982 | 調用getStaticMethodID 70FAFA30
983 | 調用DeleteLocalRef刪除該類本地ref
984 | 解密出"android/content/pm/PackageInfo"
985 | "applicationInfo", "Landroid/content/pm/ApplicationInfo;"
986 | 調用GetFieldID 71052F08
987 | 解密出 "firstInstallTime1","J"
988 | 調用GetFieldID 71053100
989 | 解密出"lastUpdateTime","J"
990 | 調用GetFieldID 71053118
991 | 調用DeleteLocalRef刪除該類本地ref
992 | 解密出"android/content/pm/ApplicationInfo","flags","I"
993 | 調用GetFieldID 71047168
994 | 調用DeleteLocalRef刪除該類本地ref
995 | 解密出"android/provider/Settings", "getString"
996 | "(Landroid/content/ContentResolver;Ljava/lang/String;)Ljava/lang/String;"
997 | 調用getStaticMethodID 7127C4E8
998 | 調用NewGlobalRef創建該類的ref 001003EA
999 | 調用DeleteLocalRef刪除該類本地ref
1000 | "java/util/List","get", "(I)Ljava/lang/Object;",
1001 | 調用getStaticMethodID 70B43A50
1002 | 解密出"size","()I"
1003 | 調用getStaticMethodID 70B43DF8
1004 | 調用DeleteLocalRef刪除該類本地ref
1005 | 解密出"android/net/wifi/WifiConfiguration","SSID","Ljava/lang/String;"
1006 | 調用GetFieldID 75F27C38
1007 | "networkId","I",調用GetFieldID 75F28078
1008 | "providerFriendlyName","Ljava/lang/String;",調用GetFieldID, 返回空
1009 | "BSSID","Ljava/lang/String;",調用GetFieldID, 75F27BF8
1010 | "FQDN","Ljava/lang/String;",調用GetFieldID, 75F27C18
1011 | "priority","I", 調用GetFieldID,75F282B8
1012 | "hiddenSSID","Z",調用GetFieldID, 75F27ED8
1013 | 調用NewGlobalRef創建該類的ref 001003EE
1014 | 調用DeleteLocalRef刪除該類本地ref
1015 | "android/net/wifi/WifiManager","getConfiguredNetworks","()Ljava/util/List;"
1016 | 調用getStaticMethodID 711FD720
1017 | "getDhcpInfo","()Landroid/net/DhcpInfo;",
1018 | 調用getStaticMethodID 711FD840
1019 | 調用DeleteLocalRef刪除該類本地ref
1020 | "android/net/DhcpInfo", "gateway","I",
1021 | 調用GetFieldID 75F29168
1022 | 調用DeleteLocalRef刪除該類本地ref
1023 | ---------------------------------------------------------------------------------------------------------------
1024 | sub_21C3C()
1025 | sub_21c70()
1026 | sub_9b3c() 同上略
1027 | ...
1028 | ---------------------------------------------------------------------------------------------------------------
1029 | sub_2148C()
1030 | sub_9b3c() 同上略
1031 | ...
1032 | ---------------------------------------------------------------------------------------------------------------
1033 | sub_210E0
1034 | sub_9b3c() 同上略
1035 | ...
1036 | ---------------------------------------------------------------------------------------------------------------
1037 | sub_41B58
1038 | sub_9b3c() 同上略
1039 | ...
1040 | ---------------------------------------------------------------------------------------------------------------
1041 | sub_27920
1042 | sub_9b3c() 同上略
1043 | ...
1044 | ---------------------------------------------------------------------------------------------------------------
1045 | sub_293E8()
1046 | sub_2941C()->sub_29708()->sub_29918()
1047 | 解密出"com/taobao/dp/util/ZipUtils","unZip","([B)[B"
1048 | findclass找到ZipUtilsClass 00100031
1049 | NewGlobalRef 001003F2
1050 | DeleteLocalRef
1051 | getMethodID 75F29618
1052 | 解密出"com/taobao/dp/util/CallbackHelper"
1053 | findclass找到CallbackHelper 00000031
1054 | NewGlobalRef 001003F6
1055 | DeleteLocalRef
1056 | getMethodID 75F29618
1057 | sub_2abf9()-->sub_2AC24()加綫程鎖
1058 | DeleteLocalRef
1059 | sub_29754()->sub_29BB4()
1060 | 解密出"getPackageManager", "()Landroid/content/pm/PackageManager;"
1061 | "android/content/Context","android/content/pm/PackageManager"
1062 | "getPackageInfo","(Ljava/lang/String;I)Landroid/content/pm/PackageInfo;"
1063 | "android/content/pm/PackageInfo","applicationInfo"
1064 | "Landroid/content/pm/ApplicationInfo;","firstInstallTime","lastUpdateTime"
1065 | "android/content/pm/ApplicationInfo","flags"
1066 | FindClass("android/content/Context") 00100031
1067 | NewGlobalRef 001003FA
1068 | getMethodID("getPackageManager") 70FC7968
1069 | FindClass("android/content/pm/PackageManager") 00000035
1070 | NewGlobalRef 001003FE
1071 | getMethodID("getPackageInfo") 70FAFA30
1072 | FindClass("android/content/pm/PackageInfo") 00000039 ??
1073 | NewGlobalRef 00100402
1074 | GetFieldID("applicationInfo") 71052F08
1075 | GetFieldID("firstInstallTime") 71053100
1076 | GetFieldID("lastUpdateTime") 71053118
1077 | FindClass("android/content/pm/ApplicationInfo") 0000003D
1078 | NewGlobalRef 00100406
1079 | GetFieldID("flags") 71047168
1080 | ---------------------------------------------------------------------------------------------------------------
1081 | sub_208F4
1082 | sub_20A0C()
1083 | 解密出"com/alibaba/wireless/security/framework/utils/UserTrackMethodJniBridge"
1084 | NewGlobalRef 0010040A, DeleteLocalRef
1085 | "utAvaiable","()I;",getStaticMethodID("utAvaiable") 75F28278
1086 | "addUtRecord","(Ljava/lang/String;IILjava/lang/String;JLjava/lang/String;"
1087 | "Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)I"
1088 | sprintf(, "%s%s", "(Ljava/lang/String;IILjava/lang/String;JLjava/lang/String;",
1089 | "Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)I")
1090 | 得到"(Ljava/lang/String;IILjava/lang/String;JLjava/lang/String;Ljava/lang/String;Ljava/lang/String;"
1091 | "Ljava/lang/String;Ljava/lang/String;)I"
1092 | getStaticMethodID("addUtRecord") 75F28188
1093 | "getStackTrace","(II)Ljava/lang/String;",getStaticMethodID("getStackTrace"), 75F281D8
1094 | 判斷獲取的methodId是否為空
1095 | ---------------------------------------------------------------------------------------------------------------
1096 | sub_B7B0
1097 | sub_b7f6() 被重命名為registerNatives
1098 | 解密出"doCommandNative","(I[Ljava/lang/Object;)Ljava/lang/Object;", fnPtr為sub_B69C()
1099 | 實際對應sub_B6F6(),重命名為doCommandNative,代碼摘自網絡
1100 | sub_9D60為goto_docommand_native_inner
1101 | 調用env->RegisterNatives()注冊這個doCommandNative
1102 | 至此JNI_OnLoad結束
1103 | ---------------------------------------------------------------------------------------------------------------
1104 | doCommandNative(12302, new Object[]{1, true}) 對應getSecToken
1105 | struct command_arg {
1106 | int arg1;
1107 | int arg2;
1108 | int arg3;
1109 | JNIEnv* env;
1110 | void* args;
1111 | };
1112 |
1113 | struct command_arg* = malloc(20); // ACB6A718
1114 |
1115 | int _R4 = 12302; // command
1116 | int _R0 = 0x68DB8BAD; // 68DB8BAD
1117 | int _R2 = 0x51EB851F; // 51EB851F
1118 |
1119 | int r0 = _R0 * _R4; // 000013AE
1120 | int r3 = _R2 * _R4; // 00000F60
1121 | // (signed int)r0 >> 0xc) = (signed int) (13AE >> 0xc) = 00000001
1122 | // r0 >> 31 = 0
1123 | r0 = ((signed int)r0 >> 0xc) + (r0 >> 31); // 0x1, 參數1
1124 | int r1 = _R4 - r0 * 10000 ; // 000008FE(2302)
1125 | r1 = _R4 * r1; // 2E0, SMMUL.W取高位
1126 | // ((signed int)r3 >> 5) = 0000007B(123)
1127 | // (r3 >> 31) = 0
1128 | r2 = _R4 - (((signed int)r3 >> 5) + (r3 >> 31)) * 100; // 2, 參數3
1129 | r3 = (signed) r1 >> 5 = 00000017(23)
1130 | r1 = r3 + (r1 >> 31) = 1; // 0x17, 參數2
1131 |
1132 | command_arg->arg1 = 1;
1133 | command_arg->arg2 = 0x17;
1134 | command_arg->arg3 = 2;
1135 | // [stack]:BE892160 DCD 0xACB6A748 sp command_arg
1136 | // [stack]:BE892164 DCD 0xBE89216C sp + 4, 棧指針
1137 | // [stack]:BE89216C DCD 0
1138 | sub_9D60->sub_9D82(1, 0x17, 2, w=1, command_arg, 一個棧變量指針)
1139 |
1140 |
1141 | // 非0時取這個
1142 | libsgmainso_6.4.36.so:B3EF7A78 dword_B3EF7A78 DCD 0xACB4A3D0
1143 | // 0時取這個
1144 | libsgmainso_6.4.36.so:B3EF7A7C dword_B3EF7A7C DCD 0xACB4A3A8
1145 | /////////////////////////////////////////////////////////////////
1146 | // 第一次w = 1 因此這個command_vdata沒有用到
1147 | debug021:ACB4A3A8 DCD 0xACB31C00
1148 | debug021:ACB4A3AC DCD 0
1149 | debug021:ACB4A3B0 DCD 0x20
1150 | debug021:ACB4A3B4 DCD 0xB3EE68F9
1151 | debug021:ACB4A3B8 DCD 0xB3EE69B5
1152 | debug021:ACB4A3BC DCD 0xB3EE69F5
1153 | debug021:ACB4A3C0 DCD 0xB3EE6A81
1154 | debug021:ACB4A3C4 DCD 0xB3EE6AF1
1155 | debug021:ACB4A3C8 DCD 0
1156 | //////////////////////////////////////////////////////////////////
1157 | // 用到了這個command_vdata
1158 | debug021:ACB4A3D0 DCD 0xACB31C80
1159 | debug021:ACB4A3D4 DCD 1
1160 | debug021:ACB4A3D8 DCD 0x20
1161 | debug021:ACB4A3DC DCD 0xB3EE68F9
1162 | debug021:ACB4A3E0 DCD 0xB3EE69B5
1163 | debug021:ACB4A3E4 DCD 0xB3EE69F5
1164 | debug021:ACB4A3E8 DCD 0xB3EE6A81
1165 | debug021:ACB4A3EC DCD 0xB3EE6AF1
1166 | debug021:ACB4A3F0 DCD 0
1167 | // data
1168 | debug021:ACB31C80 DCD 0xB4E01130
1169 | //
1170 | debug068:B4E01130 DCD 1
1171 | debug068:B4E01134 DCD 0xACB4A3F8
1172 | // command_vdata1
1173 | debug021:ACB4A3F8 DCD 0xACB31D00
1174 | debug021:ACB4A3FC DCD 0xC
1175 | debug021:ACB4A400 DCD 0x20
1176 | debug021:ACB4A404 DCD 0xB3EE68F9
1177 | debug021:ACB4A408 DCD 0xB3EE69B5
1178 | debug021:ACB4A40C DCD 0xB3EE69F5
1179 | debug021:ACB4A410 DCD 0xB3EE6A81
1180 | debug021:ACB4A414 DCD 0xB3EE6AF1
1181 | // 12個data
1182 | debug021:ACB31D00 DCD 0xACB125F8
1183 | debug021:ACB31D04 DCD 0xACB12610
1184 | debug021:ACB31D08 DCD 0xACB125E0
1185 | debug021:ACB31D0C DCD 0xACB124C0
1186 | debug021:ACB31D10 DCD 0xACB12490
1187 | debug021:ACB31D14 DCD 0xACB124F0
1188 | debug021:ACB31D18 DCD 0xACB12A00
1189 | debug021:ACB31D1C DCD 0xACB12778
1190 | debug021:ACB31D20 DCD 0xACB12910
1191 | debug021:ACB31D24 DCD 0xACB12AC0
1192 | debug021:ACB31D28 DCD 0xACB12970
1193 | debug021:ACB31D2C DCD 0xACB12BE0
1194 | // 最後取到的符合要求的 對應參數2的結構
1195 | debug021:ACB12BE0 DCD 1
1196 | debug021:ACB12BE4 DCD 0x17
1197 | debug021:ACB12BE8 DCD 0x7A005EB3
1198 | debug021:ACB12BEC DCD 0
1199 | debug021:ACB12BF0 DCD 0xACB4A7B8
1200 | debug021:ACB12BF4 DCD 0
1201 | debug021:ACB12BF8 DCD 0
1202 | debug021:ACB12BFC DCD 0
1203 | debug021:ACB12C00 DCD 0xACB12BC8
1204 | //最後取到的符合要求的 對應參數3的結構
1205 | debug021:ACB3B340 DCD 1
1206 | debug021:ACB3B344 DCD 0x17
1207 | debug021:ACB3B348 DCD 2
1208 | debug021:ACB3B34C DCD 0xC9E91B96
1209 | debug021:ACB3B350 DCD 1
1210 | debug021:ACB3B354 DCD 0x17
1211 | debug021:ACB3B358 DCD 1
1212 | debug021:ACB3B35C DCD 0xC9E91A22
1213 | debug021:ACB3B360 DCD 1
1214 | debug021:ACB3B364 DCD 0x17
1215 | debug021:ACB3B368 DCD 3
1216 | debug021:ACB3B36C DCD 0xC9E91B66
1217 | debug021:ACB3B370 DCD 1
1218 | debug021:ACB3B374 DCD 0x17
1219 | debug021:ACB3B378 DCD 4
1220 | debug021:ACB3B37C DCD 0xC9E9182E
1221 | /////////////////////////////////////////////////////////////
1222 |
1223 | stack
1224 | BE892140 00000000
1225 | BE892144 BE892148 [stack]:BE892148
1226 | BE892148 00000000 //r7 + 1c,後面用來存儲下一跳的地址
1227 | BE89214C B47A9038 dalvik_allocspace_allo
1228 | BE892150 0000300E
1229 | BE892154 00000000
1230 | BE892158 BE892180 [stack]:BE892180
1231 | BE89215C B3E76771 libsgmainso_6.4.36.so:
1232 | BE892160 ACB6A718 debug021:ACB6A718
1233 |
1234 | 我們設command變量從外到内依次為a、b、c
1235 | command_vdata-> {datalistaddr, data_count, ...}
1236 | datalist[0]->data[0]-> data{count, addr}->
1237 | command_vdata -> {datalistaddr, data_count, ...}->datalist[x]
1238 | ->24bitstruct{a, b, time(xorkey), ?, command_vdata,?}->
1239 | command_vdata -> {datalistaddr, data_count, ...}->
1240 | 16bitstruct{a, b, c, xoraddr}
1241 |
1242 | // goto_build_or_unpack_command
1243 | sub_9854(ACB4A3D0, 1, 0x17, 2, ...)
1244 | // goto_build_or_unpack_command
1245 | sub_9854->sub_9A14(a, b, c, ...) // a = arg1, b = arg2, c =arg3
1246 | //////////////////////////////////////////////////////////////
1247 | // 第一次 sub_9D82(1, 0x17, 2, 1, command_arg, 一個棧變量指針)
1248 | //////////////////////////////////////////////////////////////
1249 | ->sub_9d82(command, tmp2, tmp3, w, ...) // command_native_inner;獲取下一步跳轉地址
1250 |
1251 | // 首先找到全局command_vdata最外層指針,相對文件偏移dword_8CA7C和dword_8CA78
1252 | // 前面做處理時保存的, w!=0時取dword_8CA78,否則取dword_8CA7C
1253 | // 這裏面有很多函數, 其中還包括正向建立command_vdata過程,這裏略
1254 | sub_9d82(int n1, int n2, int n3, int w, struct command_arg* arg, int* next_addr) {
1255 | struct command_vdata* vdata = &dword_8CA7C;
1256 | if (w != 0) {
1257 | vdata = &dword_8CA78;
1258 | }
1259 |
1260 | // sub_9a14(command_vdata, n1, n2, n3, w, 0)
1261 | // 最外層
1262 | datalist = vdata->datalist;
1263 |
1264 | int i = 0;
1265 | struct $8bitstruct* _8bitstruct = NULL;
1266 | while(i < n1) {
1267 | _8bitstruct = datalist[i]->d; // 取第一層8bitstruct指針
1268 | int ra = _8bitstruct->command_arg1; // 第一層命令
1269 | if (ra == n1) { // 第一層對比相等
1270 | break;
1271 | }
1272 | i++;
1273 | }
1274 | // w不爲0,可能返回0x270F、0x26B0、0x26B1
1275 | // 這裏暫不做分析
1276 | if (_8bitstruct == NULL && w == 0) { // 沒找到的情況
1277 | return 0x26b0;
1278 | }
1279 | //獲取第二層
1280 | struct command_vdata* vdata1 = _8bitstruct->vdata;
1281 | int count = vdata1->data_count;
1282 | i = 0;
1283 | struct $24bitstruct _24bitstr = NULL;
1284 | while(i < count) {
1285 | _24bitstr = vdata1->datalist[i]->d;
1286 | int rb = _24bitstr->command_arg2;
1287 | if (rb = n2) { // 第二層對比
1288 | break;
1289 | }
1290 | i++;
1291 | }
1292 | // w不爲0,可能返回0x270F、0x26B0、0x26B1
1293 | // 這裏暫不做分析
1294 | if(_24bitstr == NULL && w == 0) { // 沒找到的情況
1295 | return 0x26b0;
1296 | }
1297 |
1298 | // 獲取第三層
1299 | struct command_vdata* vdata2 = _24bitstr->vdata;
1300 | count = vdata2->data_count;
1301 | i = 0;
1302 | struct $16bitstruct _16bitstr = NULL;
1303 | while(i < count) {
1304 | _16bitstr = vdata2->datalist[i]->d;
1305 | int rc = _16bitstr->command_arg3;
1306 | if(rc == n3) {
1307 | int xor_addr = _16bitstr->xoraddr ^ _24bitstr->time;
1308 | *next_addr = xor_addr;
1309 | break;
1310 | }
1311 | i++;
1312 | }
1313 | typedef *func(void* void*) nfunc;
1314 | nfunc nextf= (nfunc) next_addr;
1315 | return nextf(command_arg, next_addr);
1316 | }
1317 | sub_9a14用
1318 | [stack]:BE892158 DCD 0xBE892180
1319 | [stack]:BE89215C DCD 0xB3D72771
1320 | [stack]:BE892160 DCD 0xACB6A748
1321 | [stack]:BE892164 DCD 0xBE89216C // r7 + 0xc
1322 | [stack]:BE892168 DCD 0x12DE5080
1323 | [stack]:BE89216C DCD 0
1324 |
1325 | >> sub_9D60 結束
1326 |
1327 | arg1 = command_arg->arg1;
1328 | 跳轉到上面異或出來的地址処 // xor = time ^ sec; // B3E94525地址処,對應文件0x29524処
1329 | sub_2956C(command_arg, BE89216C); // 獲取傳遞參數arraylist 0xBE8921A0 -> 0x12E51660
1330 |
1331 | env = command_arg->env;
1332 | jobjectarray = command_arg->args;
1333 | 7E744 ->sub_7E784() // goto_getjarray_value
1334 | GetObjectArrayElement(env, jarray, index) // 返回jobject
1335 | 在通過GetObjectClass獲取對應jclass,在調用GetMethodID獲取對應取元素的方法
1336 | 在調用CallXXXMethod獲取數組中的value。
1337 |
1338 | 7E7EC(env, jarray, 1)->sub_7E830 // goto_getjarray_value1
1339 | functions->GetObjectArrayElement)()略,同上
1340 |
1341 | sp + 4 = 第一個數組元素對應的值
1342 | sp + 8 = 第二個數組元素對應的值
1343 | // vvarg1
1344 | [stack]:BE892118 DCD 0xACB6A748 ; sp0 command_arg
1345 | [stack]:BE89211C DCD 1 ; jarray value 1
1346 | [stack]:BE892120 DCD 1 ; jarray value 2
1347 | [stack]:BE892124 DCD 0xB47A9038
1348 | [stack]:BE892128 DCD 0xB3EF7A78 ; command_vdata1
1349 | [stack]:BE89212C DCD 0
1350 | [stack]:BE892130 DCD 0xACB6A748 // ;command_arg
1351 | // vvarg2
1352 | [stack]:BE89216C DCD 0
1353 | [stack]:BE892170 DCD 0xB47A9038
1354 | [stack]:BE892174 DCD 0x2DF
1355 | [stack]:BE892178 DCD 0x75F91FF0
1356 | [stack]:BE89217C DCD 0x12DDD080
1357 | [stack]:BE892180 DCD 0x716162A0
1358 | [stack]:BE892184 DCD 0x12E51660
1359 | [stack]:BE892188 DCD 0xB4E07800
1360 | [stack]:BE89218C DCD 0xA44E7263
1361 | [stack]:BE892190 DCD 0x75F24BF8
1362 | [stack]:BE892194 DCD 0xBE892438
1363 | [stack]:BE892198 DCD 2
1364 | [stack]:BE89219C DCD 0x12C357C0
1365 | 29FD4->sub_2A01E(vvarg1, vvarg2)
1366 |
1367 | if (vvarg1[1] != 0) { // 取第二個jarray的值, 這裏值為true
1368 | r5 = vvarg1[0]; // 取第一個jarray的值
1369 | // libsgmainso_6.4.36.so:B3E95042 BL loc_B3E9DC00
1370 | // 這應該是具體處理邏輯的函數了,分不分析無所謂了
1371 | 32C00()->sub_32C46(r5 = 1); { // 傳遞的jarray的第一個值
1372 | // 邏輯我就不細緻分析了,這個就涉及到具體算法了,我不想去花時間在逆向算法上
1373 | // 我們重點是搞清楚它都怎麽做的, 這裏我隨便記錄我想記錄的
1374 | // 分不分析看心情
1375 | 30590->sub_305BE(1,0)
1376 | // 9來自程序中寫死的
1377 | 30240->sub_3026A(1,9) // v2 = 1, v3 = 9 ; read_off_8AA50(off, index)
1378 | // 讀取:off_8AA50[108]數組某處的值, 這個值可能是一個結構指針,後面邏輯會把它free
1379 | // B3EF5A50 ; _DWORD dword_B3EF5A50[108]
1380 | // B3EF5A50 DCD 0xB3EF7E18, 0xB3EF7E24, 0, 0xB3EF7E30, 0, 0, 0, 0xB3EF7E3C, 0xB3EF7E48
1381 | // B3EF5A50 DCD 0xB3EF7E54, 0xB3EDE9D1, 0xB3EDE951, 0xB3EABEB9, 0, 0, 0, 0xB3EC2385
1382 | // B3EF5A50 DCD 0, 0x14, 0, 0xB3ED48C1, 0, 0, 0xB3EF2AB6, 0xB3EF0C73, 0xB3EF0CC4, 0xB3EF0D15
1383 | // B3EF5A50 DCD 0xB3EF2B08, 0xB3EDB6B1, 0, 0, 0, 3, 0x8AD2C, 2, 0x590, 0x17, 0x3B14
1384 | // B3EF5A50 DCD 0x14, 0x11, 0x11, 0x2704, 0x12, 0x1410, 0x13, 8, 0x6FFFFFFA, 0x276
1385 | // B3EF5A50 DCD 6, 0x18C, 0xB, 0x10, 5, 0x10FC, 0xA, 0xCA2, 4, 0x1DA0, 1, 0xC83, 1
1386 | // B3EF5A50 DCD 0xC8D, 1, 0x15, 1, 0x5A1, 1, 0xC95, 1, 0x181, 0xE, 0x1D, 0x1A, 0x8A2E0
1387 | // B3EF5A50 DCD 0x1C, 8, 0x19, 0x8AACC, 0x1B, 4, 0x1E, 8, 0x6FFFFFFB, 1, 0x6FFFFFF0
1388 | // B3EF5A50 DCD 0x2498, 0x6FFFFFFC, 0x2688, 0x6FFFFFFD, 1, 0x6FFFFFFE, 0x26A4, 0x6FFFFFFF
1389 | // B3EF5A50 DCD 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
1390 | // 第一次計算off_8AA50[9] = 0xB3EF7E54 = 文件偏移8CE54
1391 | // 第二次計算 [0xB3EF7E54 + 4] = 0
1392 | // libsgmainso_6.4.36.so:B3EF7E58 DCD 0
1393 | v5 = *(_DWORD *)(off_8AA50[index] + 4 * off);
1394 | if ( v5 && *(_DWORD *)(v5 + 4) ) // 不成立
1395 | v6 = (*(int (**)(void))(v5 + 40))();
1396 | else
1397 | v6 = 0;
1398 | // 返回0
1399 | 2D228->sub_2D1DA(1,9)->
1400 | // goto_make_vdata6436
1401 | sub_301BC(1,9) -> 301DE(index = 1, off = 9)
1402 | // 大字符數組
1403 | // B3EF02FD aA0d11c6a829475d8 DCB "a0d11c6a829475d8",0
1404 | // B3EF030E aC558656c6b70ed21 DCB "c558656c6b70ed21",0
1405 | // B3EF031F aHardinfo DCB "hardinfo",0
1406 | // B3EF0328 a9e83acb65377eab4 DCB "9e83acb65377eab4",0
1407 | // B3EF0339 a835f56fa8c204d73 DCB "835f56fa8c204d73",0
1408 | // B3EF034A a711718eb73d90dc5 DCB "711718eb73d90dc5",0
1409 | // B3EF035B a68787a1ccce468bf DCB "68787a1ccce468bf",0
1410 | // B3EF036C a999b23355c8909c1 DCB "999b23355c8909c1",0
1411 | // B3EF037D aA9122d5b7873a0d3 DCB "a9122d5b7873a0d3",0
1412 | // B3EF038E aD8b057995e905838 DCB "d8b057995e905838",0
1413 | // B3EF039F a438e0bb7721e9d78 DCB "438e0bb7721e9d78",0
1414 | // B3EF03B0 a570bfc082fe96042 DCB "570BFC082FE96042",0
1415 | // B3EF03C1 aE87e68b3aea2d029 DCB "e87e68b3aea2d029",0
1416 | // B3EF03D2 aEa6c627ab40979d1 DCB "ea6c627ab40979d1",0
1417 | // B3EF03E3 a816f27e6be7ab193 DCB "816f27e6be7ab193",0
1418 | // B3EF03F4 aB7b03fe1a0a13745 DCB "b7b03fe1a0a13745",0
1419 | // B3EF0405 a4c60fa08664a7b66 DCB "4c60fa08664a7b66",0
1420 | // B3EF0416 a624b4d174ad35f2d DCB "624b4d174ad35f2d",0
1421 | // B3EF0427 a95ed8b0357989058 DCB "95ed8b0357989058",0
1422 | // B3EF0438 a00f3acddd00fa671 DCB "00f3acddd00fa671",0
1423 | // B3EF0449 a6c709c11d2d46a7b DCB "6c709c11d2d46a7b",0
1424 | // B3EF045A aDd7893586a493dc3 DCB "dd7893586a493dc3",0
1425 | // B3EF046B a58669b0e4dd2beb8 DCB "58669b0e4dd2beb8",0
1426 | // B3EF047C a85d32f14e4edccf2 DCB "85d32f14e4edccf2",0
1427 | // B3EF048D aE5c06c338bfa3568 DCB "e5c06c338bfa3568",0
1428 | // B3EF049E a8dd236e3120fdbea DCB "8dd236e3120fdbea",0
1429 | // B3EF04AF a8d8b035705995e98 DCB "8d8b035705995e98",0
1430 | // B3EF04C0 a0357995e9858d8b0 DCB "0357995e9858d8b0",0
1431 | // B3EF04D1 aPd DCB "pd",0
1432 | // B3EF04D4 aDj DCB "dj",0
1433 | // libsgmainso_6.4.36.so:B3EF59F8 dword_B3EF59F8 DCD 0xB3EF039F
1434 | arg1 = 1, 獲得數組為off_8A9F8
1435 | // libsgmainso_6.4.36.so:B3EF59D0 dword_B3EF59D0 DCD 0xB3EF02FD
1436 | arg1 = 2, 獲得數組為off_8A9D0
1437 | // libsgmainso_6.4.36.so:B3EF5A20 dword_B3EF5A20 DCD 0xB3EF0438
1438 | 否則,獲得數組為off_8AA20
1439 | // 這裏為1,即off_8A9F8
1440 | 取字符串off_8A9F8[9] = "d8b057995e905838"
1441 | // ACB1C9E0
1442 | //7AF78 goto_create_vdata6436
1443 | 7AF78->sub_7AFB6(0x11) //參數是字符串長度+1,該函數實際上就是create_vdata6436
1444 | // 實際上就是make_vdata6436
1445 | // debug023:ACB1C938 DCD 0xACB6A5F8
1446 | 調用vdata6436->f1(vdata6436, "d8b057995e905838", 0x10);
1447 | // 30240->sub_3026A(1,9)
1448 | 繼續調用goto_read_off_8AA50(1, 9) 得到結構指針為NULL
1449 | // 7B148 goto_free_data
1450 | 7B148->sub_7B17A(0); // free_data; 執行free
1451 | // goto_docommand_inner_contains_create_free_vdata32
1452 | // ACB1C938; goto_create_vdata32; do_command_inner; free_vdata32
1453 | 30D24->sub_30D60(vdata6436,9,1,0,0,1);
1454 | 7C218->sub_7C258("d8b057995e905838", 0x10) // geto_create_vdata32
1455 | struct vdata32_nest {
1456 | void* nf1;
1457 | void* nf2;
1458 | void* nf3;
1459 | void* nf4;
1460 | };
1461 |
1462 | struct vdata32 {
1463 | struct data* data128;
1464 | int data_count;
1465 | int chunk_size;
1466 | void* f1; // goto_make_vdata32;
1467 | struct vdata32_nest* nest;
1468 | };
1469 | // debug018:ACB6A5C8
1470 | 7C0D4->sub_7C10C("d8b057995e905838", 0x10); // A1619860; create_vdata32
1471 | 7C280->sub_7C2C8(vdata32, "d8b057995e905838", 0x10); // goto_make_vdata32
1472 | 73D90 // 讀取off_90804{讀取off_xxx}的值x,這是之前保存起來的
1473 | // debug018:ACB11E20 DCD 0xAFE7EA99
1474 | // debug018:ACB11E24 DCD 0xAFE7EDF5
1475 | // debug018:ACB11E28 DCD 0xAFE7EE49
1476 |
1477 | // 讀取[x + 4] = 0xAFE7EDF5,好像是fnPtr,後面跳到這個地址執行
1478 | [stack]:BE892078 DCD 0xBE89207C // sp
1479 | [stack]:BE89207C DCD 0
1480 | [stack]:BE892080 DCD 0xA1619860 // vdata32
1481 | {1, 0x15, 2, vdata32, 指向sp+4的指針}
1482 | sub_9E30重新設置參數
1483 | [stack]:BE892068 DCD 0xBE892080 sp
1484 | [stack]:BE89206C DCD 0xBE89207C sp + 4
1485 | 走到9D60最終走到sub_9D82(1, 0x15, 2, 0, vdata32p, &saved_addrp) // command_native_inner
1486 | // 不滿足查找條件,返回0x26b0
1487 | 存儲0x26b0到[stack]:BE89207C処
1488 | [stack]:BE89207C DCD 0x26B0
1489 | [stack]:BE892080 DCD 0xA1515580
1490 | [stack]:BE892084 DCD 1
1491 | [stack]:BE892088 DCD 7
1492 | [stack]:BE89208C DCD 0xB47A9038
1493 | [stack]:BE892090 DCD 1
1494 | [stack]:BE892094 DCD 9
1495 | [stack]:BE892098 DCD 0xBE8920AC
1496 | [stack]:BE89209C DCD 0xB3C98207
1497 | sub_9D82返回0x26b0
1498 | 7C34C->sub_7C3A4(vdata32) // free_data(vdata32); 沒用符合條件,vdata32就沒用到,把它free掉
1499 | 得到剛剛獲取的0x26b0並存儲
1500 | 7B148->sub_7B17A(0); // free_data; 執行free; free_vdata6436(vdata6436);
1501 |
1502 | 32cc8->sub_32DC4(0,1,5,2)->sub_32DF0
1503 | 32F14{goto_read_off_8CE6C}->sub_32F44(1) ; // read_off_8CE6C(1)
1504 | // B3EF7E6C ; _DWORD dword_B3EF7E6C[101]
1505 | // B3EF7E6C DCD 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
1506 | // B3EF7E6C DCD 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
1507 | // B3EF7E6C DCD 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
1508 | // B3EF7E6C DCD 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
1509 | // B3EF7E6C DCD 0, 0, 0, 0, 0, 0, 0, 0, 0
1510 | 返回0
1511 | 32D78; // 調用5次goto_free_data, free掉查找到的結構指針, 應該是這個command用到的相關塊的結構
1512 |
1513 | 7B148->sub_7B17A(0); // free_data; 執行free
1514 | 30240->sub_3026A(1,9); // 調用goto_read_off_8AA50(1); 同上略
1515 | 32cc8 // 繼續32cc8, 同上略
1516 | }
1517 | }
1518 |
1519 | // goto_do_commandx
1520 | 2B468->sub_2B4BE()->73D90{讀取off_xxx值} // get_do_command_fnptr_str; 準備執行do_command_inner
1521 | // 再次調試sub_9D60(1, 9, 2, 0, 0x6f, stackbuf = 0xBE8920CC)
1522 | // 返回調用到0x9854后返回0x26b0保存到0xBE8920CC
1523 | // 應該是讀取結構指針,然後釋放
1524 | // 7B148->sub_7B17A(0); // free_data; 執行free
1525 | // 9DF4(1, 9, 2, 111) // 結果返回0,結束
1526 | 7AF78->sub_7AFB6(0x19) //參數是字符串長度+1,該函數實際上就是create_vdata6436
1527 | 調用vdata6436->f1(vdata6436, "000000000000000000000000", 0x18); // ACB1C938
1528 | // goto_create_vstring
1529 | 7B5D4(vdata6436, "000000000000000000000000", 0, 0x30)->sub_7B606 // create_vstring ; AD2BEEE0
1530 | 29E98(stackbufp = BE8920EC, stack = BE89216C = NULL)->sub_11F3C(stackbufp, stack)
1531 | *(BE8920EC + 12) = 0;
1532 | *(BE8920EC) = 1;
1533 | 2ACB0->sub_2ACDE(arg = 1) // set_wt_flag; 如果arg <= 2 設置dword_8CE10為參數值
1534 | 304E4->(1,0,1)->sub_3052E(1, 0) // do_command_innerx1
1535 | //先get_do_command_fnptr_str 重新獲取下一個代碼塊,并執行
1536 | // 此次獲取了之前構造保存的塊, ACB3B360
1537 | // 再次執行do_command_inner(1, 8, 2, ...) 返回0
1538 | 30A04->sub_30A38(1)->
1539 | 2D504->sub_2D668(1)->2AC60->sub_2AC8A() ; // get_dword_8CE0C_classid
1540 | // B3E986A2 BL sub_B3E9DC00
1541 | 獲得dword_8CE0C = 0x1003F6; CallbackHelper
1542 | 再次調用32C00略 // 返回0, 實際也沒看到做什麽實質動作
1543 | 獲取env,sub_2D6B8調用解密
1544 | 解密出"onCallBack", "(ILjava/lang/String;I)V"
1545 | 調用GetStaticMethodID(env, 0x1003F6, "onCallBack");
1546 | 調用CallStaticVoidMethod(JNIEnv*, 0x1003F6, onCallBack, 1, NULL, 0x386);
1547 |
1548 | ------------------------------------------------------------------------------------------------------
1549 | 經過這一系列的逆向發現原來sub_9B3C()這個函數是用來做建立和查找command處理的
1550 | 最後把處理結果保存在一系列的嵌套的結構體中
1551 | 這些結構體涉及上面提到的command_vdata, 8bitstruct, 16bitstruct,24bitstruct等
1552 | 核心思路是把地址和一個隨機時間異或加密,然後把地址對應的command存儲在三層的結構體中
1553 | ,這樣每次保持的地址和時間值都不一樣,反過來根據command來查找對應加密的梉,後面解密。
1554 |
1555 | 它記錄的地址實際還不是真正的程序地址,是梉,它還需要進一步去unpack才能進入真正的邏輯。
1556 |
1557 | commandNative函數查找時,command 分爲三個主要參數 :
1558 | command / 10000,
1559 | command % 10000 / 100,
1560 | command % 100
1561 | 用這三個參數查找一個嵌套的結構體,找到與這三個結構體三層都一致的結構體
1562 | 然後用之前記錄的時間和異或后的值再次異或就得到了跳轉地址。
1563 |
1564 |
--------------------------------------------------------------------------------