22、Tweak原理及部分逆向防护

news2024/11/25 4:38:48

一、Tweak原理

1.1 Tweak产物.dylib

  • 执行make命令时,在 .theos的隐藏目录中,编译出obj/debug目录,包含 arm64、arm64e两种架构,同时生成readbadges.dylib动态库

  • 在arm64、arm64e目录下,有各自架构的readbadges.dylib,而debug目录下的readbadges.dylib,是一个胖二进制文件
file readbadges.dylib
Mach-O universal binary with 2 architectures: [arm64:Mach-O 64-bit dynamically linked shared library arm64Mach-O 64-bit dynamically linked shared library arm64] [arm64e:Mach-O 64-bit dynamically linked shared library arm64eMach-O 64-bit dynamically linked shared library arm64e]
readbadges.dylib (for architecture arm64):    Mach-O 64-bit dynamically linked shared library arm64
readbadges.dylib (for architecture arm64e):    Mach-O 64-bit dynamically linked shared library arm64e

Tweak的编译产物是动态库,将其注入的方式有两种:

  • 修改MachO文件的Load Commands,注入 LC_LOAD_DYLIB(XXX),然后根据路径找到动态库.这种方式对程序的污染比较严重,容易被开发者检测出来
  • 通过DYLD_INSERT_LIBRARIES环境变量,插入动态库

Tweak插件,使用的是方式二,因为程序没有被污染.在MachO中,并没有找到LC_LOAD_DYLIB(XXX)

1.2 Tweak packages分析

执行make package命令时,在packages目录中,生成.deb文件.每执行一次打包命令,都会生成一个新的.deb文件

.deb 格式类似于 .ipa格式

  • .ipa包通过AppStore安装,将.ipa包中的App包装到设备中
  • .deb包通过Cydia安装,将 .deb包中的动态库安装到设备中
    • data.tar.lzma解压后就是动态库

  • 执行 make install命令时,在.deb包中的动态库,会被安装到设备的 /Library/MobileSubstrate/DynamicLibraries目录中
  • 以相同的名称,分别存储 .dylib和 .plist 文件
    • .dylib为动态库,而 .plist,记录 .dylib所依附的App包名

二、 DYLD_INSERT_LIBRARIES防护

  • 当前官方的dyld源码中关于DYLD_INSERT_LIBRARIES的解释
DYLD_INSERT_LIBRARIES是一个以冒号分隔的附加动态库列表,要在程序中指定的动态库之前加载。
相反,如果您的目标是替换通常会加载的库,请使用 DYLD_LIBRARY_PATH 或者 DYLD_FRAMEWORK_PATH 代替。
  • 在早期的dyld源码中,有进程限制的判断.一旦符号条件,使用 DYLD_INSERT_LIBRARIES环境变量插入的动态库将被清空

  • 打开dyld-519.2.2源码
  • 搜索DYLD_INSERT_LIBRARIES
  • 进入dyld.cpp文件,来到5907行

    • DYLD_INSERT_LIBRARIES 为NULL的判断
  • 这段代码的上面,来到5692行

    • 判断进程限制, 符合条件,调用pruneEnvironmentVariables 方法,清空插入的动态库
  • 一旦插入的动态库被清空,意味着越狱插件将会全部失效.如果我们找到进程限制的开启条件,并将其使用在项目中,相当于对越狱插件进行了防护
  • 找到 processIsRestricted 设置为 true 的代码

    • 判断条件有两个,分别是 issetugid 和 hasRestrictedSegment 两个函数
    • issetugid函数,无法在上架的App中设置,放弃使用
    • hasRestrictedSegment函数,判断主程序的MachO是否受限,可以使用
  • 进入 hasRestrictedSegment 函数

    • 传入主程序的Header
    • 读取 segment, 如果为 __RESTRICT 段
    • 读取 segment,如果为 __restrict 节
    • 如果都存在,返回 true, 表示进程限制
  • __RESTRICT 段防护
    • 在项目中, 添加 __RESTRICT段, __restrict节,开启进程限制,对越狱插件进行防护
  • 搭建App项目,命名: AntiTweak
    • 打开ViewController.m ,写入以下代码: 点击屏幕即退出App
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
    exit(0);
}
    • 进程限制,是早期dyld源码中的逻辑,在低系统下才能生效
  • 搭建 Tweak插件,附加 AntiTweak应用
    • 打开 Tweak.xm 文件,写入Hook代码
