- Linux
- windows
- OS X IOS 架构图
- OS X IOS 内核跟踪、调试、基本信息
- OS X 引导过程
- IOS 引导过程
- OS X 安装过程
- MacOS IOS launchd
- MacOS IOS 用户内核态转换
- MacOS IOS 内核运行流程
- MacOS IOS Mach 消息
- MacOS IOS Mach 同步
- MacOS IOS Mach 其他
- MacOS IOS Mach 调度
- MacOS IOS Mach 虚拟内存
- MacOS IOS BSD POSIX API
- MacOS IOS MAC 策略
- MacOS IOS MAC 网络
- linux 内核网络
Linux
- 逻辑地址(段、偏移量、段描述符)->线性地址->物理地址
- 段选择寄存器:cs代码、ss栈、ds数据、es、fs、gs普通
- cs 含两位 0内核、3用户、1、2没有用
- 段描述符(全局、本地)
- 只有86体系32位使用段,liunx内核段偏移地址等于线性地址
- 系统调用使用0x80中断
windows
- 系统调用使用0x2E中断
OS X IOS 架构图
OS X IOS 内核跟踪、调试、基本信息
- Aqua:launchd-application services-core graphics-windowserver
- plutil 转换plist、nib格式
- kevent 内核事件通知
int kq = kqueue();
EV_SET(&ke,pid,EVFILT_PROC,EV_ADD,NOTE_EXIT,0,NULL);
int rc = kevent(kq, &ke, 1, NULL, 0, NULL);
rc = kevent(kq, NULL, 0, &ke, 1, NULL) - audit、auditctl、auditon、getaudit、setaudit、getaudit_addr、setaudit_addr、mach_port_name_t、audit_session_join、audit_session_port 审计OS X only
- MAC Mandatory Access Control强制访问控制__mac_系列
- FSEvents 文件系统通知 /dev/fsevents 虚拟设备 open、ioctl设置事件、read、close
- ios权限白名单plist在二进制文件末尾未加密 cat -tv app_path | tail -31 | more
- TSTOP、TOSTOP、CONT信号、pid_suspend、pid_resume暂停继续进程。pid_shutdown_sockets
- PE32/PE32+(MZ) window、EFI,ELF(7FELF) linux、unix,脚本(#!),FAT(cafebabe<l>、bebafeca<B>),Mach-o(feedface<32>,feedfacf<64>)
- 富二进制头 [magic,narc][cputype,cpusubtype,offset,size,align]…
- Mach-o头[magic,cputype,cpusubtype,filetype,ncmds,sizeofcmds,flags,reserved<64>][cmdtype,cmdsize,cmd]… filetype:MH_OBJECT、MH_EXECUTABLE、MH_CORE、MH_DYLIB、MH_BUNDLE、MH_DSYM、MH_KEXT_BUNDLE。flags:MH_NOUNDEFS、MH_SPLITSEGS…。cmdtyp:LC_SEGMENT…
- LC_SEGMENT(_64) 0x01(0x19) 加载段[LC_SEGMENT(_64),cmdsize,segname,vmaddr,vmsize,fileoff,filesize,maxprot,initprot,nsects,flags][sects]…
- LC_DYLINKER 动态库符号绑定 用户态 LC_SYMTAB、LC_DSYMTAB、LC_LOAD_DYLIB…
- LC_UNIXTHREAD被LC_MAIN代替 启动主线程 加载寄存器 ARM(i386、x86)_THREAD_STATE(64) r15 程序计数器
- LC_THREAD 核心转储
- LC_CODE_SIGNATURE 加载数字签名 如果没有或不匹配立刻SIGKILL信号
- 函数拦截 __attribute__((used)) static struct{const void* replacement;const void* replacee;}replacestruct __attribute__((section(“__DATA,__interpose”)))={(const void*)(unsigned long)&替换函数,(const void*)(unsigned long)&被替换函数};
- void main(int argc, char **argv, char **envp, char **apple)
- 内存分段 __PAGEZERO 4KB(4G) 取消了所有权限SIGBUS信号;__TEXT 代码段;__LINKEDIT 动态符号表 字符串表 其他数据;__IMPORT i386二进制文件导入表;__DATA 可读可写数据;__MALLOC_TINY 小于一个页面的内存分配;__MALLOC_SMALL 几个页面的内存分配;__MALLOC_LARGE 1M以上的内存分配。
- commpage 段 固定地址ffff0000(7fffffe00000) arm(40000000)内核导出给用户态的共享只读页面,PPC的遗留在清除.
- alloca 在栈上分配内存
- CHUD、AppleProfileFamily、CoreProfile ios没有Dtrace
- proc_info显示设置进程线程信息
- stack_snapshot 进程快照
- kdebug 通过sysctl KERN_KDENABLE启用 内核日志int32压缩
- setrlimit 设置核心转储大小设置
- Malloc* 环境变量可以输出内存读写错误的日志
- libgmalloc.dylib 截获内存分配、调试内存
- pthread_setname_np 给线程设置名称
- NSXPCConnection XPC进程通信 SandBoxedFetch苹果例子
OS X 引导过程
- EFI(Intel Extensible Firmware Interface) PE格式
- boot.efi EFI加载器 添加了自定义头 区分 32 64
- EFI_STATUS (EFIAPI *EFI_IMAGE_ENTRY_POINT)(IN EFI_HANDLE handle, IN EFI_SYSTEM_TABLE table) main函数
- 调用ExitBootServices()前是引导服务,提供内存、硬件访问、EFI程序调用,引导服务保存在EFI_SYSTEM_TABLE结构中。
- 运行时服务在引导和操作系统模式都可以访问
- boot.efi 保存EFI_SYSTEM_TABLE到全局变量,cpuid汇编指令查看cpu是否支持AES-NI指令(AES加密解密加速),初始化控制台{调用RunTimeServices查询NVRAM变量Background Clear,调用LocateProtocol控制台,GetMode获取控制台模式},获取NVRM中ROM和MLB变量,初始化设备树,为内核分配内存,保存内核地址到全局变量,InitMemoryConfig,InitSupportedCPUTypes,检查休眠状态CheckHibernate如果是休眠跳过下面所有步骤,处理引导按键和com.apple.Boot.plist配置ProcessOptions,cupid汇编判断cpu是否支持64位,检查CoreStorage如果有CoreStorage获取分区ID、EFI句柄调用LoadCoreStorageConfiguration获取CoreStorage参数如果是加密卷调用UnlockCoreStorageVolumeKey,将控制台初始化为图形模式,绘制logo,加载内核LoadKernel,初始化内核参数BootStructå,加载设备驱动Extensions.mkext,如果指定RAMDisk将其加载到内存,结束logo动画,再次设置其他内核参数,调用ExitBootServices,跳转到内核
- 睡眠返回时调用EFI运行时hibernate_newruntime_map
- Boot Camp功能使EFI可以引导多系统其中提供了完整的驱动程序
IOS 引导过程
- 不支持EFI使用iBoot,除第一步引导ROM后续步骤都是加密且签名,ROM是固化不能升级的
- 普通引导 加载底层引导加载器LLB(IMG3)到预定义地址(84000000),加载iBoot如果失败进入DFU模式,加载iBoot引导加载器到5FF000000,调用fsboot挂载系统分区,定位内核,初始化设备树,引导系统,引导失败进入恢复模式。iBoot有main线程和串口调试线程,mian派生idleoff(自动锁屏)、poweroff(电量低关机)、usb-req(usb请求)、usb-high-current usb-no-current(充电).恢复模式使用ramdisk(内存文件系统)替换根文件系统。
- 更新模式(DFU) 加载底层初始化模块iBS(84000000),加载iBEC(85000000)处理USB命令
OS X 安装过程
- 向osrecovery.apple.com验证
- 将kernelcache、boot.efi、InstallESD.dmg复制到/Mac OS X Install Data目录
- 修改com.apple.Boot.plist Kernel Cache=*/kernelcache Kernel Flags = container-dmg=*/InstallESD.dmg rootdmg=System.dmg(根文件系统)
- bless 修改引导盘从InstallESD.dmg引导
- 重启后执行OSInstaller加载minstallconfig.xml安装配置、安装系统
MacOS IOS launchd
- 第一个用户态进程,所有用户态进程的根
- 内核加载BSD子系统的主内核线程创建一个新线程(pid=1)执行bsdinit_task->load_init_program(硬编码/sbin/launchd)->execve
- 用户登 pid=1 launchd fork新的launchd
- inetd、xinetd 监听网络,有链接请求时唤起服务(如voip)
- bootstrap_server 管理服务端口,使用plist注册服务,bootstrap_check_in函数准备好服务后调用.bootstrap_look_up查询服务,mach_msg发送接收消息
- ios lockdownd TCP62078 /var/run/lockdown.sock
- ios 由lockdownd启动afc文件传输服务
- Finder or SpringBoard(UI事件都是由SB投递的)
MacOS IOS 用户内核态转换
- Intel定义了255个中断向量,0-19是异常20-31被保留,后面是中断。转换支持模拟中断,sysenter、syscall、sysexit更高效
- ARM内核态转换只支持模拟中断
- POSIX 验证传入的快照cpu架构匹配->current_task获取当前进程数据结构->调用号为0非直接调用修改参数->参数大于6要压栈->系统调用->罕见会重新执行->返回值设置寄存器->返回用户态
- MACH陷阱 mach_call_munger(mach_call_args结构)->mach_trap_table函数表大部分没用处理函数直接调用kern_invalid
- 机器相关调用 machdep_call_talbe arm中是讲R12设置为80000000 然后R3设置调用编号
- 诊断调用 基本已经废弃
MacOS IOS 内核运行流程
- vstart根据boot_args_start是否为空判断自己是主cpu还是从cpu 调用02-06步骤
- 如果启用DBG宏 vstart调用pal_serial_init 初始化串口
- 启用NX/XD cpu防止指令指针指向堆栈或标注为数据的页面,防代码注入
- cpu_desc_init 初始化GDT和LDT内存映射
- cpu_mode_init 初始化cpu的MSR指令在用户态内核态转换时使用。初始化物理页面映射。
- i386_init/i386_init_slave/arm_init 初始化cpu状态准备内核引导 调用07-24步骤,slave不走下面,执行do_init_slave检查fast_restart区分是第一次初始化还是休眠中唤起,cpu_init,slave_main,从current_processor获取当前可执行线程,如果没有就idle
- pal_*_init Platform Abstraction Layer初始化
- PE_Init_platform 初始化全局变量PE_state、gPEClockFrequency
- kernel_early_bootrap 定时器初始化
- cpu_init 初始化cpu时钟为永远运行
- printf_init 如果连接了调试器 重定向到调试器
- panic_init 内核奔溃重定向
- PE_init_kprintf 设置kprintf能输出到控制台
- 检查serial控制台,调用switch_toserial_console
- PE_Init_printf 设置printf能输出到控制台
- 64位处理器检查 启用CPUID_EXTFEATURE_EM64标志
- i386_vm_init 从EFI接管虚拟内存管理,初始化内核物理内存映射
- 再次调用PE_init_platform参数设置为TRUE表示虚拟内存初始化完成,获取设备树。
- PE_create_console 启动图形或文本模式控制台
- tsc_init 从EFI获得FSB频率及其他参数跟cpu频率计算转换比例
- power_management_init 设置pm_init_lock锁 管理电源
- processor_bootstrap 初始化Mach处理子系统初始化了3个队列task、terminated_tasks、threads创建master_processor对象调用processor_init、processor_init设置处理器数据结构加入pset0处理器组
- thread_bootstrap 设置Mach线程对象,填充线程结构字段,设置第一个系统线程init_thread,设置为活动线程
- machine_starup 解析命令行参数MACH_KDB->ddb_init并挂起内核引导
- kernel_bootstrap 初始化Mach子系统、虚拟内存、IPC、时钟、记账工具、task=进程,线程。将kernel_bootstrap_thread设置为当前活跃线程继续初始化工作。
- kernel_bootstrap_thread创建新线程,idle线程在cpu无工作时被执行。调度器线程、线程维护线程、初始化IOKit、启用中断(调用spllo)、初始化共享区域给dyld共享库和commpage使用。
- mac_policy_initmach 启动强制访问控制
- 初始化BSD系统bsd_init 最终启动launchd
MacOS IOS Mach 消息
- 进程、线程、虚拟内存都是对象,对象与对象之间通过消息通信
- struct mach_msg_base_t{mach_msg_header_t,mach_msg_body_t}
- struct mach_msg_header_t{mach_msg_bits_t标志位,mach_msg_size_t字节大小,mach_prot_t接收端口,mach_port_t发送端口,mach_msg_size_t保留字段,mach_msg_id_t唯一id}
- 可选struct mach_msg_trailer_t{mach_msg_trailer_type_t,mach_msg_trailer_size_t},有一些预定义尾结构
- 复杂消息mach_msg_header_t中mach_msg_bits_t含有MACH_MSGH_BITS_COMPLEX位,mach_msg_header_t后紧跟描述符计数字段及描述符.主要是out-of_line(OOL)数据即数据指针
- OOL描述符struct mach_msg_ool_descriptort64_t{uint64_t指针地址,boolean_t是否释放分配内存,mach_msg_copy_options_t复制指令,unsigned int预留,mach_msg_descriptor_type_t,mach_msg_size_t指针数据尺寸}
- mach_msg(_overwrite,_trap) 发送接收消息
- 端口和权限可以在进程间传递,约定应答消息比对应请求编号大100
- Mach的IDL接口定义文件(MIG接口生成器)后缀.defs通过mig命令生成代码.
MacOS IOS Mach 同步
- 同步只是内核中的普通变量但硬件必须对其进行原子操作
- 大部分同步对象属于struct lck_grp_t对象(锁组即列表)
- 互斥锁lck_mtx_t(mutex) 硬件无关
- 读写锁lck_rw_t 硬件无关
- 自旋锁hw_lock_t 硬件相关,子类lck_spin_t,simple_lock_t,usimple_lock_t
- 信号量Semaphore 是值可以超过1的互斥锁,可以与信号量互转 可以在用户态使用
- 锁集(互斥锁数组)
MacOS IOS Mach 其他
- 主机、时钟、cpu、cpu集对象
MacOS IOS Mach 调度
- 线程 最小的执行单元 struct thread非常巨大的结构,一般通过一个模板复制出来。结构中没有资源句柄.uthread成员是BSD线程的指针.
- 任务(进程)struct task 是线程、虚拟内存、设备、资源的容器.资源被抽象为端口.
- 账本是任务的配额、限制数据.如内存限制、cpu限制
- current_task,current_thread,thread_switch,thread_block,thread_policy_set
MacOS IOS Mach 虚拟内存
- vm_map->vm_map_entry->vm_object(vm_map sub)->vm_page
- 物理内存抽象pmap 将硬件分页表、翻译查找表等硬件相关的细节隐藏,pmap可以嵌套
- kernel_map是内核的vm_map实例
- ios对vm_map_protect、vm_map_enter函数进行修改禁止即可执行也可写入的内存
- Zone内核态使用 快速频繁分配释放固定大小的内存
- 分页器并不执行内存管理逻辑,仅仅执行页面交换(交换是加密、解密、清零、报警等)
MacOS IOS BSD POSIX API
- 进程包装MACH任务,添加了文件描述符、信号处理程序、进程父子兄弟子进程关系、DTrace支持、代码签名、工作队列等. struct proc
- 进程链表 struct proclist,allproc、zombproc(僵尸进程),proc_iterate遍历allproc,pgrp_iterate遍历僵尸进程
- 进程组 struct pgrp
- 线程 struct uthread,pthread_create->bsdthread_create->thread_create->mach调用
- 进程必须从init(launch)进行fork/posix_spawn不能凭空创建,最终调用MACH的fork1,exec系列函数加载执行文件
- sysctl struct sysctl_oid、SYSCTL_NODE、SYSCTL_DECL、SYSCTL_INT、SYSCTL_PROC
- kqueue替代poll、select模型,kqueue、kevent(64)
MacOS IOS MAC 策略
- struct mac_policy_conf MAC_POLICY_SET自动注册策略模块
- mpc_ops字段指向struct mac_policy_ops 包含300多个函数
- sandbox.kext 沙盒扩展使用类SCHEME语音定义许可
- AppleMobileFileIntegrity.kext 签名检查扩展
MacOS IOS MAC 网络
- 完全照搬了POSIX的套接字。实现了物理、数据链路、网络、传输、会话
- 会话层套接字需要三个参数:地址/协议族,套接字类型,协议
- 地址/协议族 Address Family/Protocol Family PF_INET/AF_INET…
- PF_LOCAL 等同AF_UNIX和PF_UNIX UNIX domain套接字 进程间通信。可传递文件句柄。
- PF_INET ip4
- PF_ROUTE 路由控制协议
- PF_NDRV 网络驱动协议 直接在数据链路层操作数据
- PF_KEY IPSec key Management 用于安全领域软件。
- PF_INET6 ip6
- PF_SYSTEM 内核与用户空间通信 struct kern_ctl_reg、 SYSPROTO_EVENT广播消息。
- file_socket可以获取struct socket
- 传输层 tcp、udp、icmp、raw. struct pr_usrreqs 包含协议相关函数指针.
- 网络层IPv4,IPv6,AppleTalk. proto_register_input动态注册新协议,初始化struct proto_input_entry.
- 数据链路 struct ifnet. 包括 en、ppp、fw、lo、utun、vlan等接口。lo回环接口必须有,vlan虚拟局域网,utun隧道不是真正的接口定义了一些桩将数据转到用户态进程处理实现类似VPN socket代理等。
linux 内核网络
- NAPI 可以在中断与轮循两种模式切换的内核网络驱动API