博士生
阿巴阿巴
  
- 金币
- 2219
- 好评
- 244
- 信誉
- 190
|
前言:关于次元城的第一个校验请看https://bbs.binmt.cc/thread-145688-1-1.html此帖子,本次我们来完整分析它的libapp.so
准备工具:
IDA任意版本(针对手机本帖子最后给出mt的十六进制改法)
软件版本:最新版
那么教程开始:
首先我们还是要先关注到libcycnet这个so的JNI_OnLoad,这里面的第一个校验已在第一个的帖子讲过,不在赘述
我们重点看
这其中的
- strcpy((char *)&qword_5B6F0, "libapp.so");
- v7 = dlopen((const char *)&qword_5B6F0, 2);
- if ( !v7 )
- return -1;
- v8 = v7;
- if ( (byte_5BAF4 & 1) == 0 )
- byte_5BAF4 = 1;
- strcpy((char *)&qword_5B7F0, "JNI_OnLoad");
- v9 = (__int64 (__fastcall *)(JavaVM *, void *))dlsym(v7, (const char *)&qword_5B7F0);
- v10 = v9(vm, reserved);
- dlclose(v8);
- if ( v10 != 65542 )
- return -1;
复制代码
libapp.so的加载是通过diopen来进行加载,dlsym找到它的符号JNI_OnLoaddlsym和dlopen又是什么?
dlopen
用于在运行时加载一个共享库,并返回一个用于后续操作的句柄(handle)。该句柄可以传递给其他动态链接相关的函数(例如 dlsym、dlclose 等) 通过 dlopen,程序可以不在启动时链接所有库,而是在需要时动态加载,从而节省内存或实现对插件化设计的支持 - RTLD_LOCAL:与 RTLD_GLOBAL 相反,表示该共享库的符号仅在本库内部可见(这是默认行为)。
- 在 <dlfcn.h> 头文件中,dlopen 的函数原型通常定义为:
- c
- #include <dlfcn.h>
- void *dlopen(const char *filename, int flag);
复制代码filename
表示要加载的共享库的路径或文件名。如果传入 NULL,则返回主程序的句柄。路径可以是绝对路径或相对路径;同时系统也会根据环境变量(如 LD_LIBRARY_PATH)搜索指定库。
flag
指定加载的选项,常见的标志有: RTLD_NOW:立即解析共享库中所有的符号。如果某个符号解析失败,则加载失败并返回 NULL。 RTLD_LAZY:延迟解析,只有在实际使用时才解析符号。这样可以加快加载速度,但可能会延迟暴露错误。 RTLD_GLOBAL:使得该共享库的符号可供之后加载的其他共享库使用,即全局符号可见。 成功时,dlopen 返回一个非 NULL 的句柄,供后续通过 dlsym 等函数来查找共享库中导出的符号。 失败时返回 NULL,此时可以使用 dlerror 获取错误详情。
dlsym 用于从通过 dlopen 返回的句柄中查找共享库导出的符号,比如函数或全局变量的地址。
使用 dlsym 后可以调用该函数或访问该变量,就好像它们直接链接到程序中一样。 - 在 <dlfcn.h> 中,dlsym 的函数原型通常如下:
- c
- #include <dlfcn.h>
- void *dlsym(void *handle, const char *symbol);
复制代码handle
指向 dlopen 返回的句柄。如果传入 NULL 表示使用主程序的符号表(这取决于平台实现)。
symbol
需要查找的符号名称,通常是一个字符串。例如,如果共享库中导出了函数 my_function,那么就传入 "my_function"(这里它查找的就是libapp.so这个的JNI_OnLoad)。
那么我们此时就需要去libapp.so里面看它做了什么了(顺便说一下,libapp.so的加载在java层没什么用,它的native方法也就是个空壳)
打开libapp.so的导出表,很简洁,其中一个还是在java层的native方法,
而这个native方法它什么都没有做,我们直接看JNI_OnLoad吧
- jint JNI_OnLoad(JavaVM *vm, void *reserved)
- {
- unsigned int v3; // w0
- __int64 v5[2]; // [xsp+0h] [xbp-10h] BYREF
- v5[1] = *(_QWORD *)(_ReadStatusReg(ARM64_SYSREG(3, 3, 13, 0, 2)) + 40);
- v5[0] = 0LL;
- v3 = time(0LL);
- srand(v3);
- if ( (*vm)->GetEnv(vm, (void **)v5, 65542LL) )
- return -1;
- if ( (sub_1A44(v5[0]) & 1) != 0 )
- return 65542;
- return -1;
- }
复制代码
如果sub_1A44这个函数的返回值不等于0,那么它就正确返回我们需要的数return 65542,那么这其中的sub_1A44就显得很重要了,我们进去看一下
有混淆,但还是能分析,大概做的全是环境检查以及打开apk的文件路径,没有任何业务代码,那么就很简单了,它对于我们来说是不需要的 我们回到JNI_OnLoad看它的汇编 - .text:0000000000001994 JNI_OnLoad ;
- .text:0000000000001994
- .text:0000000000001994 var_30 = -0x30 ; 局部变量区域中,下标 -0x30(一般用来存放临时数据)
- .text:0000000000001994 var_28 = -0x28 ; 局部变量区域中,下标 -0x28
- .text:0000000000001994 var_20 = -0x20 ; …下标 -0x20
- .text:0000000000001994 var_18 = -0x18
- .text:0000000000001994 var_10 = -0x10
- .text:0000000000001994 var_s0 = 0 ; 局部变量保存从 SP+0x30开始的位置(偏移0)
- .text:0000000000001994 var_s8 = 8 ;
复制代码
- .text:00000000000019A4 STP X20, X19, [SP,#0x30+var_s0] 将 X20 和 X19 保存到栈中,从 SP+0x30开始(var_s0 为 0)
- .text:00000000000019A8 MRS X20, TPIDR_EL0 将系统寄存器 TPIDR_EL0(通常保存线程指针或 TLS 数据)读入 X20
- .text:00000000000019AC MOV X19, X0 将传入参数 X0(通常为 JavaVM* 指针)保存在 X19 中,后续都通过 X19 使用
- .text:00000000000019B0 LDR X8, [X20,#0x28] 从当前线程的 TLS 数据(TPIDR_EL0+0x28)中加载一个值到 X8
- .text:00000000000019B4 MOV X0, XZR ; timer 将 XZR(恒为 0)赋值给 X0,后面将作为参数调用 time() 用于获取当前时间
- .text:00000000000019B8 MOV W21, #0x10006 将立即数 0x10006 装入 W21,该值用作 JNI 版本号(如 JNI_VERSION_1_6)
- .text:00000000000019C0 STR X8, [SP,#0x30+var_28] 将之前从 TLS 读取的值(X8)存入栈中,地址为 SP+(0x30 + (-0x28)) = SP+0x08
- .text:00000000000019C4 STR XZR, [SP,#0x30+var_30] 将 0 存入栈中,位置为 SP+(0x30+(-0x30)) = SP+0
- .text:00000000000019C8 BL .time 调用 time 函数,参数为 0,返回当前时间(秒数),放在 X0
- .text:00000000000019CC BL .srand 调用 srand 以当前时间为种子初始化随机数生成器
- .text:00000000000019D0 LDR X8, [X19] 从传入的 JavaVM 指针(X19)中加载第一个成员到 X8
- .text:00000000000019D4 MOV W2, #6 将立即数 6 放到 W2,作为参数传递给 GetEnv 的某部分(初始传入参数)
- .text:00000000000019D8 MOV X1, SP 将当前栈指针赋值给 X1,作为参数 GetEnv 用来写入 JNI 环境指针的存储地址
- .text:00000000000019DC MOV X0, X19 将 JavaVM 指针放入 X0,作为第一个参数传递
- .text:00000000000019E0 MOVK W2, #1,LSL#16 用 MOVK 修改 W2 的高位,结果 W2 变为 0x10006(1<<16 加上 6),与之前常量保持一致
- .text:00000000000019E4 LDR X8, [X8,#0x30] :从 X8(即 JavaVM 虚表指针)中取偏移 0x30 处的地址
- .text:00000000000019E8 BLR X8 通过 X8 中的地址调用 GetEnv,即执行 GetEnv(JavaVM, &env, JNI_VERSION_1_6)
- .text:00000000000019EC CBZ W0, loc_19F8 检查调用 GetEnv 后返回的值(W0),如果为零(成功)则跳转到 loc_19F8
- .text:00000000000019F0 MOV W0, #0xFFFFFFFF 如果 GetEnv 返回非 0,则将 W0 设为 -1(错误代码
- .text:00000000000019F4 B loc_1A08 跳转到 loc_1A08 处,准备返回前的收尾工作
- .text:00000000000019F8 loc_19F8:
- .text:00000000000019F8 LDR X0, [SP,#0x30+var_30] 从之前存储的栈顶(偏移 0)读取数值,作为参数传递给子函数 sub_1A44
- .text:00000000000019FC BL sub_1A44 调用检查函数
- .text:0000000000001A00 TST W0, #1 测试返回值 W0 的最低位(按位与 1),设置条件标志
- .text:0000000000001A04 CSINV W0, W21, WZR, NE 这条指令很重要
- 如果条件 NE 为真(即 TST 得到的结果标志表示“不等于零”,通常表示校验失败),则将 WZR(零)写入 W0;
- 否则(校验通过)将 W21 的按位取反写入 W0。不过根据之前已知 W21 中为 0x10006,这条指令最终会选择适当的返回状态。
- .text:0000000000001A08 loc_1A08:
- .text:0000000000001A08 LDR X8, [X20,#0x28] 再次从线程私有数据(TPIDR_EL0+0x28)加载一个值到 X8
- .text:0000000000001A0C LDR X9, [SP,#0x30+var_28] 从栈中加载先前存储的 TLS 值(之前从 TPIDR_EL0+0x28中取得并保存到 SP+0x08
- .text:0000000000001A10 CMP X8, X9 比较当前从 TLS 读出的值与之前保存的值,确保两者相同
- .text:0000000000001A14 B.NE loc_1A2C 如果两者不相等,则跳转到 loc_1A2C
- .text:0000000000001A18 LDP X20, X19, [SP,#0x30+var_s0] 从栈中恢复寄存器 X20 和 X19(之前保存的 JavaVM 指针和其他数据
- .text:0000000000001A1C LDP X29, X30, [SP,#0x30+var_20] 从栈中恢复上一个栈帧的帧指针 X29 和返回地址 X30
- .text:0000000000001A20 LDR X21, [SP,#0x30+var_10] 恢复之前保存的 X21
- .text:0000000000001A24 ADD SP, SP, #0x40 ; '@' 恢复 SP,撤销之前分配的 0x40(64字节)栈空间
- .text:0000000000001A28 RET 结束
复制代码 ps:写这段真累人
那么已经很明显了,我们重点看向BL sub_1A44 ,它是不需要的,我们把它给nop掉
其次就是这个语句 CSINV W0, W21, WZR, NE,我们要它返回的是W21的值,直接改成
至此,libapp.so的校验结束,libcycnet.so的校验按照上篇帖子的即可
手机用MT去除:
MT打开libcycnet然后十六进制搜索
- FF 83 01 D1 FD 7B 01 A9 FD 43 00 91 F9 13 00 F9
- F8 5F 03 A9 F6 57 04 A9 F4 4F 05 A9 59 D0 3B D5
- C2 00 80 52 28 17 40 F9 F5 03 01 AA E1 03 00 91
- 22 00 A0 72 D3 00 80 52 F7 03 00 AA E8 07 00 F9
- 33 00 A0 72 08 00 40 F9 FF 03 00 F9 08 19 40 F9
- 00 01 3F D6 80 1A 00 35 4A C7 00 94 40 1A 00 36
- C8 01 00 90 09 C1 6B 39 69 00 00 37 29 00 80 52
- 09 C1 2B 39 A8 FF FF 90 D4 01 00 90 94 C2 1B 91
- 41 00 80 52 E0 03 14 AA 00 41 42 FD E8 0D 80 52
- 80 02 00 FD 88 12 00 79 3E C7 00 94 40 18 00 B4
- C8 01 00 90 F8 03 00 AA 09 D1 6B 39 69 00 00 37
复制代码 然后替换为- FF 83 01 D1 FD 7B 01 A9 FD 43 00 91 F9 13 00 F9
- F8 5F 03 A9 F6 57 04 A9 F4 4F 05 A9 59 D0 3B D5
- C2 00 80 52 28 17 40 F9 F5 03 01 AA E1 03 00 91
- 22 00 A0 72 D3 00 80 52 F7 03 00 AA E8 07 00 F9
- 33 00 A0 72 08 00 40 F9 FF 03 00 F9 08 19 40 F9
- 00 01 3F D6 1F 20 03 D5 1F 20 03 D5 1F 20 03 D5
- C8 01 00 90 09 C1 6B 39 69 00 00 37 29 00 80 52
- 09 C1 2B 39 A8 FF FF 90 D4 01 00 90 94 C2 1B 91
- 41 00 80 52 E0 03 14 AA 00 41 42 FD E8 0D 80 52
- 80 02 00 FD 88 12 00 79 3E C7 00 94 40 18 00 B4
- C8 01 00 90 F8 03 00 AA 09 D1 6B 39 69 00 00 37
复制代码 打开libapp.so 十六进制搜索- 88 16 40 F9 E0 03 1F AA D5 00 80 52 35 00 A0 72
- E8 07 00 F9 FF 03 00 F9 06 0C 00 94 09 0C 00 94
- 68 02 40 F9 C2 00 80 52 E1 03 00 91 E0 03 13 AA
- 22 00 A0 72 08 19 40 F9 00 01 3F D6 60 00 00 34
- 00 00 80 12 05 00 00 14 E0 03 40 F9 12 00 00 94
- 1F 00 00 72 A0 12 9F 5A 88 16 40 F9 E9 07 40 F9
- 1F 01 09 EB C1 00 00 54 F4 4F 43 A9 FD 7B 41 A9
- F5 13 40 F9 FF 03 01 91 C0 03 5F D6 F5 0B 00 94
- 08 00 40 F9 E1 FF FF F0 21 C0 2F 91 02 9D 42 F9
- 40 00 1F D6 E9 23 B9 6D FD 7B 01 A9 FD 43 00 91
- FC 6F 02 A9 FA 67 03 A9 F8 5F 04 A9 F6 57 05 A9
复制代码 十六进制替换为- 88 16 40 F9 E0 03 1F AA D5 00 80 52 35 00 A0 72
- E8 07 00 F9 FF 03 00 F9 06 0C 00 94 09 0C 00 94
- 68 02 40 F9 C2 00 80 52 E1 03 00 91 E0 03 13 AA
- 22 00 A0 72 08 19 40 F9 00 01 3F D6 60 00 00 34
- 00 00 80 12 05 00 00 14 E0 03 40 F9 1F 20 03 D5
- 1F 00 00 72 E0 03 15 2A 88 16 40 F9 E9 07 40 F9
- 1F 01 09 EB C1 00 00 54 F4 4F 43 A9 FD 7B 41 A9
- F5 13 40 F9 FF 03 01 91 C0 03 5F D6 F5 0B 00 94
- 08 00 40 F9 E1 FF FF F0 21 C0 2F 91 02 9D 42 F9
- 40 00 1F D6 E9 23 B9 6D FD 7B 01 A9 FD 43 00 91
- FC 6F 02 A9 FA 67 03 A9 F8 5F 04 A9 F6 57 05 A9
复制代码
手机去除广告
在assets目录下删除如图文件
随后dex字符串正则搜索.*sigmob.*
将搜索出来的全部替换为空
快抓紧狂欢吧,泛滥了可能就被和谐了
成功效果:
|
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有账号?立即注册
x
-
查看全部评分
总评分:好评 +11
金币 +13
|