#import <UIKit/UIKit.h>

%hook ViewController
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
  NSLog(@"touchesBegan hooked");
}
%end
    • 运行插件项目,启动应用,开启控制台查看手机日志,touchesBegan方法被插件HOOK.点击屏幕,不会闪退.
  • 为AntiTweak项目,添加 __RESTRICT段, __restrict节
    • 在Build Setting的Other Linker Flags,加入以下设置
-Wl,-sectcreate,__RESTRICT,__restrict,/dev/null
    • 编译项目,查看MachO文件

    • 成功插入 __RESTRICT 段, __restrict节
  • 低系统版本iOS手机,运行项目,点击屏幕闪退,说明插入的动态库已经被清空,越狱插件全部失效
  • 这种防护手段,在早期系统中比较有效.但在iOS11及更高系统中,dyld源码发生变化,这种方式已失去作用

针对上面这种防护手段,可以通过修改MachO破解

  • 在老系统的越狱设备上,遇到使用此方法防护的应用,导致我们的越狱插件无法使用,可以通过修改MachO文件破解防护
    • 使用MachOView打开MachO文件

    • 修改Data值,将 72改为73,52改为53.只在以前的数值上替换,位置不要改变

    • 当MachO文件修改后,使用重签名安装应用,此时 __RESTRICT段和 __restrict节已经不存在了,进程限制不会启动,越狱插件可正常使用.

三、 使用dyld源码防护

如果是自己的App,我们开启了进程限制,如果禁止攻击者的肆意修改呢?

  • 借鉴dyld的代码,循环读取segment和section, 如果缺少 __RESTRICT段或 __restrict节.说明我们的防护代码被人篡改
  • 用刚才的AntiTweak项目,将dyld中的代码迁移到项目中,
  • 打开ViewController.m文件,写入以下代码
    • 导入需要用到的头文件
#import <mach-o/loader.h>
#import <mach-o/dyld.h>
    • 添加需要用到的宏定义
#if __LP64__
    #define macho_header                mach_header_64
    #define LC_SEGMENT_COMMAND          LC_SEGMENT_64
    #define LC_SEGMENT_COMMAND_WRONG    LC_SEGMENT
    #define LC_ENCRYPT_COMMAND          LC_ENCRYPTION_INFO
    #define macho_segment_command       segment_command_64
    #define macho_section               section_64
#else
    #define macho_header                mach_header
    #define LC_SEGMENT_COMMAND          LC_SEGMENT
    #define LC_SEGMENT_COMMAND_WRONG    LC_SEGMENT_64
    #define LC_ENCRYPT_COMMAND          LC_ENCRYPTION_INFO_64
    #define macho_segment_command       segment_command
    #define macho_section               section
#endif
    • 添加hasRestrictedSegment函数, 循环读取segment和section. 如果缺少 __RESTRICT段或 __restrict节,返回false
static bool hasRestrictedSegment(const struct macho_header *mh) {
    const uint32_t cmd_count = mh->ncmds;
    const struct load_command* const cmds = (struct load_command*)(((char*)mh)+sizeof(struct macho_header));
    const struct load_command* cmd = cmds;
    for (uint32_t i = 0; i < cmd_count; ++i) {
        switch (cmd->cmd) {
            case LC_SEGMENT_COMMAND: {
                const struct macho_segment_command *seg = (struct macho_segment_command*)cmd;
                if (strcmp(seg->segname, "__RESTRICT") == 0) {
                    const struct macho_section*const sectionsStart = (struct macho_section*)((char *)seg + sizeof(struct macho_segment_command));
                    const struct macho_section*const sectionsEnd = &sectionsStart[seg->nsects];
                    for (const struct macho_section*sect=sectionsStart; sect<sectionsEnd; ++sect) {
                        if (strcmp(sect->sectname, "__restrict")==0) {
                            return true;
                        }
                    }
                }
            }
            break;
        }
        cmd = (const struct load_command *)(((char *)cmd)+cmd->cmdsize);
    }
    return false;
}
    • 加入 load方法作为调用防护代码的时机
// 加入load方法,调用防护代码
+ (void)load {
    //获取当前运行程序的MachO
    struct macho_header *mhmh = _dyld_get_image_header(0);
    if (hasRestrictedSegment(mhmh)) {
        NSLog(@"防护代码有效");
    } else {
        NSLog(@"被篡改");
    }
}
  • 修改 Other Linker Flags 中的配置,模拟MachO被篡改
