├── 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 | --------------------------------------------------------------------------------