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

news/2024/4/20 18:21:44/文章来源:https://blog.csdn.net/SharkToping/article/details/130348861

一、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 {//获取当前运行程序的MachOstruct 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.87for 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 InjectCodeint (*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.luyixian.cn/news_show_103046.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Java-01】深入浅出匿名对象 , 继承 , 抽象类

主要内容 面向对象回顾 匿名对象介绍 面向对象特征 - 继承 抽象类的使用 模板设计模式 1 面向对象回顾 面向对象的核心思想是什么 ? 用代码来模拟现实生活中的事物 , 比如学生类表示学生事物 , 对象表示的就是具体的学生 , 有了类就可以描述万千世界所有的事物了 现有的…

看完这篇文章你就彻底懂啦{保姆级讲解}-----(LeetCode刷题142环形链表II) 2023.4.24

目录 前言算法题&#xff08;LeetCode刷题142环形链表II&#xff09;—&#xff08;保姆级别讲解&#xff09;分析题目&#xff1a;算法思想环形链表II代码&#xff1a;补充 结束语 前言 本文章一部分内容参考于《代码随想录》----如有侵权请联系作者删除即可&#xff0c;撰写…

前端食堂技术周刊第 80 期:Vite 4.3、Node.js 20、TS 5.1 Beta、Windi CSS 即将落幕

美味值&#xff1a;&#x1f31f;&#x1f31f;&#x1f31f;&#x1f31f;&#x1f31f; 口味&#xff1a;东坡肉 食堂技术周刊仓库地址&#xff1a;https://github.com/Geekhyt/weekly 本期摘要 Vite 4.3Node.js 20TypeScript 5.1 BetaWindi CSS 即将落幕Pretty TypeScri…

中医脉诊仪:结合传统与现代技术的诊断工具

一、引言 随着科技的不断发展&#xff0c;医学领域也取得了举世瞩目的进步。中医作为一种古老的医学体系&#xff0c;始终保持着其独特的魅力。脉诊作为中医诊断的重要方法之一&#xff0c;历经千年的发展和传承&#xff0c;如今在现代科技的助力下&#xff0c;诞生了中医脉诊…

信息安全复习六:公开密钥密码学

一、章节梗概 1.公开密钥密码模型的基本原理 2.两个算法&#xff1a;RSA&D-H算法 主要内容 1.对称密钥密码的密钥交换问题 2.公钥密码模型的提出 3.设计公钥密码的基本要求 4.数字签名 5.RSA算法 6.公钥密码的特征总结 二、对称密钥密码 对称加密算法中&#xff0c;数据…

实例分割算法BlendMask

实例分割算法BlendMask 论文地址&#xff1a;https://arxiv.org/abs/2001.00309 github代码&#xff1a;https://github.com/aim-uofa/AdelaiDet 我的个人空间&#xff1a;我的个人空间 密集实例分割 ​ 密集实例分割主要分为自上而下top-down与自下而上bottom-up两类方法…

基于趋动云的chatGLM-6B模型的部署

首先根据官方示例教程&#xff0c;学会怎么创建项目&#xff0c;怎么使用数据&#xff0c;怎么进入开发环境&#xff0c;以及了解最重要的2个环境变量&#xff1a; 这个是进入开发环境以后的代码目录 $GEMINI_CODE 这个是引用数据集后&#xff0c;数据集存放的路径 $GEMINI_DA…

Linux内核进程管理与调度:策略优化与实践分析

Linux内核进程管理与调度 一、前言二、进程管理和多进程调度2.1 进程标识符和控制块2.2 进程状态和转换2.3 进程间通信 三、单处理器下的Linux进程调度3.1 Linux进程调度器3.2 时间片轮转调度算法3.3 最短剩余时间优先调度算法3.4 其他调度算法的不足 四、多处理器下的Linux进程…

Layui 2.8.0 正式发布,朴实归来

Layui 是一套开源的 Web UI 组件库&#xff0c;采用自身轻量级模块化规范&#xff0c;遵循原生态的 HTML/CSS/JavaScript 开发模式&#xff0c;极易上手&#xff0c;拿来即用。其风格简约轻盈&#xff0c;而内在雅致丰盈&#xff0c;甚至包括文档在内的每一处细节都经过精心雕琢…

【Linux网络】PXE高效批量网络装机

PEX高效批量网络装机 一、部署PXE远程安装服务1.1PXE的优点1.2搭建PXE网络体系的前提条件 二、实现Kincksatrt无人值守安装2.1实验思路&#xff0c;2.2实验&#xff1a;无人值守远程安装2.2.1实现 Kickstart 无人值守安装 一、部署PXE远程安装服务 PXE&#xff08;预启动执行环…

Flutter ListView组件详解

今天是2023年4月24日 今天重新复习了一下关于ListView的内容&#xff0c;现在就重新整理一下关于ListView的内容和理解 : (1)ListView和Column之间有什么区别&#xff1f; 在我理解中ListView和Column都是可以有很多子组件的组件&#xff0c;它们之间区别在于它们排列的形式和…

100天涨薪4k,从功能测试到自动化测试,我整理的3000字超全学习指南

去年6月份&#xff0c;由于经济压力让我下定决心进阶自动化测试&#xff0c;已经24的我做了3年功能测试&#xff0c;坐标广州薪资定格在8k&#xff0c;可能是生活过的太安逸&#xff0c;觉得8000的工资也够了&#xff0c;但是生活总是多变的&#xff0c;女朋友的突然怀孕&#…

Bsah shell的操作环境

文章目录 Bsah shell的操作环境路径与命令查找顺序使用案例 bash的登录与欢迎信息&#xff1a;/etc/issue、/etc/motdbash的环境配置文件如下login与non-login shell/etc/profile(login shell 才会读)~/.bash_profile(login shell 才会读)source&#xff1a;读入环境配置文件的…

上新了丨高性价比5G智能模组,美格智能SRM700正式发布

伴随着5G、AI、云计算等技术与物联网技术的融合发展&#xff0c;一个万物智联的智能世界正在到来。5G已经成为数字经济重要的基础设施&#xff0c;千行百业的用户都需要依靠高速率、大带宽、低延时的5G技术来构建数字化转型能力。 作为全球领先的无线通信模组及解决方案提供商…

51单片机(一)软硬件环境和单片机介绍

❤️ 专栏简介&#xff1a;本专栏记录了从零学习单片机的过程&#xff0c;其中包括51单片机和STM32单片机两部分&#xff1b;建议先学习51单片机&#xff0c;其实STM32等高级单片机的基础&#xff1b;这样再学习STM32时才能融会贯通。 ☀️ 专栏适用人群 &#xff1a;适用于想要…

HDCTF 2023 复盘

web yamiyami 当时考虑直接读的/proc/self/environ 读到flag是not_flag 就没考虑过/proc/1/environ了 然后不知道py3URL二次编码的特性,读不到源码,无从下手 做flask算pin码的题做多了,还以为pid是1的就是self,难顶 上面那种是非预期 预期是yaml反序列化 先读源码 /read?u…

银行数字化转型导师坚鹏:宏观经济趋势与资本行业机遇和挑战

2023年宏观经济趋势与资本行业机遇和挑战 课程背景&#xff1a; 很多学员存在以下问题&#xff1a; 不知道我国目前的宏观经济形势&#xff1f; 不清楚宏观环境对我国经济的影响&#xff1f; 不知道资本行业未来主要发展趋势&#xff1f; 课程特色&#xff1a; 精彩解…

小案例CSS

代码&#xff1a; <!DOCTYPE html> <html lang"en"> <head> <meta charset"UTF-8"> <meta http-equiv"X-UA-Compatible" content"IEedge"> <meta name"viewport" content"widthde…

QMS-云质说质量 - 4 为什么有的质量人不属于质量部?

想管理好质量&#xff0c;首先就要把质量人员放在合适的组织架构中。 对人进行管理&#xff0c;基本原则是&#xff1a;尽量让员工的利益与企业的利益保持同步&#xff0c;虽然无法做到完全重合&#xff0c;但出发点肯定要战略一致。 俗话说“屁股决定脑袋”&#xff0c;因此&a…

IS210AEBIH3BED包含逻辑集成电路、存储器集成电路、专用集成电路

IS210AEBIH3BED包含逻辑集成电路、存储器集成电路、专用集成电路 什么是集成电路测试仪   集成电路测试仪是对集成电路进行测试的专用仪器设备。集成电路测试是保证集成电路性能、质量的关键手段之一。集成电路测试技术是发展集成电路产业的三大支撑技术之一&#xff0c;因此…