-Wl,-sectcreate,__SESTRICT,__sestrict,/dev/null
    • 运行项目,输出以下结果
2023-04-15 00:12:39.528419+0800 AntiTweak[47753:1566353] 被篡改
  • 注意:
    • 当检测到MachO被篡改,不要使用痕迹明显的代码进行防护,例如: exit(0).此类代码相当于记号,让攻击者很容易找到防护的位置和逻辑
    • 高明的防护手段,应该让攻击者不易察觉,在不知不觉中被系统屏蔽封杀

四、白名单检测

进程限制的防护手段,仅低版本系统有效.对于高版本系统的防护,我们可以自制白名单进行检测.

4.1 获取正常设备上的白名单

  • 延用AntiTweak项目: 整理出App依赖库的白名单
  • 打开ViewController.m文件,写入以下代码:
+ (void)load {
    //获取镜像文件个数
    uint32_t intCount = _dyld_image_count();
    for (int intIndex = 0; intIndex < intCount; intIndex++) {
        // 获取指定索引的镜像名称
        const char *strName = _dyld_get_image_name(intIndex);
        printf("%s",strName);
    }
}
  • 在未越狱设备上,运行项目,遍历出所有image名称

  • 打印结果,相当于一份白名单.如果App运行时,加载了白名单以外的动态库,该库很可能是被第三方注入的.将输出结果拷贝出来存放

4.2 检测越狱设备上注入的动态库

  • 获取思路为: 在load方法中,循环遍历依赖的动态库.如果动态库是当前的MachO文件,或者包含在白名单中,属于合法库,直接跳过.否则,将其打印.
+ (void)load {
    //获取镜像文件个数
    uint32_t intCount = _dyld_image_count();
    for (int intIndex = 0; intIndex < intCount; intIndex++) {
        // 获取指定索引的镜像名称
        const char *strName = _dyld_get_image_name(intIndex);
        // 0位置是当前的 MachO文件
        if (intIndex == 0 || strstr(strList, strName)) {
            continue;
        }
        printf("注入的动态库: %s\n",strName);
    }
}
    • 在越狱设备上运行项目,输出很多白名单以外的动态库,其中包含自制的TouchHookDemo插件

使用白名单做防护,需要注意:

  • 在不同系统下运行项目,整理出尽可能完善的白名单.
  • 检测到白名单以外的动态库,不要直接处理.建议先收集数据,如果此动态库是因为不同系统差异造成的,将其补充到白名单中.如果确定是恶意注入,再做处理.
  • 白名单列表,由服务器下发,或者将逻辑直接做到服务器

白名单写在客户端的弊端:

  • 白名单的字符串,位于MachO的常量区,容易被攻击者发现并HOOK篡改.
  • 当系统更新,可能会出现白名单以外的依赖库,老版本App将无法使用.

五、ptrace

5.1 ptrace概述

  • App可以被lldb动态调试,因为App被设备中的debugserver附加,它会跟踪我们的应用进程(trace process), 而这一过程利用的就是ptrace 函数
  • ptrace是系统内核函数,它可以决定应用能否被debugserver附加.如果我们在项目中,调用ptrace函数,将程序设置为拒绝附加,即可对lldb动态调试进行有效的防护.
  • ptrace在iOS系统中,无法直接使用,需要导入头文件
  • ptrace函数的定义:
int ptrace(int _request, pid _pid, caddr_t _addr, int _data);
    • request: 请求ptrace执行的操作
    • pid: 目标进程的ID
    • addr: 目标进程的地址值,和request参数有关
    • data: 根据request的不同而变化.如果需要向目标进程中写入数据,data存放的是需要写入的数据.如果从目标进程中读数据,data将存放返回的数据
  • 上面的函数怎么来的?
    • 不妨回想一下,当初编译llvm源码或者Swift源码的时候,编译出附带的lldb源码,tools中就有debugserver源码,下边是编译Swift5.3.1的源码截图

    • 打开编译运行解决了lldb_codesign问题后,就可以得到自己编译的debugserver MachO了,并且可以直接调试源码,附加Mac端的进程

5.2 ptrace防护应用

  • 搭建App项目AntiDebug
  • 导入MyPtraceHeader.h头文件.
  • 写入调用代码
