另外想说一下,之前把对 Ali 壳的分析发到看雪了,可能因为我只把大概的流程放上去了所以有评论觉得这是一个很没技术的秒脱壳子,至于究竟这个壳子怎么样,好不好脱,完全没有自己尝试过。个人感觉 Ali 的壳子对于初学者来说有很深的学习意义,有不少有意思的细节,建议分析。
* 为了阅读这篇文章时更好理解文中所说内容,下面大多形如 [sub_] [unk_xxx] [loc_xxx] 的函数都经过了重命名以帮助理解。
下面言归正传,下图是反编译 apk 后的 smali 差异,另外还新增了一个 lib 文件夹。
lib 文件夹的格式如下所示。
bugly 相关的可以不用管了,是腾讯的一个类似上报 bug 之类的玩意和加固没有关系。smali 层面只做了一些简单的混淆,不做过多分析了(其实是时间太久忘了 ....),直接进入 Native 层。
直接动态 IDA 挂上,然后在 Linker 和 libdvm.so 对应调用 .init / .init_array / JNI_Onload 的偏移地址下好断点,这样下断点的好处是可以无视 .so 的 ELF 头被修改的情况直达想要的位置,也上个图简单示意一下。
触发断点之后说明运行的到了 .init / .init_array / JNI_Onload 的出发点,然后 F7 即可进入对应 .so ELF 内执行的代码位置。
.init Segment
根据上面说的来到 .init 在 .so 里的位置,偏移量是 [+ 14D4],IDA 静态 + F5 之后得到伪代码,下面是完善函数名之后的伪代码。int func_init() { unsigned int v0; // ST44_4@11 unsigned int v1; // ST40_4@11 unsigned __int64 v2; // kr00_8@13 _BYTE v3; // ST27_1@15 _DWORD j; // [sp+14h] [bp-44h]@13 int v6; // [sp+18h] [bp-40h]@13 _DWORD v7; // [sp+1Ch] [bp-3Ch]@13 char v8; // [sp+2Eh] [bp-2Ah]@13 char v9; // [sp+2Fh] [bp-29h]@13 char v10; // [sp+30h] [bp-28h]@13 char v11; // [sp+33h] [bp-25h]@13 unsigned int v12; // [sp+34h] [bp-24h]@4 int v13; // [sp+38h] [bp-20h]@4 unsigned int v14; // [sp+48h] [bp-10h]@4 unsigned int i; // [sp+4Ch] [bp-Ch]@1 for ( i = (unsigned int)func_init & 0xFFFFF000; *(_DWORD *)i != 1179403647; i -= 4096 ) ; v14 = 0; v13 = i + *(_DWORD *)(i + 28); v12 = 0; while ( v12 < *(_WORD *)(i + 44) ) { if ( *(_DWORD *)v13 != 1 || *(_DWORD *)(v13 + 24) != 5 ) { if ( *(_DWORD *)v13 == 1 && *(_DWORD *)(v13 + 24) == 6 ) { v0 = *(_DWORD *)(v13 + 8) & 0xFFFFF000; v1 = (*(_DWORD *)(v13 + 8) + *(_DWORD *)(v13 + 16) + 4095) & 0xFFFFF000; break; } } else { v14 = (*(_DWORD *)(v13 + 8) + *(_DWORD *)(v13 + 16) + 4095) & 0xFFFFF000; } ++v12; v13 += 32; } v11 = 43; v10 = -103; v9 = 32; v8 = 21; v2 = (unsigned __int64)word_A010[0] << 16; v7 = LOWORD(word_A010[0]); v6 = LOWORD(word_A010[0]) - (word_A010[0] >> 16); mmprotect( (void *)(i + HIDWORD(v2)), (void *)((v6 + 4095) & 0xFFFFF000), &bad_offset_80003911[2], (void *)(i + HIDWORD(v2))); for ( j = HIDWORD(v2); j <= v7; ++j ) { v3 = *(_BYTE *)(i + j); *(_BYTE *)(i + j) ^= (unsigned __int8)((j ^ (v10 - v9)) + v8) ^ v11; *(_BYTE *)(i + j) += v10 ^ v9 & v8; v11 += v3 & (v10 + v9 - v8) & j; v10 += v3 ^ (v11 + j); v9 ^= (unsigned __int8)(v3 - v11) ^ (unsigned __int8)j; v8 -= v3 + v11 - j; } mmprotect( (void *)(i + HIDWORD(v2)), (void *)((v6 + 4095) & 0xFFFFF000), (char *)&off_4 + 1, (void *)(i + HIDWORD(v2))); cacheflush_syscall(i + HIDWORD(v2), v6); word_A010[0] = i; dword_A380 = i; unk_A384 = v14; return sub_8630(); }略过很多字节变换,略过重命名后的 mmprotect() 和 cacheflush_syscall(),整段其实就执行了一个函数 [sub_8630],跟进之后发现伪代码如下。
int sub_8630() { int result; // r0@1 int v1; // [sp+Ch] [bp-4h]@1 v1 = 0; dword_A378 = 0; result = pthread_create(&v1, 0, anti_init, dword_A380); unk_A37C = 1; return result; }可以看出是 pthread_create 新开了一个线程执行 anti_init 函数,进入 F5 查看 anti_init 函数伪代码。
一个 while(1) 的循环里面根据不同的条件执行了 3 个 raise() 函数,不用管具体是根据什么样的 3 个条件执行的 raise() 操作,直接把 [BL j_raise] 对应 arm 十六进制码修改成 [Mov R1, R1] 就可以达到 Bypass 反调试的目的,这个地方殊途同归的 Bypass 方法很多。int __fastcall anti_init(int a1) { int v2; // r0@3 int v3; // r0@3 int v4; // r1@3 int v5; // r2@7 int v6; // r0@10 int *v7; // r3@14 int *v8; // r1@15 int *v9; // r3@15 int v10; // r2@15 unsigned int v11; // r0@15 int *v12; // r3@16 int v13; // [sp+0h] [bp-480h]@3 int v14; // [sp+4h] [bp-47Ch]@16 int v15; // [sp+8h] [bp-478h]@16 int v16; // [sp+Ch] [bp-474h]@15 int v17; // [sp+10h] [bp-470h]@14 int v18; // [sp+14h] [bp-46Ch]@14 int v19; // [sp+18h] [bp-468h]@12 int v20; // [sp+1Ch] [bp-464h]@12 int v21; // [sp+20h] [bp-460h]@9 int v22; // [sp+24h] [bp-45Ch]@7 int v23; // [sp+28h] [bp-458h]@7 int v24; // [sp+2Ch] [bp-454h]@3 int v25; // [sp+30h] [bp-450h]@3 int fd_1; // [sp+34h] [bp-44Ch]@3 int v27; // [sp+38h] [bp-448h]@3 int v28; // [sp+3Ch] [bp-444h]@1 void *v29; // [sp+40h] [bp-440h]@1 char *v30; // [sp+44h] [bp-43Ch]@1 char *v31; // [sp+48h] [bp-438h]@1 char v32; // [sp+4Ch] [bp-434h]@1 char v33; // [sp+4Dh] [bp-433h]@1 char v34; // [sp+4Eh] [bp-432h]@1 char v35; // [sp+4Fh] [bp-431h]@1 char v36; // [sp+50h] [bp-430h]@1 char v37; // [sp+51h] [bp-42Fh]@1 char v38; // [sp+52h] [bp-42Eh]@1 char v39; // [sp+53h] [bp-42Dh]@1 char v40; // [sp+54h] [bp-42Ch]@1 char v41; // [sp+55h] [bp-42Bh]@1 char v42; // [sp+56h] [bp-42Ah]@1 char v43; // [sp+57h] [bp-429h]@1 char v44; // [sp+58h] [bp-428h]@1 char v45; // [sp+59h] [bp-427h]@1 char v46; // [sp+5Ah] [bp-426h]@1 char v47; // [sp+5Bh] [bp-425h]@1 int fd; // [sp+5Ch] [bp-424h]@3 char v49; // [sp+60h] [bp-420h]@7 int v50; // [sp+460h] [bp-20h]@4 int v51; // [sp+464h] [bp-1Ch]@1 int v52; // [sp+468h] [bp-18h]@1 int v53; // [sp+46Ch] [bp-14h]@1 v53 = a1; ++dword_A378; v31 = (char *)&GLOBAL_OFFSET_TABLE_; v30 = &v32; v29 = &GLOBAL_OFFSET_TABLE_; unk_A388 = malloc(1024); v28 = sub_6DEC(); unk_A38C = sub_6EE0(0, v53, unk_A384); v52 = getppid(); v38 = unk_A2B7 ^ 0x96; v37 = unk_A2B6 ^ 0xF7; v46 = unk_A2BF ^ 0xE1; v39 = unk_A2B8 ^ 0x9E; v34 = unk_A2B3 ^ 0x85; v41 = unk_A2BA ^ 0x98; v47 = unk_A2C0; v32 = unk_A2B1 ^ 0xE9; v35 = unk_A2B4 ^ 0x95; v44 = unk_A2BD ^ 0xCA; v42 = unk_A2BB ^ 0xEE; v36 = unk_A2B5 ^ 0xEA; v33 = unk_A2B2 ^ 0x97; v45 = unk_A2BE ^ 0xD3; v43 = unk_A2BC ^ 0xA5; v40 = unk_A2B9 ^ 0xFB; v51 = opendir(&v32); if ( v51 ) { v27 = 0xFFF; fd = inotify_init(); fd_1 = fd; v2 = fcntl(fd, 3, 0); v3 = fcntl(fd_1, 4, v2 | 0x800); v4 = fd; *((_BYTE *)&v13 - 4) = byte_A2CD ^ 0x8D; *((_BYTE *)&v13 - 16) = unk_A2C1 ^ 0x91; *((_BYTE *)&v13 - 7) = byte_A2CA ^ 0xC5; *((_BYTE *)&v13 - 5) = byte_A2CC ^ 0x80; *((_BYTE *)&v13 - 13) = byte_A2C4 ^ 0xD3; *((_BYTE *)&v13 - 11) = byte_A2C6 ^ 0xE1; *((_BYTE *)&v13 - 9) = byte_A2C8 ^ 0xCA; *((_BYTE *)&v13 - 8) = byte_A2C9 ^ 0xE1; *((_BYTE *)&v13 - 2) = byte_A2CF; *((_BYTE *)&v13 - 3) = byte_A2CE ^ 0xC8; *((_BYTE *)&v13 - 15) = byte_A2C2 ^ 0x87; *((_BYTE *)&v13 - 14) = byte_A2C3 ^ 0x96; *((_BYTE *)&v13 - 6) = byte_A2CB ^ 0xDA; *((_BYTE *)&v13 - 12) = byte_A2C5 ^ 0xD7; *((_BYTE *)&v13 - 10) = byte_A2C7 ^ 0xE2; v25 = v3; v24 = inotify_add_watch(v4, (int)(&v13 - 4), v27);// "/proc/self/mem" while ( 1 ) { v50 = readdir(v51); if ( !v50 ) break; if ( *(_BYTE *)(v50 + 18) & 4 && 46 != *(_BYTE *)(v50 + 19) ) { v5 = v50 + 19; *((_BYTE *)&v13 - 11) = byte_A2DD ^ 0x8D; *((_BYTE *)&v13 - 22) = byte_A2D2 ^ 0x9E; *((_BYTE *)&v13 - 12) = byte_A2DC ^ 0xAD; *((_BYTE *)&v13 - 5) = byte_A2E3 ^ 0x86; *((_BYTE *)&v13 - 14) = byte_A2DA ^ 0xE1; *((_BYTE *)&v13 - 8) = byte_A2E0 ^ 0xB1; *((_BYTE *)&v13 - 10) = byte_A2DE ^ 0xCF; *((_BYTE *)&v13 - 15) = byte_A2D9 ^ 0xB1; *((_BYTE *)&v13 - 24) = unk_A2D0 ^ 0xA7; *((_BYTE *)&v13 - 13) = byte_A2DB ^ 0xE0; *((_BYTE *)&v13 - 7) = byte_A2E1 ^ 0xA2; *((_BYTE *)&v13 - 3) = byte_A2E5 ^ 0xAB; *((_BYTE *)&v13 - 17) = byte_A2D7 ^ 0x8B; *((_BYTE *)&v13 - 2) = byte_A2E6; *((_BYTE *)&v13 - 23) = byte_A2D1 ^ 0xBD; *((_BYTE *)&v13 - 19) = byte_A2D5 ^ 0xCC; *((_BYTE *)&v13 - 9) = byte_A2DF ^ 0xA7; *((_BYTE *)&v13 - 6) = byte_A2E2 ^ 0xE6; *((_BYTE *)&v13 - 16) = byte_A2D8 ^ 0xA0; *((_BYTE *)&v13 - 18) = byte_A2D6 ^ 0x83; *((_BYTE *)&v13 - 21) = byte_A2D3 ^ 0x98; *((_BYTE *)&v13 - 20) = byte_A2D4 ^ 0xD2; *((_BYTE *)&v13 - 4) = byte_A2E4 ^ 0xC2; v23 = sprintf(&v49, &v13 - 6, v5); v22 = inotify_add_watch(fd, (int)&v49, 0xFFF);// "/proc/self/task/{pid}/mem" } } v21 = closedir(v51); while ( 1 ) { *((_BYTE *)&v13 - 12) = byte_A2FC ^ 0x8D; *((_BYTE *)&v13 - 7) = byte_A301; *((_BYTE *)&v13 - 10) = byte_A2FE ^ 0xD9; *((_BYTE *)&v13 - 14) = byte_A2FA ^ 0xD2; *((_BYTE *)&v13 - 17) = byte_A2F7 ^ 0xD5; *((_BYTE *)&v13 - 19) = byte_A2F5 ^ 0x81; *((_BYTE *)&v13 - 22) = byte_A2F2 ^ 0xB8; *((_BYTE *)&v13 - 13) = byte_A2FB ^ 0xC7; *((_BYTE *)&v13 - 15) = byte_A2F9 ^ 0xB2; *((_BYTE *)&v13 - 18) = byte_A2F6 ^ 0x81; *((_BYTE *)&v13 - 24) = unk_A2F0 ^ 0x9C; *((_BYTE *)&v13 - 9) = byte_A2FF ^ 0x95; *((_BYTE *)&v13 - 20) = byte_A2F4 ^ 0x82; *((_BYTE *)&v13 - 23) = byte_A2F1 ^ 0x81; *((_BYTE *)&v13 - 16) = byte_A2F8 ^ 0x88; *((_BYTE *)&v13 - 8) = byte_A300 ^ 0xC; *((_BYTE *)&v13 - 11) = byte_A2FD ^ 0xC8; *((_BYTE *)&v13 - 21) = byte_A2F3 ^ 0x8B; v6 = chk_status_trace((int)(&v13 - 6)); if ( v6 != v52 ) { *((_BYTE *)&v13 - 16) = byte_A2F8 ^ 0x88; *((_BYTE *)&v13 - 11) = byte_A2FD ^ 0xC8; *((_BYTE *)&v13 - 24) = unk_A2F0 ^ 0x9C; *((_BYTE *)&v13 - 9) = byte_A2FF ^ 0x95; *((_BYTE *)&v13 - 8) = byte_A300 ^ 0xC; *((_BYTE *)&v13 - 10) = byte_A2FE ^ 0xD9; *((_BYTE *)&v13 - 20) = byte_A2F4 ^ 0x82; *((_BYTE *)&v13 - 18) = byte_A2F6 ^ 0x81; *((_BYTE *)&v13 - 7) = byte_A301; *((_BYTE *)&v13 - 23) = byte_A2F1 ^ 0x81; *((_BYTE *)&v13 - 19) = byte_A2F5 ^ 0x81; *((_BYTE *)&v13 - 14) = byte_A2FA ^ 0xD2; *((_BYTE *)&v13 - 21) = byte_A2F3 ^ 0x8B; *((_BYTE *)&v13 - 12) = byte_A2FC ^ 0x8D; *((_BYTE *)&v13 - 13) = byte_A2FB ^ 0xC7; *((_BYTE *)&v13 - 22) = byte_A2F2 ^ 0xB8; *((_BYTE *)&v13 - 15) = byte_A2F9 ^ 0xB2; *((_BYTE *)&v13 - 17) = byte_A2F7 ^ 0xD5; if ( chk_status_trace((int)(&v13 - 6)) ) { *((_BYTE *)&v13 - 6) = byte_A304 ^ 0xAF; *((_BYTE *)&v13 - 8) = unk_A302 ^ 0x8B; *((_BYTE *)&v13 - 5) = byte_A305 ^ 0xF3; *((_BYTE *)&v13 - 7) = byte_A303 ^ 0xCB; *((_BYTE *)&v13 - 4) = byte_A306; *((_BYTE *)&v13 - 13) = byte_A30A ^ 0xA7; *((_BYTE *)&v13 - 5) = byte_A312 ^ 0xDF; *((_BYTE *)&v13 - 9) = byte_A30E ^ 0xB5; *((_BYTE *)&v13 - 14) = byte_A309 ^ 0xAC; *((_BYTE *)&v13 - 4) = byte_A313 ^ 0x80; *((_BYTE *)&v13 - 8) = byte_A30F ^ 0xFD; *((_BYTE *)&v13 - 12) = byte_A30B ^ 0xC4; *((_BYTE *)&v13 - 7) = byte_A310 ^ 0xE7; *((_BYTE *)&v13 - 15) = byte_A308 ^ 0xC5; *((_BYTE *)&v13 - 16) = unk_A307 ^ 0xA9; *((_BYTE *)&v13 - 3) = byte_A314; *((_BYTE *)&v13 - 6) = byte_A311 ^ 0x9E; *((_BYTE *)&v13 - 10) = byte_A30D ^ 0x93; *((_BYTE *)&v13 - 11) = byte_A30C ^ 0xE3; v20 = log(6, (int)(&v13 - 2), (int)(&v13 - 4), (int)(&v13 - 4));// log("anti", "tracer antied") v19 = j_raise(0x11); } } if ( read(fd, &v49, dword_400) > 0 ) { *((_BYTE *)&v13 - 5) = byte_A305 ^ 0xF3; *((_BYTE *)&v13 - 4) = byte_A306; *((_BYTE *)&v13 - 6) = byte_A304 ^ 0xAF; *((_BYTE *)&v13 - 8) = unk_A302 ^ 0x8B; *((_BYTE *)&v13 - 7) = byte_A303 ^ 0xCB; v7 = &v13 - 4; *(_BYTE *)v7 = unk_A315 ^ 0xB2; *((_BYTE *)&v13 - 14) = unk_A317 ^ 0xA6; *((_BYTE *)&v13 - 11) = unk_A31A ^ 0xBF; *((_BYTE *)&v13 - 13) = unk_A318 ^ 0xBA; *((_BYTE *)&v13 - 15) = unk_A316 ^ 0xAF; *((_BYTE *)&v13 - 10) = unk_A31B ^ 0x92; *((_BYTE *)&v13 - 7) = unk_A31E ^ 0xE7; *((_BYTE *)&v13 - 9) = unk_A31C ^ 0x9E; *((_BYTE *)&v13 - 8) = unk_A31D ^ 0xB3; *((_BYTE *)&v13 - 12) = unk_A319 ^ 0xDD; *((_BYTE *)v7 + 10) = unk_A31F; v18 = log(6, (int)(&v13 - 2), (int)(&v13 - 4), (int)(&v13 - 4));// log("anti", "mem antied") v17 = j_raise(17); } v8 = (int *)&v31[(_DWORD)&dword_438[2]]; v9 = (int *)&v31[(_DWORD)&dword_438[4]]; ++*((_DWORD *)v31 + 269); v10 = *v8; v16 = *v9; v11 = sub_6EE0(0, v53, v10); if ( v16 != v11 ) { *((_BYTE *)&v13 - 5) = byte_A305 ^ 0xF3; *((_BYTE *)&v13 - 4) = byte_A306; *((_BYTE *)&v13 - 7) = byte_A303 ^ 0xCB; *((_BYTE *)&v13 - 8) = unk_A302 ^ 0x8B; *((_BYTE *)&v13 - 6) = byte_A304 ^ 0xAF; v12 = &v13 - 2; *(_BYTE *)v12 = unk_A320 ^ 0xCD; *((_BYTE *)&v13 - 6) = unk_A322 ^ 0x87; *((_BYTE *)&v13 - 7) = unk_A321 ^ 0xDF; *((_BYTE *)&v13 - 3) = unk_A325 ^ 0xF5; *((_BYTE *)&v13 - 5) = unk_A323 ^ 0xFC; *((_BYTE *)&v13 - 2) = unk_A326; *((_BYTE *)v12 + 4) = unk_A324 ^ 0x1A; v15 = log(6, (int)(&v13 - 2), (int)(&v13 - 2), (int)(&v13 - 2));// log("anti", "antied") v14 = j_raise(17); } v13 = sleep(1); } } return 0; }
JNI_Onload
还是同样的方法来到 JNI_Onload 在 .so 里的位置,偏移量是 [+ 65A8],IDA 静态查看,F5 之后得到对应的伪代码,动态 + 静态结合调试可以还原出大部分函数的真实目的。
void *__fastcall JNI_Onload(JavaVM *J_vm_1, JNIEnv *J_env) { char v2; // r0@5 int v3; // r0@9 int v4; // lr@9 int v5; // r3@9 char *v6; // r12@9 int v8; // [sp+0h] [bp-450h]@8 int (__fastcall *J_dlsym_1)(_DWORD, _DWORD); // [sp+4h] [bp-44Ch]@10 int v10; // [sp+8h] [bp-448h]@9 int v11; // [sp+Ch] [bp-444h]@9 int v12; // [sp+10h] [bp-440h]@9 int *v13; // [sp+14h] [bp-43Ch]@9 int a1a; // [sp+18h] [bp-438h]@9 int v15; // [sp+1Ch] [bp-434h]@8 int v16; // [sp+20h] [bp-430h]@4 char *v17; // [sp+24h] [bp-42Ch]@1 int v18; // [sp+28h] [bp-428h]@1 int (__fastcall *J_dlsym)(_DWORD, _DWORD); // [sp+2Ch] [bp-424h]@9 int v20; // [sp+30h] [bp-420h]@9 int v21; // [sp+34h] [bp-41Ch]@2 JNIEnv *J_env_1; // [sp+434h] [bp-1Ch]@1 JavaVM *J_vm; // [sp+438h] [bp-18h]@1 void *v24; // [sp+43Ch] [bp-14h]@10 J_vm = J_vm_1; J_env_1 = J_env; v18 = 0; v17 = (char *)&GLOBAL_OFFSET_TABLE_; while ( sub_69D4((int)&v21) ) ; if ( !*(_DWORD *)&v17[(_DWORD)dword_438] ) v16 = j_raise(9); while ( 1 ) { v2 = 0; if ( *((_DWORD *)v17 + 269) ) v2 = 1; if ( !(((unsigned __int8)v2 ^ 1) & 1) ) break; *((_BYTE *)&v8 - 7) = byte_A025 ^ 0xB5; *((_BYTE *)&v8 - 8) = unk_A024 ^ 0x81; *((_BYTE *)&v8 - 4) = byte_A028 ^ 0xEC; *((_BYTE *)&v8 - 6) = byte_A026 ^ 0xD4; *((_BYTE *)&v8 - 5) = byte_A027 ^ 0xF5; *((_BYTE *)&v8 - 3) = byte_A029; *((_BYTE *)&v8 - 13) = byte_A207 ^ 0xBA; *((_BYTE *)&v8 - 6) = byte_A20E; *((_BYTE *)&v8 - 14) = byte_A206 ^ 0x88; *((_BYTE *)&v8 - 8) = byte_A20C ^ 0xD3; *((_BYTE *)&v8 - 9) = byte_A20B ^ 0xC9; *((_BYTE *)&v8 - 12) = byte_A208 ^ 0xF7; *((_BYTE *)&v8 - 11) = byte_A209 ^ 0xED; *((_BYTE *)&v8 - 16) = unk_A204 ^ 0xD1; *((_BYTE *)&v8 - 10) = byte_A20A ^ 0xEB; *((_BYTE *)&v8 - 15) = byte_A205 ^ 0xCE; *((_BYTE *)&v8 - 7) = byte_A20D ^ 0x91; v15 = log(6, (int)(&v8 - 2), (int)(&v8 - 4), (int)(&v8 - 4)); } a1a = 6; v13 = &v21; v12 = (int)&GLOBAL_OFFSET_TABLE_; v11 = J_unzip((int)&v21, dword_A020); v3 = linker_method_dlopen((int)v13, 0); v20 = v3; v4 = v12 + 715; *((_BYTE *)&v8 - 6) = *(_BYTE *)(v12 + 725); *((_BYTE *)&v8 - 14) = *(_BYTE *)(v4 + 2) ^ 0x8B; *((_BYTE *)&v8 - 7) = *(_BYTE *)(v4 + 9) ^ 0xB0; *((_BYTE *)&v8 - 8) = *(_BYTE *)(v4 + 8) ^ 0x92; *((_BYTE *)&v8 - 9) = *(_BYTE *)(v4 + 7) ^ 0xCD; *((_BYTE *)&v8 - 11) = *(_BYTE *)(v4 + 5) ^ 0x84; *((_BYTE *)&v8 - 16) = *(_BYTE *)v4 ^ 0xC3; *((_BYTE *)&v8 - 12) = *(_BYTE *)(v4 + 4) ^ 0xA4; *((_BYTE *)&v8 - 13) = *(_BYTE *)(v4 + 3) ^ 0xB1; *((_BYTE *)&v8 - 10) = *(_BYTE *)(v4 + 6) ^ 0x9E; *((_BYTE *)&v8 - 15) = *(_BYTE *)(v4 + 1) ^ 0xDB; J_dlsym = (int (__fastcall *)(_DWORD, _DWORD))linker_method_dlsym(v3, &v8 - 4); v5 = v12; v6 = &byte_E0[v12]; *((_BYTE *)&v8 - 7) = byte_E0[v12 + 1] ^ 0xB5; *((_BYTE *)&v8 - 4) = v6[4] ^ 0xEC; *((_BYTE *)&v8 - 3) = v6[5]; *((_BYTE *)&v8 - 8) = *v6 ^ 0x81; *((_BYTE *)&v8 - 5) = v6[3] ^ 0xF5; *((_BYTE *)&v8 - 6) = v6[2] ^ 0xD4; *((_BYTE *)&v8 - 13) = *(_BYTE *)(v5 + 729) ^ 0xAA; *((_BYTE *)&v8 - 12) = *(_BYTE *)(v5 + 730) ^ 0xBE; *((_BYTE *)&v8 - 16) = *(_BYTE *)(v5 + 726) ^ 0x84; *((_BYTE *)&v8 - 15) = *(_BYTE *)(v5 + 727) ^ 0xC9; *((_BYTE *)&v8 - 6) = *(_BYTE *)(v5 + 736); *((_BYTE *)&v8 - 7) = *(_BYTE *)(v5 + 735) ^ 0xC7; *((_BYTE *)&v8 - 14) = *(_BYTE *)(v5 + 728) ^ 0xA9; *((_BYTE *)&v8 - 11) = *(_BYTE *)(v5 + 731) ^ 0x95; *((_BYTE *)&v8 - 9) = *(_BYTE *)(v5 + 733) ^ 0x9D; *((_BYTE *)&v8 - 10) = *(_BYTE *)(v5 + 732) ^ 0xDC; *((_BYTE *)&v8 - 8) = *(_BYTE *)(v5 + 734) ^ 0xC2; v10 = log(a1a, (int)(&v8 - 2), (int)(&v8 - 4), v5);// log("txtag", "load done!") if ( J_dlsym ) { J_dlsym_1 = J_dlsym; v24 = (void *)J_dlsym(J_vm, J_env_1); } else { v24 = &unk_10004; } return v24; }
跳到 .so 外的一段内存,很明显是程序 mmap 进来的内容,至于怎么 mmap mmprotect 之类的不需要做太多关注,看看这里指向代码的功能。
debug150:7860E800 ; signed int __fastcall sub_7860E800(int a1, int) debug150:7860E800 sub_7860E800 debug150:7860E800 debug150:7860E800 var_14= -0x14 debug150:7860E800 debug150:7860E800 PUSH {R0,R1,R4-R6,LR} debug150:7860E802 ADD R5, SP, #0x18+var_14 debug150:7860E804 MOVS R4, #0 debug150:7860E806 MOVS R1, R5 debug150:7860E808 LDR R2, =0x10006 debug150:7860E80A MOVS R6, R0 debug150:7860E80C STR R4, [SP,#0x18+var_14] debug150:7860E80E BL J_getEnv debug150:7860E812 CMP R0, R4 debug150:7860E814 BEQ loc_7860E844 debug150:7860E816 MOVS R0, R6 debug150:7860E818 MOVS R1, R5 debug150:7860E81A LDR R2, =0x10004 debug150:7860E81C BL J_getEnv debug150:7860E820 CMP R0, R4 debug150:7860E822 BEQ loc_7860E848 debug150:7860E824 MOVS R0, R6 debug150:7860E826 MOVS R1, R5 debug150:7860E828 LDR R2, =0x10002 debug150:7860E82A BL J_getEnv debug150:7860E82E CMP R0, R4 debug150:7860E830 BEQ loc_7860E84C debug150:7860E832 MOVS R0, R6 debug150:7860E834 MOVS R1, R5 debug150:7860E836 LDR R2, =0x10001 debug150:7860E838 BL J_getEnv debug150:7860E83C CMP R0, R4 debug150:7860E83E BNE loc_7860E85E debug150:7860E840 LDR R4, =0x10001 debug150:7860E842 B loc_7860E84E debug150:7860E844 ; --------------------------------------------------------------------------- debug150:7860E844 debug150:7860E844 loc_7860E844 ; CODE XREF: sub_7860E800+14 j debug150:7860E844 LDR R4, =0x10006 debug150:7860E846 B loc_7860E84E debug150:7860E848 ; --------------------------------------------------------------------------- debug150:7860E848 debug150:7860E848 loc_7860E848 ; CODE XREF: sub_7860E800+22 j debug150:7860E848 LDR R4, =0x10004 debug150:7860E84A B loc_7860E84E debug150:7860E84C ; --------------------------------------------------------------------------- debug150:7860E84C debug150:7860E84C loc_7860E84C ; CODE XREF: sub_7860E800+30 j debug150:7860E84C LDR R4, =0x10002 debug150:7860E84E debug150:7860E84E loc_7860E84E ; CODE XREF: sub_7860E800+42 j debug150:7860E84E ; sub_7860E800+46 j ... debug150:7860E84E LDR R3, [SP,#0x18+var_14] debug150:7860E850 CMP R3, #0 debug150:7860E852 BEQ loc_7860E85E debug150:7860E854 BL sub_7860EFB8 debug150:7860E858 LDR R0, [SP,#0x18+var_14] debug150:7860E85A BL sub_7860E7C4 debug150:7860E85E debug150:7860E85E loc_7860E85E ; CODE XREF: sub_7860E800+3E j debug150:7860E85E ; sub_7860E800+52 j debug150:7860E85E MOVS R0, R4 debug150:7860E860 POP {R1,R2,R4-R6,PC} debug150:7860E860 ; End of function sub_7860E800
还是一堆的赋值操作略过不表,看到执行了 [sub_7860EFB8] [sub_7860E7C4] 两个函数,分别看下这两个函数的作用。
signed int sub_7860EFB8() { signed int result; // r0@1 dword_78626068 = (int)"java/lang/String"; dword_7862606C = (int)"getBytes"; dword_78626070 = (int)"()[B"; dword_78626074 = (int)"android/os/Build$VERSION"; dword_78626078 = (int)"SDK_INT"; dword_7862607C = (int)"I"; ....... }
[sub_7860EFB8] 全是赋值操作,跳过。下面是 F5 之后的 [sub_7860E7C4],主要执行了 [sub_7860E780] 然后打了个 registerNatives 相关的 log,相信作安卓逆向的同学看到 registerNative 这个都会比较激动吧,跟进 [sub_7860E780]。
F5 后的伪代码如下,亮眼的 0x35C 刚好是 registerNatives 相对于 JNINativeInterface 的偏移量,在这下断。int __fastcall sub_7860E7C4(int a1) { int v1; // r4@1 v1 = sub_7860E780(a1, (int)"com/tencent/StubShell/TxAppEntry", (int)&dword_78626004, 5); if ( v1 ) v1 = 1; else log(3, (int)"SecShell", (int)"registerNatives Fail"); return v1; }
触发断点之后查看 R2 寄存器的值。int __fastcall sub_7860E780(int a1, int a2, int a3, int a4) { int v4; // r5@1 int v5; // r4@1 int v6; // r6@1 int J_env; // r1@1 int v8; // r0@2 v4 = a4; v5 = a1; v6 = a3; J_env = (*(int (**)(void))(*(_DWORD *)a1 + 0x18))(); if ( J_env ) { v8 = (*(int (__fastcall **)(int, int, int, int))(*(_DWORD *)v5 + 0x35C))(v5, J_env, v6, v4);// registerNatives J_env = 1; if ( v8 < 0 ) { ((void (__fastcall *)(signed int, const char *, const char *))log)(3, "SecShell", "register nativers error"); J_env = 0; } } return J_env; }
可以看到这里的 RegisterNative 是用来注册 native load(Landroid/content/Context;)V ,函数指针则是 [0x78615839],至于为什么是这样可以参考我 *这一篇文章。
接着跳入 [0x78615839],这里我直接贴 F5 + 重命名函数之后的伪代码了,如图。
可以看到先检查了 * sdk 版本,* dalvik Or art,* 是否存在 zjdroid,然后在分别进行了两个操作,因为这里我用的是 dalvik,所以跟进 [sub_78614CD0]。
_DWORD *__fastcall sub_78614CD0(int a1, int a2) { int v2; // r6@1 int v3; // r0@2 int v4; // r4@2 int v5; // r0@2 int v6; // r0@2 int v7; // r0@2 int v8; // r7@2 int v9; // ST00_4@3 int v10; // ST00_4@3 int v11; // r0@5 int v12; // ST00_4@5 const char *v13; // r1@6 const char *v14; // r2@6 int v15; // r0@16 int v16; // r5@16 _DWORD *v17; // r3@16 int v18; // ST00_4@17 int v19; // ST00_4@18 const char *v20; // r1@20 const char *v21; // r2@20 int v22; // r4@21 int v23; // r1@23 const char *v24; // r1@24 const char *v25; // r2@24 int v26; // r4@33 int v27; // ST14_4@37 int v28; // r0@37 int v29; // r1@38 int v30; // r1@41 int v31; // r5@44 int v32; // ST00_4@44 int v33; // r0@45 int v34; // ST00_4@46 int v35; // r5@46 int v36; // r4@50 int v37; // r4@54 int v38; // r2@58 int v39; // r3@59 int v40; // r3@61 int v41; // r3@62 int v42; // r3@63 int v43; // r3@64 int v44; // r5@64 int v45; // r2@65 int v46; // r5@77 int v47; // r2@77 int v48; // r0@79 int v49; // r0@80 int v50; // r4@82 int v51; // r0@84 int v52; // r5@84 int m; // r4@84 int v54; // r0@86 int v55; // r2@87 const char *v56; // r3@87 int v57; // ST00_4@87 int v58; // r1@87 int v59; // r0@87 int v60; // r0@76 int i; // r4@76 int v62; // r0@90 int v63; // r5@92 int v64; // r0@92 int j; // r4@92 int v66; // r0@94 int v67; // r5@95 int v68; // r4@95 int v69; // r0@95 int k; // r4@95 int v71; // r0@97 int v72; // r5@98 int v73; // r4@98 int v74; // r7@98 int v75; // r0@98 int v76; // r0@98 int l; // r4@98 int v78; // r0@100 int v79; // r4@101 int v80; // r0@101 int v81; // ST00_4@102 int v82; // ST00_4@103 _DWORD *result; // r0@105 int v84; // [sp+10h] [bp-120h]@3 int v85; // [sp+10h] [bp-120h]@76 int v86; // [sp+14h] [bp-11Ch]@5 signed int v87; // [sp+14h] [bp-11Ch]@37 int v88; // [sp+14h] [bp-11Ch]@95 int v89; // [sp+18h] [bp-118h]@3 int v90; // [sp+18h] [bp-118h]@13 int v91; // [sp+1Ch] [bp-114h]@1 signed int v92; // [sp+20h] [bp-110h]@33 int v93; // [sp+20h] [bp-110h]@51 int v94; // [sp+24h] [bp-10Ch]@3 int v95; // [sp+24h] [bp-10Ch]@95 int v96; // [sp+28h] [bp-108h]@2 signed int v97; // [sp+28h] [bp-108h]@51 int v98; // [sp+2Ch] [bp-104h]@3 int v99; // [sp+30h] [bp-100h]@13 int v100; // [sp+34h] [bp-FCh]@13 int v101; // [sp+38h] [bp-F8h]@2 int v102; // [sp+3Ch] [bp-F4h]@13 int v103; // [sp+40h] [bp-F0h]@37 int v104; // [sp+44h] [bp-ECh]@3 int v105; // [sp+4Ch] [bp-E4h]@92 int v106; // [sp+54h] [bp-DCh]@2 _DWORD *v107; // [sp+5Ch] [bp-D4h]@1 int v108; // [sp+60h] [bp-D0h]@34 char v109; // [sp+64h] [bp-CCh]@37 char v110; // [sp+74h] [bp-BCh]@50 int v111; // [sp+88h] [bp-A8h]@50 char v112; // [sp+8Ch] [bp-A4h]@50 int v113; // [sp+A0h] [bp-90h]@50 char v114; // [sp+A4h] [bp-8Ch]@34 int v115; // [sp+B8h] [bp-78h]@34 signed int v116; // [sp+C4h] [bp-6Ch]@37 int v117; // [sp+114h] [bp-1Ch]@1 v2 = a1; v117 = *(_DWORD *)dword_78625DA4; v107 = (_DWORD *)dword_78625DA4; v91 = J_GC_object_method( a1, a2, (int)"android/content/Context", (int)"getClassLoader", (int)"()Ljava/lang/ClassLoader;"); if ( !v91 ) goto LABEL_105; v3 = getEnv(v2, "com/tencent/StubShell/TxAppEntry"); v4 = v3; v5 = ((int (__fastcall *)(int, int, const char *, const char *))unk_78610864)( v2, v3, "mSrcPath", "Ljava/lang/String;"); v101 = ((int (__fastcall *)(int, int, int))unk_78610872)(v2, v4, v5); v96 = J_copy_array_bytes(v2, v101); v6 = ((int (__fastcall *)(int, int, const char *, const char *))unk_78610864)(v2, v4, "mPKName", "Ljava/lang/String;"); v7 = ((int (__fastcall *)(int, int, int))unk_78610872)(v2, v4, v6); v106 = J_copy_array_bytes(v2, v7); v8 = unk_78625DA8; if ( J_sdk_int > 10 ) { v9 = *(_DWORD *)(unk_78625DA8 + 248); v104 = ((int (__fastcall *)(int, int, _DWORD, _DWORD))unk_7860EE40)( v2, v91, *(_DWORD *)(unk_78625DA8 + 240), *(_DWORD *)(unk_78625DA8 + 244)); v10 = *(_DWORD *)(v8 + 220); v98 = ((int (__fastcall *)(int, int, _DWORD, _DWORD))unk_7860EE40)( v2, v104, *(_DWORD *)(v8 + 212), *(_DWORD *)(v8 + 216)); v94 = J_getArrayLength(v2, v98); v89 = 0; v84 = 0; while ( 1 ) { if ( v89 >= v94 ) { v90 = 0; v102 = 0; v100 = 0; v99 = 0; goto LABEL_33; } v11 = ((int (__fastcall *)(int, int, int))unk_7860E8C8)(v2, v98, v89); v12 = *(_DWORD *)(v8 + 232); v86 = ((int (__fastcall *)(_DWORD, _DWORD, _DWORD, _DWORD))unk_7860EE40)( v2, v11, *(_DWORD *)(v8 + 224), *(_DWORD *)(v8 + 228)); if ( !v86 ) break; v84 = ((int (__fastcall *)(int, int, _DWORD, _DWORD))unk_7860F770)( v2, v86, *(_DWORD *)(v8 + 236), *(_DWORD *)(v8 + 424)); if ( !v84 ) { v84 = ((int (__fastcall *)(int, int, _DWORD, _DWORD))unk_7860F950)( v2, v86, *(_DWORD *)(v8 + 236), *(_DWORD *)(v8 + 424)); if ( !v84 ) { v13 = "SecShell"; v14 = "SetDexClassLoaderCookie GetIntField fail"; goto LABEL_10; } } if ( *(_DWORD *)v84 && !((int (__cdecl *)(_DWORD))unk_7861EC2C)(*(_DWORD *)v84) ) { v90 = 0; v102 = 0; v100 = 0; v99 = 0; goto LABEL_33; } LABEL_14: ++v89; } v13 = "SecShell"; v14 = "SetDexClassLoaderCookie GetObjectField fail:pDexPathListElementsClassName"; LABEL_10: log(3, (int)v13, (int)v14); goto LABEL_14; } v15 = getEnv(v2, *(_DWORD *)(unk_78625DA8 + 456)); v16 = ((int (__fastcall *)(int, int, int))unk_7861080E)(v2, v91, v15); v17 = (_DWORD *)(v8 + 204); if ( v16 ) { v18 = *(_DWORD *)(v8 + 208); v99 = ((int (__fastcall *)(_DWORD, _DWORD, _DWORD, _DWORD))unk_7860EE40)(v2, v91, *(_DWORD *)(v8 + 456), *v17); v100 = ((int (__fastcall *)(int, int, _DWORD, const char *))unk_7860EE40)(v2, v91, *(_DWORD *)(v8 + 456), "mPaths"); v102 = ((int (__fastcall *)(_DWORD, _DWORD, _DWORD, const char *))unk_7860EE40)( v2, v91, *(_DWORD *)(v8 + 456), "mFiles"); v90 = ((int (__fastcall *)(_DWORD, _DWORD, _DWORD, const char *))unk_7860EE40)( v2, v91, *(_DWORD *)(v8 + 456), "mZips"); } else { v19 = *(_DWORD *)(v8 + 208); v99 = ((int (__fastcall *)(_DWORD, _DWORD, _DWORD, _DWORD))unk_7860EE40)(v2, v91, *(_DWORD *)(v8 + 200), *v17); v102 = ((int (__fastcall *)(_DWORD, _DWORD, _DWORD, const char *))unk_7860EE40)( v2, v91, *(_DWORD *)(v8 + 200), "mFiles"); v100 = 0; v90 = ((int (__fastcall *)(_DWORD, _DWORD, _DWORD, const char *))unk_7860EE40)( v2, v91, *(_DWORD *)(v8 + 200), "mZips"); } if ( !v99 ) { v20 = "SecShell"; v21 = "SetDexClassLoaderCookie GetObjectField fail:pmDexs"; goto LABEL_48; } v22 = 0; v94 = J_getArrayLength(v2, v99); v84 = 0; while ( 1 ) { if ( v22 >= v94 ) { v98 = 0; v104 = 0; goto LABEL_33; } v23 = ((int (__fastcall *)(int, int, int))unk_7860E8C8)(v2, v99, v22); if ( !v23 ) { v24 = "SecShell"; v25 = "SetDexClassLoaderCookie GetObjectArrayElement fail"; LABEL_27: log(3, (int)v24, (int)v25); goto LABEL_30; } v84 = ((int (__fastcall *)(int, int, _DWORD, _DWORD))unk_7860F770)( v2, v23, *(_DWORD *)(v8 + 236), *(_DWORD *)(v8 + 424)); if ( !v84 ) { v24 = "SecShell"; v25 = "SetDexClassLoaderCookie GetIntField fail"; goto LABEL_27; } if ( *(_DWORD *)v84 && !((int (__cdecl *)(_DWORD))unk_7861EC2C)(*(_DWORD *)v84) ) break; LABEL_30: ++v22; } v98 = 0; v104 = 0; LABEL_33: v26 = sub_786123A4(v106, (int)"classes.dex", 0); v92 = 0; if ( !v26 ) { ((void (__fastcall *)(char *, int, int *))unk_786124E8)(&v114, v96, &v108); log(3, (int)"SecShell", (int)"strSrcPath:%s"); ((void (__fastcall *)(char *))unk_78612A54)(&v114); log(3, (int)"SecShell", (int)"strSrcPath:%s"); v26 = sub_786123A4(v115, (int)"classes.dex", 0); ((void (__fastcall *)(char *))unk_786124A4)(&v114); if ( v26 ) { v92 = 0; } else { v26 = ((int (__fastcall *)(int))unk_786117A4)(v84) - 40; v92 = 1; } } v27 = ((int (__fastcall *)(int))unk_786108CA)(v26 + 40); log(3, (int)"SecShell", (int)"orgDexOffset:%d"); j_j_memset_0((int)&v114, 0, 112); memcpy((int)&v114, v26 + v27 + 40); j_j_memset_0((int)&v109, 0, 16); ((void (__fastcall *)(char *, char *, signed int, signed int))unk_78617E4C)(&v109, &v114, 112, 32); v103 = v26 + v27 + 40; v87 = v116; v28 = log(3, (int)"SecShell", (int)"fileSize:%d"); if ( v92 ) { v29 = v87; if ( v87 & 0xFFF ) v29 = (v87 / 4096 + 1) << 12; v28 = ((int (__fastcall *)(int, int, signed int))unk_7861EC7C)(v26, v29, 3); if ( v28 ) { v30 = v87; if ( v87 & 0xFFF ) v30 = (v87 / 4096 + 1) << 12; v28 = ((int (__fastcall *)(int, int, signed int))unk_7861EC7C)(v26, v30, 5); } } v31 = ((int (__fastcall *)(int))unk_78610CD4)(v28); v32 = *(_DWORD *)errno(); log(3, (int)"SecShell", (int)"mRes:%d error:%d"); if ( v31 != -1 || (v33 = log(3, (int)"SecShell", (int)"wrong code1"), ((int (__fastcall *)(int))unk_78610D24)(v33) != -1) ) { LABEL_50: ((void (__fastcall *)(char *, int, signed int, signed int))unk_78617E4C)(&v109, v103, 112, 32); ((void (__fastcall *)(char *, const char *, int *))unk_786124E8)(&v110, "/data/data/", &v108); ((void (__fastcall *)(char *, int))loc_7861261A)(&v110, v106); ((void (__fastcall *)(char *, char *, const char *))unk_786127D4)(&v112, &v110, "/mix.so"); ((void (__fastcall *)(char *, const char *))loc_7861261A)(&v110, "/mix.dex"); v36 = sub_7860ECA4(v2, v111); sub_7860ECA4(v2, v113); if ( ((int (__fastcall *)(int, int, int))unk_786112A0)(v2, v101, v111) && (v93 = J_GC_static_method( v2, (int)"dalvik/system/DexFile", (int)"loadDex", (int)"(Ljava/lang/String;Ljava/lang/String;I)Ldalvik/system/DexFile;")) != 0 ) { v101 = v36; v97 = 0; } else { log(3, (int)"SecShell", (int)"load mix.dex failed"); ((void (__fastcall *)(char *, int))unk_78612738)(&v110, v96); v93 = J_GC_static_method( v2, (int)"dalvik/system/DexFile", (int)"loadDex", (int)"(Ljava/lang/String;Ljava/lang/String;I)Ldalvik/system/DexFile;"); log(3, (int)"SecShell", (int)"load org.dex end"); v97 = 1; } v37 = ((int (__fastcall *)(_DWORD, _DWORD, _DWORD, _DWORD))unk_7860F770)( v2, v93, *(_DWORD *)(v8 + 236), *(_DWORD *)(v8 + 424)); if ( !v37 ) { v37 = ((int (__fastcall *)(int, int, _DWORD, _DWORD))unk_7860F950)( v2, v93, *(_DWORD *)(v8 + 236), *(_DWORD *)(v8 + 424)); if ( !v37 ) log(3, (int)"SecShell", (int)"testCookie is null"); } if ( v97 ) { v38 = J_sdk_int; } else { v38 = J_sdk_int; if ( J_sdk_int > 10 ) { v39 = *(_DWORD *)(*(_DWORD *)(v37 + 8) + 4); goto LABEL_64; } } v40 = *(_DWORD *)(v37 + 12); if ( v38 == 8 ) v41 = *(_DWORD *)(v40 + 36); else v42 = *(_DWORD *)(v40 + 40); LABEL_64: v108 = 0; ((void (__fastcall *)(int, int, signed int, int *))unk_78611690)(v2, v103, v87, &v108); v43 = v108; v44 = *(_DWORD *)(v108 + 4); if ( v97 ) { *(_DWORD *)(v37 + 8) = v108; *(_BYTE *)(v37 + 4) = 1; if ( J_sdk_int == 10 ) *(_DWORD *)(v84 + 16) = v103; } else { v45 = J_sdk_int; if ( J_sdk_int > 10 ) { if ( J_sdk_int <= 18 && chk_yunos() ) ((void (__fastcall *)(_DWORD, int, int))unk_78615CF0)(*(_DWORD *)(*(_DWORD *)(v37 + 8) + 4), v44, J_sdk_int); else ((void (__fastcall *)(_DWORD, int, int))unk_78615D04)(*(_DWORD *)(*(_DWORD *)(v37 + 8) + 4), v44, J_sdk_int); LABEL_75: if ( J_sdk_int <= 10 ) { v60 = getEnv(v2, "dalvik/system/DexFile"); v85 = ((int (__fastcall *)(int, int, int, _DWORD))unk_78610880)(v2, v94 + 1, v60, 0); ((void (__fastcall *)(int, int, _DWORD, int))unk_7860E8D6)(v2, v85, 0, v93); for ( i = 0; i < v94; ((void (__fastcall *)(int, int, int, int))unk_7860E8D6)(v2, v85, i, v62) ) v62 = ((int (__fastcall *)(int, int, int))unk_7860E8C8)(v2, v99, i++); if ( v100 ) { v63 = J_getArrayLength(v2, v100); v64 = getEnv(v2, "java/lang/String"); v105 = ((int (__fastcall *)(int, int, int, _DWORD))unk_78610880)(v2, v63 + 1, v64, 0); ((void (__fastcall *)(int, int, _DWORD, int))unk_7860E8D6)(v2, v105, 0, v101); for ( j = 0; j < v63; ((void (__fastcall *)(_DWORD, _DWORD, int, _DWORD))unk_7860E8D6)(v2, v105, j, v66) ) v66 = ((int (__fastcall *)(_DWORD, _DWORD, int))unk_7860E8C8)(v2, v100, j++); } v67 = J_getArrayLength(v2, v102); v68 = getEnv(v2, "java/io/File"); v88 = ((int (__fastcall *)(_DWORD, int, _DWORD, _DWORD))unk_78610880)(v2, v67 + 1, v68, 0); v69 = J_getObjectClass(v2, v68, " ", "(Ljava/lang/String;)V"); v95 = J_NewObjectV(v2, v68, v69, v101); ((void (__fastcall *)(_DWORD, _DWORD, _DWORD, _DWORD))unk_7860E8D6)(v2, v88, 0, v95); for ( k = 0; k < v67; ((void (__fastcall *)(_DWORD, _DWORD, _DWORD, _DWORD))unk_7860E8D6)(v2, v88, k, v71) ) v71 = ((int (__fastcall *)(_DWORD, _DWORD, int))unk_7860E8C8)(v2, v102, k++); v72 = J_getArrayLength(v2, v90); v73 = getEnv(v2, "java/util/zip/ZipFile"); v74 = ((int (__fastcall *)(_DWORD, int, _DWORD, _DWORD))unk_78610880)(v2, v72 + 1, v73, 0); v75 = J_getObjectClass(v2, v73, " ", "(Ljava/io/File;)V"); v76 = J_NewObjectV(v2, v73, v75, v95); ((void (__fastcall *)(_DWORD, _DWORD, _DWORD, _DWORD))unk_7860E8D6)(v2, v74, 0, v76); for ( l = 0; l < v72; ((void (__fastcall *)(_DWORD, _DWORD, _DWORD, _DWORD))unk_7860E8D6)(v2, v74, l, v78) ) v78 = ((int (__fastcall *)(_DWORD, _DWORD, int))unk_7860E8C8)(v2, v90, l++); v79 = unk_78625DA8; v80 = getEnv(v2, *(_DWORD *)(unk_78625DA8 + 456)); if ( ((int (__fastcall *)(int, int, int))unk_7861080E)(v2, v91, v80) ) { v81 = *(_DWORD *)(v79 + 208); ((void (__fastcall *)(int, int, _DWORD, _DWORD))unk_7860EEFC)( v2, v91, *(_DWORD *)(v79 + 456), *(_DWORD *)(v79 + 204)); ((void (__fastcall *)(int, int, _DWORD, const char *))unk_7860EEFC)( v2, v91, *(_DWORD *)(v79 + 456), "mPaths"); ((void (__fastcall *)(_DWORD, _DWORD, _DWORD, const char *))unk_7860EEFC)( v2, v91, *(_DWORD *)(v79 + 456), "mFiles"); v55 = *(_DWORD *)(v79 + 456); v59 = v2; v58 = v91; v56 = "mZips"; } else { v82 = *(_DWORD *)(v79 + 208); ((void (__fastcall *)(int, int, _DWORD, _DWORD))unk_7860EEFC)( v2, v91, *(_DWORD *)(v79 + 200), *(_DWORD *)(v79 + 204)); ((void (__fastcall *)(_DWORD, _DWORD, _DWORD, const char *))unk_7860EEFC)( v2, v91, *(_DWORD *)(v79 + 200), "mFiles"); v55 = *(_DWORD *)(v79 + 200); v59 = v2; v58 = v91; v56 = "mZips"; } goto LABEL_88; } v46 = getEnv(v2, "dalvik/system/DexPathList$Element"); v47 = J_getObjectClass(v2, v46, " ", "(Ljava/io/File;Ljava/util/zip/ZipFile;Ldalvik/system/DexFile;)V"); if ( v47 || (((void (__fastcall *)(int))unk_78610804)(v2), (v47 = J_getObjectClass(v2, v46, " ", "(Ljava/io/File;Ljava/io/File;Ldalvik/system/DexFile;)V")) != 0) ) { v48 = J_NewObjectV(v2, v46, v47, 0); } else { ((void (__fastcall *)(int))unk_78610804)(v2); v49 = J_getObjectClass(v2, v46, " ", "(Ljava/io/File;ZLjava/io/File;Ldalvik/system/DexFile;)V"); if ( !v49 ) { v50 = 0; LABEL_84: v51 = getEnv(v2, "dalvik/system/DexPathList$Element"); v52 = ((int (__fastcall *)(int, int, int, _DWORD))unk_78610880)(v2, v94 + 1, v51, 0); ((void (__fastcall *)(_DWORD, _DWORD, _DWORD, _DWORD))unk_7860E8D6)(v2, v52, 0, v50); for ( m = 0; m < v94; ((void (__fastcall *)(_DWORD, _DWORD, _DWORD, _DWORD))unk_7860E8D6)(v2, v52, m, v54) ) v54 = ((int (__fastcall *)(_DWORD, _DWORD, int))unk_7860E8C8)(v2, v98, m++); v55 = *(_DWORD *)(v8 + 212); v56 = *(const char **)(v8 + 216); v57 = *(_DWORD *)(v8 + 220); v58 = v104; v59 = v2; LABEL_88: ((void (__fastcall *)(int, int, int, const char *))unk_7860EEFC)(v59, v58, v55, v56); dword_78626714 = (*(int (__fastcall **)(int, int))(*(_DWORD *)v2 + 84))(v2, v93); log(3, (int)"SecShell", (int)&unk_78622BD8); ((void (__fastcall *)(char *))unk_786124A4)(&v112); ((void (__fastcall *)(char *))unk_786124A4)(&v110); goto LABEL_105; } v48 = J_NewObjectV(v2, v46, v49, 0); } v50 = v48; goto LABEL_84; } *(_BYTE *)(v37 + 4) = 1; *(_DWORD *)(v37 + 8) = v43; if ( v45 == 10 ) *(_DWORD *)(v84 + 16) = v103; } *(_DWORD *)(v37 + 12) = 0; goto LABEL_75; } log(3, (int)"SecShell", (int)"wrong code"); v34 = ((int (__fastcall *)(const char *, signed int))unk_7861EDBC)("/dev/zero", 2); v35 = ((int (__cdecl *)(_DWORD, signed int))unk_7861EEEC)(0, v87); ((void (__fastcall *)(int))unk_7861EE2C)(v34); if ( v35 ) { memmove(); v103 = v35; goto LABEL_50; } v20 = "SecShell"; v21 = "mmap fail"; LABEL_48: log(3, (int)v20, (int)v21); LABEL_105: result = v107; if ( v117 != *v107 ) _stack_chk_fail(v107); return result; }