#import "ViewController.h"
#import "MyPtraceHeader.h"
@interface ViewController ()
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    ptrace(PT_DENY_ATTACH, 0, 0, 0);
}
    • 使用Xcode运行项目,启动后立即退出.使用ptrace设置为拒绝附加,只能手动启动App,也就是说,用户在使用App时,不会有任何影响.一旦被debugserver附加,就会闪退.
  • 如果在越狱环境,手动对App进行debugserver附加呢?
    • 找到AntiDebug进程,手动对App进行debugserver附加
Holothurian6P:~ root# ps -A | grep AntiDebug
48329 ??         0:00.23 /var/containers/Bundle/Application/3D3083F3-295D-4F55-83DB-40887FF4FF46/AntiDebug.app/AntiDebug
48336 ttys000    0:00.00 grep AntiDebug
Holothurian6P:~ root# debugserver localhost:22 -a 48329
debugserver-@(#)PROGRAM:LLDB  PROJECT:lldb-900.3.87
 for arm64.
Attaching to process 48329...
Segmentation fault: 11
    • 同样附加失败,无论以何种方式,都会被ptrace函数阻止.

5.3 ptrace防护破解

  • ptrace是系统内核函数,被开发者所熟知.ptrace的防护痕迹也很明显,手动运行程序正常,Xcode运行程序闪退
  • 我们在逆向一款App时,遇到上述情况,第一时间就会想到ptrace防护
  • 由于ptrace是系统函数,需要间接符号表,我们可以尝试下ptrace的符号断点

    • ptrace的断点命中,确定了对方的防护手段,接下来尝试破解
  • 采用AntiDebug项目,模拟应用重签名,注入动态库
  • 创建 Inject动态库,创建 InjectCode类
  • 在Inject动态类中,导入fishhook,导入MyPtraceHeader.h头文件
#import "InjectCode.h"
#import "MyPtraceHeader.h"
#import "fishhook.h"

@implementation InjectCode

int (*sys_ptrace)(int _request, pid_t _pid, caddr_t _addr, int _data);

int my_ptrace(int _request, pid_t _pid, caddr_t _addr, int _data){
    if (_request == PT_DENY_ATTACH) {
        return 0;
    }
    return sys_ptrace(_request,_pid,_addr,_data);
}
+ (void)load {
    struct rebinding rebPtrace;
    rebPtrace.name = "ptrace";
    rebPtrace.replacement = my_ptrace;
    rebPtrace.replaced    = (void *)&sys_ptrace;
    struct rebinding rebs[] = {rebPtrace};
    rebind_symbols(rebs, 1);
}

@end
  • 在my_ptrace函数中,如果是 PT_DENY_ATTACH 宏定义值,直接返回,如果是其他类型,系统由特定的作用,需要执行ptrace原始函数.
  • 运行项目,进入lldb动态调试,ptrace防护破解成功

六、总结

Tweak原理

  • Tweak编译产物是动态库
  • 打包时,将动态库打包成 .deb 格式
  • 插件安装到 /Library/MobileSubstrate/DynamicLibraries目录中
    • 安装.dylib和 .plist文件
    • .plist记录 .dylib 所要附加的App包名
  • Tweak插件使用 DYLD_INSERT_LIBRARIES方式,插入动态库

DYLD_INSERT_LIBRARIES

  • 早期的dyld源码中,有进程限制的判断( processIsRestricted)
  • 启动进程限制,segment 存在 __RESTRICT段,section存在 __restrict节
  • 符合进程限制的条件,清空插入动态库,越狱插件失效

__RESTRICT段防护

  • 在Build Setting的 Other Linker Flags中配置
    • -Wl,-sectcreate,__RESTRICT,__restrict,/dev/null
  • iOS11.0及更高系统,此防护无效

修改MachO破解__RESTRICT段防护

  • 使用MachOView打开MachO文件,修改Data段
  • 只在以前的数值上替换,不要对其增减,位数不要改变

使用dyld源码防护

  • 借鉴dyld源码,读取 segment和section.如果缺少 __RESTRICT段或 __restrict节,说明我们的防护代码被人篡改
  • 检测到程序被篡改,不要使用痕迹明显的代码进行防护,容易暴露
  • 尽量让攻击者在不知不觉中被系统屏蔽封杀

白名单检测

  • 遍历image名称
    • _dyld_image_count()
    • _dyld_get_image_name()
  • 在不同系统下运行项目,整理出尽可能完善的白名单
  • 检测到白名单以外的动态库,不要直接处理
  • 白名单列表,由服务端下发,或者将逻辑直接做到服务端

ptrace

  • 可阻止App被debugserver附加
  • 在 iOS系统中,无法直接使用,需要导入头文件
  • ptrace函数的定义
    • int ptrace(int _request, pid_t _pid, caddr_t _addr, int _data);
  • 破解ptrace
  • 防护效果: 手动运行程序正常,Xcode运行程序闪退
  • 使用ptrace符号断点试探
  • 使用fishhook对ptrace函数HOOK
  • 是PT_DENY_ATTACH宏定义值,直接返回.其他类型,执行原始函数

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/456792.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

ShareSDK QQ平台注册

注册开发者账号 1.在QQ互联开放平台首页 QQ互联官网首页 &#xff0c;点击右上角的“登录”按钮&#xff0c;使用QQ帐号登录&#xff0c;如下图所示&#xff1a; 重要提示&#xff1a; 开发者QQ号码一旦注册不能变更&#xff0c;建议使用公司公共QQ号码而不是员工私人号码注册…

软件测试好学习吗?

软件测试好不好学习其实各自的认知都不同&#xff0c;想要知道自己能不能学会&#xff0c;对于自己怎么样&#xff0c;最简单的方法就是找个基础教程先去学习一下了~ 其实软件测试这个行业与其他岗位相比&#xff0c;对零基础的学习者更加友好。即使你不懂互联网&#xff0c;不…

小程序过审失败,怎么解决?

小程序过审失败&#xff0c;怎么解决&#xff1f; 如果你的小程序未能通过审核&#xff0c;可以参考以下步骤解决问题&#xff1a; 1、审核不通过原因&#xff1a;在审核失败的通知中会注明不通过的具体原因和相关文件路径。请先认真阅读并理解不通过的原因&#xff0c;找到问…

存储电路:计算机存储芯片的电路结构是怎样的?

我们把用于存储数据的电路叫做存储器&#xff0c;按照到 CPU 距离的远近&#xff0c;存储器主要分为寄存器、缓存和主存。我们就来重点分析这三种存储器的特点、原理&#xff0c;以及应用场景。 存储器是由基本的存储单元组成的&#xff0c;要想搞清楚存储器原理&#xff0c;我…

【C++关联容器】set的成员函数

目录 set 1. 构造、析构和赋值运算符重载 1.1 构造函数 1.2 析构函数 1.3 赋值运算符重载 2. 迭代器 3. 容量 4. 修改器 5. 观察者 6. 操作 7. 分配器 set set是按照特定顺序存储唯一元素的容器。 在一个set中&#xff0c;一个元素的值也是它的标识&#xff08;值…

插装式两位两通电磁阀DSV-080-2NCP、DDSV-080-2NCP

特性 压力4000 PSI(276 Bar) 持续的电磁。 硬化处理的提升阀和柱塞可获得更长的寿命和低泄漏量。 有效的混式电磁铁结构。 插装阀允许交流电压。可选的线圈电压和端子。 标准的滤网低泄漏量选择 手动关闭选择。 工业化通用阀腔。 紧凑的尺寸。 两位两通常闭式双向电磁…

热门好用的企业网盘工具大盘点

企业网盘作为热门的企业文件管理工具相比于个人网盘&#xff0c;更注重安全性&#xff0c;并增加了协同功能。当下市面上的企业网盘工具可谓是百花齐放&#xff0c;今天就盘点几款热门好用的网盘工具&#xff0c;希望能帮助您挑选到心仪的网盘工具~ 1. Zoho Workdrive Zoho Wo…

#PythonPytorch 2.如何对CTG特征数据建模

系列文章目录 #Python&Pytorch 1.如何入门深度学习模型 #Python&Pytorch 2.如何对CTG特征数据建模 我之前也写过一篇使用GBDT对UCI-CTG特征数据进行建模的博客&#xff0c;不过那是挺早的时候写的&#xff0c;只是简单贴了代码&#xff0c;方便了解流程而已&#xff0…

原神3.2剧情服搭建教程

同步官服所有剧情和交互 优化后电脑16G运行内存也可以完美运行 数据库再次启动报错的,把将redis.service中的Type=forking配置删除或者注释掉即可。 位于:/usrb/systemd/system/redis.service 然后重启服务就不会爆错了。 下面是具体步骤 su root (此处会提示输入密…

相机雷达联合标定cam_lidar_calibration

文章目录 运行环境&#xff1a;1.1 ROS环境配置1&#xff09;工作空间创建和编译2&#xff09;官方数据集测试环境 2.1 在线标定1&#xff09;数据类型2&#xff09;标定板制作3&#xff09;配置文件4&#xff09;开始标定5&#xff09;完整实现步骤 3.1 python版本选择3.2 rvi…

医疗保障信息平台HASF应用系统技术架构名词解释技术选型架构图

下载地址&#xff1a; 医疗保障信息平台HASF应用系统技术架构规范.pdf下载—无极低码 HSAF 医疗保障应用框架&#xff08;Healthcare Security Application Framework&#xff09; IaaS 基础设施即服务&#xff08;Infrastructure-as-a-Service&#xff09; PaaS 平台即服务…

实现了单链表各种功能,并配上详细解读。

单链表 链表的概念及结构链表的分类链表的实现初始化打印申请结点头插尾插头删尾删查找在pos位置之后插入在pos位置之前插入删除pos位置之后的值删除pos位置的值销毁 链表的概念及结构 概念&#xff1a;链表是一种物理存储结构上非连续、非顺序的存储结构&#xff0c;数据元素…

离散数学期末复习第一章 数理逻辑

离散数学 离散数学是研究各种各样的离散量的结构及离散量之间的关系一门学科&#xff0c;是计算机科学中基础理论的核心课程。 什么是连续变量&#xff1f; 在一定区间内可以任意取值的变量叫连续变量&#xff0c;其数值是连续不断的&#xff0c;相邻两个数值可作无限分割&a…

buuctf4

目录 [极客大挑战 2019]LoveSQL [极客大挑战 2019]Http [极客大挑战 2019]Knife qr 镜子里面的世界 ningen 小明的保险箱 爱因斯坦 easycap 隐藏的钥匙 另外一个世界 FLAG [极客大挑战 2019]LoveSQL 1.启动环境&#xff0c; 使用万能密码尝试一下 2.跳转到了check.php…

维度云工业品ERP进销存软件教您如何突破工业品生意的困境?

是困境也是机遇 随着全球化和技术进步的不断推进&#xff0c;工业品贸易正逐渐成为国际贸易的重要组成部分。工业品包含了从原材料、零部件到工业设备、机械以及其他工业用品等范畴的产品&#xff0c;涉及各种制造、加工和组装过程。在全球供应链互联互通之下&#xff0c;工业品…

【人工智能概论】 用Python实现数据的归一化

【人工智能概论】 用Python实现数据的归一化 文章目录 【人工智能概论】 用Python实现数据的归一化一. 数据归一化处理的意义二. 常见的归一化方法2.1 最大最小标准化&#xff08;Min-Max Normalization&#xff09;2.2 z-score 标准化 三. 用sklearn实现归一化 一. 数据归一化…

服务(第十一篇)LVS

什么是群集&#xff1f; 多台主机组成的一个整体&#xff0c;提供一个ip访问通道&#xff0c;所有的主机干一件事 提供同样的服务。 群集有哪些类型&#xff1f; ①负载均衡群集&#xff08;LB&#xff09;&#xff1a; 提高系统的响应能力&#xff0c;处理更多的访问请求&a…

20、Theos越狱调试Wallet

前面的总结中使用砸壳重签后的App进行调试,本篇在越狱环境下不重签App进行调试,但是还是需要砸壳获取Headers. 一、Cycript 1.1 在越狱环境中使用Cycript 在越狱环境上,安装Cycript插件.需要先安装adv-cmds插件,因为被Cycript插件所依赖、在Cydia中,安装Cycript 在设备中找到…

观察者设计模式(Observer Design Pattern)[论点:概念、组成角色、相关图示、示例代码、框架中的运用、适用场景]

文章目录 概念组成角色相关图示示例代码框架中的运用适用场景 概念 观察者设计模式&#xff08;Observer Design Pattern&#xff09;是一种行为型设计模式&#xff0c;它定义了一种对象间的一对多的依赖关系&#xff0c;让多个观察者对象同时监听某一个主题对象&#xff0c;当…

LLaMA模型文件 (搬运工)

LLaMA需要进行申请才能获得官方模型权重。 但是申请的审批时间一般都很长。 这里提供现有的huggingface上&#xff0c;第三方上传的一些LLaMA模型文件&#xff1a; LLaMA-7BLLaMA-13BLLaMA-7B-hfLLaMA-13B-hf 这里要注意&#xff0c;原始的LLaMA权重文件&#xff0c;是不能…