├── .gitignore ├── LICENSE ├── Makefile ├── README.md ├── make.bat └── source ├── _static └── .gitkeep ├── architecture ├── bios.rst ├── bus.rst ├── cpu.rst ├── device.rst ├── disk.rst ├── gpu.rst ├── index.rst ├── io.rst ├── kernel.rst ├── memory.rst └── organization.rst ├── assembly ├── arm.rst ├── diff.rst ├── index.rst ├── isa.rst ├── mips.rst ├── ppc.rst ├── x64.rst └── x86.rst ├── basic ├── bool.rst ├── endian.rst ├── history.rst └── index.rst ├── compile ├── basic.rst ├── generation.rst ├── index.rst ├── intermediate.rst ├── jit.rst ├── lexical.rst ├── llvm.rst ├── optimization.rst ├── semantic.rst ├── syntax.rst └── terminology.rst ├── conf.py ├── defense ├── antivirus.rst ├── edr.rst └── index.rst ├── exploit ├── index.rst └── shellcode.rst ├── firmware ├── 4g.rst ├── android.rst ├── ble.rst ├── hal.rst ├── hardware.rst ├── index.rst ├── ios.rst ├── iov.rst ├── router.rst ├── secureboot.rst ├── security.rst └── unpack.rst ├── fuzz ├── boxes.rst ├── genm.rst ├── history.rst ├── index.rst ├── intro.rst ├── ref.rst └── techs.rst ├── heap ├── index.rst ├── offByOne.rst ├── uaf.rst └── unlink.rst ├── images └── AndroidSystemFramework.png ├── index.rst ├── malware ├── antiav.rst ├── index.rst └── windows.rst ├── misc ├── gc.rst ├── index.rst ├── sandbox.rst └── terminology.rst ├── mitigations ├── aslr.rst ├── canary.rst ├── cfi.rst ├── dep.rst ├── index.rst ├── sandbox.rst └── secureprogramming.rst ├── os ├── android.rst ├── boot.rst ├── index.rst ├── ios.rst ├── linux │ ├── boot.rst │ ├── device │ │ ├── class.rst │ │ ├── driver.rst │ │ ├── index.rst │ │ ├── misc.rst │ │ ├── mtd.rst │ │ ├── operations.rst │ │ └── terminal.rst │ ├── fs │ │ ├── fuse.rst │ │ ├── index.rst │ │ ├── io.rst │ │ ├── jffs.rst │ │ ├── overlay.rst │ │ ├── unionfs.rst │ │ ├── vfs.rst │ │ └── yaffs.rst │ ├── history.rst │ ├── index.rst │ ├── intro.rst │ ├── io.rst │ ├── mem │ │ ├── addr.rst │ │ ├── alloc.rst │ │ ├── heap.rst │ │ ├── index.rst │ │ └── stack.rst │ ├── network │ │ ├── index.rst │ │ ├── netdev.rst │ │ ├── netfilter.rst │ │ └── socket.rst │ ├── process │ │ ├── coroutine.rst │ │ ├── dispatch.rst │ │ ├── elfload.rst │ │ ├── elfrun.rst │ │ ├── index.rst │ │ ├── ipc.rst │ │ ├── process.rst │ │ ├── sem.rst │ │ ├── shm.rst │ │ ├── signal.rst │ │ └── thread.rst │ ├── ref.rst │ ├── sec │ │ ├── capabilities.rst │ │ ├── cgroups.rst │ │ ├── index.rst │ │ ├── mitigation.rst │ │ ├── namespace.rst │ │ └── seccomp.rst │ ├── source.rst │ └── syscall │ │ ├── device │ │ ├── index.rst │ │ └── ioctl.rst │ │ ├── index.rst │ │ ├── intro.rst │ │ ├── io │ │ ├── close.rst │ │ ├── dup.rst │ │ ├── epoll.rst │ │ ├── fcntl.rst │ │ ├── index.rst │ │ ├── open.rst │ │ ├── poll.rst │ │ ├── read.rst │ │ ├── seek.rst │ │ ├── select.rst │ │ ├── sync.rst │ │ └── write.rst │ │ ├── mem │ │ ├── brk.rst │ │ ├── index.rst │ │ └── mmap.rst │ │ ├── net │ │ ├── accept.rst │ │ ├── bind.rst │ │ ├── index.rst │ │ ├── recv.rst │ │ ├── send.rst │ │ ├── socket.rst │ │ └── sockopt.rst │ │ ├── process │ │ ├── clone.rst │ │ ├── execve.rst │ │ ├── fork.rst │ │ ├── index.rst │ │ ├── prctl.rst │ │ ├── ptrace.rst │ │ ├── vfork.rst │ │ └── wait.rst │ │ ├── session │ │ ├── index.rst │ │ └── setsid.rst │ │ └── signal.rst ├── macos.rst ├── overview.rst └── windows │ ├── concept.rst │ ├── dotnet.rst │ ├── fs.rst │ ├── fsenc.rst │ ├── history.rst │ ├── index.rst │ ├── iodriver.rst │ ├── kernel │ ├── basic.rst │ ├── dll.rst │ ├── executive.rst │ ├── index.rst │ ├── misc.rst │ ├── subsystem.rst │ └── wsl.rst │ ├── logon.rst │ ├── malware.rst │ ├── mem.rst │ ├── network.rst │ ├── process │ ├── container.rst │ ├── dll.rst │ ├── index.rst │ ├── job.rst │ ├── process.rst │ ├── struct.rst │ └── thread.rst │ ├── ref.rst │ ├── registry.rst │ ├── security │ ├── acl.rst │ ├── history.rst │ ├── ident.rst │ ├── index.rst │ ├── policy.rst │ └── virtual.rst │ ├── services.rst │ ├── terminology.rst │ └── wmi.rst ├── reverse ├── antidebug.rst ├── brief.rst ├── dll.rst ├── elf.rst ├── index.rst ├── macho.rst ├── obfuscation.rst ├── pe.rst └── taint.rst ├── stack ├── call.rst ├── index.rst ├── overflow.rst └── rop.rst ├── tools ├── booklist.rst ├── compiler │ ├── clang.rst │ ├── cmake.rst │ ├── gcc.rst │ ├── index.rst │ ├── msvc.rst │ └── nasm.rst ├── debuger │ ├── gdb.rst │ ├── index.rst │ ├── misc.rst │ ├── trace.rst │ └── windbg.rst ├── document.rst ├── index.rst ├── list │ ├── android.rst │ ├── compile.rst │ ├── demo.rst │ ├── dynamic.rst │ ├── exploit.rst │ ├── firm.rst │ ├── fuzz.rst │ ├── index.rst │ ├── misc.rst │ ├── persistence.rst │ ├── red.rst │ ├── resources.rst │ ├── reverse.rst │ ├── sidechannel.rst │ └── virtual.rst ├── reverse │ ├── ida.rst │ ├── index.rst │ ├── objdump.rst │ └── readelf.rst └── systool.rst ├── virtual ├── basic.rst ├── cpu.rst ├── detect.rst ├── hypervisor.rst ├── index.rst ├── intel.rst ├── kvm │ ├── basic.rst │ ├── index.rst │ ├── ref.rst │ └── tool.rst ├── libvirt.rst ├── mem.rst ├── misc.rst ├── qemu │ ├── arch.rst │ ├── basic.rst │ ├── device.rst │ ├── event.rst │ ├── index.rst │ ├── iothread.rst │ ├── misc.rst │ ├── opts.rst │ ├── qmp.rst │ ├── qom.rst │ ├── ref.rst │ ├── runtime.rst │ ├── sec.rst │ └── source.rst ├── sec.rst ├── tech.rst ├── unicorn.rst ├── virtio.rst ├── vmware.rst └── xen.rst └── vulns ├── fmtstr.rst ├── index.rst └── typeConfusion.rst /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | env/ 12 | build/ 13 | develop-eggs/ 14 | dist/ 15 | downloads/ 16 | eggs/ 17 | .eggs/ 18 | lib/ 19 | lib64/ 20 | parts/ 21 | sdist/ 22 | var/ 23 | *.egg-info/ 24 | .installed.cfg 25 | *.egg 26 | 27 | # PyInstaller 28 | # Usually these files are written by a python script from a template 29 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 30 | *.manifest 31 | *.spec 32 | 33 | # Installer logs 34 | pip-log.txt 35 | pip-delete-this-directory.txt 36 | 37 | # Unit test / coverage reports 38 | htmlcov/ 39 | .tox/ 40 | .coverage 41 | .coverage.* 42 | .cache 43 | nosetests.xml 44 | coverage.xml 45 | *,cover 46 | .hypothesis/ 47 | 48 | # Translations 49 | *.mo 50 | *.pot 51 | 52 | # Django stuff: 53 | *.log 54 | local_settings.py 55 | 56 | # Flask stuff: 57 | instance/ 58 | .webassets-cache 59 | 60 | # Scrapy stuff: 61 | .scrapy 62 | 63 | # Sphinx documentation 64 | docs/_build/ 65 | 66 | # PyBuilder 67 | target/ 68 | 69 | # IPython Notebook 70 | .ipynb_checkpoints 71 | 72 | # pyenv 73 | .python-version 74 | 75 | # celery beat schedule file 76 | celerybeat-schedule 77 | 78 | # dotenv 79 | .env 80 | 81 | # virtualenv 82 | venv/ 83 | ENV/ 84 | 85 | # Spyder project settings 86 | .spyderproject 87 | 88 | # Rope project settings 89 | .ropeproject 90 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # Minimal makefile for Sphinx documentation 2 | # 3 | 4 | # You can set these variables from the command line. 5 | SPHINXOPTS = 6 | SPHINXBUILD = python -msphinx 7 | SPHINXPROJ = bin-sec 8 | SOURCEDIR = source 9 | BUILDDIR = build 10 | 11 | # Put it first so that "make" without argument is like "make help". 12 | help: 13 | @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 14 | 15 | .PHONY: help Makefile 16 | 17 | # Catch-all target: route all unknown targets to Sphinx using the new 18 | # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). 19 | %: Makefile 20 | @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) -------------------------------------------------------------------------------- /make.bat: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | 3 | pushd %~dp0 4 | 5 | REM Command file for Sphinx documentation 6 | 7 | if "%SPHINXBUILD%" == "" ( 8 | set SPHINXBUILD=python -msphinx 9 | ) 10 | set SOURCEDIR=source 11 | set BUILDDIR=build 12 | set SPHINXPROJ=pdoc 13 | 14 | if "%1" == "" goto help 15 | 16 | if errorlevel 9009 ( 17 | echo. 18 | echo.The Sphinx module was not found. Make sure you have Sphinx installed, 19 | echo.then set the SPHINXBUILD environment variable to point to the full 20 | echo.path of the 'sphinx-build' executable. Alternatively you may add the 21 | echo.Sphinx directory to PATH. 22 | echo. 23 | echo.If you don't have Sphinx installed, grab it from 24 | echo.http://sphinx-doc.org/ 25 | exit /b 1 26 | ) 27 | 28 | %SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% 29 | goto end 30 | 31 | :help 32 | %SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% 33 | 34 | :end 35 | popd 36 | -------------------------------------------------------------------------------- /source/_static/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LyleMi/Learn-Binary-Hacking/8ac631da0a6facecf7b2e4d6687f0b4203edfc5a/source/_static/.gitkeep -------------------------------------------------------------------------------- /source/architecture/bios.rst: -------------------------------------------------------------------------------- 1 | BIOS 2 | ======================================== 3 | 4 | 简介 5 | ---------------------------------------- 6 | BIOS这个字眼是在1975年第一次由CP/M操作系统中出现,是个人电脑启动时加载的第一个软件。 7 | 8 | 功能 9 | ---------------------------------------- 10 | - 开机自检( Power On Self Test,POST) 11 | - 计算机开机时系统将控制权交给BIOS,BIOS针对CPU各项寄存器、标志位等先检查CPU是否工作正常,接下来会检查8254定时器、8259A可编程中断控制器、8237DMA控制器等的状态,测试其是否正常工作 12 | - 系统初始化 13 | - 针对CPU Cache、DRAM、南北桥芯片组、显卡、PCI设备控制器、IDE设备控制器、网卡等的寄存器作初始化操作,填充相应寄存器的值,设定成可支持的默认工作模式,并检測是否能够正常工作 14 | - 提供常驻内存的运行时服务( Runtime services) 15 | - 这些服务程序常驻在某段系统内存中,操作系统和应用程序能够通过中断方式调用这些服务代码,典型的如Int 10h、Int13h、Int 15h等 16 | - 系统设置 17 | - BIOS提供文本或图形界面的设置程序(通常称为BIOS Setup)供用户在进入操作系统前对系统的一些参数值进行设置,如BOS密码、光盘/硬盘/软盘引导顺序、系统时间等 18 | - 引导操作系统 19 | 20 | 传统的BIOS缺陷 21 | ---------------------------------------- 22 | - 传统固件BIOS仍然运行在16位实模式下,这使得Pentium 4的CPU在BIOS运行阶段只相当于一块高速的8086中央处理器。不能充分的发挥中央处理器硬件新技术上的优势 23 | - 传统固件BIOS封闭的开发方式严重阻碍了固件技术发展。传统固件BIOS缺乏统一和开放的架构,不同固件BIOS厂商其BIOS产品结构设计千差万别 24 | - 传统固件BIOS的设计,一开始就缺乏安全方面的考虑 25 | -------------------------------------------------------------------------------- /source/architecture/bus.rst: -------------------------------------------------------------------------------- 1 | 总线 2 | ======================================== 3 | -------------------------------------------------------------------------------- /source/architecture/device.rst: -------------------------------------------------------------------------------- 1 | 设备 2 | ======================================== 3 | 4 | I/O 设备 5 | ---------------------------------------- 6 | I/O 设备是用于和计算机进行通信的外部硬件。输入/输出设备能够向计算机发送数据并从计算机接收数据。 7 | 8 | I/O 设备通常由机械组件 (mechanical component) 和电子组件 (electronic component) 构成,其中电子组件被称为设备控制器 (device controller)或者适配器 (adapter)。I/O 设备通常采用可插入 PCI (Periheral Component Interconnect) 扩展插槽的主板上的芯片或印刷电路卡的形式。 9 | 10 | 编址方式 11 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 12 | - 统一编址 13 | - 将 I/O 设备当做存储器地址的一部分 14 | - 独立编址 15 | - 将 I/O 设备与存储器地址分开,使用专门的 I/O 指令访问 16 | 17 | 设备控制器 18 | ---------------------------------------- 19 | 设备控制器是处理 CPU 传入和传出信号的系统。设备通过插头和插座连接到计算机,并且插座连接到设备控制器。设备控制器从连接的设备处接收数据,并将其存储在控制器内部的一些特殊目的寄存器 (special purpose registers) 也就是本地缓冲区中。 20 | -------------------------------------------------------------------------------- /source/architecture/disk.rst: -------------------------------------------------------------------------------- 1 | 硬盘 2 | ======================================== 3 | -------------------------------------------------------------------------------- /source/architecture/gpu.rst: -------------------------------------------------------------------------------- 1 | GPU 2 | ======================================== 3 | 4 | 简介 5 | ---------------------------------------- 6 | GPU最初是设计用于图形渲染的外围设备。和CPU不同,GPU提供了大量的专用处理器,GPU处理数据有天然的并行性。 7 | 8 | 参考链接 9 | ---------------------------------------- 10 | - `深入GPU硬件架构及运行机制 `_ 11 | - `GPU体系架构(一):数据的并行处理 `_ 12 | - `GPU体系架构(二):GPU存储体系 `_ 13 | -------------------------------------------------------------------------------- /source/architecture/index.rst: -------------------------------------------------------------------------------- 1 | 计算机体系结构 2 | ======================================== 3 | 4 | .. toctree:: 5 | :maxdepth: 2 6 | :caption: 目录: 7 | 8 | organization 9 | cpu 10 | bios 11 | memory 12 | disk 13 | gpu 14 | bus 15 | device 16 | io 17 | kernel 18 | -------------------------------------------------------------------------------- /source/architecture/io.rst: -------------------------------------------------------------------------------- 1 | I/O 2 | ======================================== 3 | 4 | I/O 接口 5 | ---------------------------------------- 6 | 接口是两个系统或两个部件之间的交接部分,可以是两种硬设备之间的连接电路,也可以是两个软件之间的共同逻辑边界。 7 | 8 | I/O 接口是主机与I/O设备间设置的硬件电路及其相应的软件控制,用于实现设备的选择、数据缓冲、通过接口传送控制命令等功能。 9 | 10 | I/O 端口指接口电路中的一些寄存器这些寄存器用于存放数据、控制命令、状态信息等。CPU对I/O接口(或I/O设备)的信息读写,实际上都是对端口的操作。 11 | 12 | I/O 接口类型 13 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 14 | - 按数据传送方式 15 | - 并行接口 / 串行接口 16 | - 按功能选择分类 17 | - 可编程 / 不可编程接口 18 | - 按通用性分类 19 | - 通用接口 / 专用接口 20 | - 按数据传送的控制方式分类 21 | - 程序型接口:用于低速设备,采用程序中断方式 22 | - DMA 接口:用于连接高速I/O设备 23 | 24 | 内存映射 I/O 25 | ---------------------------------------- 26 | 每个设备控制器都会有几个寄存器用来和 CPU 进行通信。通过写入这些寄存器,操作系统可以命令设备发送数据,接收数据、开启或者关闭设备等。通过从这些寄存器中读取信息,操作系统能够知道设备的状态,是否准备接受一个新命令等。 27 | 28 | 为了控制寄存器,许多设备都会有数据缓冲区 (data buffer),来供系统进行读写。例如,在屏幕上显示一个像素的常规方法是使用一个视频 RAM,这一 RAM 基本上只是一个数据缓冲区,用来供程序和操作系统写入数据。 29 | 30 | CPU 与设备寄存器和设备数据缓冲区进行通信有三种方式。第一种方法是,每个控制寄存器都被分配一个 I/O 端口号,端口号是一个 8 位或 16 位的整数。操作系统可以使用类似 ``IN REG,PORT`` / ``OUT PORT,REG`` 的指令访问。 31 | 32 | 第二种方式是将所有控制寄存器映射到内存空间中。 33 | 34 | 第三种方式是一种混合方式,这种方式具有与内存映射 I/O 的数据缓冲区,而控制寄存器则具有单独的 I/O 端口。 35 | 36 | 在这种方式下,当 CPU 想要读入一个字的时候,将需要的地址放到总线地址线上,然后在总线的一条控制线上调用一个 READ 信号。还有第二条信号线来表明需要的是 I/O 空间还是内存空间。如果是内存空间,内存将响应请求。如果是 I/O 空间,那么 I/O 设备将响应请求。如果只有内存空间,那么每个内存模块和每个 I/O 设备都会将地址线和它所服务的地址范围进行比较。如果地址落在这一范围之内,它就会响应请求。 37 | 38 | 直接内存访问 39 | ---------------------------------------- 40 | 无论一个 CPU 是否具有内存映射 I/O,都需要寻址设备控制器以便与交换数据。CPU 可以从 I/O 控制器每次请求一个字节的数据,但是这么做会浪费 CPU 时间,所以经常会用到一种称为直接内存访问 (Direct Memory Access) 的方案。 41 | 42 | 直接内存访问是一种完全由硬件执行I/O交换的工作方式,主存与I/O 设备间高速交换批量数据,传送速度快。硬件DMA控制器从CPU完全接管对总线的控制,数据交换不经过CPU,直接在主存和I/O设备之间进行。 43 | 44 | 参考链接 45 | ---------------------------------------- 46 | - `I/O 设备 `_ 47 | -------------------------------------------------------------------------------- /source/architecture/kernel.rst: -------------------------------------------------------------------------------- 1 | 内核 2 | ======================================== 3 | 4 | 宏内核 5 | ---------------------------------------- 6 | 宏内核(Monolithic Kernel)是操作系统核心架构的一种,此架构的特性是整个核心程序都是以核心空间(Kernel Space)的身份及监管者模式(Supervisor Mode)来运行。 7 | 8 | 宏内核通常是以单一静态二进制文件的方式被存储在磁盘,或是高速缓存上,在开机之后被加载存储器中的核心空间,并开始运作。 9 | 10 | 宏内核的优点是效率高、反应快,但是耦合度高、灵活性差。 11 | 12 | 微内核 13 | ---------------------------------------- 14 | 微内核只有最基本的操作系统功能。非基本的服务和应用都在微内核之外构造。 15 | 16 | 微内核有着扩展性强、灵活、可移植、支持分布式系统等优势。 17 | -------------------------------------------------------------------------------- /source/architecture/memory.rst: -------------------------------------------------------------------------------- 1 | 内存 2 | ======================================== 3 | 4 | RAM 5 | ---------------------------------------- 6 | 主存通常被称做 RAM(Random Access Memory),由于 1950 年代和 1960 年代的计算机使用微小的可磁化铁氧体磁芯作为主存储器,因此有时将其称为核心存储器。所有不能再高速缓存中得到满足的内存访问请求都会转往主存中。 7 | 8 | VRAM 9 | ---------------------------------------- 10 | VRAM (Video Random Access Memory) 是GPU或VGA使用的一种特殊RAM类型。 11 | -------------------------------------------------------------------------------- /source/architecture/organization.rst: -------------------------------------------------------------------------------- 1 | 计算机系统构成 2 | ======================================== 3 | 4 | 处理器(Processor) 5 | ---------------------------------------- 6 | 7 | 简介 8 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 9 | 处理器是计算机的核心部件,由超大规模集成电路芯片构成,通常简称CPU。 10 | 11 | 一方面,它完成各种基本运算,包括加、减、乘、除等算术运算和逻辑判断、比较、位移等逻辑运算。另一方面,CPU还控制计算机各部件协调地工作,也就是说,整个计算机工作的顺序、信息输入、输出都是由CPU统一控制。 12 | 13 | RISC与CISC 14 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 15 | 精简指令集计算机(Reduced Instruction Set Computer,RISC)和复杂指令集计算机(Complex Instruction Set Computer )是当前CPU的两种架构,它们的区别在于不同的CPU设计理念和方法。 16 | 17 | 早期的CPU全部是CISC架构,它的设计目的是要用最少的机器语言指令来完成所需的计算任务。比如对于乘法运算,只需要一条指令 ``mul addra, addrb`` 就可以完成,将地址中的数据读入寄存器,相乘和将结果写回内存的操作全部依赖于CPU中设计的逻辑来实现。这种架构会增加CPU结构的复杂性和对CPU工艺的要求,但对于编译器的开发十分有利。 18 | 19 | RISC架构要求软件来指定各个操作步骤。上面的例子如果要在RISC架构上实现,指令可能为 ``mov eax, addra; mov ebx, addrb; mul eax, ebx; str addra, a`` 这种架构可以降低CPU的复杂性以及允许在同样的工艺水平下生产出功能更强大的CPU,但对于编译器的设计有更高的要求。 20 | 21 | 内存储器(Memory) 22 | ---------------------------------------- 23 | 内存储器简称内存。内存分为两部分,有一部分用于永久存放特殊专用数据,只能从 24 | 中取出数据,不能向内写入数据,称为只读存储器(简称ROM)。其余的部分由计算机执行程序时使用,既可存入数据又可取出数据,称为随机存储器(简称RAM)。 25 | 26 | 外存储器(Auxiliary Memory) 27 | ---------------------------------------- 28 | 内部存储器容量是有限的,而且当计算机断电后,里面的内容会消失。因此需要容量更大,且能永久保存数据的存储器,这就是外存储器,也称为辅助存储器。BIOS固件就是一种特殊的外存贮器。 29 | 30 | 输入设备 31 | ---------------------------------------- 32 | 从计算机外部获取信息的设备称为输入设备。 33 | 34 | 常见的输入设备有键盘、鼠标、话筒、扫描仪等。 35 | 36 | 输出设备 37 | ---------------------------------------- 38 | 输出设备将计算机中的数据以文字、图形、声音等方式显示出来。 39 | 40 | 常见的输出设备有:显示器、打印机等。 41 | -------------------------------------------------------------------------------- /source/assembly/diff.rst: -------------------------------------------------------------------------------- 1 | 区别 2 | ======================================== 3 | 4 | 汇编常用的有AT&T和Intel两种格式,其区别有下面这些。 5 | 6 | 前缀 7 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 8 | 在AT&T汇编格式中,寄存器名要加上 ``%`` 作为前缀,如 ``pushl %eax``;而在Intel汇编格式中,寄存器名不需要加前缀,如: ``push eax`` 9 | 10 | 立即操作数 11 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 12 | 在AT&T汇编格式中,用 ``$`` 前缀表示一个立即操作数,如 ``pushl $1`` ;而在Intel汇编格式中,立即数的表示不用带任何前缀,如 ``push 1`` 13 | 14 | 操作数顺序 15 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 16 | AT&T和Intel格式中的源操作数和目标操作数的位置正好相反。 17 | 在AT&T汇编格式中,目标操作数在源操作数的右边,如 ``addl $1, %eax`` ; 而在Intel汇编格式中,目标操作数在源操作数的左边,如 ``add eax, 1``。 18 | 19 | 字长 20 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 21 | 在AT&T汇编格式中,操作数的字长由操作符的最后一个字母决定,后缀 ``b`` 、 ``w`` 、 ``l`` 分别表示操作数为字节(byte,8bit)、字(word,16bit)和长字(long,32bit),如 ``movb val, %al`` ;而在Intel汇编格式中,操作数的字长是用 ``byte ptr`` 和 ``word ptr`` 等前缀来表示的,如 ``mov al, byte ptr val`` 22 | 23 | 绝对转移和调用指令 24 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 25 | 在AT&T汇编格式中,绝对转移和调用指令(jump/call)的操作数前要加上 ``*`` 作为前缀,而在Intel格式中则不需要。 26 | 27 | 远程转移指令和远程子调用指令 28 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 29 | 远程转移指令和远程子调用指令的操作码,在AT&T汇编格式中为 ``ljump`` 和 ``lcall`` ,如 ``ljump $section, $offset`` ``jmp far section:offset`` 。 30 | 31 | 而在Intel汇编格式中则为 ``jmp far`` 和 ``call far`` ,即 ``lcall $section, $offset`` 和 ``call far section:offset`` 。 32 | 33 | 与之相应的远程返回指令则AT&T格式为 ``lret $stack_adjust`` ,Intel格式为 ``ret far stack_adjust`` 。 34 | 35 | 寻址 36 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 37 | AT&T 汇编格式中,内存操作数的寻址方式是 ``section:disp(base, index, scale)`` 。Intel汇编格式中,内存操作数的寻址方式为:``section:[base + index*scale + disp]`` 。 38 | -------------------------------------------------------------------------------- /source/assembly/index.rst: -------------------------------------------------------------------------------- 1 | 汇编基础 2 | ======================================== 3 | 4 | .. toctree:: 5 | :maxdepth: 2 6 | :caption: 目录: 7 | 8 | isa 9 | diff 10 | x86 11 | x64 12 | arm 13 | mips 14 | ppc 15 | -------------------------------------------------------------------------------- /source/assembly/isa.rst: -------------------------------------------------------------------------------- 1 | 指令集架构 2 | ======================================== 3 | 4 | 简介 5 | ---------------------------------------- 6 | 指令集体系结构 (Instruction set architecture, ISA)是计算机的抽象模型。它也称为体系结构或计算机体系结构。 7 | 8 | 分类 9 | ---------------------------------------- 10 | ISA可以通过多种方式分类,常见的分类方式是根据架构的复杂性分为复杂指令集计算机(CISC,complex instruction set computer)和精简指令集计算机(RISC,reduced instruction set computer)。CISC具有许多专门的指令,其中某些指令可能很少在实际程序中使用。RISC通过仅有效地执行程序中经常使用的指令来简化处理器。 11 | 12 | 指令类型 13 | ---------------------------------------- 14 | 15 | 数据处理和内存操作 16 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 17 | - 给寄存器设置值 18 | - 将数据从内存拷贝到寄存器 19 | - 将数据从寄存器拷贝到内存 20 | - 从硬件设备中存/取数据 21 | 22 | 算术和逻辑操作 23 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 24 | - 加/减/乘/除并设置状态寄存器 25 | - 位运算 26 | - 比较寄存器中的值 27 | - 浮点运算 28 | 29 | 控制流操作 30 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 31 | - 有条件跳转 32 | - 无条件跳转 33 | - 调用 34 | 35 | 协处理器 36 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 37 | - 从协处理器存/取数据 38 | - 协处理器操作 39 | 40 | 复杂指令集指令 41 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 42 | - 一次性操作多个寄存器 (e.g. 存/取到栈上) 43 | - 移动大块内存 (e.g. DMA操作) 44 | - 复杂的算术操作 (e.g. 开平方) 45 | - SIMD 操作 46 | - ... 47 | -------------------------------------------------------------------------------- /source/assembly/ppc.rst: -------------------------------------------------------------------------------- 1 | PowerPC 2 | ======================================== 3 | -------------------------------------------------------------------------------- /source/assembly/x64.rst: -------------------------------------------------------------------------------- 1 | x64 2 | ======================================== 3 | 4 | 常用寄存器 5 | ---------------------------------------- 6 | - RAX 7 | - 易失的 8 | - 返回值寄存器 9 | - RCX 10 | - 易失的 11 | - 函数调用的第四个参数 12 | - RDX 13 | - 易失的 14 | - 函数调用的第三个参数 15 | - RDI 16 | - 非易失的 17 | - 必须由被调用方保留 18 | - 函数调用的第一个参数 19 | - RSI 20 | - 非易失的 21 | - 必须由被调用方保留 22 | - 函数调用的第二个参数 23 | - RBX 24 | - 非易失的 25 | - 必须由被调用方保留 26 | - RBP 27 | - 非易失的 28 | - 可用作帧指针;必须由被调用方保留 29 | - RSP 30 | - 非易失的 31 | - 堆栈指针 32 | - R8 33 | - 函数调用的第五个参数 34 | - R9 35 | - 函数调用的第六个参数 36 | - R10-R11 37 | - 易失的 38 | - 必须根据需要由调用方保留 39 | - 在 syscall/sysret 指令中使用 40 | - R10为系统调用的第四个参数 41 | - R12-R15 42 | - 非易失的 43 | - 必须由被调用方保留 44 | 45 | 系统调用号 46 | ---------------------------------------- 47 | 需要注意的是,x86和x64架构下系统调用号并不相同。系统调用可在 ``/usr/include/asm/unistd.h`` 文件中查看。 48 | 49 | 参考链接 50 | ---------------------------------------- 51 | - `Intel® 64 and IA-32 Architectures Software Developer Manuals `_ 52 | -------------------------------------------------------------------------------- /source/assembly/x86.rst: -------------------------------------------------------------------------------- 1 | x86 2 | ======================================== 3 | 4 | 寄存器 5 | ---------------------------------------- 6 | 7 | 寄存器分类 8 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 9 | x86架构的寄存器可以分为通用寄存器、内存管理寄存器、EFLAGS寄存器、EIP寄存器、浮点运算寄存器、控制寄存器等。 10 | 11 | 寄存器说明 12 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 13 | - ESP 14 | - Extended Stack Pointer 栈指针寄存器 15 | - 指向最上面帧的栈顶 16 | - EBP 17 | - Extended Base Pointer 基址指针寄存器 18 | - 指向最上面帧的栈底 19 | - EIP 20 | - Extended Instruction Pointer 指令寄存器 21 | - 指向当前的指令地址 22 | - EFLAGS 23 | - 保存当前执行状态的所有Flag 24 | - CR0-CR7 25 | - 控制寄存器 26 | - 保存系统的控制位 27 | - IDTR 28 | - Interrupt Descriptor Table Register 29 | - 中断寄存器,记录当前中断处理函数的地址 30 | - IDTR 31 | - Global Descriptor Table Register 32 | - 记录段表 33 | 34 | 内存管理机制 35 | ---------------------------------------- 36 | 37 | 分段机制 38 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 39 | 分段机制就是把虚拟地址空间中的虚拟内存组织成一些长度可变的称为段的内存单元。分段机制由逻辑地址、段选择寄存器、段描述符、段描述表四个部分构成。 40 | 41 | 分页机制 42 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 43 | 分页机制是用粒度更小的页来管理线性地址空间和物理地址空间,x86下一个典型的页大小是4KB。 44 | 45 | 页表是用于将线性地址转换为物理地址的主要数据结构。4KB大小的页面使用两级页表结构。 46 | 47 | 运行模式 48 | ---------------------------------------- 49 | x86的运行模式有:实模式(Real Mode),保护模式(Protected Mode),虚拟8086模式(Virtual 8086 Mode)、系统管理模式(System management mode ,SMM)四种,每种模式下可执行的指令和可用的功能可能不一样。 50 | 51 | 实模式是早期处理器的运行模式,通常处理器上电后会处于这个模式,在实地址模式中,可以访问的物理地址空间只有1MB。 52 | 53 | 保护模式是最常见的模式,这个模式下对内存及一些外围设备提供了硬件级别的保护设置,如分段机制、分页机制。大部分OS都运行在这个模式下。 54 | 55 | 参考链接 56 | ---------------------------------------- 57 | - `Intel 80386 Reference Programmer's Manual `_ 58 | -------------------------------------------------------------------------------- /source/basic/bool.rst: -------------------------------------------------------------------------------- 1 | 布尔代数 2 | ======================================== 3 | -------------------------------------------------------------------------------- /source/basic/endian.rst: -------------------------------------------------------------------------------- 1 | 大小端与数据表示 2 | ======================================== 3 | 4 | 数字 5 | ---------------------------------------- 6 | 有补码编码 (two's complement) 与反码编码 (one's complement) 7 | -------------------------------------------------------------------------------- /source/basic/history.rst: -------------------------------------------------------------------------------- 1 | 计算机发展简史 2 | ======================================== 3 | -------------------------------------------------------------------------------- /source/basic/index.rst: -------------------------------------------------------------------------------- 1 | 基础知识 2 | ======================================== 3 | 4 | 5 | .. toctree:: 6 | :maxdepth: 2 7 | :caption: 目录: 8 | 9 | history 10 | bool 11 | endian 12 | -------------------------------------------------------------------------------- /source/compile/basic.rst: -------------------------------------------------------------------------------- 1 | 基础知识 2 | ======================================== 3 | 4 | 编译器 5 | ---------------------------------------- 6 | 简单来说,编译程序是一种翻译程序,它将高级语言所写的源程序翻译成等价的机器语言或汇编语言的目标程序。 7 | 8 | 解释程序也是一种翻译程序,它将源程序作为输入并执行之,解释程序与编译程序的主要区别是解释程序的执行过程中不生成目标程序。 9 | 10 | 编译的过程大致可分为词法分析、语法分析、语义分析、中间代码生成、代码优化、代码生成等几步。 11 | 12 | 词法分析阶段的任务是对构成源程序的字符串从左到右进行扫描和分解,根据语言的词法规则,识别出一个一个具有独立意义的token。 13 | 14 | 词法规则是单词符号的形成规则,它规定了哪样的字符串构成一个单词符号。 15 | 16 | 语法分析的任务是在词法分析的基础上, 根据语言的语法规则从单词符号串中识别出各种语法单位 (如表达式、说明、语句等) ,并进行语法检查,即检查各种语法单位在语法结构上的正确性。 17 | 18 | 语言的语法规则规定了如何从单词符号形成语法单位,语法规则是语法单位的形成规则。 19 | 20 | 语义分析的任务是首先对每种语法单位进行静态的语义审查,然后分析其含义,并用另一种语言形式 (比源语言更接近于目标语言的一种中间代码或直接用目标语言 ) 来描述这种语义。 21 | 22 | 代码优化的任务是对前阶段产生的中间代码进行等价变换或改造,以期获得更为高效,(省时间和空间)的目标代码。优化主要包括局部优化和循环优化等。 23 | 24 | 相关书籍 25 | ---------------------------------------- 26 | 编译原理领域最有名的三本书昵称为龙、虎、鲸。 27 | 28 | 龙书原名 ``Compilers: Principles, Techniques, and Tools`` ,由Alfred V.Aho等人编写。主要讨论了编译器设计的主题,包括词法分析、语法分析、语法制导分析、类型检查、运行环境、中间代码生成、代码生成、代码优化等问题。 29 | 30 | 虎书原名 ``Modern Compiler Implenentation in C`` 由Andrew W.Apple等人编写。虎书与龙书内容相似,但是增加了数据流分析、循环优化、内存管理等内容。 31 | 32 | 鲸书原名 ``Advanced Compiler Design and Implementation`` 由Steven S.Muchnick编写,和前两本书相比,鲸书涉及到了更多的比较高级的编译器实现。 33 | 34 | 编译阶段 35 | ---------------------------------------- 36 | 编译第一阶段为预处理阶段,涉及以下操作 37 | 38 | + 执行预编译指令 #define 等 39 | + 处理条件预编译指令 #ifdef 等 40 | + 删除注释 41 | + 添加行号和文件名标识 42 | + 保留 #pragma 预编译指令 43 | + ``gcc -E hello.c -o hello.i`` 44 | 45 | 编译阶段,对预处理完的文件进行词法分析、语法分析、语义分析以及优化后生成相应的汇编代码。将文本文件hello.i翻译成文本文件.s,包含一个汇编语言程序。可使用gcc的 ``-S`` 参数, 例如 ``gcc -S hello.i -o hello.s`` 。 46 | 47 | 汇编阶段,汇编器将.s文件翻译成机器语言指令,使用 gcc 的 ``-c`` 参数,例如 ``gcc -c hello.s -o hello.o`` 。 48 | 49 | 链接阶段,编译器以动态链接或静态链接的方式生成二进制文件。 50 | -------------------------------------------------------------------------------- /source/compile/generation.rst: -------------------------------------------------------------------------------- 1 | 代码生成 2 | ======================================== 3 | -------------------------------------------------------------------------------- /source/compile/index.rst: -------------------------------------------------------------------------------- 1 | 编译原理 2 | ======================================== 3 | 4 | 5 | .. toctree:: 6 | :maxdepth: 2 7 | :caption: 目录: 8 | 9 | basic 10 | lexical 11 | syntax 12 | semantic 13 | intermediate 14 | optimization 15 | generation 16 | llvm 17 | jit 18 | terminology 19 | -------------------------------------------------------------------------------- /source/compile/intermediate.rst: -------------------------------------------------------------------------------- 1 | 中间代码生成 2 | ======================================== 3 | -------------------------------------------------------------------------------- /source/compile/jit.rst: -------------------------------------------------------------------------------- 1 | JIT 2 | ======================================== 3 | -------------------------------------------------------------------------------- /source/compile/lexical.rst: -------------------------------------------------------------------------------- 1 | 词法分析 2 | ======================================== 3 | 4 | 词法分析的任务是对字符串表示的源程序从左到右地进行扫描和分解,根据语言的词法规则识别出一个一个具有独立意义的单词符号。 5 | 6 | 其中语言的单词符号是指语言中具有独立意义的最小语法单位。词法分析程序所输出的单词符号通常表示成如下的二元式:<单词种别,单词自身的值> 。 7 | -------------------------------------------------------------------------------- /source/compile/optimization.rst: -------------------------------------------------------------------------------- 1 | 代码优化 2 | ======================================== 3 | 4 | 简介 5 | ---------------------------------------- 6 | 代码优化对程序实施各种等价变化,使得变换后程序能生成高效率的目标代码。好的编译器需要生成目标代码占用的存储空间少,且运行时间短。另外,编译器的编译时间、资源消耗也是需要考虑的指标。 7 | 8 | 优化方式 9 | ---------------------------------------- 10 | 代码优化可以分为与机器有关的优化和与机器无关的优化。 11 | 12 | 机器无关的优化主要有下面几种方式: 13 | 14 | - 局部优化 15 | - 合并已知量 16 | - 删除公共子表达式 (删除多余的运算) 17 | - 删除无用赋值 18 | - 循环优化 19 | - 代码外提 20 | - 删除归纳变量 21 | - 强度削弱 22 | - 全局优化 23 | - 在整个程序范围内进行优化,需要进行数据流分析,代价很高 24 | 25 | 优化原则 26 | ---------------------------------------- 27 | 在当前,优化越来越重要,一个是因为现代处理器越来越复杂,有更多的机制来提供优化的机会。 28 | 29 | 另一个原因是多核并行越来越普遍,编译器需要适应,但是在硬件条件多变的情况下,很难知道一个解是不是最优解,那么就遵循以下的原则: 30 | 31 | + 优化必须保证正确 32 | + 优化要保证大部分程序都能提升表现 33 | + 优化带来的编译时间消耗需要是可以接受的 34 | + 工程量要能接受 35 | -------------------------------------------------------------------------------- /source/compile/semantic.rst: -------------------------------------------------------------------------------- 1 | 语义分析 2 | ======================================== 3 | -------------------------------------------------------------------------------- /source/compile/syntax.rst: -------------------------------------------------------------------------------- 1 | 语法分析 2 | ======================================== 3 | 4 | 简介 5 | ---------------------------------------- 6 | 语法分析以词法分析生成的单词符号序列作为输入,根据语法规则识别出语法成分。 7 | 8 | 分析方法 9 | ---------------------------------------- 10 | 11 | 自上而下 12 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 13 | 自上而下的分析法从文法开始符号开始,正向推导。 14 | 15 | 自下而上 16 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 17 | 自下而上的分析法从给定的输入串开始,逐步归约。 18 | 19 | 语法 20 | ---------------------------------------- 21 | 22 | 上下文无关语法 23 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 24 | 上下文无关语法(context-free grammar)有四个模块 25 | 26 | + 一组终结符(terminal symbols),有时候又叫token 27 | + 一组非终结符(nonterminal)syntactic variables. 28 | + 一组产生式(productions) 29 | + 一个非终结符作为起始符号 30 | 31 | 二义性文法 32 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 33 | ambiguous grammars 34 | 35 | 错误处理 36 | ---------------------------------------- 37 | 错误发生时,有一些可选的方法,最简单一种处理方式是 遇到第一个错误就退出,但是当错误很多的时候,最好能够容忍,并报出之后的错误。 38 | 39 | Panic-Mode Recovery 40 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 41 | 当遇到错误的时候,就开始丢弃遇到的符号,直到遇到一个终结符,例如分号等。 42 | 43 | Phrase-Level Recovery 44 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 45 | 这个方式是遇到错误的时候,替换一个能让当前parse执行下去的符号。 46 | 47 | Error Productions 48 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 49 | 把错误的产生式加到语法解析里面。 50 | 51 | Global Corrections 52 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 53 | 还有一种做法是找到一个最近的能正常parse的源程序然后往下,但是这种做法太过消耗时间和空间资源,实际情况下使用的情况较少。 54 | -------------------------------------------------------------------------------- /source/compile/terminology.rst: -------------------------------------------------------------------------------- 1 | 相关术语 2 | ======================================== 3 | 4 | 符号与字母 5 | ---------------------------------------- 6 | - 字母表 7 | - 元素的非空有穷集合 8 | - 符号 9 | - 字母表中的元素 10 | - 符号串 11 | - 符号的有穷序列 12 | 13 | 文法的形式定义 14 | ---------------------------------------- 15 | - 规则 16 | - 也称产生式,是符号和符号串的有序对 17 | - 符号分为终结符,非终结符 18 | - 非终结符,出现在规则左部,能派生出符号(串)的符号 19 | - 终结符,语言的基本符号,不可再分 20 | - 文法 21 | - 规则的非空有穷集合,通常表示为四元组的形式。包含非终结符的集合、终结符的集合、文法规则的集合、非终结符号 22 | -------------------------------------------------------------------------------- /source/defense/antivirus.rst: -------------------------------------------------------------------------------- 1 | 杀软 2 | ======================================== 3 | 4 | 常见关注点 5 | --------------------------------------- 6 | - 文件 7 | - 压缩包内容 8 | - 内存监控 9 | - 邮件监控 10 | - 网页防护 11 | - 行为防护 12 | 13 | 常见技术 14 | --------------------------------------- 15 | - 病毒库 16 | - 云查杀 17 | 18 | 常见杀软进程: 19 | --------------------------------------- 20 | - 360 21 | - zhudongfangyu 22 | - 360tray 23 | - ... 24 | - 火绒 25 | - hipstray 26 | - wsctrl 27 | - ... 28 | 29 | 检测技术 30 | --------------------------------------- 31 | - 基于签名 32 | - 字节序 33 | - DLL 34 | - 汇编指令 35 | - 基于行为 36 | - API Call 37 | - 系统调用 38 | - CFG 39 | - n-gram 40 | - ... 41 | - 启发式算法 42 | - API Call 43 | - 系统调用 44 | - ... 45 | - 基于云 46 | - 基于机器学习 47 | -------------------------------------------------------------------------------- /source/defense/edr.rst: -------------------------------------------------------------------------------- 1 | EDR 2 | ======================================== 3 | 4 | 常见的EDR软件有MS Defender for Endpoint、Symantec EDR、Sentinel One等。 5 | 6 | EDR常用的检测方案有静态分析、动态分析、行为分析。 7 | 8 | 静态分析通常使用从二进制文件中提取信息进行分析的方式,主要是判断二进制文件中是否包含已知的恶意特征、命中IoC的IP或者域名,哈希是否能和已知的恶意文件匹配等。 9 | 对于加密或者混淆的二进制文件,静态分析通常会尝试解密或者将其认为是恶意特征而对应报警。 10 | 11 | 动态分析是通过执行恶意文件,从恶意文件的动作中判断是否有可疑的网络连接、注册表操作、内存访问、文件操作等。 12 | 在这个阶段,恶意软件常使用检测沙箱环境、选择性等待等方法来绕过沙箱。 13 | 14 | 行为分析则是通过监控、hook等方式在二进制文件实际执行的阶段进行分析,判断二进制文件是否执行了恶意的用户操作、系统调用等。 15 | 由于EDR是安装在用户端的防护,恶意软件在对应环境下使用的绕过方式和动态免杀会有所不同。常用的方式有重写EDR的hook,直接将系统调用传递至内核绕过监控,通过内核dll代码段执行系统调用等。 16 | 17 | 其中静态分析、动态分析也是杀毒软件常用的方法,而edr则多关注于行为分析。 18 | -------------------------------------------------------------------------------- /source/defense/index.rst: -------------------------------------------------------------------------------- 1 | 防御技术 2 | ======================================== 3 | 4 | .. toctree:: 5 | :maxdepth: 2 6 | :caption: 内容索引: 7 | 8 | antivirus 9 | edr 10 | -------------------------------------------------------------------------------- /source/exploit/index.rst: -------------------------------------------------------------------------------- 1 | 漏洞利用基础 2 | ======================================== 3 | 4 | 5 | .. toctree:: 6 | :maxdepth: 2 7 | :caption: 目录: 8 | 9 | shellcode 10 | -------------------------------------------------------------------------------- /source/exploit/shellcode.rst: -------------------------------------------------------------------------------- 1 | Shellcode 2 | ======================================== 3 | 4 | 技巧 5 | ---------------------------------------- 6 | 在写shellcode的时候,可能会出现\x00的情况,这就需要一定的技巧 7 | 一个方法是直接替换掉含null的指令。另外一种方法是用xor inc等运算把0凑出来。 8 | 9 | 10 | 常见Shellcode功能 11 | ---------------------------------------- 12 | - Unix 13 | - execve /bin/sh 14 | - port-binding 15 | - reverse shell 16 | - setuid 17 | - breaking chroot 18 | - Windows 19 | - WinExec 20 | - Reverse shell using CreateProcess cmd.exe 21 | -------------------------------------------------------------------------------- /source/firmware/4g.rst: -------------------------------------------------------------------------------- 1 | 4G 2 | ======================================== 3 | 4 | 参考链接 5 | ---------------------------------------- 6 | - `IMP4GT Attacks `_ 7 | -------------------------------------------------------------------------------- /source/firmware/hal.rst: -------------------------------------------------------------------------------- 1 | HAL 2 | =================================== 3 | 4 | 硬件抽象层 5 | ----------------------------------- 6 | 硬件抽象层是位于操作系统内核与硬件电路之间的接口层,其目的在于将硬件抽象化。它隐藏了特定平台的硬件接口细节,为操作系统提供虚拟硬件平台,使其具有硬件无关性,可在多种平台上进行移植。从软硬件测试的角度来看,软硬件的测试工作都可分别基于硬件抽象层来完成,使得软硬件测试工作的并行进行成为可能。 7 | -------------------------------------------------------------------------------- /source/firmware/hardware.rst: -------------------------------------------------------------------------------- 1 | 硬件 2 | ======================================== 3 | 4 | NVRAM 5 | ---------------------------------------- 6 | NVRAM( Non-Volatile Random Access Memory) 是非易失性随机访问存储器,指断电后仍能保持数据的一种RAM。 7 | 8 | UART 9 | ---------------------------------------- 10 | UART(Universal Asynchronous Receiver/Transmitter),译作通用异步收发传输器,用于将要传输的资料在串行通信与并行通信之间加以转换。作为把并行输入信号转成串行输出信号的芯片,UART通常被集成于其他通讯接口的连结上。 11 | -------------------------------------------------------------------------------- /source/firmware/index.rst: -------------------------------------------------------------------------------- 1 | 嵌入式设备 2 | =================================== 3 | 4 | .. toctree:: 5 | :maxdepth: 2 6 | :caption: 目录: 7 | 8 | unpack 9 | hal 10 | hardware 11 | 4g 12 | ble 13 | secureboot 14 | router 15 | android 16 | ios 17 | iov 18 | security 19 | -------------------------------------------------------------------------------- /source/firmware/ios.rst: -------------------------------------------------------------------------------- 1 | iOS 2 | ======================================== 3 | 4 | 系统结构 5 | ---------------------------------------- 6 | 所有iOS设备中,系统与硬件都高度集成,从系统启动、系统更新、应用的安装、应用的运行时等多个方面来保全系统的安全,具体包括以下几个限制。 7 | 8 | 所有iOS设备在处理器内都集成有一段名为Boot Room的代码,此代码被烧制到处理其内的一块存储上,并且只读,可以认为是完全可信的。系统启动时,Boot Room通过苹果的Apple Root CA Public证书对Low-Level BootLoader进行验证,如果通过验证,Low-Level BootLoader将运行iBoot,较Low-Level Bootloader高层次的Bootloader,如果这一步也通过,那么iBoot将运行iOS的内核, XNU,系统开始运行。以上这几个步骤任一步骤无法通过,都将导致系统无法启动,这样,处理期内烧制的Boot Room保证了iOS系统只能在Apple自家设备上运行,而这些设备也将无法运行iOS之外的系统。 9 | 10 | iOS设备的系统升级之后是不允许降级的。这样做的好处是系统的安全等级只会越来越高,二不会出现由于系统降级,已修复安全风险又暴露出来的问题。iOS系统在升级过程需要联网进行验证,系统升级之前,设备会将LLB、iBoot、内核、镜像,外加一个随机的不可重复的值发送到苹果的服务器进行验证,服务器端对所有这些进行验证,如果通过验证,将会返回一个通过的结果,结果加入了与设备唯一相关的ECID。这样做的好处是此值是无法重用的,只能对应与一台设备,且只能使用一次。通过这种机制,保证了系统升级过程都是符合苹果要求的。 11 | 12 | 所有运行在iOS上的代码都是需要签名的。苹果自带应用已经打上了苹果的签名,而第三方应用,则需要开发者账号进行签名,而开发者账号都是通过苹果官方实名审核的账号,从开发者源头上控制了程序的安全性,也就是说,系统内所有运行的程序都是可信的,且知道来源的。 13 | 14 | 运行与iOS系统的第三方软件都是运行与sandbox之内,每个第三方程序都有自己的独占的路径,其只能访问独占路境内的内容,其他程序的文件一般情况下无法访问,如果要访问,只能通过苹果官方API,而不能自行操作文件。连个应用之间无法共享文件,如要互相通信,只能通过URL Schema或shared key chain。另外,每个应用都有其运行权限,不同权限可进行的操作是不同的,将应用的权限限制在其需要的范围内,而不赋予额外的权限。 15 | 16 | 数据的加密与保护 17 | ---------------------------------------- 18 | 19 | 强制加密 20 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 21 | 而iOS内所有用户数据都是强制加密的,加密功能不能关闭。所以,苹果的AES加解密引擎都是硬件级的,位于存储与系统之间的DMA内,这样提供了较高的效率与性能。加密解密使用的KEY主要来自unique ID(UID)以及Group ID(gid),UID与唯一设备相关,GID与某种特定型号的CPU相关,一台设备的UID及GID全部被烧制到芯片内部,除了AES加密引擎,没有其他方法直接读取,能看到的只有使用UID及GID加密后的数据。这样,不同设备的加密结果是不同的,同一套密文只能在加密的机器上进行解密。除了GID及UID,其他加密使用的KEY全部来自系统自带的随机数生成器,具体使用的算法为Yarrow。 22 | 23 | 数据保护 24 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 25 | iOS提供了名为File Data Protection的数据保护方法。所有文件在加密时使用的key都是不同的,这些key被称作的prefile key,存储于metafile内。prefile的访问需要进行解密的key,这些key包括: 26 | 27 | 1. File System Key: 系统安装时生成的一个随机的key 28 | 2. Class Key,这个key与UID相关,如果用户设置了锁屏密码,那么此Class Key将的来源也包括锁屏密码。 29 | 30 | 只有有了这两个key,一个文件的prefilekey才能被读取出来,此加密的文件才能被解密,也就是说,当锁屏之后,或存储位于不同的设备之上,数据是无法读取的。 31 | 32 | File System Key还有一个重要作用,远程删除数据时,其实不用真正的删除磁盘上的数据,只要删除此key,那么所有文件的prefile key 将不能访问,也就是所有文件将无法读取。 33 | 34 | 锁屏密码 35 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 36 | 锁屏密码为了防止暴力破解,增加了三个限制: 37 | 38 | 1. 与uid绑定,只能在该密码生成的设备上进行尝试, 39 | 2. 两次尝试的间隔被强制设成80ms,机器暴力破解的时间将大大加长 40 | 3. 增加选项,如果连续输错次数超过10次,可以选择删除设备内数据 41 | 42 | Keychain 43 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 44 | 应用的小量极敏感数据,例如密码,最好存储与KeyChain内,而不是应用自己管理。 45 | 46 | 网络安全 47 | ---------------------------------------- 48 | 49 | 除了本地数据的保护,苹果还对数据的传输提供了多种多样的保护机制。苹果提供了可靠的、可信以及加密的连接。因为iOS平台限制了同时监听的端口的数量,并将那些不必要的网络组建,例如telnet,shell以及web server等,所以不需要防火墙的保护。 50 | 51 | 设备权限控制 52 | ---------------------------------------- 53 | 针对企业用户,iOS系统提供了多样的安全策略,管理原可以根据需求对设备的安全特性进行多样化的设置,包括密码策略,数据保护策略,应用使用策略,远程数据删除等功能,给企业级用户提供了高安全性以及极大的灵活性。 54 | -------------------------------------------------------------------------------- /source/firmware/iov.rst: -------------------------------------------------------------------------------- 1 | 车联网 2 | =================================== 3 | 4 | 参考链接 5 | ----------------------------------- 6 | - `Awesome Vehicle Security `_ 7 | - `CAN bus wiki `_ 8 | - `How to hack a car — a quick crash-course `_ 9 | - `THE CAR HACKER’S HANDBOOK `_ 10 | - `浅析车联网安全技术要点 `_ 11 | - `从车联网安全到BLE安全(一) `_ 12 | - `Remote Exploitation of an Unaltered Passenger Vehicle `_ 13 | - `国内在线车联网平台(道路运输车辆卫星定位系统)安全威胁分析报告 `_ 14 | -------------------------------------------------------------------------------- /source/firmware/router.rst: -------------------------------------------------------------------------------- 1 | 路由设备 2 | ======================================== 3 | 4 | 常见厂商 5 | ---------------------------------------- 6 | - ASUS 7 | - D-Link 8 | - Linksys 9 | - Mercury 10 | - Netgear 11 | - TP-Link 12 | - Tenda 13 | 14 | 常见协议 15 | ---------------------------------------- 16 | - ARP 17 | - DHCP 18 | - FTP 19 | - TFTP 20 | - HTTP 21 | - SSH 22 | - Telnet 23 | - DNS 24 | - ICMP 25 | -------------------------------------------------------------------------------- /source/firmware/secureboot.rst: -------------------------------------------------------------------------------- 1 | 可信启动 2 | ======================================== 3 | 4 | 简介 5 | ---------------------------------------- 6 | 安全启动机制一般包括多种机制,主要是: 7 | 8 | - 用于在启动目标镜像之前对其进行验证。 9 | - 在更新前验证更新固件的完整性,完全擦除旧固件以及防止攻击者恢复为已知状态的回滚防止机制。 10 | - 用于安全维护和证明设备内部信任链的机制, 11 | 12 | 参考链接 13 | ---------------------------------------- 14 | - `Secure Firmware Development Best Practices `_ 15 | -------------------------------------------------------------------------------- /source/firmware/security.rst: -------------------------------------------------------------------------------- 1 | 安全性 2 | ======================================== 3 | 4 | 常见安全问题 5 | ---------------------------------------- 6 | - 硬编码凭证 7 | - 硬编码的API端点和后端服务器详细信息 8 | -------------------------------------------------------------------------------- /source/firmware/unpack.rst: -------------------------------------------------------------------------------- 1 | 固件解包 2 | =================================== 3 | 4 | 固件 5 | ----------------------------------- 6 | 在电子系统和计算中,固件是一种特定的计算机软件类,它为设备的特定硬件提供低级控制。固件可以为设备的更复杂的软件提供标准化的操作环境,或者对于较不复杂的设备,充当设备的完整操作系统,执行所有的控制、监视和数据操作功能。包含固件的设备的典型例子是嵌入式系统、消费设备、计算机、计算机外设等。几乎所有电子设备都包含固件。 7 | 8 | 计算机固件是计算机系统中不可缺少的底层基础系统。这些固件往往是以软件的形式固化存储在硬件芯片中。计算机主板上有最重要、最核心的计算机固件,通过称为BIOS(Basic Input / Output System,基本输入输出系统),计算机加电时,中央处理器(CPU)取得并执行的第一条指令,就储存在固件中。 9 | 10 | 获取固件 11 | ----------------------------------- 12 | - 直接从开发团队、制造商/供应商或用户获取 13 | - 使用制造商提供的项目从头编译 14 | - 从供应商的网站获取 15 | - 从论坛、博客,或官方评论中获取 16 | - 设备更新进行中间人(MITM)获取 17 | - 通过 UART、JTAG、PICit 等直接从硬件中提取 18 | - 嗅探 硬件组件中的串行通信 中的更新服务器请求 19 | - 通过移动应用程序中的硬编码接口 20 | - 将固件从引导加载程序(如:U-boot )转储到闪存或通过tftp的网络转储 21 | - 从主板卸下闪存芯片(如:SPI )或 MCU,以进行离线分析和数据提取 22 | - 通过telent / ssh等登录系统后获取 23 | 24 | 文件系统 25 | ----------------------------------- 26 | 常见的文件系统类型有squashfs、ubifs、romfs、rootfs、jffs2、yaffs2、cramfs、initramfs等。 27 | 28 | 常见模式 29 | ----------------------------------- 30 | 无加密,使用binwalk等工具解包即可。 31 | 32 | 加密但是在运行后会解密,提取nvram可获得固件。 33 | 34 | 若之前版本存在无加密固件,可通过劫持升级过程获得新版本固件。 35 | 36 | 参考链接 37 | ----------------------------------- 38 | - `OWASP Firmware Security Testing Methodology `_ 39 | -------------------------------------------------------------------------------- /source/fuzz/boxes.rst: -------------------------------------------------------------------------------- 1 | 黑灰白盒 2 | ======================================== 3 | 4 | 黑盒 5 | ---------------------------------------- 6 | 黑盒Fuzz是一个有效和找到漏洞的简单方法,和白盒不同的是,黑盒Fuzz不关心程序执行的状态,认为程序是一个黑盒。其直接产生输入然后尝试找到结果。黑盒Fuzz也常被称为是数据驱动的Fuzz,大部分传统Fuzzer都是黑盒的。 7 | 8 | 白盒 9 | ---------------------------------------- 10 | 白盒Fuzz在测试之前通常会先对应用进行分析,获取一定的信息来辅助其创建的输入能在应用程序中发现崩溃。 11 | 12 | 其通常遇到的问题是一个应用程序一般有有许多分支,然后形成许多可能的执行流。不过如果有了很大的测试空间,就有可能创建几乎无限的输入来遍历所有的执行流。一般白盒Fuzz会试图创造在更少的输入的同时来尽量覆盖更多的路径。 13 | 14 | 但是由于执行流程过多和复杂的约束,白盒Fuzz在应用程序中可能并不精确。 15 | 16 | 灰盒 17 | ---------------------------------------- 18 | 在白盒和黑盒之后,一些研究者提出了灰盒Fuzz,结合黑盒和白盒两种方式进行Fuzz。使用黑盒Fuzz进行执行,也一定程度上使用轻量的白盒方式为黑盒提供反馈。比单纯的白盒Fuzz更轻量级,比黑盒Fuzz更有效率。 19 | 20 | 总结 21 | ---------------------------------------- 22 | 通常来说,越偏向黑盒的测试方法,执行测试的速度更快,找到的漏洞会相对浅。越偏向白盒的方法,执行测试的速度会更慢,但是找到的漏洞会更深一些。 23 | -------------------------------------------------------------------------------- /source/fuzz/genm.rst: -------------------------------------------------------------------------------- 1 | 生成与变异 2 | ======================================== 3 | 4 | 基于生成的测试 5 | ---------------------------------------- 6 | 基于生成的测试通常使用的方法有基于随机字符的生成、基于语法结构的生成等。相对基于变异的测试,直接生成样本的方式覆盖率会更高。但是相对的,这种方式也需要更多的种子样本,对样本的依赖性也更强。 7 | 8 | 基于变异的测试 9 | ---------------------------------------- 10 | 在基于变异的测试中,一般会提供一个到多个有效的样本,基于变异Fuzz方式对这些样本进行变异。常用的方式有字节级跳变、块级别的替换、删除、增加、重复、基于字典的变异等。 11 | 12 | 相对来说,这种Fuzz方式比较好实现,而且几乎不需要任何的先验知识,只要有一个或几个构造好的样本即可。但是相对来说,这种Fuzz方式也更依赖于给定的样本,如果样本触发的代码覆盖率不高,那么这种方式的覆盖率一般也不会高。 13 | 14 | Hybrid Fuzz 15 | ---------------------------------------- 16 | 考虑到基于生成和基于变异的优缺点,那么另一种方式就是结合两种模式共同进行Fuzz,生成随机样本之后再进行相应的变换,以获得更好的Fuzz效率。 17 | -------------------------------------------------------------------------------- /source/fuzz/history.rst: -------------------------------------------------------------------------------- 1 | 历史 2 | ======================================== 3 | 4 | 1988年,Barton Miller教授在威斯康星大学的 `计算机实验课上 `_ ,首次提出Fuzz生成器(Fuzz Generator)的概念,用于测试Unix程序的健壮性,即用随机数据来测试程序直至崩溃。 5 | 6 | 而后1990年,论文An empirical study of the 7 | reliability of UNIX utilities发表,这也是第一篇模糊测试领域的论文。 8 | 9 | 1995年,Miller教授又发表了一篇名为 Fuzz revisited: A re-examination of the reliability of UNIX utilities and services 的论文,对网络应用和GUI程序进行测试。 10 | 11 | 2000年,研究者们开始测试Windows程序,论文 An empirical study of the robustness of Windows NT applications using random testing 发表。 12 | 13 | 2001年,芬兰奥卢大学将模糊测试技术应用在网络协议的安全测试当中。 14 | 15 | 2012年,``SAGE: whitebox fuzzing for security testing`` 发表,研究者们开始使用符号执行和动态分析来对程序进行动态测试。 16 | -------------------------------------------------------------------------------- /source/fuzz/index.rst: -------------------------------------------------------------------------------- 1 | Fuzz 2 | ======================================== 3 | 4 | 5 | .. toctree:: 6 | :maxdepth: 2 7 | :caption: 目录: 8 | 9 | intro 10 | history 11 | genm 12 | boxes 13 | techs 14 | ref 15 | -------------------------------------------------------------------------------- /source/fuzz/intro.rst: -------------------------------------------------------------------------------- 1 | 简介 2 | ======================================== 3 | 4 | 模糊测试 5 | ---------------------------------------- 6 | 总的来说,模糊测试,是通过不断用生成的输入来运行程序,观察程序状态来查找漏洞的过程。不管是在二进制程序的漏洞挖掘,还是渗透测试中模糊测试都是非常重要的技术。 7 | 8 | 模糊测试是一种侧重于发现软件安全漏洞的方法。典型的Fuzz测试过程是通过自动的或半自动的方法,反复驱动目标软件运行,并为其提供特别构造的输入数据,同时监控软件运行的异常,进而根据异常结果及输入数据查找软件的安全漏洞。谷歌、微软、思科等公司都使用模糊测试作为软件安全开发流程的一部分。 9 | 10 | 目标 11 | ---------------------------------------- 12 | 模糊测试的目标多为找到软件的缺陷。常用的自动化判断软件缺陷的方式有:基于crash、基于各种sanitizer,基于差分测试等。 13 | -------------------------------------------------------------------------------- /source/fuzz/ref.rst: -------------------------------------------------------------------------------- 1 | 参考资料 2 | ======================================== 3 | 4 | Papers 5 | ---------------------------------------- 6 | - Miller, B.P., Fredriksen, L. and So, B., 1990. An empirical study of the reliability of UNIX utilities. Communications of the ACM, 33(12), pp.32-44. 7 | - Miller, B.P., Koski, D., Lee, C.P., Maganty, V., Murthy, R., Natarajan, A. and Steidl, J., 1995. Fuzz revisited: A re-examination of the reliability of UNIX utilities and services. Technical report. 8 | - Forrester, J.E. and Miller, B.P., 2000, August. An empirical study of the robustness of Windows NT applications using random testing. In Proceedings of the 4th USENIX Windows System Symposium(Vol. 4, pp. 59-68). 9 | - Godefroid, P., Levin, M.Y. and Molnar, D., 2012. SAGE: whitebox fuzzing for security testing. Queue, 10(1), p.20. 10 | 11 | Blog 12 | ---------------------------------------- 13 | - `Fuzzing for eBPF JIT bugs in the Linux kernel `_ 在用户态测试内核态代码 14 | - `对 fuzz 的一点总结 `_ 15 | - `从研究者的视角看Fuzzing技术发展30年 `_ 16 | - `2021, PHDays: Fuzzing the Linux kernel `_ 17 | 18 | Workshop 19 | ---------------------------------------- 20 | - `Fuzzing with AFL workshop `_ 21 | - `libfuzzer-workshop `_ 22 | -------------------------------------------------------------------------------- /source/fuzz/techs.rst: -------------------------------------------------------------------------------- 1 | 常用技巧 2 | ======================================== 3 | 4 | 符号执行 5 | ---------------------------------------- 6 | 符号执行是白盒Fuzz的一个常用技术。其关键思想就是,把输入变为符号值,那么程序计算的输出值就是一个符号输入值的函数。简而言之,就是一个程序执行的路径通常是true和false条件的序列,这些条件是在分支语句处产生的。 7 | 8 | 符号执行要解决的问题主要是路径选择、约束求解、内存建模、处理并发这几个方面。 9 | -------------------------------------------------------------------------------- /source/heap/index.rst: -------------------------------------------------------------------------------- 1 | 堆相关漏洞 2 | ================================ 3 | 4 | 5 | .. toctree:: 6 | :maxdepth: 2 7 | :caption: 目录: 8 | 9 | uaf 10 | offByOne 11 | unlink 12 | -------------------------------------------------------------------------------- /source/heap/offByOne.rst: -------------------------------------------------------------------------------- 1 | Off By One 2 | ================================= 3 | 4 | 一个字节溢出被称为off-by-one,曾经的一段时间里,off-by-one被认为是不可以利用的,但是后来研究发现在堆上哪怕只有一个字节的溢出也会导致任意代码的执行。同时堆的off-by-one利用也出现在国内外的各类CTF竞赛中。 5 | 6 | 参考链接 7 | ------------------------------------- 8 | 9 | - `Linux下堆漏洞利用 off by one `_ 10 | -------------------------------------------------------------------------------- /source/heap/uaf.rst: -------------------------------------------------------------------------------- 1 | Use After Free 2 | ======================================== 3 | 4 | 概述 5 | ---------------------------------------- 6 | 7 | 基本概念 8 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 9 | UAF的产生涉及到两个事件,产生和使用悬垂指针。 10 | 11 | 当所指向的对象被释放或者收回,但是对该指针没有作任何的修改,以至于该指针仍旧指向已经回收的内存地址,此情况下该指针便称悬垂指针(也叫迷途指针,Dangling pointer)。 12 | 13 | 某些编程语言允许未初始化的指针的存在,而这类指针即为野指针(Wild pointer)。 14 | 15 | 成因 16 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 17 | 在许多编程语言中(比如C),显示地从内存中删除一个对象或者返回时通过销毁栈帧,并不会改变相关的指针的值。该指针仍旧指向内存中相同的位置,即使引用已经被删除,现在可能已经挪作他用。 18 | 19 | 举例来说 20 | 21 | :: 22 | 23 | char* a = malloc(512); 24 | char* b = malloc(256); 25 | char* c; 26 | strcpy(a, "A here"); 27 | free(a); 28 | c = malloc(500); 29 | strcpy(c, "C here"); 30 | 31 | 因为glibc使用首次适应(FirstFit)来选取合适的chunk,当a被free后,调用相近大小的malloc,则会分配a的地址。此时没有设置a的地址为 ``null`` ,则可以通过a来访问和修改c指向的空间的内容。 32 | 33 | 危害 34 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 35 | 可以概括为三方面: 36 | 37 | - 破坏完整性:例如对已经释放的内存进行的操作可能破坏正常的数据 38 | - 破坏可用性:例如内存块释放后恰好发生了内存块合并,一些进程使用非法数据作为内存块就会崩溃 39 | - 破坏访问控制:利用UAF读取私密信息 40 | -------------------------------------------------------------------------------- /source/images/AndroidSystemFramework.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LyleMi/Learn-Binary-Hacking/8ac631da0a6facecf7b2e4d6687f0b4203edfc5a/source/images/AndroidSystemFramework.png -------------------------------------------------------------------------------- /source/index.rst: -------------------------------------------------------------------------------- 1 | 二进制安全学习笔记 2 | =================================== 3 | 4 | .. toctree:: 5 | :numbered: 6 | :maxdepth: 2 7 | :caption: 目录: 8 | 9 | basic/index 10 | architecture/index 11 | firmware/index 12 | assembly/index 13 | compile/index 14 | os/index 15 | virtual/index 16 | reverse/index 17 | exploit/index 18 | stack/index 19 | heap/index 20 | vulns/index 21 | malware/index 22 | defense/index 23 | mitigations/index 24 | fuzz/index 25 | tools/index 26 | misc/index 27 | 28 | 29 | 目录 30 | ================== 31 | 32 | * :ref:`genindex` 33 | * :ref:`modindex` 34 | * :ref:`search` 35 | -------------------------------------------------------------------------------- /source/malware/antiav.rst: -------------------------------------------------------------------------------- 1 | 杀软绕过技巧 2 | ======================================== 3 | 4 | - 修改特征 5 | - shellcode 6 | - 硬编码字符串 7 | - 小众语言后门 8 | - 白Loader 9 | - 加密ShellCode 10 | - 加壳 11 | - 分隔加载 12 | - 少见api 13 | - 通过长时间 sleep 绕过沙箱分析 14 | - 通过大量无用 api 调用,延长执行时间,绕过沙箱分析 15 | -------------------------------------------------------------------------------- /source/malware/index.rst: -------------------------------------------------------------------------------- 1 | 恶意软件 2 | ======================================== 3 | 4 | .. toctree:: 5 | :maxdepth: 2 6 | :caption: 目录: 7 | 8 | windows 9 | antiav 10 | -------------------------------------------------------------------------------- /source/misc/gc.rst: -------------------------------------------------------------------------------- 1 | 垃圾回收 2 | ======================================== 3 | 4 | 简介 5 | --------------------------------------- 6 | 垃圾回收(Garbage Collection, GC)指程序不用的内存空间。 7 | 8 | 满足 `找到内存空间里的垃圾` + `回收垃圾,让程序员能再次利用` 两项功能的程序就是GC。由John McCarthy在1960年首次发布。 9 | 10 | 常用概念 11 | --------------------------------------- 12 | 13 | mutator 14 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 15 | 用于生成对象和更新指针。 16 | 17 | 堆 18 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 19 | 用于动态存放对象的内存空间,当mutator申请存放对象时,所需的内存空间就会从堆分配给mutator。 20 | 21 | 活动对象/非活动对象 22 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 23 | 活动对象指能通过mutator引用的对象,非活动对象指不能通过程序引用的对象。 24 | 25 | 分配 26 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 27 | 分配(allocation)在内存空间中分配对象。当没有可分配空间时,GC有两种选择:销毁所有的计算结果,输出错误信息,扩大堆,分配可用空间。 28 | 29 | 评价标准 30 | --------------------------------------- 31 | 评价GC算法的性能,采用吞吐量、最大暂停时间、堆使用效率、访问的局部性4个标准。 32 | 33 | 其中吞吐量指单位时间内的处理能力。最大暂停时间指因执行GC而暂停执行mutator的最长时间。 34 | 35 | GC算法 36 | --------------------------------------- 37 | 38 | 标记 - 清除算法 (Mark Sweep GC) 39 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 40 | 分为标记阶段和清除阶段两个阶段。 41 | 标记阶段为对象打上标签。 42 | collector会遍历整个堆,回收没有打上标签的对象 43 | 44 | 分配策略: 45 | 46 | - First-fit 分配找到的第一个大于等于size的分块 47 | - Best-fit 返回大于等于size的最小分块 48 | - Worst-fit 找最大的分块 49 | 50 | 优点在于实现简单,与保守式GC算法兼容。 51 | 52 | 缺点在于碎片化,分配速度慢,与写时复制技术不兼容。 53 | 54 | 引用计数算法 55 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 56 | 引入计数器的概念,表示对象的人气指数。 57 | 58 | 优点在于可即刻回收垃圾,最大暂停时间短,没有必要沿指针查找。 59 | 60 | 缺点在于计数器值增减处理繁重,计数器需要占用很多位,实现烦琐复杂,循环引用无法回收。 61 | -------------------------------------------------------------------------------- /source/misc/index.rst: -------------------------------------------------------------------------------- 1 | 其他 2 | ======================================== 3 | 4 | 5 | .. toctree:: 6 | :maxdepth: 2 7 | :caption: 目录: 8 | 9 | gc 10 | sandbox 11 | terminology 12 | -------------------------------------------------------------------------------- /source/misc/sandbox.rst: -------------------------------------------------------------------------------- 1 | 沙箱 2 | ======================================== 3 | 4 | 沙箱环境检测 5 | --------------------------------------- 6 | - 延迟运行 7 | - 自动化沙箱运行时间较短,可延迟一段时间后再运行 8 | - 检测开机时间 9 | - 许多沙箱检测完毕后会重置系统,开机时间很短 10 | - 检测配置 11 | - 沙箱环境的配置大多不高 12 | - 检测进程 / 服务 13 | - 代码运行时间 14 | 15 | 参考链接 16 | --------------------------------------- 17 | - `反虚拟机和沙箱检测的一些小技巧 `_ 18 | - `CheckVM Sandbox `_ 19 | -------------------------------------------------------------------------------- /source/mitigations/aslr.rst: -------------------------------------------------------------------------------- 1 | ASLR 2 | ======================================== 3 | 4 | 简介 5 | ---------------------------------------- 6 | 地址空间布局随机化(Address Space Layout Randomization, ASLR)是一种针对缓冲区溢出的安全保护技术。其通过对 7 | 堆、栈、共享库等地址的随机化,防止攻击者直接定位攻击代码位置。达到阻止缓冲区溢出的目的。 8 | 9 | 爆破 10 | ---------------------------------------- 11 | ASLR只在exec时生效,fork时并不会改变,因此在一些情况下可以爆破。在32位的程序中,可随机化的范围为8bit,在64位的程序中,可随机化的范围为22bit。 12 | 13 | 关闭 14 | ---------------------------------------- 15 | 在Linux下可以通过 ``echo 0 > /proc/sys/kernel/randomize_va_space`` 关闭。 16 | -------------------------------------------------------------------------------- /source/mitigations/canary.rst: -------------------------------------------------------------------------------- 1 | Canary 2 | ================================ 3 | 4 | 简介 5 | ------------------------------- 6 | 在发生栈溢出攻击时,通常会修改函数栈,那么通过在缓冲区和控制信息(如 EBP 等)间插入一个 ``canary`` 。这样,当缓冲区溢出发生时,在返回地址被覆盖之前 ``canary`` 会首先被覆盖。通过检查 ``canary`` 的值是否被修改,就可以判断是否发生了溢出。 7 | 8 | 特点 9 | ------------------------------- 10 | - 在fork时,canary并不会改变,可以利用这种方式来爆破其值 11 | -------------------------------------------------------------------------------- /source/mitigations/cfi.rst: -------------------------------------------------------------------------------- 1 | CFI 2 | ======================================== 3 | 4 | 简介 5 | ---------------------------------------- 6 | 攻击者常常溢出覆盖或者直接篡改寄存器EIP的值,篡改间接调用的地址,进而控制了程序的执行流程。 7 | 8 | CFI(控制流完整性)是一种漏洞利用的缓解措施。CFI用于降低攻击的可能性。最简单的理解CFI的概念,在运行时强制要求程序按编译时希望的想法去执行。 9 | 10 | 一个程序的控制流可以用一张图来呈现,这张图被称为控制流图(CFG,control flow graph)。CFG是一个每个节点都是程序基本块的有向图,图中的每一条有向边都是可能的控制流路径。CFI则用来保证CFG在运行时和编译时相同。 11 | 12 | 粒度 13 | ---------------------------------------- 14 | 较细粒度的CFI通过一些方法严格控制每一个间接跳转指令的转移目标。对于由间接跳转指令或者间接分支跳转指令引起的前向控制流,CFI根据CFG在每一个目标地址前插入标记,在控制流转移前插入检查标记的指令,如果检查成功,则控制流转移合法。 15 | 16 | 细粒度的CFI存在性能开销较大的问题,因此有人提出了粗粒度的CFI,基于攻击特征做检查。 17 | 18 | CFI On Window 19 | ---------------------------------------- 20 | 执行流保护(CFG,Control Flow Guard)是微软从Windows 8.1 update 3及Windows 10技术预览版开始,默认启用的一项缓解技术。该技术是对CGI的一个实现。 21 | 22 | 这项技术通过在间接跳转前插入校验代码,检查目标地址的有效性,进而可以阻止执行流跳转到预期之外的地点,最终及时并有效的进行异常处理,避免引发相关的安全问题。 23 | 24 | CFG原理 25 | ---------------------------------------- 26 | 在编译启用了CFG的模块时,编译器会分析出该模块中所有间接函数调用可达的目标地址,并将这一信息保存在Guard CF Function Table中。 27 | 28 | 同时,编译器还会在所有间接函数调用之前插入一段校验代码,以确保调用的目标地址是预期中的地址 29 | 30 | 操作系统在创建支持CFG的进程时,将CFG Bitmap映射到其地址空间中,并将其基址保存在ntdll!LdrSystemDllInitBlock中。 31 | 32 | CFG Bitmap是记录了所有有效的间接函数调用目标地址的位图,出于效率方面的考虑,平均每1位对应8个地址(偶数位对应1个0x10对齐的地址,奇数位对应剩下的15个非0x10对齐的地址)。 33 | 34 | 提取目标地址对应位的过程如下: 35 | 36 | - 取目标地址的高24位作为索引i 37 | - 将CFG-Bitmap当作32位整数的数组,用索引i取出一个32位整数bits 38 | - 取目标地址的第4至8位作为偏移量n 39 | - 如果目标地址不是0x10对齐的,则设置n的最低位 40 | - 取32位整数bits的第n位即为目标地址的对应位 41 | 42 | 操作系统在加载支持CFG的模块时,根据其Guard CF Function Table来更新CFG Bitmap中该模块所对应的位。同时,将函数指针_guard_check_icall_fptr初始化为指向 ntdll!LdrpValidateUserCallTarget。 43 | 44 | ntdll!LdrpValidateUserCallTarget从CFG Bitmap中取出目标地址所对应的位,根据该位是否设置来判断目标地址是否有效。若目标地址有效,则该函数返回进而执行间接函数调用;否则,该函数将抛出异常而终止当前进程。 45 | 46 | 参考链接 47 | ---------------------------------------- 48 | - `Let's talk about CFI: clang edition `_ 49 | - `分析及防护 Win10 执行流保护绕过问题 `_ 50 | - `Enforcing Forward-Edge Control-Flow Integrity in GCC & LLVM `_ 51 | -------------------------------------------------------------------------------- /source/mitigations/dep.rst: -------------------------------------------------------------------------------- 1 | NX 2 | ================================================= 3 | 4 | 简介 5 | ------------------------------------------------- 6 | 即使在今天,栈溢出也是一个很常见的安全问题。而其最常见的攻击方式则是覆盖返回地址,并跳转至shellcode。 7 | 8 | DEP通常会去掉堆栈的可执行权限(Non-Executable Stack)并设置代码段为不可写来使得这种payload无法生效。 9 | 10 | 在DEP提出之后,也出现了相当多的绕过方式,几乎所有的绕过方式都基于一个事实:即使堆栈被标记为不可执行,但是其他地方仍然可以执行代码,而且,基于覆写返回地址的攻击几乎一直有效。 11 | 12 | 最开始的绕过方法是return-into-libc,而后则扩展到ret2plt, ret2strpy, ret2gets, ret2syscall, ret2data, ret2text, ret2code, ret2dl-resolve等方法。 13 | 14 | - ret2data: 很常见的一种方式,把shellcode放到data段中,然后跳至data段执行 15 | - ret2libc: 栈溢出攻击对栈有完全的控制权,即可以完全覆写返回地址和参数 16 | - ret2strcpy:这个方式也是基于ret2libc,但是几乎可以执行任意代码。在这里,返回到strcpy,src指向栈上的shellcode,dst指向选择好的可写可执行的内存地址 17 | - ret2gets:类似strcpy 18 | 19 | -------------------------------------------------------------------------------- /source/mitigations/index.rst: -------------------------------------------------------------------------------- 1 | 防御策略 2 | ================================ 3 | 4 | .. toctree:: 5 | :maxdepth: 2 6 | :caption: 目录: 7 | 8 | aslr 9 | canary 10 | cfi 11 | dep 12 | sandbox 13 | secureprogramming 14 | -------------------------------------------------------------------------------- /source/mitigations/sandbox.rst: -------------------------------------------------------------------------------- 1 | 沙箱机制 2 | ======================================== 3 | 4 | 命名空间 5 | --------------------------------- 6 | Linux中支持namespace(命名空间)机制,这是一种轻量级的虚拟化形式。命名空间建立系统的不同视图,对于每一个命名空间看来,都像是一台独立的Linux机器。目前Linux支持六种命名空间,分别为: 7 | 8 | - mnt (mount points, file systems) 9 | - pid (processes) 10 | - net (network stack) 11 | - ipc (system V IPC) 12 | - uts (host name) 13 | - user (UIDs) 14 | 15 | chroot 16 | --------------------------------- 17 | chroot是较老的沙箱实现方式,其内部的机制和文件系统的命名空间类似。 18 | 19 | 参考链接 20 | --------------------------------- 21 | - `Many approaches to sandboxing in Linux `_ 22 | -------------------------------------------------------------------------------- /source/mitigations/secureprogramming.rst: -------------------------------------------------------------------------------- 1 | 安全编程 2 | ================================ 3 | 4 | 内存安全 5 | -------------------------------- 6 | - 初始化所有变量 7 | - 保持数组和缓冲区的边界检查 8 | - 检查整数的上溢和下溢 9 | - 使用安全的函数 10 | - 永远不给内存可执行权限 11 | -------------------------------------------------------------------------------- /source/os/android.rst: -------------------------------------------------------------------------------- 1 | Android 2 | ======================================== 3 | 4 | Root检测 5 | ---------------------------------------- 6 | - 检测是否存在su 7 | - 主动申请busybox 8 | - 检查是否为模拟器环境 9 | - 检查是否安装frida、xposed等框架 10 | 11 | 设备识别码 12 | ---------------------------------------- 13 | 14 | IMEI 15 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 16 | 国际移动设备识别码(IMEI :International Mobile EquipmentIdentity),即通常所说的手机序列号、手机“串号”,用于在移动电话网络中识别每一部独立的手机等移动通信设备,相当于移动电话的身份证,IMEI号共有15~17位数字。国际移动设备识别码一般贴于机身背面与外包装上,同时也存在于手机存储器中。 17 | 18 | MEID 19 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 20 | 移动设备识别码(MEID:Mobile Equipment Identifier)是支持CDMA手机等移动通信设备唯一的识别码。 21 | 22 | Android ID 23 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 24 | Android_ID是运行安卓系统的手机等设备随机生成一串64位的号码,每一个Android_ID都是独一无二。Android8.0及更高版本中,Android_ID的值通过签名密钥等确定范围。在低于Android8.0的版本中,Android_ID在用户第一次启动设备时随机生成。在恢复出厂设置、或重装系统后,Android_ID会被重置。获取Android_ID不需要开启任何系统权限,可直接通过运行相应代码获取。 25 | 26 | 设备序列号 27 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 28 | 设备序列号(SN:SerialNumber)通常用于验证产品的出厂生产的正规性和合法性,也称作机器码、认证码、注册码,通常可在系统信息中的序列号一栏看到,不可更改。App通常可以使用命令、调用READ_PHONE_STATE权限相关函数读取SN值,但是因操作系统、手机型号版本等不同存在差异。 29 | 30 | IMSI 31 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 32 | 国际移动用户识别码(IMSI:International Mobile SubscriberIdentification Number)是区别移动用户的标志,储存在SIM卡中,在全网和全球范围内唯一。 33 | 34 | ICCID 35 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 36 | 手机SIM卡序列号(ICCID:ICC identity)是集成电路卡标识,是唯一标识SIM卡的序列号。ICCID存储在SIM卡中,完整的ICCID为19或20个字符。 37 | 38 | 参考链接 39 | ---------------------------------------- 40 | - `手机设备识别码类型分析 `_ 41 | - `Android Security `_ suplimentary material for Android Training's done by Anant Shrivastava 42 | -------------------------------------------------------------------------------- /source/os/boot.rst: -------------------------------------------------------------------------------- 1 | Boot 2 | ======================================== 3 | 4 | BIOS 5 | ---------------------------------------- 6 | BIOS (Basic Input/Output System) 是固化到计算机内主板上一个ROM芯片上的程序,它保存着计算机最重要的基本输入输出的程序、开机后自检程序和系统自启动程序,提供了一种载入操作系统的方式。 7 | 8 | BIOS的主要功能有开机自检、系统初始化、提供运行时服务、系统设置、引导操作系统等。 9 | 10 | 在电源启动后做自检,如果硬件有问题,则发出蜂鸣,没问题则根据设定好的启动顺序把控制权转交给下一阶段的启动程序。 11 | 12 | 转交给下阶段启动程序后,计算机会读取设备的第一个扇区,如果扇区的最后两个字节是 ``0x55AA`` 则表明设备可以用于启动,否则将控制权转移给下一个设备。 13 | 14 | 扇区共512字节,其中第1-446字节记录调用操作系统的机器码,第447-510字节记录分区表(Partition table),将硬盘分为多个分区,第511-512字节为主引导记录签名(0x55AA)。 15 | 16 | UEFI 17 | ---------------------------------------- 18 | UEFI,全称是统一的可扩展固件接口 (Unified Extensible Firmware Interface),是计算机操作系统和平台固件之间的接口规范,提供了灵活的配置。 19 | 20 | 在UEFI之后,BIOS也被称作Legacy。和之前的BIOS相比,UEFI最大的区别在于编码几乎都是用C语言完成,只使用少量的汇编。运行使用32位的保护模式,不再使用16位的实模式。 21 | 22 | BIOS标准将bootlloader存放在主引导记录(MBR)中,容量有限,而UEFI中引入了新的系统分区来存储bootloader以及驱动等数据。 23 | 24 | 另外,UEFI通过固件签名验证提供了安全的启动加载,拒绝不合法的UEFI执行程序和驱动程序。 25 | 26 | GRUB 27 | ---------------------------------------- 28 | GNU GRUB(GRand Unified Bootloader)是一个来自GNU项目的多操作系统启动程序。GRUB是多启动规范的实现,它允许用户可以在计算机内同时拥有多个操作系统,并在计算机启动时选择希望运行的操作系统。GRUB可用于选择操作系统分区上的不同内核,也可用于向这些内核传递启动参数。 29 | 30 | 参考链接 31 | ---------------------------------------- 32 | - `UEFI `_ 33 | - `计算机是如何启动的 `_ 34 | - `Extensible Firmware Interface Specification `_ 35 | -------------------------------------------------------------------------------- /source/os/index.rst: -------------------------------------------------------------------------------- 1 | 操作系统 2 | ======================================== 3 | 4 | 5 | .. toctree:: 6 | :maxdepth: 2 7 | :caption: 目录: 8 | 9 | overview 10 | boot 11 | linux/index 12 | macos 13 | windows/index 14 | android 15 | ios 16 | -------------------------------------------------------------------------------- /source/os/ios.rst: -------------------------------------------------------------------------------- 1 | iOS 2 | ======================================== 3 | 4 | 设备识别码 5 | ---------------------------------------- 6 | 7 | IDFV 8 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 9 | 应用开发商标识符(IDFV - Identifier For Vendor)是苹果iOS系统给App开发商生成的唯一性标识符,同一个开发商开发的不同的App获取的IDFV值相同,常用于自开发App及跨App追踪用户行为。 10 | 11 | 参考链接 12 | ---------------------------------------- 13 | - `iOS Debugging Magic `_ 14 | -------------------------------------------------------------------------------- /source/os/linux/boot.rst: -------------------------------------------------------------------------------- 1 | 系统启动流程 2 | ======================================== 3 | 4 | 流程简介 5 | ---------------------------------------- 6 | 接通电源后,进行开机自检 (Power On Self Test, POST) ,检测计算机硬件设备是否存在故障。 7 | 8 | 随后计算机加载BIOS或UEFI,进行相应的启动程序。BIOS中记录了主板的相关设置,如启动设备、硬盘信息、系统时间等。BIOS/UEFI根据设定的引导次序读取硬盘,通过硬盘的主引导记录MBR读取Boot loader。Boot loader加载Grub程序。 9 | 10 | GRUB程序加载内核文件,内核探测硬件并加载驱动 (initrd) ,挂载根文件系统。 11 | 12 | 之后执行 ``/sbin/init`` 作为所有系统进程的起点。 ``init`` 将 ``initrd`` 中的 ``/proc`` ``/sys`` ``/dev`` 挂载到当前的主分区中的相应目录。通过mknod完成字符设备、块设备的创建,再完成内核模块的加载,最后完成根切换。 13 | 14 | ``init`` 之后完毕之后读取配置文件 ``/etc/inittab`` ,并根据 ``inittab`` 执行相应程序。 15 | 16 | ``initab`` 通常先执行 ``/etc/rc.d/rc.sysinit`` ,``rc.sysinit`` 进行设定主机名、挂载/etc/fstab中其他文件系统、启动swap分区、基于 ``/etc/sysctl.conf`` 设定内核参数等操作。 17 | 18 | 然后根据不同的运行级别执行 ``/etc/rcX.d/`` 目录下的文件, 例如运行级别为5时,执行 ``/etc/rc5.d/`` 下的文件,接着执行 ``/etc/rc.d/rc.local`` ,最后设置好tty,为用户登录做准备。 19 | 20 | 常见内核文件 21 | ---------------------------------------- 22 | - vmlinux 23 | - 编译出来的最原始的内核文件,未压缩。 24 | - zImage 25 | - vmlinux经过gzip压缩后的文件。 26 | - zImage解压缩内核到低端内存(第一个640K) 27 | - bzImage 28 | - bz表示 ``big zImage`` 29 | - bzImage解压缩内核到高端内存(1M以上) 30 | - uImage 31 | - U-boot专用的映像文件,在zImage之前加上一个长度为0x40的tag 32 | - vmlinuz 33 | - bzImage/zImage文件的拷贝或指向bzImage/zImage的链接。 34 | - initrd 35 | - ``initial ramdisk`` 的简写 36 | - 一般被用来临时的引导硬件到实际内核vmlinuz能够接管并继续引导的状态 37 | 38 | 运行级别 39 | ---------------------------------------- 40 | 默认运行级别如下: 41 | 42 | +------+---------------------------------+ 43 | | 级别 | 含义 | 44 | +======+=================================+ 45 | | 0 | halt | 46 | +------+---------------------------------+ 47 | | 1 | single user mode | 48 | +------+---------------------------------+ 49 | | 2 | multi user mode, without NFS | 50 | +------+---------------------------------+ 51 | | 3 | multi user mode, text mode | 52 | +------+---------------------------------+ 53 | | 4 | reserved | 54 | +------+---------------------------------+ 55 | | 5 | multi user mode, graphic mode | 56 | +------+---------------------------------+ 57 | | 6 | reboot | 58 | +------+---------------------------------+ 59 | -------------------------------------------------------------------------------- /source/os/linux/device/class.rst: -------------------------------------------------------------------------------- 1 | 设备分类 2 | ======================================== 3 | 4 | 字符设备 5 | ---------------------------------------- 6 | Linux字符设备是一种按字节来访问的设备,字符驱动则负责驱动字符设备,这样的驱动通常实现open、close、read和write系统调用。例如:串口、Led、按键等。 7 | 8 | 块设备 9 | ---------------------------------------- 10 | 块设备是一种具有一定结构的随机存取设备,对这种设备的读写是按块进行的,他使用缓冲区来存放暂时的数据,待条件成熟后,从缓存一次性写入设备或者从设备一次性读到缓冲区。可以随机访问,块设备的访问位置必须能够在介质的不同区间前后移动。 11 | 12 | 网络接口 13 | ---------------------------------------- 14 | 通常是个硬件设备,但也可能是个软设备,例如回环(loopback)接口。 15 | -------------------------------------------------------------------------------- /source/os/linux/device/driver.rst: -------------------------------------------------------------------------------- 1 | 驱动 2 | ======================================== 3 | 4 | 错误码 5 | ---------------------------------------- 6 | - 1-34 错误码在 ``asm-generic/errno-base.h`` 中定义 7 | - 35-133 错误码在 ``asm-generic/errno.h`` 中定义 8 | -------------------------------------------------------------------------------- /source/os/linux/device/index.rst: -------------------------------------------------------------------------------- 1 | 设备 2 | ======================================== 3 | .. toctree:: 4 | :maxdepth: 2 5 | :caption: 目录: 6 | 7 | class 8 | driver 9 | operations 10 | terminal 11 | mtd 12 | misc 13 | -------------------------------------------------------------------------------- /source/os/linux/device/misc.rst: -------------------------------------------------------------------------------- 1 | 其他 2 | ======================================== 3 | 4 | 设备号 5 | ---------------------------------------- 6 | Linux系统中一个设备号由主设备号和次设备号构成,Linux内核用主设备号来定位对应的设备驱动程序(即是主设备找驱动),而次设备号用来标识它同个驱动所管理的若干的设备(次设备号找设备)。设备号可以通过 ``/proc/devices`` 查看。 7 | -------------------------------------------------------------------------------- /source/os/linux/device/mtd.rst: -------------------------------------------------------------------------------- 1 | MTD 2 | ======================================== 3 | 4 | 简介 5 | ---------------------------------------- 6 | 内存技术设备(Memory Technology Device, MTD)是Linux的存储设备中的一个子系统。设计此系统的目的是,对于内存类的设备提供一个抽象层的接口。 7 | 8 | MTD设备通常可分为四层,依次为:设备节点、MTD设备层、MTD原始设备层和硬件驱动层。 9 | 10 | 设备节点通过mknod在/dev子目录下建立MTD块设备节点(主设备号为31)和MTD字符设备节点(主设备号为90)。通过访问此设备节点即可访问MTD字符设备和块设备。MTD设备层定义出MTD的块设备(主设备号31)和字符设备(设备号90)。原始设备层定义了大量的关于MTD的数据和操作函数。硬件驱动层负责对硬件的读、写和擦除操作。 11 | 12 | 源码 13 | ---------------------------------------- 14 | Linux中MTD的所有源码位于 ``/drivers/mtd`` 子目录下。 15 | 16 | 其中目录如下: 17 | 18 | - drivers/mtd/chips: CFI/jedec接口通用驱动 19 | - drivers/mtd/nand: nand通用驱动和部分底层驱动程序 20 | - drivers/mtd/maps: nor flash映射关系相关函数 21 | - drivers/mtd/devices: nor flash底层驱动 22 | 23 | 主要文件为: 24 | 25 | - mtdcore.c: MTD原始设备接口相关实现 26 | - mtdpart.c: MTD分区接口相关实现 27 | - mtdchar.c: MTD字符设备接口相关实现,设备号31 28 | - mtdblock.c: MTD块设备接口相关实现,设备号90 29 | 30 | dev 31 | ---------------------------------------- 32 | /dev/mtdN是Linux中的MTD架构中,系统自己实现的mtd分区所对应的字符设备,其里面添加了一些ioctl,支持很多命令,如MEMGETINFO,MEMERASE等。mtdN系列字符设备的主设备号为90,次设备号为0、2、4、6。 33 | 34 | ``/dev/mtdN`` 和 ``/dev/mtdblockN`` 是同一个MTD设备的同一个分区,mtdblockN 块设备的主设备号为31,次设备号为0、1、2、3。 35 | -------------------------------------------------------------------------------- /source/os/linux/device/terminal.rst: -------------------------------------------------------------------------------- 1 | 终端设备 2 | ======================================== 3 | 4 | 简介 5 | ---------------------------------------- 6 | 在计算机早期,人们将一种被称作teletype的设备连到计算机上,作为计算机的终端,使得人们可以操作计算机。计算机为了支持这些teletype,于是设计了名为TTY的子系统。而后随着计算机技术的不断发展,teletype这些设备逐渐消失,但是内核TTY驱动这一架构没有发生变化,和系统中的进程进行I/O交互时还是需要通过TTY设备,于是出现了各种终端模拟软件。 7 | 8 | 串行端口终端 (/dev/ttySn) 9 | ---------------------------------------- 10 | 串行端口终端(Serial Port Terminal)是使用计算机串行端口连接的终端设备。计算机把每个串行端口都看作是一个字符设备。 11 | 12 | 这些串行端口所对应的设备名称是/dev/tts/0(或/dev/ttyS0)、/dev/tts/1(或/dev/ttyS1)等,设备号分别是(4,0)、(4,1)等,分别对应于DOS系统下的COM1、COM2等。 13 | 14 | 伪终端 (/dev/pty/) 15 | ---------------------------------------- 16 | 伪终端(Pseudo Terminal)是成对的逻辑终端设备,提供双向通信,一般由master与slave组成,例如/dev/ptyp3和/dev/ttyp3,它们与实际物理设备并不直接相关。pty的出现是为了网络登陆(ssh登陆、telnet登陆等)、Xwindow等登陆需求。 17 | 18 | 如果一个程序把ttyp3看作是一个串行端口设备,则它对该端口的读/写操作会反映在该逻辑终端设备对的另一个上面(ttyp3)。而ttyp3则是另一个程序用于读写操作的逻辑设备。这样,两个程序就可以通过这种逻辑设备进行互相交流,而其中一个使用ttyp3的程序则认为自己正在与一个串行端口进行通信。 19 | 20 | pty历史上有BSD与UNIX 98两套接口标准,当前大多数pts都是基于UNIX 98标准来实现的。 21 | 22 | UNIX 98标准通过调用 ``posix_openpt`` 打开未使用的UNIX 98伪终端主机。 (此函数将打开主克隆设备/dev/ptmx)。执行任何特定于程序的初始化之后,使用 ``grantpt`` 更改从属设备的所有权和权限,并使用 ``unlockpt`` 解锁从属设备。可以通过在调用 ``open`` 时传递 ``ptsname`` 返回的名称来打开相应的从属设备。 23 | 24 | pty是虚拟终端 (pseudo-tty),pts(pseudo-terminal slave)是pty的实现方法,和ptmx(/dev/ptmx, pseudo-terminal master x)配合使用实现pty。 25 | 26 | Linux内核对可用的UNIX 98伪终端的数量施加了限制。在2.6.3及以下版本的内核中,此限制是在内核编译时(CONFIG_UNIX98_PTYS)配置的,允许的伪终端数量最多为2048,默认设置为256。自内核2.6.4起,此限制为可以通过 ``/proc/sys/kernel/pty/max`` 进行动态调整, ``/proc/sys/kernel/pty/nr`` 指示当前使用了多少个伪终端。 27 | 28 | 其中/dev/ptmx是pty主设备, ``/dev/pts/*`` 是pty从设备。 29 | 30 | BSD样式的伪终端以预先创建的对的形式提供,名称的形式为/dev/ptyXY(主)和/dev/ttyXY(从),其中X是16个字符集[p-za-e]中的字母,Y是来自16个字符集[0-9a-f]的字母(这两组字母的精确范围在UNIX实现中有所不同)。例如,/dev/ptyp1和/dev/ttyp1构成一个BSD伪终端对。进程通过尝试打开每个伪终端主机直到打开成功找到未使用的伪终端对,然后可以打开相应的伪终端从站。 31 | 32 | 控制终端(/dev/tty) 33 | ---------------------------------------- 34 | /dev/tty是当前进程的控制终端的设备特殊文件。可以使用命令 ``ps –ax`` 来查看进程与哪个控制终端相连。 35 | 36 | 控制台终端(/dev/ttyn, /dev/console) 37 | ---------------------------------------- 38 | 在Linux系统中,计算机显示器通常被称为控制台终端(Console)。它仿真了类型为Linux的一种终端(TERM=Linux),并且有一些设备特殊文件与之相关联:tty0、tty1、tty2等。 39 | 40 | 当在控制台上登录时,使用的是tty1。使用Alt+[F1—F6]组合键时,就可以切换到tty2、tty3等上面去。tty1-tty6等称为虚拟终端,而tty0则是当前所使用虚拟终端的一个别名,系统所产生的信息会发送到该终端上。因此不管当前正在使用哪个虚拟终端,系统信息都会发送到控制台终端上。 41 | 42 | 其他 43 | ---------------------------------------- 44 | tty是终端设备的统称,可以将tty理解成一个管道(pipe),将输入输出连接起来。 45 | 46 | 对用户空间的程序来说,TTY与PTS是透明的,但是从内核的视角看,pts的另一端连接ptmx,tty的另一端连接内核的终端模拟器,ptmx和终端模拟器都只是负责维护会话和转发数据包。ptmx的另一端连接用户空间的应用程序,如sshd、tmux等,而内核终端模拟器的另一端连接的是具体的硬件,如键盘和显示器。 47 | -------------------------------------------------------------------------------- /source/os/linux/fs/fuse.rst: -------------------------------------------------------------------------------- 1 | 用户态文件系统 2 | ======================================== 3 | 4 | 简介 5 | ---------------------------------------- 6 | 用户态文件系统 (Filesystem in Userspace, FUSE) 是指一个文件系统的data和metadata都是由用户态的进程提供的。 7 | -------------------------------------------------------------------------------- /source/os/linux/fs/index.rst: -------------------------------------------------------------------------------- 1 | 文件系统与IO 2 | ======================================== 3 | 4 | 5 | .. toctree:: 6 | :maxdepth: 2 7 | :caption: 目录: 8 | 9 | vfs 10 | io 11 | overlay 12 | unionfs 13 | fuse 14 | jffs 15 | yaffs 16 | -------------------------------------------------------------------------------- /source/os/linux/fs/io.rst: -------------------------------------------------------------------------------- 1 | I/O 2 | ======================================== 3 | 4 | I/O模型 5 | ---------------------------------------- 6 | Linux下主要有以下五种I/O模型 7 | 8 | - 阻塞式I/O (blocking IO) 9 | - 非阻塞式I/O (nonblocking I/O) 10 | - I/O 复用 (I/O multiplexing) 11 | - 信号驱动I/O (signal driven I/O (SIGIO)) 12 | - 异步I/O (asynchronous I/O) 13 | 14 | 阻塞I/O 进程会一直阻塞,直到数据拷贝完成。 15 | 16 | 非阻塞I/O 通过进程反复调用IO函数,在数据拷贝过程中,进程是阻塞的。 17 | 18 | I/O 复用主要是select和epoll。一个线程可以对多个IO端口进行监听,当socket有读写事件时分发到具体的线程进行处理。 19 | 20 | 信号驱动I/O在进程运行时注册一个信号处理函数,进程继续运行并不阻塞。当数据准备好时,进程会收到一个SIGIO信号,可以在信号处理函数中调用I/O操作函数处理数据。 21 | 22 | 异步I/O相对于同步IO,异步IO不是顺序执行。用户进程进行aio_read系统调用之后,无论内核数据是否准备好,都会直接返回,用户态进程继续运行。等到数据准备好后,内核直接复制数据给进程,然后从内核向进程发送通知。在两个IO阶段,进程都是非阻塞的。 23 | 24 | IO复用 25 | ---------------------------------------- 26 | 常见的IO复用相关函数有select、poll、epoll。其中epoll是Linux所特有,而select是POSIX所规定,一般操作系统均有实现。 27 | 28 | select 29 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 30 | select本质是通过设置或检查存放fd标志位的数据结构来进行下一步处理。缺点是: 31 | 32 | - 单个进程可监视的fd数量被限制,限制数目可以通过 ``cat /proc/sys/fs/file-max`` 察看。32位默认是1024个,64位默认为2048个 33 | - 对socket进行扫描时是线性扫描,即采用轮询方法,效率低 34 | - 需要维护一个用来存放大量fd的数据结构,会使得用户空间和内核空间在传递该结构时复制开销大 35 | 36 | poll 37 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 38 | poll本质和select相同,将用户传入的数据拷贝到内核空间,然后查询每个fd对应的设备状态,如果设备就绪则在设备等待队列中加入一项并继续遍历,如果遍历所有fd后没有发现就绪设备,则挂起当前进程,直到设备就绪或主动超时,被唤醒后又要再次遍历fd。 39 | 40 | 它基于链表来存储数据,因此没有最大连接数的限制,但缺点是: 41 | 42 | - 大量的fd的数组不管是否需要,整体在用户态和内核空间之间复制 43 | - poll有“水平触发”的特点,如果报告了fd后,没有被处理,那么下次poll时会再次报告 44 | 45 | epoll 46 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 47 | epoll使用“事件”的就绪通知方式,通过epoll_ctl注册fd,一旦fd就绪,内核就会采用回调机制来激活该fd,epoll_wait便可以收到通知。 48 | 49 | 因此epoll有以下优点: 50 | 51 | - 没有最大并发连接的限制 52 | - 效率提升,只有活跃可用的FD才会调用回调函数 53 | - 内存拷贝,利用mmap()文件映射内存加速与内核空间的消息传递 54 | 55 | io_uring 56 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 57 | io_uring 引入了一套全新的 syscall 与一套 async API ,相比之前的实现有更高的性能与兼容性。 58 | 59 | IO调度 60 | ---------------------------------------- 61 | I/O调度器的基本目的是将请求按照它们对应在块设备上的扇区号进行排列,以减少磁头的移动,提高效率。常见的调度算法有Noop算法、Deadline算法、Anticipatory算法、CFQ算法等。 62 | -------------------------------------------------------------------------------- /source/os/linux/fs/jffs.rst: -------------------------------------------------------------------------------- 1 | JFFS 2 | ======================================== 3 | 4 | 简介 5 | ---------------------------------------- 6 | JFFS意为“Journaling Flash File System”,该文件系统是瑞典Axis通信公司开发的一种基于Flash存储器的日志文件系统。 7 | 8 | 该公司于1999年在GNU/Linux上发行了第一版JFFS文件系统,后来经过Redhat公司的发展,发行了第二个版本的JFFS2。JFFS2 是一个日志结构(log-structured)的文件系统,将文件系统的数据和原数据以节点的形式存储在闪存上。 9 | 10 | 主要用于NOR型闪存,基于MTD驱动层,特点是:可读写的、支持数据压缩的、基于哈希表的日志型文件系统,并提供了崩溃/掉电安全保护,提供“写平衡”支持等。缺点主要是当文件系统已满或接近满时,因为垃圾收集的关系而使JFFS2的运行速度大大放慢。 11 | 12 | JFFS2的缺点包括:挂载时间过长;对芯片存储块读写不均衡;扩展性较差等。JFFS2不适合用于NAND闪存主要是因为NAND闪存的容量一般较大,这样导致JFFS2为维护日志节点所占用的内存空间迅速增大,另外,JFFS2文件系统在挂载时需要扫描整个FLASH的内容,以找出所有的日志节点,建立文件结构,对于大容量的NAND闪存会耗费大量时间。 13 | -------------------------------------------------------------------------------- /source/os/linux/fs/overlay.rst: -------------------------------------------------------------------------------- 1 | Overlayfs 2 | ======================================== 3 | 4 | 简介 5 | ---------------------------------------- 6 | OverlayFS是一种堆叠文件系统,它依赖并建立在其它的文件系统之上,并不直接参与磁盘空间结构的划分,仅仅将原来底层文件系统中不同的目录进行“合并”,然后向用户呈现。 7 | 8 | 它于2014年被合并到Linux内核的3.18版本。其4.0版本带来了必要的改进,例如Docker中所需的overlay2存储驱动程序。 9 | 10 | 机制 11 | ---------------------------------------- 12 | OverlayFS的主要机制涉及当两个文件系统提供同一名称的目录时目录访问的合并,分为upper层(读写层)和lower(只读层)。OverlayFS下的文件并不是upper层或者lower层文件的拷贝,而是记录了文件的层次信息。 13 | 14 | 在OverlayFS中,会为每个文件分配一个 ``ovl_entry`` 变量,通过文件 ``dentry`` 的 ``d_fsdata`` 字段指向这个分配的 ``ovl_entry`` 变量。 15 | -------------------------------------------------------------------------------- /source/os/linux/fs/unionfs.rst: -------------------------------------------------------------------------------- 1 | UnionFS 2 | ======================================== 3 | 4 | 简介 5 | ---------------------------------------- 6 | 联合文件系统(Union File System)在2004年由纽约州立大学石溪分校开发,它可以把多个目录内容联合挂载到同一个目录下,而目录的物理位置是分开的。 7 | -------------------------------------------------------------------------------- /source/os/linux/fs/vfs.rst: -------------------------------------------------------------------------------- 1 | 虚拟文件系统 2 | ======================================== 3 | 4 | 简介 5 | ---------------------------------------- 6 | Linux 以一组通用对象的角度看待所有文件系统。虚拟文件系统(Virtual Filesystem Switch, VFS)是在具体的文件系统之上抽象的一层,用来处理与Posix文件系统相关的所有调用。 7 | VFS提供给各种文件系统提供一个通用的接口,使上层的应用程序能够使用通用的接口访问不同文件系统,同时也为不同文件系统的通信提供了媒介。 8 | 9 | 在用户态使用read/write系统调用后,会对应至内核的vfs\_read/vfs\_write。 10 | 11 | 基本的对象 12 | ---------------------------------------- 13 | VFS定义了superblock、inode、dentry和file四种基本的对象。 14 | 15 | superblock 是文件系统最基本的元数据,用于描述和维护文件系统的状态。它存储了文件系统的信息,包括文件系统名称、文件系统的大小和状态、块设备的引用和元数据信息(比如空闲列表等等)。 16 | 17 | inode,也称索引节点,表示文件系统中的一个对象,它具有惟一标识符。inode包含管理文件系统中的对象所需的所有元数据,描述文件、目录、设备文件、socket、管道等文件系统对象,每个inode保存了文件系统对象数据的属性和磁盘块位置。文件系统对象属性包含了各种元数据,如权限、时间戳、flags等。各个文件系统提供将文件名映射为惟一 inode 标识符,对应关系可通过 `ls -id` 查看。 18 | 19 | dentry是directory entry的缩写,用来实现名称和 inode 之间的映射,是目录项缓存,是存放在内存里的缩略版的磁盘文件系统目录树结构。 20 | 21 | file记录了进程打开文件的上下文。 22 | -------------------------------------------------------------------------------- /source/os/linux/fs/yaffs.rst: -------------------------------------------------------------------------------- 1 | YAFFS 2 | ======================================== 3 | 4 | 简介 5 | ---------------------------------------- 6 | YAFFS/YAFFS2是专为嵌入式系统使用NAND型闪存而设计的一种日志型文件系统。与JFFS2相比,它减少了一些功能(例如不支持数据压缩),所以速度更快,挂载时间很短,对内存的占用较小。另外,它还是跨平台的文件系统。 7 | 8 | YAFFS/YAFFS2自带NAND芯片的驱动,并且为嵌入式系统提供了直接访问文件系统的API,用户可以不使用Linux中的MTD与VFS,直接对文件系统操作。当然,YAFFS也可与MTD驱动程序配合使用。这方便了其跨平台移植。 9 | 10 | YAFFS与YAFFS2的主要区别在于,前者仅支持小页(512 Bytes)NAND闪存,后者则可支持大页(2KB) NAND闪存。同时,YAFFS2在内存空间占用、垃圾回收速度、读/写速度等方面均有大幅提升。 11 | -------------------------------------------------------------------------------- /source/os/linux/history.rst: -------------------------------------------------------------------------------- 1 | 历史 2 | ======================================== 3 | 4 | Linux的想法在1991年8月25日首次被Linus公开,随后在9月17日发布首个版本0.0.1。1994年Linus采用GPL(GNU General Public License)许可证发布Linux 1.0版本。1994年RedHat诞生。1996年,Linux第一个桌面KDE诞生。1997年,GNOME项目诞生。2004年,Ubuntu诞生。 5 | 6 | Linux内核采用单内核结构,也借鉴类微内核的优点:模块、抢占式内核、支持内核线程以及动态装载内核模块。 7 | 8 | Linux的版本以 ``kernel_version.major_revision.minor_revision`` 的格式表示,其中偶数 ``major_revision`` 代表稳定版,奇数代表开发版。 9 | 10 | Linux的所有历史版本都可以在 `这里 `_ 找到。 11 | -------------------------------------------------------------------------------- /source/os/linux/index.rst: -------------------------------------------------------------------------------- 1 | Linux 2 | ======================================== 3 | .. toctree:: 4 | :maxdepth: 2 5 | :caption: 目录: 6 | 7 | intro 8 | history 9 | source 10 | boot 11 | fs/index 12 | device/index 13 | process/index 14 | io 15 | mem/index 16 | network/index 17 | sec/index 18 | syscall/index 19 | ref 20 | -------------------------------------------------------------------------------- /source/os/linux/intro.rst: -------------------------------------------------------------------------------- 1 | 简介 2 | ======================================== 3 | 4 | 内核功能划分 5 | ---------------------------------------- 6 | - 进程管理:进程管理负责创建和销毁进程,不同进程之间的通信也有内核处理。 7 | - 内存管理:内存是计算机的主要资源之一。 8 | - 文件系统:类Unix系统的对象几乎都可以当作文件处理。 9 | - 设备控制:几乎所有系统操作都会映射到物理设备上,需要通过相应的代码完成,这段代码被称为驱动程序。 10 | - 网络功能:操作系统通过在应用程序和网络接口之间传递数据包,并根据网络活动控制程序执行。 11 | -------------------------------------------------------------------------------- /source/os/linux/io.rst: -------------------------------------------------------------------------------- 1 | I/O 2 | ======================================== 3 | 4 | I/O模型 5 | ---------------------------------------- 6 | Linux下主要有以下五种I/O模型 7 | 8 | - 阻塞式I/O (blocking IO) 9 | - 非阻塞式I/O (nonblocking I/O) 10 | - I/O 复用 (I/O multiplexing) 11 | - 信号驱动I/O (signal driven I/O (SIGIO)) 12 | - 异步I/O (asynchronous I/O) 13 | 14 | 阻塞I/O 进程会一直阻塞,直到数据拷贝完成。 15 | 16 | 非阻塞I/O 通过进程反复调用IO函数,在数据拷贝过程中,进程是阻塞的。 17 | 18 | I/O 复用主要是select和epoll。一个线程可以对多个IO端口进行监听,当socket有读写事件时分发到具体的线程进行处理。 19 | 20 | 信号驱动I/O在进程运行时注册一个信号处理函数,进程继续运行并不阻塞。当数据准备好时,进程会收到一个SIGIO信号,可以在信号处理函数中调用I/O操作函数处理数据。 21 | 22 | 异步I/O相对于同步IO,异步IO不是顺序执行。用户进程进行aio_read系统调用之后,无论内核数据是否准备好,都会直接返回,用户态进程继续运行。等到数据准备好后,内核直接复制数据给进程,然后从内核向进程发送通知。在两个IO阶段,进程都是非阻塞的。 23 | 24 | IO复用 25 | ---------------------------------------- 26 | 常见的IO复用相关函数有select、poll、epoll。其中epoll是Linux所特有,而select是POSIX所规定,一般操作系统均有实现。 27 | 28 | select 29 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 30 | select本质是通过设置或检查存放fd标志位的数据结构来进行下一步处理。缺点是: 31 | 32 | - 单个进程可监视的fd数量被限制,限制数目可以通过 ``cat /proc/sys/fs/file-max`` 察看。32位默认是1024个,64位默认为2048个 33 | - 对socket进行扫描时是线性扫描,即采用轮询方法,效率低 34 | - 需要维护一个用来存放大量fd的数据结构,会使得用户空间和内核空间在传递该结构时复制开销大 35 | 36 | poll 37 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 38 | poll本质和select相同,将用户传入的数据拷贝到内核空间,然后查询每个fd对应的设备状态,如果设备就绪则在设备等待队列中加入一项并继续遍历,如果遍历所有fd后没有发现就绪设备,则挂起当前进程,直到设备就绪或主动超时,被唤醒后又要再次遍历fd。 39 | 40 | 它基于链表来存储数据,因此没有最大连接数的限制,但缺点是: 41 | 42 | - 大量的fd的数组不管是否需要,整体在用户态和内核空间之间复制 43 | - poll有“水平触发”的特点,如果报告了fd后,没有被处理,那么下次poll时会再次报告 44 | 45 | epoll 46 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 47 | epoll使用“事件”的就绪通知方式,通过epoll_ctl注册fd,一旦fd就绪,内核就会采用回调机制来激活该fd,epoll_wait便可以收到通知。 48 | 49 | 因此epoll有以下优点: 50 | 51 | - 没有最大并发连接的限制 52 | - 效率提升,只有活跃可用的FD才会调用回调函数 53 | - 内存拷贝,利用mmap()文件映射内存加速与内核空间的消息传递 54 | 55 | io_uring 56 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 57 | io_uring 引入了一套全新的 syscall 与一套 async API ,相比之前的实现有更高的性能与兼容性。 58 | -------------------------------------------------------------------------------- /source/os/linux/mem/addr.rst: -------------------------------------------------------------------------------- 1 | 地址 2 | ======================================== 3 | 4 | 32位内核内存分布 5 | ---------------------------------------- 6 | :: 7 | 8 | +------------------------+ 9 | | Kernel Space | 1GB 10 | +------------------------+ 11 | | | 12 | +------------------------+ 13 | | Stack | 14 | | (向下增长) | 15 | +------------------------+ 16 | | | 17 | +------------------------+ 18 | | Memory Mapping Segment | 19 | | (文件映射或匿名映射) | 20 | | (向下增长) | 21 | +------------------------+ 22 | | | 23 | +------------------------+ program break (brk) 24 | | Heap | 25 | | (向上增长) | 26 | +------------------------+ start_brk 27 | | | 28 | +------------------------+ 29 | | Bss 段 | 30 | +------------------------+ end_data 31 | | Data 段 | 32 | +------------------------+ start_data 33 | +------------------------+ end_code 34 | | Text 段 | 35 | +------------------------+ 0x08048000 36 | | | 37 | +------------------------+ 0 38 | 39 | 地址定位方式 40 | ---------------------------------------- 41 | - 固定定位方式 42 | - 汇编和机器代码一一对应 43 | - 容易覆盖操作系统 44 | - 只支持单道程序 45 | - 静态重定位方式 46 | - 源程序经编译和连接后生产的目标代码的地址是以0为起始地址的相对地址 47 | - 当需要执行时,由装入程序运行重定位程序模块,根据作业在本次分配到的内存起始地址将可执行代码装如指定内存地址,并修改有关地址部分的值 48 | - 修改的方式是对每一个逻辑地址的值加上内存区首地址 49 | - 需要整块的地址 50 | - 动态重定位 51 | - 在装入内存的时,不修改逻辑地址,访问逻辑地址时,动态的讲逻辑地址变成物理地址 52 | - 在执行指令时,若设计到逻辑地址,则将该地址送入虚地址寄存器VR,再将BR和VR相加送入地址寄存器MR 53 | 54 | 虚拟地址转换 55 | ---------------------------------------- 56 | 地址转换负责将虚拟地址转换成物理地址,有多个应用场景。 57 | 58 | 应用在虚拟内存中,可以给应用程序一种独占整个计算机内存的假象,可以使用超过实际物理大小的内存,应用程序之间互不干扰。 59 | 60 | 用于进程隔离,可以构建沙盒技术,避免操作系统内核和应用程序受到病毒或者恶意代码的攻击。 61 | 62 | 进程间通信时,地址转换可以将不同进程空间的地址映射到同一段物理内存,从而实现进程间通信。 63 | 64 | 加载动态链接库时,可以在多个程序实例之间进行共享。 65 | -------------------------------------------------------------------------------- /source/os/linux/mem/index.rst: -------------------------------------------------------------------------------- 1 | 内存管理 2 | ======================================== 3 | 4 | 5 | .. toctree:: 6 | :maxdepth: 2 7 | :caption: 目录: 8 | 9 | alloc 10 | addr 11 | stack 12 | heap 13 | -------------------------------------------------------------------------------- /source/os/linux/mem/stack.rst: -------------------------------------------------------------------------------- 1 | Stack 2 | =========================================== 3 | 4 | 函数调用 5 | ------------------------------------------- 6 | - 参数入栈,将参数从右到左压入系统栈 7 | - 返回地址入栈,将当前代码区调用指令的下一条指令压入栈中,供函数返回时执行 8 | - 代码区跳转,处理区从当前代码区跳转到被调用函数的入口 9 | - 栈帧调整 10 | - 保存当前栈帧,EBP入栈 11 | - 切换到新栈帧,ESP装入EBP 12 | - 给新栈帧分配空间,ESP减去所需的空间,抬高栈顶 13 | 14 | 栈结构 15 | ------------------------------------------- 16 | :: 17 | 18 | 栈底 19 | ----------------- 20 | | ... | 21 | | ... | 22 | | ... | 较 23 | | ... | 早 24 | | ... | 的 25 | | ... | 帧 26 | | ... | 27 | | ... | 28 | ----------------- 29 | | ... | 调 30 | | ... | 用 31 | | ... | 者 32 | ----------------- 的 33 | +4 + 4n | 参数n | 帧 34 | ----------------- 35 | | ... | 36 | | ... | 37 | | ... | 38 | ----------------- 39 | +8 | 参数1 | 40 | ----------------- 41 | +4 | 返回地址 | 42 | ----------------- 43 | | 保存的ebp | 当 44 | ----------------- 前 45 | -4 | 保存的 | 帧 46 | | 寄存器 | 47 | | 本地变量 | 48 | | 临时变量 | 49 | ----------------- 50 | | 参数构造区域 | 51 | ----------------- 52 | 栈顶 53 | -------------------------------------------------------------------------------- /source/os/linux/network/index.rst: -------------------------------------------------------------------------------- 1 | 网络 2 | ======================================== 3 | .. toctree:: 4 | :maxdepth: 2 5 | :caption: 目录: 6 | 7 | socket 8 | netdev 9 | netfilter 10 | -------------------------------------------------------------------------------- /source/os/linux/network/netdev.rst: -------------------------------------------------------------------------------- 1 | 网络设备 2 | ======================================== 3 | 4 | 网桥 5 | ---------------------------------------- 6 | 网桥(Bridge)也称桥接器,是连接两个局域网的存储转发设备,用它可以完成具有相同或相似体系结构网络系统的连接。 7 | 8 | Linux网络协议栈已经支持了网桥的功能,但需要进行相关的配置才可以进行正常的转发。而要配置Linux网桥功能,需要配置工具bridge-utils,生成网桥配置的工具有brctl、ip等。 9 | 10 | 网桥可以理解为实现在内核中的二层交换机。 11 | 12 | 配置方法 13 | 14 | :: 15 | 16 | ip link add br0 type bridge 17 | ip link set br0 up 18 | ip link set br0 down 19 | 20 | tun/tap 21 | ---------------------------------------- 22 | tun/tap 是一种主流的虚拟网卡方案,在 Linux 2.4 之后的内核都默认编译 tun/tap 的驱动,支持很多的类UNIX平台。 23 | 24 | tun/tap 设备除了没有物理网卡的硬件功能外,功能和物理网卡是一致的。 25 | tun 设备位于网络的三层,表示虚拟的是点对点设备。读取写入的都是 IP 数据包。 26 | tap位于网络OSI模型的二层,tap表示虚拟的是以太网设备。读取写入的都是 MAC 层数据。 27 | 28 | veth-pair 29 | ---------------------------------------- 30 | Virtual Ethernet Pair简称veth pair,是一对的虚拟设备接口,是一个成对的端口。所有从一端进入的数据包都将从另一端出来。 31 | 32 | veth 在 Linux 2.6 之后的版本引入,用于支持网络命名空间的隔离,使得两个隔离的网络空间可以相互通信,这也是 veth 成对出现的原因。 33 | Docker 的网桥模式就是通过 veth-pair 连接到 docker0 网桥进行通信的。 34 | 35 | veth 可以通过 ``ip link add eth1-br1 type veth peer name phy-br1`` 命令创建。 36 | -------------------------------------------------------------------------------- /source/os/linux/network/netfilter.rst: -------------------------------------------------------------------------------- 1 | netfilter 2 | ======================================== 3 | 4 | 简介 5 | ---------------------------------------- 6 | netfilter是Linux在2.4版本引入的一个子系统,是一个通用网络管理框架,提供了一整套hook函数的管理机制,使得诸如数据包过滤、NAT和基于协议类型的连接跟踪等功能成为了可能。 7 | 8 | 在实际的网络控制中,用户通过iptables设置命令,iptables通过系统调用与iptables内核模块进行交互,iptables的内核模块再和netfilter进行交互,由netfilter在网络层进行具体的控制。 9 | -------------------------------------------------------------------------------- /source/os/linux/process/coroutine.rst: -------------------------------------------------------------------------------- 1 | 协程 2 | ======================================== 3 | 协程可以当作用户态的线程,其调度状态由用户态决定。用户态的优势使得其在调度时不用触发大量系统调用,也不依赖于时钟阻塞。 4 | 5 | 另外协程的轻量级也减少了创建线程、切换线程的性能损耗。 6 | 7 | 根据协程之间是否存在调用栈,协程可以分为有栈协程和无栈协程。 8 | 9 | 有栈协程的实现类似内核中的线程,不同协程间切换还是需要切换上下文,典型代表有:goroutine、libco。无栈协程的上下文则在公共内存中,在协程切换时通过状态机切换,典型代表是 JavaScript、Rust、C++ 20。 10 | 11 | 协程也可以分为 对称协程 (Symmetric Coroutine) 和 非对称协程 (Asymmetric Coroutine) 。非对称协程是协程之间拥有调用栈,协程间存在调用和被调用关系。对称协程则互相之间不存在调用关系。 12 | -------------------------------------------------------------------------------- /source/os/linux/process/dispatch.rst: -------------------------------------------------------------------------------- 1 | 调度算法 2 | ======================================== 3 | 4 | 作业调度算法 5 | ---------------------------------------- 6 | - 先来先服务(FCFS) 有利于长作业而不利于短作业。 7 | - 短作业优先(SJF) 较短的作业平均等待时间 ,较大的系统吞吐率。 8 | - 响应比高优先(HRN) 求等待时间与执行时间两者时间之比。相对等待时间长优先。 9 | - 优先级调度 作业的紧急程度、资源要求、类别等。 10 | 11 | 进程调度 12 | ---------------------------------------- 13 | - 先来先服务(FIFO)调度算法 14 | - 时间片轮转法 15 | - 优先级调度算法 16 | - 多级反馈队列调度算法 17 | - 实时系统调度策略 18 | -------------------------------------------------------------------------------- /source/os/linux/process/elfrun.rst: -------------------------------------------------------------------------------- 1 | 进程启动 2 | ======================================== 3 | 4 | _start函数 5 | ---------------------------------------- 6 | 在加载器完成堆栈设置,argc、argv、envp设置、文件描述符配置之后,加载器会完成重定位,调用预置的初始化函数,并在最后将程序控制权交还给 ``_start`` 。 7 | 8 | __libc_start_main 9 | ---------------------------------------- 10 | ``__libc_start_main`` 的定义如下: 11 | 12 | .. code-block:: cpp 13 | 14 | int __libc_start_main( 15 | int (*main) (int, char * *, char * *), 16 | int argc, char * * ubp_av, 17 | void (*init) (void), 18 | void (*fini) (void), 19 | void (*rtld_fini) (void), 20 | void (*stack_end) 21 | ); 22 | 23 | 其中 ``stack_end`` 是已经对齐的栈指针。 24 | 25 | 26 | ``__libc_start_main`` 的的主要功能为: 27 | 28 | - 处理 ``setuid`` / ``setgid`` 程序的安全问题 29 | - 启动线程 30 | - 把 ``fini`` 函数和 ``rtld_fini`` 函数作为参数传递给 ``at_exit`` 调用,使它们在 ``at_exit`` 里被调用,从而完成用户程序和加载器的调用结束之后的清理工作 31 | - 调用 ``main`` 函数 32 | - 调用 ``exit`` 函数,并将main函数的返回值传递给它 33 | -------------------------------------------------------------------------------- /source/os/linux/process/index.rst: -------------------------------------------------------------------------------- 1 | 进程与线程 2 | ======================================== 3 | 4 | .. toctree:: 5 | :maxdepth: 2 6 | :caption: 目录: 7 | 8 | process 9 | thread 10 | coroutine 11 | elfload 12 | elfrun 13 | dispatch 14 | ipc 15 | shm 16 | sem 17 | signal 18 | -------------------------------------------------------------------------------- /source/os/linux/process/ipc.rst: -------------------------------------------------------------------------------- 1 | 进程间通信 2 | ======================================== 3 | 4 | 概念 5 | ---------------------------------------- 6 | 进程间通信 (Inter Process Communication, IPC) 。 7 | 8 | 同一台主机各个进程间的通信方式有:管道、FIFO、消息队列、信号量以及共享内存。不同主机上间的进程通信可以通过套接字和stream。 9 | 10 | 管道可用于具有亲缘关系进程间的通信,允许一个进程和另一个与它有共同祖先的进程之间进行通信,但是速度慢,容量有限。 11 | 12 | 命名管道克服了管道没有名字的限制,因此,除具有管道所具有的功能外,它还允许无亲缘关系进程间的通信。命名管道在文件系统中有对应的文件名。命名管道通过命令mkfifo或系统调用mkfifo来创建。 13 | 14 | 信号是比较复杂的通信方式,用于通知接受进程有某种事件发生,除了用于进程间通信外,进程还可以发送信号给进程本身。 15 | 16 | 消息队列,是消息的链接表,存放在内核中。一个消息队列由一个标识符(即队列ID)来标识。 17 | 18 | 信号量(semaphore)是一个计数器,用于实现进程间的互斥与同步,而不是用于存储进程间通信数据。 19 | 20 | 共享内存指多个进程可以访问同一块内存空间,是最快的可用IPC形式。是针对其他通信机制运行效率较低而设计的。但是默认情况下并不是线程安全的,往往与其它通信机制,如信号量结合使用,来达到进程间的同步及互斥。 21 | -------------------------------------------------------------------------------- /source/os/linux/process/process.rst: -------------------------------------------------------------------------------- 1 | 进程 2 | ======================================== 3 | 4 | 概念 5 | ---------------------------------------- 6 | 进程是程序处于一个执行环境中在一个数据集上的运行过程,它是系统进行资源分配和调度的一个可并发执行的独立单位。 7 | 8 | 状态 9 | ---------------------------------------- 10 | 进程一般存在7种基础状态:D-不可中断睡眠、R-可执行(TASK_RUNNING)、S-可中断睡眠、T-暂停态、t-跟踪态(TASK_TRACED)、X-死亡态、Z-僵尸态。 11 | 12 | 不可中断睡眠态。位于这种状态的进程处于睡眠中,并且不允许被其他进程或中断)打断。因此这种状态的进程,是无法使用kill杀死的。这种状态一般由I/O等待(比如磁盘I/O、网络I/O、外设I/O等)引起,出现时间非常短暂。 13 | 14 | 可执行态。这种状态的进程都位于CPU的可执行队列中,正在运行或者正在等待运行。 15 | 16 | 可中断睡眠态。这种状态的进程虽然也处于睡眠中,但是是允许被中断的。这种进程一般在等待某事件的发生,而被挂起。系统中大部分进程都处于S态。SLEEP态进程不会占用任何CPU资源。 17 | 18 | 暂停与跟踪态。这种两种状态的进程都处于运行停止的状态,暂停态进程会释放所有占用资源。 19 | 20 | 僵尸态的进程实际上已经结束了,但是父进程还没有回收它的资源(比如进程的描述符、PID等)。僵尸态进程会释放除进程入口之外的所有资源。 21 | 22 | 死亡态。进程的真正结束态,这种状态一般在正常系统中无法被捕获到。 23 | 24 | 进程创建 25 | ---------------------------------------- 26 | Linux有几种进程创建方式,一种是通过fork()系统调用创建进程,一种是在用户级通过pthread库中的pthread_create()创建线程,一种在内核级通过kthread_create()创建。 27 | 28 | 组成 29 | ---------------------------------------- 30 | - 进程控制块(PCB) 31 | - 进程执行的程序(code) 32 | - 进程执行时所用的数据 33 | - 进程执行时使用的工作区 34 | 35 | PCB 36 | ---------------------------------------- 37 | 进程控制块(Process Control Block, PCB),是操作系统内核中一种数据结构,主要用于表示进程状态。 38 | 39 | 当进程创建时,生成PCB。进程终止时,操作系统会回收它的PCB。PCB的主要内容如下: 40 | 41 | - 调度和状态信息 42 | - 调度进程和处理机使用情况 43 | - 进程间通信信息 44 | - 进程间通信相关的各种标识 45 | - 存储管理信息 46 | - 指向进程映像存储空间数据结构 47 | - 进程所用资源 48 | - 进程使用的系统资源,如打开文件等 49 | - 有关数据结构连接信息 50 | - 与PCB相关的进程队列 51 | 52 | 进程间通信 53 | ---------------------------------------- 54 | - 消息通信 55 | - 共享存储区 56 | - 管道通信 57 | -------------------------------------------------------------------------------- /source/os/linux/process/sem.rst: -------------------------------------------------------------------------------- 1 | 信号量 2 | ======================================== 3 | -------------------------------------------------------------------------------- /source/os/linux/process/shm.rst: -------------------------------------------------------------------------------- 1 | 共享内存 2 | ======================================== 3 | 4 | 简介 5 | ---------------------------------------- 6 | 共享内存相关的函数在 ``#include `` / ``#include `` 中定义。 7 | 8 | shm_open 9 | ---------------------------------------- 10 | shm_open 的原型为 ``int shm_open(const char *name, int oflag, mode_t mode);`` 。 11 | 12 | 该函数用于创建或打开一个共享内存,成功返回一个整数的文件描述符,错误返回-1。 13 | 14 | 其中name为共享内存区的名字,oflag为标志位,mode为权限位。 15 | 16 | shm_unlink 17 | ---------------------------------------- 18 | shm_unlink 的原型为 ``int shm_unlink(const char *name);`` 。 19 | 20 | shmget 21 | ---------------------------------------- 22 | shmget 的原型为 ``int shmget(key_t key, size_t size, int shmflg)`` 。 23 | 24 | key为0(IPC_PRIVATE)时,会建立新共享内存对象。key为大于0的32位整数时,根据参数shmflg来确定操作。 25 | 26 | size为大于0的整数时,表示新建的共享内存大小,以字节为单位。size为0时,只获取共享内存。 27 | 28 | shmflg为0时,取共享内存标识符,若不存在则函数会报错。当 ``shmflg&IPC_CREAT`` 为真时,如果内核中不存在键值与key相等的共享内存,则新建一个共享内存;如果存在这样的共享内存,返回此共享内存的标识符。 29 | 30 | 函数成功返回共享内存的标识符,出错返回-1,错误原因存储到errno中。n 31 | 32 | shmat 33 | ---------------------------------------- 34 | shmat用于把共享内存区对象映射到调用进程的地址空间,函数原型为 ``void *shmat(int shmid, const void *addr, int flag);`` 。 35 | 36 | shmdt 37 | ---------------------------------------- 38 | shmdt用于解除共享内存的映射,函数原型为 ``int shmdt(void *addr);`` 。 39 | 40 | shmctl 41 | ---------------------------------------- 42 | 函数原型 ``int shmctl(int shmid, int cmd, struct shmid_ds *buf);`` 。 43 | 44 | 其中shmid表示要操作的共享内存标识符。 45 | 46 | cmd取值为: 47 | 48 | - IPC_STAT (获取对象属性) 49 | - IPC_SET (设置对象属性) 50 | - IPC_RMID (删除对象) 51 | 52 | 其中buf指定IPC_STAT/IPC_SET时用以保存/设置属性。 53 | 54 | 函数返回值0表示成功,-1表示出错。 55 | 56 | ftok 57 | ---------------------------------------- 58 | ``key_t ftok(const char *pathname, int proj_id);`` 59 | 成功返回key,失败返回-1。 60 | 61 | 操作命令 62 | ---------------------------------------- 63 | ipcs / ipcrm / ipcmk。 64 | -------------------------------------------------------------------------------- /source/os/linux/process/thread.rst: -------------------------------------------------------------------------------- 1 | 线程 2 | ======================================== 3 | 4 | 简介 5 | ---------------------------------------- 6 | 进程有独立的地址空间,线程没有单独的地址空间。 7 | 进程的线程共享一块虚拟地址空间,一块页表。 8 | 9 | TCB 10 | ---------------------------------------- 11 | 线程控制块 (Thread Control Block, TCB)是与进程的控制块(PCB)相似的子控制块。 12 | 13 | .. code-block:: cpp 14 | 15 | struct tcb { 16 | u32_t status; 17 | struct reg_context thread_context; 18 | void *stack; 19 | struct thread_info thread_params; 20 | u32_t executedTime; 21 | struct tcb *recoveryTask; 22 | u32_t sched_field; 23 | u32_t magic_key; 24 | }; 25 | 26 | 线程特点 27 | ---------------------------------------- 28 | - 线程是资源竞争的基本单位。 29 | - 线程是程序执行的最小单位 30 | - 线程共享进程数据,但也拥有自己独立的一部分数据: 31 | - 线程ID 32 | - 一组寄存器 33 | - 栈 34 | - errno值 35 | - 信号 36 | 37 | 线程控制 38 | ---------------------------------------- 39 | 与线程有关的函数构成了一个完整的系列,绝大多数函数的名字都是以 ``pthread_`` 开头的。 40 | 41 | 要使用这些函数库,要通过引入头文件,链接这些线程函数库时要使用编译器命令的 ``-lpthread`` 选项。 42 | 43 | pthread_create 44 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 45 | ``int pthread_create(pthread_t *tid, const pthread_attr_t *attr, void *(*func) (void *), void *arg);`` pthread_create用于创建一个线程,成功返回0,否则返回错误号。 46 | 47 | 其中参数含义为: 48 | 49 | - ``pthread_t *tid`` 50 | - 线程id的类型为pthread_t,通常为无符号整型,当调用pthread_create成功时,通过*tid指针返回 51 | - ``const pthread_attr_t *attr`` 52 | - 指定创建线程的属性,如线程优先级、初始栈大小、是否为守护进程等 53 | - 可以使用NULL来使用默认值,通常情况下都使用默认值 54 | - ``void *(*func) (void *)`` 55 | - 函数指针func,指定当新的线程创建之后,将执行的函数 56 | - ``void *arg`` 57 | - 线程将执行的函数的参数 58 | - 如果想传递多个参数,需要封装在一个结构体中 59 | 60 | pthread_join 61 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 62 | ``int pthread_join(pthread_t tid, void **status);`` 等待线程结束,成功返回0,否则返回错误号。 63 | 64 | 其中tid为要等待的线程ID。如果status如果不为NULL,那么线程的返回值存储在status指向的空间中。 65 | 66 | pthread_self 67 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 68 | 函数原型为 ``pthread_t pthread_self (void);`` ,用于返回当前线程的ID。 69 | 70 | pthread_detach 71 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 72 | 在默认情况下,新线程默认是joinable的。线程退出后,需要对其进行pthread_join操作来回收资源,否则无法释放资源,造成内存泄露。 73 | 74 | 如果不关心线程的返回值,join就是一种负担。线程提供一种线程分离的自动回收方法。调用线程分离退出后,自动释放线程资源。 75 | 76 | 函数原型为 ``int pthread_detach(pthread_t thread);`` 。 77 | 78 | pthread_cancel 79 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 80 | 函数原型为 ``int pthread_cancel(pthread_t thread);`` 。pthread_cancel调用并不等待线程终止,只发起取消请求。 81 | 82 | pthread_exit 83 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 84 | 函数原型为 ``void pthread_exit(void *status);`` 。 85 | 86 | 用于终止线程,可以指定返回值,以便其他线程通过pthread_join函数获取该线程的返回值。 87 | 88 | 优点 89 | ---------------------------------------- 90 | - 开销小 91 | - 线程间通信方便 92 | -------------------------------------------------------------------------------- /source/os/linux/sec/cgroups.rst: -------------------------------------------------------------------------------- 1 | Cgroups 2 | ======================================== 3 | 4 | 四个组件 5 | ---------------------------------------- 6 | Cgroups包含Cgroup、Subsystem、hierarchy、task四个组件。 7 | 8 | Cgroup 9 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 10 | Cgroup是对进程分组管理的一种机制,一个Cgroup包含一组进程,并可以在上面添加添加Linux Subsystem的各种参数配置,将一组进程和一组Subsystem的系统参数关联起来。 11 | 12 | Subsystem 13 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 14 | Subsystem是一个资源调度控制器不同版本的Kernel所支持的有所偏差,可以通过 ``cat /proc/cgroups`` 查看 15 | 16 | - blkio 17 | - 对块设备(比如硬盘)的IO进行访问限制 18 | - cpu 19 | - 设置进程的CPU调度的策略,比如CPU时间片的分配 20 | - cpuacct 21 | - 统计/生成cgroup中的任务占用CPU资源报告 22 | - cpuset 23 | - 在多核机器上分配给任务(task)独立的CPU和内存节点(内存仅使用于NUMA架构) 24 | - devices 25 | - 控制cgroup中对设备的访问 26 | - freezer 27 | - 挂起(suspend) / 恢复 (resume) cgroup 中的进程 28 | - memory 29 | - 用于控制cgroup中进程的占用以及生成内存占用报告 30 | - net_cls 31 | - 使用等级识别符(classid)标记网络数据包,这让 Linux 流量控制器 tc (traffic controller) 可以识别来自特定 cgroup 的包并做限流或监控 32 | - net_prio 33 | - 设置cgroup中进程产生的网络流量的优先级 34 | - hugetlb 35 | - 限制使用的内存页数量 36 | - pids 37 | - 限制任务的数量 38 | - net_cls 39 | - 可以使不同cgroups下面的进程使用不同的namespace。 40 | - 每个subsystem会关联到定义的cgroup上,并对这个cgoup中的进程做相应的限制和控制。 41 | 42 | hierarchy 43 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 44 | hierarchy树形结构的 CGroup 层级,每个子 CGroup 节点会继承父 CGroup 节点的子系统配置,每个 Hierarchy 在初始化时会有默认的 CGroup(Root CGroup)。 45 | 46 | Task 47 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 48 | Task (任务) 在cgroups中,任务就是系统的一个进程。 49 | 50 | 四个组件的关系 51 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 52 | - 系统在创建新的hierarchy之后,该系统的所有任务都会加入这个hierarchy的cgroup,称之为root cgroup,此cgroup在创建hierarchy自动创建,后面在该hierarchy中创建都是cgroup根节点的子节点 53 | - 一个subsystem只能附加到一个hierarchy上面 54 | - 一个hierarchy可以附加多个subsystem 55 | - 一个task可以是多个cgroup的成员,但这些cgroup必须在不同的hierarchy 56 | - 一个进程fork出子进程时,该子进程默认自动成为父进程所在的cgroup的成员,也可以根据情况将其移动到到不同的cgroup中 57 | -------------------------------------------------------------------------------- /source/os/linux/sec/index.rst: -------------------------------------------------------------------------------- 1 | 安全机制 2 | ======================================== 3 | 4 | .. toctree:: 5 | :maxdepth: 2 6 | :caption: 目录: 7 | 8 | cgroups 9 | namespace 10 | seccomp 11 | mitigation 12 | capabilities 13 | -------------------------------------------------------------------------------- /source/os/linux/sec/mitigation.rst: -------------------------------------------------------------------------------- 1 | 漏洞利用缓解措施 2 | ======================================== 3 | 4 | kptr_restrict 5 | ---------------------------------------- 6 | 在Linux内核漏洞利用中常常使用 ``commit_creds`` 和 ``prepare_kernel_cred`` 来完成提权,其地址可以从/proc/kallsyms中读取。 7 | 8 | 因此Linux启用了kptr_restrict,其值和对应的功能如下: 9 | 10 | - 0: root和普通用户都可以读取 11 | - 1: root用户有权限读取, 普通用户没有权限 12 | - 2: 内核将符号地址打印为全0, root和普通用户都没有权限 13 | 14 | 该值可以通过 ``sysctl kernel.kptr_restrict`` 查看和修改 15 | 16 | SMEP 17 | ---------------------------------------- 18 | SMEP(Supervisor Mode Execution Protection)是一种减缓内核利用的cpu策略,禁止内核态到用户态内存页的代码执行,每一页都有smep标识来标明是否允许ring0的代码执行。 19 | -------------------------------------------------------------------------------- /source/os/linux/sec/namespace.rst: -------------------------------------------------------------------------------- 1 | namespace 2 | ======================================== 3 | 4 | 简介 5 | ---------------------------------------- 6 | namespace 是 Linux 内核用来隔离内核资源的方式。通过 namespace 可以让一些进程只能看到与自己相关的一部分资源,而另外一些进程也只能看到与它们自己相关的资源,这两拨进程根本就感觉不到对方的存在。具体的实现方式是把一个或多个进程的相关资源指定在同一个 namespace 中。 7 | 8 | Linux 在很早的版本中就实现了部分的 namespace,比如内核 2.4 就实现了 mount namespace。大多数的 namespace 支持是在内核 2.6 中完成的,比如 IPC、Network、PID、和 UTS。还有个别的 namespace 比较特殊,比如 User,从内核 2.6 就开始实现了,但在内核 3.8 中才宣布完成。同时,随着 Linux 自身的发展以及容器技术持续发展带来的需求,也会有新的 namespace 被支持,比如在内核 4.6 中就添加了 Cgroup namespace。 9 | 10 | 隔离内容 11 | ---------------------------------------- 12 | .. list-table:: 隔离功能 13 | :header-rows: 1 14 | 15 | * - namespace 16 | - 系统调用参数 17 | - 隔离内容 18 | * - UTS 19 | - CLONE_NEWUTS 20 | - 主机和域名 21 | * - IPC 22 | - CLONE_NEWIPC 23 | - 信号量、消息队列和共享内存 24 | * - PID 25 | - CLONE_NEWPID 26 | - 进程编号 27 | * - Network 28 | - CLONE_NEWNET 29 | - 网络设备、网络栈、端口等 30 | * - Mount 31 | - CLONE_NEWNS 32 | - 挂载点 (文件系统) 33 | * - User 34 | - CLONE_NEWUSER 35 | - 用户和用户组 36 | -------------------------------------------------------------------------------- /source/os/linux/sec/seccomp.rst: -------------------------------------------------------------------------------- 1 | seccomp 2 | ======================================== 3 | seccomp (secure computing mode) 是Linux Kernel 从2.6.23版本引入的一种安全机制。 4 | 5 | seccomp可以通过系统调用 ``ptrctl`` 或者 ``seccomp`` 开启,需要内核配置中开启了 ``CONFIG_SECCOMP`` 和 ``CONFIG_SECCOMP_FILTER`` 。 6 | 7 | seccomp支持 ``SECCOMP_MODE_STRICT`` 和 ``SECCOMP_MODE_FILTER`` 两种模式。在 ``SECCOMP_MODE_STRICT`` 模式下,进程不能使用 ``read`` ``write`` ``_exit``和``sigreturn`` 以外的其他系统调用。 8 | 9 | 在 ``SECCOMP_MODE_FILTER`` 模式下,可以利用 BerkeleyPacket Filter 配置哪些系统调用及它们的参数可以被进程使用。 10 | -------------------------------------------------------------------------------- /source/os/linux/syscall/device/index.rst: -------------------------------------------------------------------------------- 1 | 设备管理类系统调用 2 | ======================================== 3 | 4 | .. toctree:: 5 | :maxdepth: 2 6 | :caption: 目录: 7 | 8 | ioctl 9 | -------------------------------------------------------------------------------- /source/os/linux/syscall/device/ioctl.rst: -------------------------------------------------------------------------------- 1 | ioctl 2 | ======================================== 3 | ioctl 是设备驱动程序中设备控制接口函数,一个字符设备驱动通常会实现设备打开、关闭、读、写等功能,在一些需要细分的情境下,如果需要扩展新的功能,通常以增设 ioctl 命令的方式实现。 4 | 5 | .. code-block:: cpp 6 | 7 | #include 8 | int ioctl(int fd, int cmd, ...) ; 9 | 10 | 其中fd是文件描述符,cmd是交互协议,设备驱动将根据 cmd 执行对应操作,最后是可变参数,依赖 cmd 指定长度以及类型。ioctl 函数执行成功时返回 0,失败则返回 -1 并设置全局变量 errorno 值。 11 | -------------------------------------------------------------------------------- /source/os/linux/syscall/index.rst: -------------------------------------------------------------------------------- 1 | syscall 2 | ======================================== 3 | 4 | .. toctree:: 5 | :maxdepth: 2 6 | :caption: 目录: 7 | 8 | intro 9 | process/index 10 | session/index 11 | io/index 12 | device/index 13 | net/index 14 | mem/index 15 | signal 16 | -------------------------------------------------------------------------------- /source/os/linux/syscall/intro.rst: -------------------------------------------------------------------------------- 1 | 基础 2 | ======================================== 3 | 4 | 简介 5 | ---------------------------------------- 6 | syscall是内核提供用户空间程序与内核空间进行交互的一套标准接口,这些接口让用户态程序能受限访问硬件设备,比如申请系统资源、操作设备读写、创建新进程等。用户空间发起请求,内核空间负责执行,这些接口便是用户空间和内核空间共同识别的桥梁。 7 | 8 | Syscall是通过中断方式实现的,用户程序通过软中断让程序陷入内核态,执行相应的操作。Linux内核中,每个Syscall都有唯一的系统调用号对应。 9 | 10 | 基于Syscall机制,内核驻留在受保护的地址空间,用户空间程序无法直接执行内核代码,也无法访问内核数据,通过系统调用 11 | 12 | 系统调用列表可在 ``linux/arch/sh/include/uapi/asm/unistd_64.h`` 中找到,以arm为例,其他Syscall相关的源码包括: 13 | 14 | - arch/arm/include/Uapi/asm/unistd.h 15 | - arch/arm/kernel/calls.S 16 | - arch/arm/kernel/entry-armv.S 17 | - arch/arm/kernel/entry-common.S 18 | - include/linux/syscalls.h 19 | - include/uapi/asm-generic/unistd.h 20 | - kernel/signal.c 21 | 22 | Syscall流程 23 | ---------------------------------------- 24 | 25 | x86/64 26 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 27 | 在x86/64架构上, ``arch/x86/syscalls/syscall_64.tbl`` 映射了系统调用号到函数定义的关系。同目录的syscalltbl.sh脚本,根据syscall_64.tbl生成一个头文件arch/x86/include/generated/asm/syscalls_64.h,并用__SYSCALL_COMMON将系统调用号和系统函数地址做映射,最终保存到sys_call_table数组。 28 | 29 | 进程用户态执行syscall指令后进入到内核入口函数system_call(),此时寄存器状态: 30 | 31 | - rax -> 系统调用号 32 | - rdi -> 参数1 33 | - rsi -> 参数2 34 | - rdx -> 参数3 35 | - r10 -> 参数4 36 | - r8 -> 参数5 37 | - r9 -> 参数6 38 | 39 | system_call()的地址在内核初始化时被syscall_init()写入进MSR_LSTAR寄存器,该寄存器的作用是保存syscall指令的处理函数地址。 40 | 41 | ARM 42 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 43 | 在ARM架构上,通过swi中断来实现系统调用,实现从用户态切换到内核态,发送软中断swi时,从中断向量表中查看跳转代码,其中异常向量表定义在文件 ``arch/arm/kernel/entry-armv.S`` 。当执行系统调用时会根据系统调用号从系统调用表中来查看目标函数的入口地址,在calls.S文件中声明了入口地址信息。 44 | 45 | 性能 46 | ---------------------------------------- 47 | 系统调用会明显影响程序的性能,其中一个原因是内核态的数据是共享的,读写时需要同步,使得操作一旦陷入内核态就需要更多的时间。 48 | -------------------------------------------------------------------------------- /source/os/linux/syscall/io/close.rst: -------------------------------------------------------------------------------- 1 | close系列调用 2 | ======================================== 3 | 4 | close 5 | ---------------------------------------- 6 | .. code-block:: cpp 7 | 8 | #include 9 | int close(int fd); 10 | 11 | shutdown 12 | ---------------------------------------- 13 | .. code-block:: cpp 14 | 15 | #include 16 | int shutdown(int sockfd, int how); 17 | 18 | howto 的取值可以为: 19 | 20 | - SHUT_RD 21 | - 断开输入流,清空输入缓冲区 22 | - 套接字无法接收数据,无法调用输入相关函数 23 | - SHUT_WR 24 | - 传递输出缓冲区中还有未传输的数据,断开输出流 25 | - 套接字无法发送数据 26 | - SHUT_RDWR 27 | - 同时断开 I/O 流 28 | - 相当于分别以 SHUT_RD / SHUT_WR 为参数两次调用 shutdown 29 | 30 | 在socket的使用场景下, ``shutdown`` 会等待输出缓冲区中的数据传输完毕再发送FIN包,而 ``close`` 不会处理输出缓冲区,立即向网络中发送FIN包。也就是说,调用 ``close`` 将丢失输出缓冲区中的数据。另外 ``shutdown`` 并不会关闭套接字,关闭套接字仍需要调用 ``close`` 。 31 | -------------------------------------------------------------------------------- /source/os/linux/syscall/io/dup.rst: -------------------------------------------------------------------------------- 1 | dup 2 | ======================================== 3 | 4 | dup 5 | ---------------------------------------- 6 | dup函数的原型为 ``int dup(int oldfd);`` ,头文件为 ``#include `` 。 7 | 8 | dup用于复制参数oldfd所指向的文件描述符。当复制成功时,返回最小的尚未被使用过的文件描述符,若有错误则返回-1。错误代码存入errno中,返回的新文件描述符和参数oldfd指向同一个文件,这两个描述符共享各种文件状态。包括所有的锁,读写位置和各项权限及flags等。 9 | 10 | 调用 ``dup(oldfd)`` 等效于 ``fcntl(oldfd, F_DUPFD, 0)`` 。 11 | 12 | dup2 13 | ---------------------------------------- 14 | dup2函数的原型为 ``int dup2(int oldfd, int newfd);`` ,头文件为 ``#include `` 。 15 | 16 | dup2与dup区别是dup2可以用参数newfd指定新文件描述符的数值。若参数newfd已经被程序使用,则系统就会将newfd所指的文件关闭,若newfd等于oldfd,则返回newfd,而不关闭newfd所指的文件。dup2所复制的文件描述符与原来的文件描述符共享各种文件状态。包括所有的锁,读写位置和各项权限及flags等。 17 | 18 | 若dup2调用成功则返回新的文件描述符,出错则返回-1。 19 | -------------------------------------------------------------------------------- /source/os/linux/syscall/io/epoll.rst: -------------------------------------------------------------------------------- 1 | epoll 2 | ======================================== 3 | ``epoll`` 系统调用的接口如下: 4 | 5 | .. code-block:: cpp 6 | 7 | #include 8 | 9 | struct epoll_event { 10 | _u32 events; 11 | union { 12 | void *ptr; 13 | int fd; 14 | _32 u32; 15 | _u64 u64; 16 | } data; 17 | } 18 | 19 | int epoll_create(int size); 20 | int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event); 21 | int epoll_wait(int epfd, struct epoll_event * events, int maxevents, int timeout); 22 | 23 | epoll 在 Linux 2.6 之后提出,是基于事件驱动的I/O方式。 24 | 25 | epoll_event 的取值有: 26 | 27 | - EPOLLIN 文件有数据可读 28 | - EPOLLOUT 文件可写 29 | - EPOLLHUP 文件被挂起 30 | 31 | epoll_create 函数用于创建 epoll 句柄,参数 size 表明内核要监听的描述符数量。调用成功时返回 epoll 句柄,失败时返回-1。 32 | 33 | epoll_ctl函数用于注册要监听的事件类型,其中 epfd 表示 epoll 句柄,op 表示 fd 操作类型,fd 是要操作的描述符。 34 | 35 | op 的操作类型有: 36 | 37 | - EPOLL_CTL_ADD 注册新的fd 38 | - EPOLL_CTL_MOD 修改已注册的fd 39 | - EPOLL_CTL_DEL 从epfd中删除fd 40 | -------------------------------------------------------------------------------- /source/os/linux/syscall/io/fcntl.rst: -------------------------------------------------------------------------------- 1 | fcntl 2 | ======================================== 3 | fcntl用于根据文件描述词来操作文件的特性,函数原型如下: 4 | 5 | .. code-block:: cpp 6 | 7 | #include ; 8 | int fcntl(int fd, int cmd); 9 | int fcntl(int fd, int cmd, long arg); 10 | int fcntl(int fd, int cmd, struct flock *lock); 11 | 12 | fcntl函数有5种功能: 13 | 14 | - 复制一个现有的描述符 ``cmd=F_DUPFD`` 15 | - 获得/设置文件描述符标记 ``cmd=F_GETFD或F_SETFD`` 16 | - 获得/设置文件状态标记 ``cmd=F_GETFL或F_SETFL`` 17 | - 获得/设置异步I/O所有权 ``cmd=F_GETOWN或F_SETOWN`` 18 | - 获得/设置记录锁 ``cmd=F_GETLK,F_SETLK或F_SETLKW`` 19 | 20 | cmd 选项有 21 | 22 | - F_DUPFD 返回一个如下的描述符: 23 | - 最小的大于或等于arg的一个可用的描述符 24 | - 与原始操作符一样的某对象的引用 25 | - 如果对象是文件的话,返回一个新的描述符,这个描述符与arg共享相同的偏移量(offset) 26 | - 相同的访问模式(读、写或读/写) 27 | - 相同的文件状态标志(如:两个文件描述符共享相同的状态标志) 28 | - 与新的文件描述符结合在一起的close-on-exec标志被设置成交叉式访问execve系统调用 29 | - F_GETFD 30 | - 取得与文件描述符fd联合close-on-exec标志,类似FD_CLOEXEC 31 | - 如果返回值和FD_CLOEXEC进行与运算结果是0的话,文件保持交叉式访问exec() 32 | - 否则如果通过exec运行的话,文件将被关闭(arg被忽略) 33 | - F_SETFD 34 | - 设置close-on-exec。该flag以参数arg的FD_CLOEXEC位决定 35 | - F_GETFL 36 | - 取得fd的文件状态标志,如同下面的描述一样(arg被忽略) 37 | - F_SETFL 38 | - 设置给arg描述符状态标志,可以更改的几个标志是:O_APPEND、O_NONBLOCK、O_SYNC和O_ASYNC 39 | - F_GETOWN 40 | - 取得当前正在接收SIGIO或者SIGURG信号的进程id或进程组id,进程组id返回成负值(arg被忽略) 41 | - F_SETOWN 42 | - 设置将接收SIGIO和SIGURG信号的进程id或进程组id,进程组id通过提供负值的arg来说明,否则arg将被认为是进程id 43 | 44 | F_GETFL和F_SETFL的标志如下面的描述: 45 | 46 | - O_NONBLOCK 47 | - 非阻塞I/O 48 | - 如果read调用没有可读取的数据或者如果write操作将阻塞,read或write调用返回-1和EAGAIN错误 49 | - O_APPEND 50 | - 强制每次写(write)操作都添加在文件大的末尾,相当于open的O_APPEND标志 51 | - O_DIRECT 52 | - 最小化或去掉reading和writing的缓存影响,系统将企图避免缓存你的读或写的数据 53 | - 如果不能够避免缓存,那么它将最小化已经被缓存了的数 据造成的影响.如果这个标志用的不够好,将大大的降低性能 54 | - O_ASYNC 55 | - 当I/O可用的时候,允许SIGIO信号发送到进程组,例如当有数据可以读的时候 56 | 57 | fcntl的返回值与命令有关。如果出错,所有命令都返回-1,如果成功则返回某个其他值。下列三个命令有特定返回值:F_DUPFD、F_GETFD、F_GETFL以及F_GETOWN。第一个返回新的文件描述符,第二个返回相应标志,最后一个返回一个正的进程ID或负的进程组ID。 58 | -------------------------------------------------------------------------------- /source/os/linux/syscall/io/index.rst: -------------------------------------------------------------------------------- 1 | IO相关系统调用 2 | ======================================== 3 | 4 | .. toctree:: 5 | :maxdepth: 2 6 | :caption: 目录: 7 | 8 | open 9 | read 10 | write 11 | close 12 | dup 13 | fcntl 14 | seek 15 | sync 16 | select 17 | poll 18 | epoll 19 | 20 | 除了系统调用对应的函数外,C 同样提供了 fopen / fdopen / fclose / fgetc / fputc 等函数,这些函数是对系统调用的封装,在用户层实现了 I/O 的缓冲。这些函数也被称为 标准I/O 。 21 | 22 | 对于I/O唤醒,最经典的方式是IO多路复用,常见的系统调用有 select / poll / epoll 。 23 | 此外还有 FreeBSD 独有的 kqueue 。 24 | -------------------------------------------------------------------------------- /source/os/linux/syscall/io/open.rst: -------------------------------------------------------------------------------- 1 | open / openat 2 | ======================================== 3 | 当传给函数的路径名是绝对路径时,open与openat无区别,此时openat自动忽略第一个参数fd。 4 | 5 | 当传给函数的是相对路径时,如果openat()函数的第一个参数fd是常量AT_FDCWD时,则其后的第二个参数路径名是以当前工作目录为基址的;否则以fd指定的目录文件描述符为基址。 6 | 7 | .. code-block:: cpp 8 | 9 | int open(const char *path, int oflag); 10 | int open(const char *path, int oflag, mode_t mode); 11 | int openat(int fd, const char *path, int oflag, mode_t mode); 12 | 13 | 其中oflag可取的值如下: 14 | 15 | - O_RDONLY: 只读打开 16 | - O_WRONLY: 只写打开 17 | - O_RDWR: 读,写打开 18 | - O_CREAT: 若文件不存在,则创建它,需要使用mode选项。来指明新文件的访问权限 19 | - O_APPEND: 追加写,如果文件已经有内容,这次打开文件所写的数据附加到文件的末尾而不覆盖原来的内容 20 | - O_DIRECT:对文件的操作不使用系统缓存,需要手动字节对齐 21 | - O_SYNC:使用系统缓存、所有操作落盘 22 | - DEFAULT:类似 O_SYNC ,操作不一定落盘 23 | 24 | 其中mode可取的值如下: 25 | 26 | - S_IRUSR 27 | - 文件所有者有读 (r) 权限 28 | - S_IWUSR 29 | - 文件所有者有写 (w) 权限 30 | - S_IRGRP 31 | - 文件所属组有读 (r) 权限 32 | - S_IWGRP 33 | - 文件所属组有写 (w) 权限 34 | - S_IROTH 35 | - 文件所属other有读 (r) 权限 36 | - S_IWOTH 37 | - 文件所属other有写 (w) 权限 38 | -------------------------------------------------------------------------------- /source/os/linux/syscall/io/poll.rst: -------------------------------------------------------------------------------- 1 | poll 2 | ======================================== 3 | ``poll`` 系统调用的接口如下: 4 | 5 | .. code-block:: cpp 6 | 7 | #include 8 | 9 | typedef struct pollfd { 10 | int fd; // 监听的文件描述符 11 | short events; // 需要关注的的事件 12 | short revents; // 实际发生的事件 13 | } pollfd_t; 14 | 15 | int poll(struct pollfd fds[], nfds_t nfds, int timeout); 16 | 17 | 在参数中, fds 是要监听的文件描述符结合。其中 events 的取值有: 18 | 19 | - POLLIN 有数据可读 20 | - POLLRDNORM 有普通数据可读 21 | - POLLRDBAND 有优先数据可读 22 | - POLLPRI 有紧迫数据可读 23 | - POLLOUT 文件写操作不阻塞 24 | - POLLWRNORM 写普通数据不会导致阻塞 25 | - POLLWRBAND 写优先数据不会导致阻塞 26 | - POLLMSGSIGPOLL 消息可用 27 | 28 | 需要监听多个事件时,可以使用按位与的方式为 events 赋值。 29 | nfds 为文件描述符集合的数量,timeout 为超时时间。 30 | 31 | poll() 函数返回fds集合中就绪的读、写,或异常的描述符数量,返回0表示超时,返回-1表示出错。 32 | -------------------------------------------------------------------------------- /source/os/linux/syscall/io/read.rst: -------------------------------------------------------------------------------- 1 | read 2 | ======================================== 3 | read的函数原型为 ``ssize_t read(int fd, void *buf, size_t nbytes);`` ,定义在 ``#include `` 中。 4 | 5 | read()返回值为读到的字节数,如果已经到文件末尾,返回0,若错误发生,返回-1。 6 | -------------------------------------------------------------------------------- /source/os/linux/syscall/io/seek.rst: -------------------------------------------------------------------------------- 1 | seek 2 | ======================================== 3 | 4 | lseek 函数的原型为 5 | 6 | .. code-block:: cpp 7 | 8 | #include 9 | #include 10 | 11 | off_t lseek(int fd, off_t offset, int whence); 12 | 13 | 参数 offset 的含义取决于参数 whence: 14 | 15 | - ``whence`` 为 ``SEEK_SET`` ,设置偏移量为 offset 16 | - ``whence`` 是 ``SEEK_CUR``,设置当前偏移加 offset,offset 可以为负 17 | - ``whence`` 为 ``SEEK_END`` ,设置当前偏移为文件长度加 offset,offset 可以为负 18 | 19 | 成功时返回新的偏移,否则返回 -1 。 20 | -------------------------------------------------------------------------------- /source/os/linux/syscall/io/select.rst: -------------------------------------------------------------------------------- 1 | select 2 | ======================================== 3 | select是IO多种复用的一种实现,它将需要监控的fd分为读、写、异常三类,其返回时是读、写、异常事件发生或者超时。 4 | 5 | ``select`` 系统调用的原型如下: 6 | 7 | .. code-block:: cpp 8 | 9 | #include 10 | #include 11 | 12 | int select( 13 | int __nfds, 14 | fd_set *__restrict __readfds, 15 | fd_set *__restrict __writefds, 16 | fd_set *__restrict __exceptfds, 17 | struct timeval *__restrict __timeout 18 | ); 19 | 20 | 相关的宏定义有: 21 | 22 | .. code-block:: cpp 23 | 24 | FD_ZERO (fd_set *set); // 清空文件描述符 25 | FD_CLR (int fd, fd_set *set); // 在指定集合中删除文件描述符 26 | FD_SET (int fd, fd_set *set); // 向指定集合中添加文件描述符 27 | FD_ISSET (int fd, fd_set *set); // 检查文件描述符是否在集合中 28 | 29 | select 的主要缺陷在于效率较低,并不能直接遍历 readfds ,而需要遍历所有传入的 fd ,判断是否存在于 readfds 中。在只有少量 fd 有数据的情况下,遍历会消耗较多的资源。 30 | -------------------------------------------------------------------------------- /source/os/linux/syscall/io/sync.rst: -------------------------------------------------------------------------------- 1 | sync 系列 2 | ======================================== 3 | sync 系列函数有 ``sync`` ``fsync`` ``fdatasync`` ,性能消耗依次降低。 4 | 5 | sync 函数原型为 ``void sync (void);`` 用于将内核缓冲区的所有数据写回磁盘,一般不建议使用。 6 | 7 | fsync 函数原型为 ``int fsync (int fd);`` ,要求传入一个以写权限打开的 fd ,将文件描述符对应的内核缓冲区数据写回磁盘。 8 | 9 | fdatasync 函数原型为 ``int fdatasync (int fd);`` ,和 fsync 不同的是,fdatasync 只会更新文件数据而不会更新文件的元数据(时间戳等)。 10 | -------------------------------------------------------------------------------- /source/os/linux/syscall/io/write.rst: -------------------------------------------------------------------------------- 1 | write 2 | ======================================== 3 | write的函数原型为 ``ssize_t write(int fd, void *buf, size_t nbytes);`` 。 4 | 5 | write()返回值通常与参数nbytes相同,否则可能出错。出错存在两种情况,返回-1时表示写操作失败,返回值小于nbytes时,只写入了部分数据。 6 | 7 | 进程调用 write 时,write 更新内核空间中的页缓存,更新完毕后,向进程返回成功。此时只会写入数据到页缓存中,操作系统触发页回写后,才会真正把数据写入磁盘。 8 | -------------------------------------------------------------------------------- /source/os/linux/syscall/mem/brk.rst: -------------------------------------------------------------------------------- 1 | brk与sbrk 2 | ======================================== 3 | .. code-block:: cpp 4 | 5 | #include 6 | int brk(void *end_data_segment); 7 | void * sbrk(intptr_t increment); 8 | 9 | ``brk`` 将数据段的结束地址设置为传入的参数 ``end_data_segment`` 的值,成功返回0,失败返回-1并且设置errno值为ENOMEM。 10 | 11 | brk从内核获取内存是通过增加 ``brk`` (program break) 地址的方式,开始于 ``start_brk`` 、结束于 ``brk`` ,初始的时候两者都指向的是同一个位置。 12 | 当ASLR关闭的时候, ``start_brk`` 和 ``brk`` 都是指向bss段的尾部的,当ASLR开启的时候, ``start_brk`` 和 ``brk`` 初始位置是bss段的尾部加一个随机的偏移。 13 | 14 | sbrk会根据传入的 ``increment`` 调整空间,increment为0时返回当前堆的结束地址,为正数时增加堆的空间,为负数时减小堆的空间。 15 | -------------------------------------------------------------------------------- /source/os/linux/syscall/mem/index.rst: -------------------------------------------------------------------------------- 1 | 内存管理类系统调用 2 | ======================================== 3 | 4 | .. toctree:: 5 | :maxdepth: 2 6 | :caption: 目录: 7 | 8 | mmap 9 | brk 10 | -------------------------------------------------------------------------------- /source/os/linux/syscall/mem/mmap.rst: -------------------------------------------------------------------------------- 1 | mmap系列函数 2 | ======================================== 3 | 4 | mmap 5 | ---------------------------------------- 6 | 内存映射函数mmap负责把文件内容映射到进程的虚拟内存空间,通过对这段内存的读取和修改,来实现对文件的读取和修改,而不需要再调用read/write等操作。 7 | 8 | .. code-block:: cpp 9 | 10 | void* mmap(void * addr, size_t len, int prot, int flags, int fd, off_t offset) 11 | 12 | 对应头文件为 ``#include `` 。 13 | 14 | 其中addr指定映射的起始地址, 通常设为NULL, 由内核指定;length表示映射到内存区域的大小。 15 | 16 | prot映射区的保护方式,可以是: 17 | 18 | - PROT_EXEC: 映射区可被执行 19 | - PROT_READ: 映射区可被读取 20 | - PROT_WRITE: 映射区可被写入 21 | - PROT_NONE: 映射区域不能存取 22 | 23 | flags表示映射区的特性,可以是: 24 | 25 | - MAP_FIXED: 如果参数 ``start`` 所指的地址无法成功建立映射时,则放弃映射,不对地址做修正,通常不鼓励用此flag。 26 | - MAP_FIXED_NOREPLACE: (Linux 4.17后) 功能与 MAP_FIXED 类似。不同点在于,如果页已经存在,则不会建立映射。 27 | - MAP_SHARED: 对映射区域的写入数据会复制回文件内,而且允许其他映射该文件的进程共享。 28 | - MAP_SHARED_VALIDATE: (Linux 4.15后) 与 MAP_SHARED 类似,但是会检查其他 flag 29 | - MAP_PRIVATE: 对映射区域的写入操作会产生一个映射文件的复制,即私有的写入时复制(copy-on-write)对此区域作的任何修改都不会写回原来的文件内容。 30 | - MAP_ANONYMOUS: 建立匿名映射。此时会忽略参数fd,不涉及文件,而且映射区域无法和其他进程共享。 31 | - MAP_DENYWRITE: 只允许对映射区域的写入操作,其他对文件直接写入的操作将会被拒绝。 32 | - MAP_LOCKED: 将映射区域锁定住,这表示该区域不会被置换(swap)。 33 | - MAP_POPULATE: 预先读需要的页,减少之后的发生页错误时的消耗 34 | - MAP_UNINITIALIZED: (Linux 2.6.33后可以使用) 不初始化页,仅在内核配置了 ``CONFIG_MMAP_ALLOW_UNINITIALIZED`` 时可以使用,主要用于优化嵌入式设备的性能 35 | 36 | fd是由open返回的文件描述符, 代表要映射的文件,如果使用匿名内存映射时,fd设为-1。当系统不支持匿名内存映射时,则可以使用fopen打开/dev/zero文件。 37 | 38 | offset表示以文件开始处的偏移量,必须是分页大小的整数倍,通常为0,表示从文件头开始映射。 39 | 40 | 若映射成功则返回映射区的内存起始地址,否则返回MAP_FAILED(-1),错误原因存于errno 中。 41 | 42 | 具体的错误代码如下: 43 | 44 | - EBADF: 参数fd 不是有效的文件描述词 45 | - EACCES: 存取权限有误。如果是MAP_PRIVATE 情况下文件必须可读,使用MAP_SHARED则要有PROT_WRITE以及该文件要能写入 46 | - EINVAL: 参数start、length 或offset有一个不合法 47 | - EAGAIN: 文件被锁住,或是有太多内存被锁住 48 | - ENOMEM: 内存不足 49 | 50 | munmap 51 | ---------------------------------------- 52 | 解除映射可使用 ``munmap`` 函数,原型为 53 | 54 | .. code-block:: cpp 55 | 56 | int munmap(void *start, size_t length); 57 | 58 | msync 59 | ---------------------------------------- 60 | 进程在映射空间的对共享内容的改变往往在调用 ``munmap`` 后才写回到磁盘文件中,如果要在这之前同步,可以使用 ``msync`` ,其函数原型为: 61 | 62 | .. code-block:: cpp 63 | 64 | int msync(void * addr, size_t len, int flags); 65 | 66 | 其中addr为需要同步的地址,len表示要同步数据的大小。flags 取值如下: 67 | 68 | - MS_ASYN: 异步写 69 | - MS_SYN: 同步写 70 | - MS_INVALIDAT: 无效的cache 数据 71 | -------------------------------------------------------------------------------- /source/os/linux/syscall/net/index.rst: -------------------------------------------------------------------------------- 1 | 网络类系统调用 2 | ======================================== 3 | 4 | .. toctree:: 5 | :maxdepth: 2 6 | :caption: 目录: 7 | 8 | socket 9 | sockopt 10 | bind 11 | accept 12 | send 13 | recv 14 | -------------------------------------------------------------------------------- /source/os/linux/syscall/net/recv.rst: -------------------------------------------------------------------------------- 1 | recv系列系统调用 2 | ======================================== 3 | .. code-block:: cpp 4 | 5 | #include 6 | #include 7 | ssize_t recv(int sock, void *buf, size_t len, int flags); 8 | ssize_t recvfrom(int sock, void *buf, size_t len, int flags, 9 | struct sockaddr *from, socklen_t *fromlen); 10 | ssize_t recvmsg(int sock, struct msghdr *msg, int flags); 11 | 12 | 其中参数的含义如下: 13 | 14 | - sock:表示发送数据的套接字 15 | - buf:指向将要发送数据的缓冲区 16 | - len:缓冲区的长度 17 | - flags:是零个或者多个标志的组合体,可通过or一起设置 18 | - from:指向存放对端地址的区域,如果为NULL,不储存对端地址 19 | - fromlen 20 | - 作为入口参数,指向存放表示from最大容量的内存单元 21 | - 作为出口参数,指向存放表示from实际长度的内存单元 22 | - msg:指向存放进入消息头的内存缓冲 23 | 24 | 其中flag的标志如下: 25 | 26 | - MSG_DONTWAIT:操作不会被阻塞 27 | - MSG_ERRQUEUE:指示应该从套接字的错误队列上接收错误值 28 | - MSG_PEEK:指示数据接收后,在接收队列中保留原数据,不将其删除,随后的读操作还可以接收相同的数据 29 | - MSG_TRUNC:返回封包的实际长度,即使它比所提供的缓冲区更长,只对packet套接字有效 30 | - MSG_WAITALL:要求阻塞操作,直到请求得到完整的满足。然而,如果捕捉到信号,错误或者连接断开发生,或者下次被接收的数据类型不同,仍会返回少于请求量的数据 31 | - MSG_EOR:指示记录的结束,返回的数据完成一个记录 32 | - MSG_TRUNC:指明数据报尾部数据已被丢弃,因为它比所提供的缓冲区需要更多的空间 33 | - MSG_CTRUNC:指明由于缓冲区空间不足,一些控制数据已被丢弃 34 | - MSG_OOB:指示接收到out-of-band数据 35 | - MSG_ERRQUEUE:指示除了来自套接字错误队列的错误外,没有接收到其它数据 36 | 37 | 返回值 38 | 39 | - 成功执行时,返回接收到的字节数 40 | - 若另一端已关闭连接则返回0 41 | - 失败返回-1,并设置errno 42 | 43 | errno的含义如下: 44 | 45 | - EAGAIN:套接字已标记为非阻塞,而接收操作被阻塞或者接收超时 46 | - EBADF:sock不是有效的描述词 47 | - ECONNREFUSE:远程主机阻绝网络连接 48 | - EFAULT:内存空间访问出错 49 | - EINTR:操作被信号中断 50 | - EINVAL:参数无效 51 | - ENOMEM:内存不足 52 | - ENOTCONN:与面向连接关联的套接字尚未被连接上 53 | - ENOTSOCK:sock索引的不是套接字 54 | -------------------------------------------------------------------------------- /source/os/linux/syscall/net/send.rst: -------------------------------------------------------------------------------- 1 | send系列系统调用 2 | ======================================== 3 | 4 | 函数原型 5 | ---------------------------------------- 6 | .. code-block:: cpp 7 | 8 | #include 9 | #include 10 | ssize_t send(int sock, const void *buf, size_t len, int flags); 11 | ssize_t sendto(int sock, const void *buf, size_t len, int flags, const struct sockaddr *to, socklen_t tolen); 12 | ssize_t sendmsg(int sock, const struct msghdr *msg, int flags); 13 | 14 | 其中参数的含义如下: 15 | 16 | - sock:表示发送数据的套接字 17 | - buf:指向将要发送数据的缓冲区 18 | - len:缓冲区的长度 19 | - flags:是以下零个或者多个标志的组合体,可通过or一起设置 20 | - MSG_DONTROUTE 21 | - 不要使用网关来发送封包,只发送到直接联网的主机 22 | - 这个标志主要用于诊断或者路由程序 23 | - MSG_DONTWAIT:操作不会被阻塞 24 | - MSG_EOR:终止一个记录 25 | - MSG_MORE:调用者有更多的数据需要发送 26 | - MSG_NOSIGNAL:当另一端终止连接时,请求在基于流的错误套接字上不要发送SIGPIPE信号 27 | - MSG_OOB:发送out-of-band数据 28 | - to:指向存放接收端地址的区域,可为NULL 29 | - tolen:以上内存区的长度,可以为0 30 | - msg:指向存放发送消息头的内存缓冲 31 | 32 | 返回值有三类: 33 | 34 | - 返回值 = 0 35 | - 返回值 < 0:发送失败,错误原因存于全局变量errno中 36 | - 返回值 > 0:表示发送的字节数(实际上是拷贝到发送缓冲中的字节数) 37 | 38 | 错误代码: 39 | 40 | - EBADF 非合法的socket处理代码 41 | - EFAULT 参数中有一指针指向无法存取的内存空间 42 | - ENOTSOCK sockfd是文件描述符,非socket 43 | - EINTR 被信号中断 44 | - EAGAIN 此操作会令进程阻断,但sockfd为不可阻断 45 | - ENOBUFS 系统的缓冲内存不足 46 | - ENOMEM 核心内存不足 47 | - EINVAL 传给系统调用的参数不正确 48 | -------------------------------------------------------------------------------- /source/os/linux/syscall/process/clone.rst: -------------------------------------------------------------------------------- 1 | clone 2 | ======================================== 3 | 4 | 简介 5 | ---------------------------------------- 6 | clone的函数原型为 ``int clone(int (fn)(void ), void *child_stack, int flags, void *arg);`` 。 7 | 8 | 其中fn是函数指针,child_stack是为子进程分配系统堆栈空间,flags标志用来描述需要从父进程继承哪些资源,arg是传给子进程的参数。 9 | 10 | 其中flags取值如下: 11 | 12 | - CLONE_PARENT 13 | - 创建的子进程的父进程是调用者的父进程,新进程与创建它的进程成了“兄弟”而不是“父子” 14 | - CLONE_FS 15 | - 子进程与父进程共享相同的文件系统,包括root、当前目录、umask 16 | - CLONE_FILES 17 | - 子进程与父进程共享相同的文件描述符(file descriptor)表 18 | - CLONE_NEWNS 19 | - 在新的namespace启动子进程 20 | - namespace描述了进程的文件hierarchy 21 | - CLONE_SIGHAND 22 | - 子进程与父进程共享相同的信号处理(signal handler)表 23 | - CLONE_PTRACE 24 | - 若父进程被trace,子进程也被trace 25 | - CLONE_VFORK 26 | - 父进程被挂起,直至子进程释放虚拟内存资源 27 | - CLONE_VM 28 | - 子进程与父进程运行于相同的内存空间 29 | - CLONE_PID 30 | - 子进程在创建时PID与父进程一致 31 | - CLONE_THREAD 32 | - Linux 2.4中增加以支持POSIX线程标准 33 | - 子进程与父进程共享相同的线程群 34 | 35 | 源码分析 36 | ---------------------------------------- 37 | .. code-block:: cpp 38 | 39 | #ifdef CONFIG_CLONE_BACKWARDS 40 | SYSCALL_DEFINE5(clone, unsigned long, clone_flags, unsigned long, newsp, 41 | int __user *, parent_tidptr, 42 | unsigned long, tls, 43 | int __user *, child_tidptr) 44 | #elif defined(CONFIG_CLONE_BACKWARDS2) 45 | SYSCALL_DEFINE5(clone, unsigned long, newsp, unsigned long, clone_flags, 46 | int __user *, parent_tidptr, 47 | int __user *, child_tidptr, 48 | unsigned long, tls) 49 | #elif defined(CONFIG_CLONE_BACKWARDS3) 50 | SYSCALL_DEFINE6(clone, unsigned long, clone_flags, unsigned long, newsp, 51 | int, stack_size, 52 | int __user *, parent_tidptr, 53 | int __user *, child_tidptr, 54 | unsigned long, tls) 55 | #else 56 | SYSCALL_DEFINE5(clone, unsigned long, clone_flags, unsigned long, newsp, 57 | int __user *, parent_tidptr, 58 | int __user *, child_tidptr, 59 | unsigned long, tls) 60 | #endif 61 | { 62 | return _do_fork(clone_flags, newsp, 0, parent_tidptr, child_tidptr, tls); 63 | } 64 | #endif 65 | -------------------------------------------------------------------------------- /source/os/linux/syscall/process/execve.rst: -------------------------------------------------------------------------------- 1 | execve 2 | ======================================== 3 | exec系列系统调用的原型如下: 4 | 5 | .. code-block:: cpp 6 | 7 | #include 8 | int execl(const char *path, const char *arg, ...); 9 | int execle(const char *path, const char *arg, ..., char * const envp[]); 10 | int execlp(const char *file, const char *arg, ...); 11 | int execv(const char *path, char *const argv[]); 12 | int execvp(const char *file, char *const argv[]); 13 | int execvpe(const char *file, char *const argv[], char *const envp[]); 14 | 15 | 其中path参数表示要启动程序的完整路径,file表示程序文件名,argv表示执行参数,一般argv第一个参数为要执行命令名,不是带路径且argv必须以NULL结束,envp表示环境变量。 16 | 17 | 上述exec系列函数底层都是通过execve系统调用实现, ``int execve(const char *filename, char *const argv[], char *const envp[]);`` 。 18 | 19 | execve() 系统调用的作用是运行另外一个指定的程序。它会把新程序加载到当前进程的内存空间内,当前的进程会被丢弃,它的堆、栈和所有的段数据都会被新进程相应的部分代替,然后会从新程序的初始化代码和main函数开始运行。同时,进程的ID将保持不变。 20 | -------------------------------------------------------------------------------- /source/os/linux/syscall/process/index.rst: -------------------------------------------------------------------------------- 1 | 进程控制类系统调用 2 | ======================================== 3 | 4 | .. toctree:: 5 | :maxdepth: 2 6 | :caption: 目录: 7 | 8 | ptrace 9 | execve 10 | fork 11 | vfork 12 | clone 13 | wait 14 | prctl 15 | -------------------------------------------------------------------------------- /source/os/linux/syscall/process/prctl.rst: -------------------------------------------------------------------------------- 1 | prctl 2 | ======================================== 3 | prctl的函数原型如下: 4 | 5 | .. code-block:: cpp 6 | 7 | #include 8 | int prctl (int option, unsigned long arg2, unsigned long arg3, unsigned long arg4, unsigned long arg5); 9 | -------------------------------------------------------------------------------- /source/os/linux/syscall/process/ptrace.rst: -------------------------------------------------------------------------------- 1 | ptrace 2 | ======================================== 3 | ptrace函数原型为 ``long ptrace(enum __ptrace_request request, pid_t pid, void *addr, void *data);`` ,其中 ``enum __ptrace_request request`` 指示了ptrace要执行的命令,``pid_t pid`` 指示ptrace要跟踪的进程,``void *addr`` 指示要监控的内存地址,``void *data`` 存放读取出的或者要写入的数据。 4 | 5 | 函数执行成功时返回0,错误时返回-1,同时设置errno。 6 | 7 | 其中request的选项包括: 8 | 9 | - PTRACE_TRACEME 10 | - 表示本进程将被其父进程跟踪 11 | - PTRACE_PEEKTEXT 12 | - 从内存地址中读取一个WORD,内存地址为addr 13 | - PTRACE_PEEKDATA 14 | - 由于Linux不区分文本与数据段的地址空间,PTRACE_PEEKDATA与PTRACE_PEEKTEXT无区别 15 | - PTRACE_PEEKUSER 16 | - 从USER区域中读取一个WORD,内存地址为addr,值将作为结果返回,其中偏移地址addr通常是是字对齐的,data将被忽略 17 | - PTRACE_PEEKTEXT 18 | - 向内存地址中写入一个WORD,内存地址为addr 19 | - PTRACE_PEEKDATA 20 | - PTRACE_PEEKUSER 21 | - 向USER区域中写入一个WORD,内存地址为addr 22 | - PTRACE_CONT 23 | - 继续运行之前停止的子进程 24 | - 如果data是非空的,它被解释为要发送给Tracee 的信号 25 | - PTRACE_KILL 26 | - 杀掉子进程 27 | - PTRACE_SINGLESTEP 28 | - 设置单步执行标志 29 | - 子进程在每次机器指令后都被暂停 30 | - PTRACE_GETREGS 31 | - 读取寄存器 32 | - PTRACE_GETFPREGS 33 | - 读取浮点寄存器 34 | - PTRACE_SETREGS 35 | - 设置寄存器 36 | - PTRACE_SETFPREGS 37 | - 设置浮点寄存器 38 | - PTRACE_ATTACH 39 | - attach到一个指定的进程,使其成为当前进程跟踪的子进程 40 | - 子进程的行为等同于它进行了一次PTRACE_TRACEME操作 41 | - PTRACE_DETACH 42 | - PTRACE_SYSCALL 43 | - 进程在每次系统调用之后暂停 44 | - PT_DENY_ATTACH 45 | - 反调试 46 | - PTRACE_GETSIGINFO 47 | - 获取导致子进程停止执行的信号信息,并将其存放在父进程内由data指向的位置 48 | - addr参数将被忽略 49 | - PTRACE_SETSIGINFO 50 | - 将父进程内由data指向的数据作为siginfo_t结构体拷贝到子进程 51 | - addr参数将被忽略 52 | - PTRACE_SETOPTIONS 53 | - 将父进程内由data指向的值设定为ptrace选项 54 | - data作为位掩码来解释 55 | - PTRACE_GETEVENTMSG 56 | - 获取刚发生的ptrace事件消息,并存放在data指向的位置 57 | - addr参数将被忽略 58 | - PTRACE_SYSEMU 59 | - 用于用户模式的程序仿真子进程的所有系统调用 60 | - PTRACE_SYSEMU_SINGLESTEP 61 | - 用于用户模式的程序仿真子进程的所有系统调用 62 | 63 | 其中PTRACE_TRACEME和PTRACE_ATTACH的区别为:PTRACE_TRACEME是子进程主动申请被TRACE。而PTRACE_ATTACH是父进程自己要attach到子进程,相当于子进程是被动的trace。 64 | 65 | WORD的长度在64位程序中是64位,32位程序中是32位。 66 | ptrace系统调用在核心对应的处理函数为sys_ptrace。 67 | 68 | 在trace中Tracer指追踪进程,Tracee指被追踪、被观察的进程。 69 | 70 | PTRACE_SETOPTIONS 的取值可能为: 71 | 72 | - PTRACE_O_EXITKILL 73 | - 当跟踪进程退出时,向所有被跟踪进程发送SIGKILL信号将其退出 74 | - PTRACE_O_TRACECLONE 75 | - 被跟踪进程在下一次调用clone()时将其停止,并自动跟踪新产生的进程 76 | - 新的进程在开始时收到SIGSTOP信号 77 | - 其新产生的进程的pid可以通过PTRACE_GETEVENTMSG获取 78 | - PTRACE_O_TRACEEXEC 79 | - 被跟踪进程在下一次调用exec()函数时使其停止 80 | - PTRACE_O_TRACEEXIT 81 | - 被跟踪进程在退出是停止其执行 82 | - 被跟踪进程的退出状态可通过PTRACE_GETEVENTMSG获得 83 | - PTRACE_O_TRACEFORK 84 | - 被跟踪进程在下次调用fork()时停止执行,并自动跟踪新产生的进程 85 | - 新的进程在开始时收到SIGSTOP信号 86 | - 其新产生的进程的pid可以通过PTRACE_GETEVENTMSG获取 87 | - PTRACE_O_TRACEVFORK 88 | - 被跟踪进程在下次调用vfork()时停止执行,并自动跟踪新产生的进程 89 | - 新的进程在开始时收到SIGSTOP信号 90 | - 其新产生的进程的pid可以通过PTRACE_GETEVENTMSG获取 91 | -------------------------------------------------------------------------------- /source/os/linux/syscall/process/vfork.rst: -------------------------------------------------------------------------------- 1 | vfork 2 | ======================================== 3 | 4 | 简介 5 | ---------------------------------------- 6 | vfork创建的子进程与父进程共享数据段,而且由vfork()创建的子进程将先于父进程运行。 7 | 8 | - 由vfork创造出来的子进程还会导致父进程挂起,除非子进程exit或者execve才会唤起父进程 9 | - 由vfok创建出来的子进程共享了父进程的所有内存,包括栈地址,直至子进程使用execve启动新的应用程序为止 10 | - 由vfork创建出来的子进程不应该使用return返回调用者,或者使用exit()退出,但是可以使用_exit()函数来退出 11 | 12 | 源码分析 13 | ---------------------------------------- 14 | .. code-block:: cpp 15 | 16 | SYSCALL_DEFINE0(vfork) 17 | { 18 | return _do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, 0, 19 | 0, NULL, NULL, 0); 20 | } 21 | 22 | 与fork区别 23 | ---------------------------------------- 24 | - fork子进程拷贝父进程的数据段、代码段,vfork子进程与父进程共享数据段 25 | - fork父子进程的执行次序不确定,vfork保证子进程先运行 26 | -------------------------------------------------------------------------------- /source/os/linux/syscall/process/wait.rst: -------------------------------------------------------------------------------- 1 | wait / waitpid 2 | ======================================== 3 | 4 | wait 5 | ---------------------------------------- 6 | wait的函数原型为 ``pid_t wait (int * status);`` ,相关的头文件是 ``#include`` / ``#include`` 。 7 | 8 | 进程调用wait后,就立即阻塞自己,由wait自动分析是否当前进程的某个子进程已经退出,如果找到了这样一个已经变成僵尸的子进程,wait就会收集这个子进程的信息,并把它彻底销毁后返回。如果没有找到这样的子进程,wait就会一直阻塞直到出现一个这样的子进程为止。 9 | 10 | 子进程的结束状态值会由参数status返回,如果不在意结束状态值,则参数status可以设成NULL。 11 | 12 | 如果执行成功则返回子进程识别码(PID),如果有错误发生则返回-1。失败原因存于errno中。 13 | 14 | waitpid 15 | ---------------------------------------- 16 | waitpid的函数原型为 ``pid_t waitpid(pid_t pid,int * status,int options);`` ,相关的头文件是 ``#include`` / ``#include`` 。 17 | 18 | waitpid会暂时停止目前进程的执行,直到有信号来到或子进程结束。如果在调用waitpid时子进程已经结束,则waitpid会立即返回子进程结束状态值。子进程的结束状态值会由参数status返回,如果不在意结束状态值,则参数status可以设成NULL。 19 | 20 | 参数pid 为欲等待的子进程识别码,其他数值意义如下: 21 | 22 | - pid < -1 23 | - 等待进程组识别码为pid绝对值的任何子进程 24 | - pid = -1 25 | - 等待任何子进程,相当于wait 26 | - pid = 0 27 | - 等待进程组识别码与目前进程相同的任何子进程 28 | - pid > 0 29 | - 等待任何子进程识别码为pid的子进程 30 | 31 | 参数option可以为0或下面的OR组合: 32 | 33 | - WNOHANG 34 | - 如果没有任何已经结束的子进程则马上返回,不予以等待。 35 | - WUNTRACED 36 | - 如果子进程进入暂停执行情况则马上返回,但结束状态不予以理会 37 | 38 | 子进程的结束状态返回后存于status,可用下面几个宏判别结束情况: 39 | 40 | - WIFEXITED(status) 41 | - 如果子进程正常结束则为非0值 42 | - WEXITSTATUS(status) 43 | - 取得子进程exit()返回的结束代码,一般会先用WIFEXITED来判断是否正常结束才能使用此宏 44 | - WIFSIGNALED(status) 45 | - 如果子进程是因为信号而结束则此宏值为真 46 | - WTERMSIG(status) 47 | - 取得子进程因信号而中止的信号代码,一般会先用WIFSIGNALED来判断后才使用此宏 48 | - WIFSTOPPED(status) 49 | - 如果子进程处于暂停执行情况则此宏值为真。一般只有使用WUNTRACED时才会有此情况 50 | - WSTOPSIG(status) 51 | - 取得引发子进程暂停的信号代码,一般会先用WIFSTOPPED来判断后才使用此宏 52 | 53 | 如果执行成功则返回子进程识别码(PID),如果有错误发生则返回-1。失败原因存于errno中。 54 | -------------------------------------------------------------------------------- /source/os/linux/syscall/session/index.rst: -------------------------------------------------------------------------------- 1 | 进程会话类系统调用 2 | ======================================== 3 | 4 | .. toctree:: 5 | :maxdepth: 2 6 | :caption: 目录: 7 | 8 | setsid 9 | -------------------------------------------------------------------------------- /source/os/linux/syscall/session/setsid.rst: -------------------------------------------------------------------------------- 1 | setsid 2 | ======================================== 3 | 4 | setsid的函数原型为 5 | 6 | .. code-block:: cpp 7 | 8 | #include 9 | pid_t setsid(void); 10 | 11 | 12 | 如果该函数的调用进程不是进程组组长,那么调用后执行如下操作: 13 | 14 | - 创建一个新会话,会话ID等于进程ID,调用进程成为会话的首进程。 15 | - 创建一个进程组,进程组ID等于进程ID,调用进程成为进程组的组长。 16 | - 该进程没有控制终端,如果调用setsid前,该进程有控制终端,这种联系就会断掉。 17 | 18 | 调用setsid函数的进程不能是进程组的组长,否则调用会失败,返回-1,并置errno为EPERM。 19 | -------------------------------------------------------------------------------- /source/os/macos.rst: -------------------------------------------------------------------------------- 1 | Mac OS 2 | ======================================== 3 | 4 | 参考链接 5 | ---------------------------------------- 6 | - `The Darwin Kernel `_ 7 | - `Kernel Architecture Overview `_ 8 | - `iOS冰与火之歌 `_ 9 | - `macOS notes `_ 10 | - `Mac OS X Debugging Magic `_ 11 | -------------------------------------------------------------------------------- /source/os/windows/concept.rst: -------------------------------------------------------------------------------- 1 | 概念 2 | ======================================== 3 | 4 | COM 5 | ---------------------------------------- 6 | 早期Windows大多使用C风格的API,其和操作系统底层最契合。但是C风格的API在发展中出现了缺少命名一致性、缺少逻辑分组(类似C++的命名空间)等缺点,使得 COM (Component Object Model) API机制发展起来。 7 | 8 | COM 最开始在微软文档系列应用中使用,用于数据交互和内嵌文档。这个能力也被称作 OLE (Object Linking and Embedding)。 9 | 10 | OLE在早期是使用 DDE (Dynamic Data Exchange) 机制实现的,而OLE在设计上存在一些缺陷,因此COM诞生了。实际上,COM在早期(1993年)发布时也被称作 OLE 2。 11 | 12 | COM基于两个基本的原则设计。首先,clients通过由一系列良好定义方法组成的接口和objects通信。其中接口通常是C++的虚函数实现的,这带来了良好的命名兼容性。 13 | 14 | 第二个原则是接口都是动态加载的而不是静态链接的。 15 | 16 | COM server通常指具体实现COM对象的一个DLL或EXE。 17 | 18 | Runtime 19 | ---------------------------------------- 20 | Windows Runtime是在Windows 8引入的概念,在一些文档中被缩写为 WinRT(不同与Windows RT,Windows RT是Windows 8为ARM开发的定制版本)。 21 | 22 | WinRT包含了一系列各个平台(Windows IoT设备、Xbox等)的面向Windows应用开发者的服务。 23 | 24 | 25 | -------------------------------------------------------------------------------- /source/os/windows/dotnet.rst: -------------------------------------------------------------------------------- 1 | .NET 2 | ======================================== 3 | +-------------------------+------------------------+ 4 | | Windows Version | .Net Framework Version | 5 | +=========================+========================+ 6 | | Windows 8 | 4.5 | 7 | +-------------------------+------------------------+ 8 | | Windows 8.1 | 4.5.1 | 9 | +-------------------------+------------------------+ 10 | | Windows 10 | 4.6 | 11 | +-------------------------+------------------------+ 12 | | Windows 10 version 1511 | 4.6.1 | 13 | +-------------------------+------------------------+ 14 | | Windows 10 version 1607 | 4.6.2 | 15 | +-------------------------+------------------------+ 16 | 17 | .NET 框架由 CLR (The Common Language Runtime) 和 FCL (The .NET Framework Class Library) 两个核心模块组成。 18 | 19 | CLR 是 .NET 的运行时引擎,同时包含一个将 CIL (Common 20 | Intermediate Language) 指令转义为机器语言的 JIT,还包含GC、类型检查等模块。 21 | CLR 以 COM in-process server (DLL) 的形式实现。 22 | 23 | FCL 包含了一些网络、数据库等函数接口的实现。 24 | 25 | 具体来说,一个 .NET 程序,自顶向下为 .NET APP (EXE) -> FCL (DLLs) -> CLR (COM DLL Server) -> Windows API DLLs -> Windows Kernel 。 26 | -------------------------------------------------------------------------------- /source/os/windows/fs.rst: -------------------------------------------------------------------------------- 1 | 文件系统 2 | ======================================== 3 | 4 | 系统支持 5 | ---------------------------------------- 6 | Windows支持以下几种文件系统格式: 7 | 8 | - CDFS 9 | - 适用于CD的只读文件系统 10 | - UDF 11 | - 适用于DVD的只读文件系统 12 | - FAT12, FAT16, FAT32 13 | - File Allocation Table,文件分配表文件系统 14 | - NTFS 15 | - New Technology File System,Windows NT以及之后 Windows的标准文件系统 16 | 17 | FAT 18 | ---------------------------------------- 19 | FAT(File Allocation Table)是“文件分配表”的意思。顾名思义,就是用来记录文件所在位置的表格, 20 | 21 | FAT-16 22 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 23 | FAT16使用了16位的空间来表示每个扇区(Sector)配置文件的状态,故称之为FAT16。FAT-16磁盘分区最大只能到2GB。 24 | 25 | FAT-32 26 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 27 | FAT16使用了32位的空间来表示每个扇区(Sector)配置文件的状态,最大支持32GB分区,单个文件最大支持4GB。 28 | 29 | exFAT 30 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 31 | exFAT(Extended File Allocation Table File System)又称扩展FAT或扩展文件分配表。 32 | 33 | NTFS 34 | ---------------------------------------- 35 | NTFS(New Technology File System)是Windows NT内核的系列操作系统支持的、一个特别为网络和磁盘配额、文件加密等管理安全特性设计的磁盘格式,提供长文件名、数据保护和恢复,能通过目录和文件许可实现安全性,并支持跨越分区。 36 | 37 | NTFS支持功能 38 | 39 | - 访问控制(Access control) 40 | - 磁盘配额(Disk quotas) 41 | - 加密文件系统(Encrypting File System, EFS) 42 | - 支持多重数据流(Multiple data streams) 43 | - 支持硬链接和联结点(Hard links and junction points) 44 | - 基于Unicode的命名方式 45 | 46 | 权限管理 47 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 48 | 文件夹的标准权限:读取、写入、列目录、读取和执行、修改、完全控制。 49 | 50 | 文件的标准权限:读取、写入、读取和执行、修改、完全控制。 51 | 52 | 多重权限规则: 53 | 54 | - 权限是累加的 55 | - 拒绝权限优先于其他权限 56 | - 设置给文件的权限优先于给文件夹的权限 57 | 58 | 共享文件夹权限 59 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 60 | - 比NTFS权限简单,优先级比NTFS权限低 61 | - 和NTFS权限可以进行组合,结果取决于哪个权限更严格 62 | - 共享允许的权限:读取、更改、完全操作 63 | 64 | 共享文件夹权限的特点 65 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 66 | - 共享文件夹权限只适用于文件夹、而不适用于单独的文件,也不能对该文件夹中的子文件夹和文件设置共享权限。 67 | - 共享文件夹权限并不对直接登录到计算机上的用户起作用,只适用于通过网络连接该文件夹的用户。 68 | - 在FAT32文件系统上,共享文件夹权限是保证网络资源被安全访问的唯一方法。 69 | - 默认的共享文件夹权限是指派给Everyone组的读取权限。 70 | 71 | ReFS 72 | ---------------------------------------- 73 | ReFS(Resilient File System,弹性文件系统) 是在Windows Server 2012中新引入的一个文件系统。只能应用于存储数据,不能引导系统。ReFS是与NTFS大部分兼容的,其主要目的 是为了保持较高的稳定性,可以自动验证数据是否损坏,并尽力恢复数据。 74 | -------------------------------------------------------------------------------- /source/os/windows/fsenc.rst: -------------------------------------------------------------------------------- 1 | 文件加密与安全 2 | ======================================== 3 | 4 | EFS文件加密系统 5 | ---------------------------------------- 6 | EFS(Encrypting File System, 加密文件系统) 7 | 8 | - 公私钥加密体系 9 | - 加密时,系统使用当前用户的公钥将数据加密并保存到硬盘上;解密时,系统使用该用户对应的私钥将数据解密出来。 10 | - EFS的优势 11 | - 与操作系统结合紧密,对用户透明。 12 | - 支持EFS的操作系统 13 | - Windows 2000 14 | - Windows XP专业版 15 | - Windows Server 2003 16 | - Windows Vista/7/8商业版、企业版、旗舰版 17 | - Windows Server 2008 18 | 19 | EFS的数据加密过程 20 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 21 | - 文件被复制到临时文件。若复制过程中发生错误,则利用此文件进行恢复。 22 | - 文件被一个随机产生的Key加密,这个Key叫作文件加密密钥(FEK),这个文件使用DESX或者3DES加密算法进行加密。 23 | - 数据加密区域(DDF,Data decryption field)产生,这个区域包含 了使用RSA算法加密的FEK和用户的公钥。 24 | - 数据恢复区域(DRF,Data recovery field)产生,这个区域的目的是为了在用户解密文件的中可能解密文件不可用(丢失Key、离开公 司等)。这些用户叫做恢复代理,恢复代理在加密数据恢复策略( EDRP)中定义,它是一个域的安全策略。如果一个域的EDRP没有设置,本地EDRP被使用。DRF包含使用RSA算法加密的FEK和恢复 代理的公钥。如果在EDRP列表中有多个恢复代理,FEK须用每个恢复代理的公钥进行加密,也就是会为每个恢复代理创建一个DRF。 25 | - 包含加密数据、DDF及所有DRF的加密文件被写入磁盘, 文件大小一般保持不变。 26 | - 在第1步中创建的临时文件被删除。 27 | 28 | Bitlocker磁盘加密 29 | ---------------------------------------- 30 | Bitlocker是Windows Vista开始引入的一项数据保护新功能,可以解决计算机设备的物理丢失导致的数据失窃或恶意攻击泄漏。Bitlocker通过将Windows的安装分区进行整卷加密,防止被攻击者通过启动其他操作系统来获取文件的“脱机攻击”。 31 | 32 | Bitlocker的工作模式 33 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 34 | Bitlocker的工作模式有TPM(Trusted Platform Module)模式和U盘模式。 35 | 36 | TPM模式要求计算机必须带有TPM芯片,这种芯片要通过硬件提供,一般只出现在安全性要求较高的商用计算机或工作站上。 37 | 38 | U盘模式要求计算机上有USB接口且BIOS支持在开机的时候访问USB设备,用于解密系统盘的密钥文件保存在U盘上,每次重启系统的时候必须在计算机上连接U盘。 39 | 40 | 文件数据的备份和还原 41 | ---------------------------------------- 42 | 43 | 数据备份类型 44 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 45 | - 常规备份(完全备份,Full Backup) 46 | - 对整个系统进行备份,包括操作系统和应用程序生成的数据。 47 | - 优点:当发生数据丢失的灾难时,只要用一盘磁带(即灾难发生前 一天的备份磁带),就可以恢复全部的数据。 48 | - 缺点:数据量大,占用备份的存储设备较多,备份时间较长。 49 | - 增量备份 (Incremental Backup) 50 | - 每次备份的数据只是上一次备份后增加和修改过的数据。 51 | - 优点:没有重复的备份数据,节省存储空间,又缩短了备份时间。 52 | - 缺点:发生灾难时恢复数据比较麻烦,需要环环相套的所有备份。 53 | - 差异备份(Differential Backup) 54 | - 每次备份的数据是相对于上一次全备份之后增加和修改过的数据。 55 | - 优点:备份所需时间短,节省磁带空间,灾难恢复也很方便,因为只需两盘磁带,即系统全备份与发生灾难前一天的备份。 56 | 57 | 删除与还原 58 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 59 | Windows删除文件只是简单的将硬盘上MFT(主文件分配表)中有关该文件的位置信息删除,而文件内容实际上还保存在硬盘相应的簇中。如果一个文件被删除了,但保存该文件的簇还没有被覆盖新数据的话,就可以将该文件重新恢复。如果需要彻底删除文件,不仅需要删除硬盘上MFT中的记录,还需要删除硬盘簇中实际保存的文件。 60 | -------------------------------------------------------------------------------- /source/os/windows/history.rst: -------------------------------------------------------------------------------- 1 | 版本历史 2 | ======================================== 3 | 4 | +----------------------------+---------+--------------+ 5 | | Windows Version | Version | Release Date | 6 | +============================+=========+==============+ 7 | | Windows NT 3 .1 | 3.1 | 1993.7 | 8 | +----------------------------+---------+--------------+ 9 | | Windows NT 3 .5 | 3.5 | 1994.9 | 10 | +----------------------------+---------+--------------+ 11 | | Windows NT 3 .51 | 3.51 | 1995.5 | 12 | +----------------------------+---------+--------------+ 13 | | Windows NT 4 .0 | 4.0 | 1996.7 | 14 | +----------------------------+---------+--------------+ 15 | | Windows 2000 | 5.0 | 1999.12 | 16 | +----------------------------+---------+--------------+ 17 | | Windows XP | 5.1 | 2001.8 | 18 | +----------------------------+---------+--------------+ 19 | | Windows Server 2003 | 5.2 | 2003.3 | 20 | +----------------------------+---------+--------------+ 21 | | Windows Vista | 6.0 | 2007.1 | 22 | +----------------------------+---------+--------------+ 23 | | Windows Server 2008 | 6.0 | 2008.3 | 24 | +----------------------------+---------+--------------+ 25 | | Windows 7 | 6.1 | 2009.10 | 26 | +----------------------------+---------+--------------+ 27 | | Windows Server 2008 R2 | 6.1 | 2009.10 | 28 | +----------------------------+---------+--------------+ 29 | | Windows 8 | 6.2 | 2012.10 | 30 | +----------------------------+---------+--------------+ 31 | | Windows 10 | 10.0 | 2015.7 | 32 | +----------------------------+---------+--------------+ 33 | | Windows Server 2016 | 10.0 | 2016.9 | 34 | +----------------------------+---------+--------------+ 35 | | Windows Server 2019 | 10.0 | 2019.10 | 36 | +----------------------------+---------+--------------+ 37 | 38 | Windows NT 39 | ---------------------------------------- 40 | Windows NT是Microsoft发行的一系列操作系统,其第一个版本于1993年7月发布。它是一个独立于处理器的多处理和多用户操作系统。 41 | 42 | Windows NT的第一个版本是Windows NT 3.1,是为工作站和服务器计算机生成的。它旨在补充基于MS-DOS(包括Windows 1.0到Windows 3.1x)的Windows的消费者版本。 43 | 44 | 渐渐地,Windows NT系列已经扩展到微软针对所有个人计算机的通用操作系统产品线,不再使用Windows 9x系列。 45 | 46 | NT是第一个纯粹的32位Windows版本,而面向消费者的对应产品Windows 3.1x和Windows 9x则是16位/32位的混合版本。它是一种多架构操作系统。最初,它支持多种指令集架构,包括IA-32,MIPS和DEC Alpha;稍后添加了对PowerPC,Itanium,x64和ARM的支持。 47 | 48 | 最新版本支持x86(更具体地说是IA-32和x64)和ARM。 Windows NT系列的主要功能包括Windows Shell,Windows API,Native API,Active Directory,组策略,硬件抽象层,NTFS,BitLocker,Windows应用商店,Windows Update和Hyper-V。 49 | -------------------------------------------------------------------------------- /source/os/windows/index.rst: -------------------------------------------------------------------------------- 1 | Windows 2 | ======================================== 3 | 4 | .. toctree:: 5 | :maxdepth: 2 6 | :caption: 目录: 7 | 8 | history 9 | concept 10 | kernel/index 11 | logon 12 | dotnet 13 | services 14 | process/index 15 | mem 16 | iodriver 17 | fs 18 | fsenc 19 | network 20 | registry 21 | wmi 22 | security/index 23 | malware 24 | terminology 25 | ref 26 | -------------------------------------------------------------------------------- /source/os/windows/iodriver.rst: -------------------------------------------------------------------------------- 1 | IO与驱动 2 | ======================================== 3 | 4 | 管理器 5 | ---------------------------------------- 6 | - 输入输出管理器(I/O Manager) 7 | - 即插即用管理器 (Plug and Play Manager) 8 | - 电源管理器 (Power Manager) 9 | 10 | 输入输出管理器(I/O Manager)接收应用程序的请求 后,创建相应的IRP (I/O request packets,输入输 出请求数据包)并传送至驱动程序进行处理: 11 | 12 | - 根据IRP的请求,直接操作具体硬件设备,然后完成此IRP, 并返回 13 | - 将此IRP的请求,转发到更底层的驱动程序中去,并等待底层驱动的返回 14 | - 接收到IRP请求后,不是急于完成,而是分配新的IRP发送到 其他驱动程序中去,并等待返回 15 | -------------------------------------------------------------------------------- /source/os/windows/kernel/dll.rst: -------------------------------------------------------------------------------- 1 | Ntdll.dll 2 | ======================================== 3 | Ntdll是用于subsytem和原生应用的特殊系统调用支持库。 4 | 5 | Ntdll有很多功能,包括镜像载入(以Ldr开头的函数)、堆管理、Windows子系统进程间通信(以Csr开头的函数)等。 6 | 7 | 一些不属于任何子系统的可执行文件不会链接到子系统的dll(Kernel32.dll等),仅仅会链接到Ntdll.dll,这是较为底层的通信方式。这种可执行文件一般都是微软发布的。 8 | -------------------------------------------------------------------------------- /source/os/windows/kernel/executive.rst: -------------------------------------------------------------------------------- 1 | Executive 2 | ======================================== 3 | Windows executive 是 Ntoskrnl.exe 的上层。Executive包含下面几种函数: 4 | 5 | - 暴露给用户模式调用的函数 6 | - 通过 DeviceIoControl 调用的设备驱动函数 7 | - 通过WDK暴露的,内核模式下调用的函数 8 | - 未文档化的,内核模式下调用的函数 9 | - 定义为的全局符号但是未导出的函数 10 | - 属于模块内部的函数 11 | 12 | Executive包含下面几个主要模块: 13 | 14 | - 配置管理:系统注册表的实现与管理 15 | - 进程管理 16 | - Security Reference Monitor (SRM) 17 | - I/O管理 18 | - Plug and Play (PnP)管理 19 | - 电源管理 20 | - Windows Driver Model (WDM) 21 | - Windows Management Instrumentation (WMI) routines 22 | - 内存管理 23 | - 缓存管理 24 | -------------------------------------------------------------------------------- /source/os/windows/kernel/index.rst: -------------------------------------------------------------------------------- 1 | Windows Kernel 2 | ======================================== 3 | 4 | .. toctree:: 5 | :maxdepth: 2 6 | :caption: 目录: 7 | 8 | basic 9 | subsystem 10 | wsl 11 | dll 12 | executive 13 | misc 14 | -------------------------------------------------------------------------------- /source/os/windows/kernel/misc.rst: -------------------------------------------------------------------------------- 1 | 其他 2 | ======================================== 3 | 4 | 字符 5 | ---------------------------------------- 6 | Windows在内核中以UTF-16LE的格式处理字符串。由于许多程序都使用ANSI字符串,因此Windows在大部分函数中提供了支持ANSI和Unicode的两个接口。例如CreateFile实际对应CreateFileA(ANSI)和CreateFileW (Wide, unicode) 两个函数。 7 | 8 | 其中对unicode的原生支持是在9x版本后才引入的。 9 | -------------------------------------------------------------------------------- /source/os/windows/kernel/subsystem.rst: -------------------------------------------------------------------------------- 1 | 子系统 2 | ======================================== 3 | Windows中每个可执行文件都与一个环境子系统(Environment subsystems)相对应。在可执行文件执行时,系统根据文件头中的信息对应找到环境子系统。 4 | 5 | 可执行文件在对应调用DLL时,也是调用对应子系统的DLL(subsystem DLL)。具体来说,调用分为三种情况: 6 | 7 | - 函数仅涉及子系统的用户模式 8 | - 函数需要子系统的系统进程 9 | - 函数涉及到Windows系统调用,例如ReadFile/WriteFile 10 | 11 | 子系统由 Session Manager (Smss.exe) 进程启动,相关信息在注册表 HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\SubSystems 中。 12 | 13 | -------------------------------------------------------------------------------- /source/os/windows/kernel/wsl.rst: -------------------------------------------------------------------------------- 1 | WSL 2 | ======================================== 3 | WSL (Windows Subsystem for Linux) 是一个可以让原生 ELF 二进制文件运行在 Windows 中的组件集合。 4 | 5 | WSL1 6 | ---------------------------------------- 7 | WSL1 包含用户态和内核态组件,主要有以下部分: 8 | 9 | - 用户态会话管理服务:处理 Linux 实例生命周期 10 | - 系统调用:通过微型驱动(Pico Provider Drivers) (lxss.sys/lxcore.sys) 翻译 Linux 系统调用以模拟 Linux 内核 11 | - 文件系统:提供VoIFs与DriverFs,VolFs 提供对 Linux 文件系统的完整支持,DriveFs 与 Windows 进行通信 12 | - 微进程(Pico Processes):托管原生的用户态 Linux 程序 (例如 /bin/bash) 13 | 14 | :: 15 | 16 | 17 | +----------+ +--------------+ +-----------+ 18 | | Bash.exe | ---> | LXSS Manager | <---> | /bin/bash | 19 | +----------+ | Service | +-----------+ 20 | +--------------+ | 21 | | | User Mode 22 | ----------------------------------------------------------------------- 23 | | | Kernel Mode 24 | +-------------------------------------+ 25 | | LXCore / LXSS | 26 | +-------------------------------------+ 27 | | 28 | +--------------------+ 29 | | Executive & Kernel | 30 | +--------------------+ 31 | 32 | 33 | 34 | WSL2 35 | ---------------------------------------- 36 | WSL2 在 WSL1 上有较大的改动,基于Hyper-V虚拟机实现。 37 | -------------------------------------------------------------------------------- /source/os/windows/logon.rst: -------------------------------------------------------------------------------- 1 | Logon 2 | ======================================== 3 | Windows的登陆操作是由 ``%SystemRoot%\System32\Winlogon.exe`` 处理的。用户的识别和验证功能是由一系列被称为 ``credential providers`` 的DLL提供的。 4 | 5 | 标准的Windows credential providers实现了默认的认证方式:密码与智能卡。在Windowws 10中引入了新的生物认证方式:Windows Hello,基于面容识别进行验证。用户也可以通过实现对应接口的方式来完成自己的验证机制。 6 | 7 | 由于 Winlogon.exe 系列进程比较敏感,这些进程都被设置为 LogonUI.exe 的子进程。当用户登录过程结束后,LogonUI相关进程都会结束。 Winlogon.exe 也可以调用网络相关DLL来进行需要网络交互的认证。 8 | 9 | 当用户名密码输入结束后,会被发送到 Local 10 | Security Authentication Service process (Lsass.exe) 。而后在DLL中,完成具体的实现,例如对应的用户名和密码是否被存储在SAM中。如果是域登录的话,则对应发起网络请求。 11 | -------------------------------------------------------------------------------- /source/os/windows/malware.rst: -------------------------------------------------------------------------------- 1 | 恶意软件 2 | ======================================== 3 | 4 | 常见攻击顺序 5 | ---------------------------------------- 6 | - 运行记事本等白名单程序 7 | - 开启 process handle 8 | - 申请一块内存 9 | - 将内存设置为 RWX 10 | - 在每一个实例中注入一部分 payload 11 | - 触发 payload 12 | 13 | 行为检测绕过 14 | ---------------------------------------- 15 | - 使用 Native API 调用 16 | - Windows Kernel 开放程度有效,大部分检测基于 ntdll hook 17 | - 绕过 ntdll 直接进行交互能绕过部分检测 18 | - 使用间接 API 调用 19 | - 复制 API 函数代码 20 | - 直接跳转制 API 函数 21 | - 直接调用 System Call 22 | 23 | DLL注入 24 | ---------------------------------------- 25 | 26 | API Call 27 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 28 | - CreateToolhelp32Snapshot 29 | - Process32First 30 | - Process32Next 31 | - OpenProcess 32 | - VirtualAlloc 33 | - VirtualAllocEx 34 | - CreateRemoteThread 35 | - WriteProcessMemory 36 | -------------------------------------------------------------------------------- /source/os/windows/mem.rst: -------------------------------------------------------------------------------- 1 | 内存管理 2 | ======================================== 3 | 4 | 内存管理器 5 | ---------------------------------------- 6 | - 每个进程都有属于它的巨大的、连续的私有内存地址空间(即虚拟地址)。 7 | - 内存管理器的功能: 8 | - 将虚拟的私有内存翻译/映射到真正存放数据的物理内存,可以隔离不同进程之间的数据读写。 9 | - 当物理内存耗尽时,将内存换页(page)到磁盘上去;然后当需要时再换页回来。 10 | 11 | 虚拟内存(Virtural Memory) 12 | ---------------------------------------- 13 | - 每个进程都有它自己的虚拟地址空间。 14 | - 虚拟内存提供了和物理内存不相关的逻辑视图。 15 | - 换页(Paging)是和磁盘传输内存内容的过程。 16 | - 虚拟内存的大小可以超过可用的物理内存。 17 | -------------------------------------------------------------------------------- /source/os/windows/network.rst: -------------------------------------------------------------------------------- 1 | 网络机制 2 | ======================================== 3 | 4 | Windows的网络结构和组件 5 | ---------------------------------------- 6 | - 网络应用程序与服务进程 7 | - 对应OSI应用层,通常使用各类网络API DLL来实现网络交互与通信功能。 8 | - 网络API DLL及TDI客户端 9 | - 对应OSI会话层与表示层,为应用程序提供 了独立于具体协议的网络交互实现方式,包括Windows套接字(Winsock)、远程过程 调用(RPC)、Web访问API、命名管道和 邮件槽以及其他网络API接口。 10 | - TDI客户端作为内核模式驱动程序,是网络 API接口内核部分的具体实现:将网络API的请求转换成IRP,通过TDI标准格式化后,发 送给下层的协议驱动(TDI传输器)。 11 | 12 | TDI 13 | ---------------------------------------- 14 | TDI(Transport Driver Interface)传输驱动程序接口,也被称之为TDI传输器、NDIS协议驱动程序 、协议驱动程序等,对应OSI的网络层和传输层,实现了TCP/IP、NetBEUI、IPX等协议栈,接受上层TDI客户端的IRP请求,并 调用NDIS库中提供的网卡驱动程序功能进行网络传输。 15 | 16 | TDI传输器通过透明地进行如分片与重组、排序确认与重传等一 系列消息操作,为上层网络应用提供了便捷的支持。 17 | Windows Vista之后,不再使用TDI,而是Windows filter platform(WFP)和Winsock kernel(WSK)了。 18 | 19 | WSK,Winsock内核:提供内核模式下的网络通信,使用类似 于用户态Winsock的编程语法,但也提供IRP和事件回调函数的 异步I/O操作等特性。WSK还在Windows下一代TCP/IP网络协议 栈中默认支持IPv6功能。 20 | 21 | WFP,Windows过滤平台:一套API函数和系统服务,提供创建 网络过滤应用程序的能力,允许应用程序追踪、过滤甚至修改网 络数据包 22 | 23 | NDIS 24 | ---------------------------------------- 25 | NDIS(Network Driver Interface Specification)库及小端 口(miniport)驱动程序位于OSI的链路层,为各种不同的网卡驱动程序和TDI传输层之间 构建一个封装接口。 26 | 27 | NDIS库(ndis.sys)对于上层为网络程序模块屏蔽了不同的网 卡硬件类型,NDIS miniport驱动对于下层,为网卡制造商开发设备驱动程序提供了屏蔽Windows内核环境细节信息的编程接口。 28 | 29 | NDIS包含各种网卡硬件的设备驱动程序,处于OSI模型的物理层。 30 | -------------------------------------------------------------------------------- /source/os/windows/process/container.rst: -------------------------------------------------------------------------------- 1 | Windows 容器 2 | ======================================== 3 | 随着云计算的不断发展,Windows也引入了容器技术,在Windows中,Docker可以以两种模式运行: 4 | 5 | - 部署一个重量级的、完全隔离的,基于 Hyper-V 的容器。桌面版和服务器版本都支持 6 | - 部署一个轻量级的、基于OS隔离的,服务器容器 (server silo container)。仅支持有对应 license 的服务器版本。 7 | 8 | Silo 9 | ---------------------------------------- 10 | silo实际上基于一个特殊的、配置了额外规则和能力的job。silo也可以分为 application silo 和 server silo。 11 | 12 | Silo 的隔离使用以下的技术完成: 13 | 14 | - 被称为 base OS 的基础 Windows 镜像 (WIM) 15 | - 宿主操作系统的 Ntdll 16 | - 基于 Wcifs.sys 驱动的虚拟文件系统沙箱 17 | - 基于 VReg 内核模块的虚拟注册表沙箱 18 | - Session Manager (smss.exe) 19 | 20 | 每一个 Server Silo 都会拥有以下的隔离的属性: 21 | 22 | - 用户数据:包含客制化的系统路径、session id, pid 等 23 | - 对象目录命名空间:包含 \SystemRoot \Device 等目录 24 | - 基于 base OS WIM 的 API 集合 25 | - Logon Session 26 | - ETW Tracing 与 logger 上下文 27 | -------------------------------------------------------------------------------- /source/os/windows/process/dll.rst: -------------------------------------------------------------------------------- 1 | DLL 2 | ======================================== 3 | 4 | 由于DLL分布在各个位置,不能在链接时硬编码,因此在加载时使用动态解析的方法 (name resolution)。 5 | 6 | 在解析二进制文件的依赖时,Windows在搜索路径中查找文件。搜索DLL路径的优先级如下: 7 | 8 | - 启动的进程的位置 9 | - Windows系统目录 (例如 C:\Windows\System32) 10 | - 16位 Windows系统目录 (例如 C:\Windows\System) 11 | - Windows目录 (例如 C:\Windows) 12 | - 当前目录 13 | - %PATH% 环境变量指定的位置 14 | -------------------------------------------------------------------------------- /source/os/windows/process/index.rst: -------------------------------------------------------------------------------- 1 | 进程与线程 2 | ======================================== 3 | 4 | .. toctree:: 5 | :maxdepth: 2 6 | :caption: 目录: 7 | 8 | process 9 | thread 10 | dll 11 | job 12 | container 13 | struct 14 | -------------------------------------------------------------------------------- /source/os/windows/process/job.rst: -------------------------------------------------------------------------------- 1 | Job 2 | ======================================== 3 | 4 | 基础 5 | ---------------------------------------- 6 | Windows的Job是用于控制一个或多个进程的内核对象。进程可以属于任意数量的Job,在大部分情况下只属于某一个Job。 7 | 8 | Job在Windows中扮演了重要的角色,作用包括: 9 | 10 | - 管理Windows现代APP(UWP) 11 | - 实现Windows的容器管理 12 | - 实现 DAM (Desktop Activity Moderator) 的相关功能 13 | - 实现 DFSS 的定义和管理 (Dynamic Fair-Share Scheduling) 14 | - 用于辅助实现 Run As / Application Box / Program Compatibility Assistant 15 | - 提供应用沙箱的部分功能 16 | 17 | Job 设置 18 | ---------------------------------------- 19 | Job 支持以下的配置: 20 | 21 | - 活动进程的最大值 22 | - 以Job为单位的用户模式的CPU时间限制 23 | - 以进程为单位的用户模式的CPU时间限制 24 | - Job 的CPU亲和性 (affinity) 25 | - 进程 / Job 的最大虚拟内存使用量 26 | - CPU 时间控制 27 | - 网络带宽控制 28 | - 磁盘 I/O 控制 29 | - ... 30 | -------------------------------------------------------------------------------- /source/os/windows/process/struct.rst: -------------------------------------------------------------------------------- 1 | 数据结构 2 | ======================================== 3 | 4 | 每个Windows进程都是由一个执行体进程(EPROCESS)块来表示,包含与进程有关的属性及其他的相关数据结构(一个或者多个线程)。 5 | 6 | 线程由执行体线程(ETHREAD) 块来表示。 7 | 8 | EPROCESS 块和相关的大部分数据结构都位于系统地址空间中,不过PEB (Process Environment Block, 进程环境块)和TEB(Thread Environment Block, 线程环境块)则位于进程地址空间中 9 | 10 | Windows 子系统也会创建一个和进程平行的 CSR_PROCESS 结构体。 11 | 12 | 需要对应查看具体的数据结构时,可以使用 ``dt nt!_eprocess`` 等调试命令。 13 | -------------------------------------------------------------------------------- /source/os/windows/process/thread.rst: -------------------------------------------------------------------------------- 1 | 线程 2 | ======================================== 3 | 4 | 基础 5 | ---------------------------------------- 6 | 线程(Thread)是CPU调度执行的基本单元,其包含CPU状态、两个栈、线程本地存储(TLS)、线程标识号和访问控制令牌(Access Token)。 7 | 8 | 线程的两个栈分别用于内核模式和用户模式。线程本地存储(TLS)包含一个私有存储空间,用来保存子系统、运行时库以及DLL文件等。 9 | 10 | 访问控制令牌(Access Token),用以唯一的标识所有者及其所属组以及和该线程相关联的特权(Privilege)信息 11 | 12 | 线程创建 13 | ---------------------------------------- 14 | 在用户模式下,线程创建最简单的方式是调用 CreateThread ,这个函数将会在当前进程创建线程,并接受以下参数 15 | 16 | - 指向线程入口的函数指针 17 | - 安全属性结构体(可选) 18 | - 栈空间大小(可选),为零时使用可执行文件头部中设置的默认值 19 | - ... 20 | -------------------------------------------------------------------------------- /source/os/windows/ref.rst: -------------------------------------------------------------------------------- 1 | 参考链接 2 | ======================================== 3 | 4 | 文档 5 | ---------------------------------------- 6 | - `Windows Management Instrumentation `_ 7 | - `Windows NT Wiki `_ 8 | - `AppLocker `_ 9 | - `Antimalware Scan Interface (AMSI) `_ 10 | - `Virtualization documentation `_ 11 | 12 | 漏洞利用 13 | ---------------------------------------- 14 | - `windows kernel exploit tutorial `_ 15 | - `HEVD `_ 16 | - `HolicPOC `_ 17 | - `Basics of Windows shellcode writing `_ 18 | 19 | 漏洞 20 | ---------------------------------------- 21 | - `进程注入 `_ 22 | 23 | 系统架构 24 | ---------------------------------------- 25 | - `Deeper into Windows Architecture `_ 26 | -------------------------------------------------------------------------------- /source/os/windows/registry.rst: -------------------------------------------------------------------------------- 1 | 注册表 2 | ======================================== 3 | 4 | 简介 5 | ---------------------------------------- 6 | 注册表(Registry)是包含操作系统和其它软件的所有设置和配置相关数据的目录。 7 | 8 | 注册表的逻辑结构类似于磁盘上的文件系统。注册表包含了键(key)和值(value)。其中键类似文件系统中的目录,而值就像文件,键可以包含子键(subkey)和值。值中存储着配置数据,数据有多种类型。最顶层的键称为根键(root key)。 9 | 10 | 涉及到注册表的有: 11 | 12 | 1. 在启动时,boot loader从注册表中读取数据。 13 | 2. 内核启动时,内核驱动从注册表中读取配置。 14 | 3. 在登陆时,读取网络驱动设置、墙纸、菜单、启动项等。 15 | 4. 在应用启动时,读取各种配置文件。 16 | 17 | 数据类型 18 | ---------------------------------------- 19 | - REG_NONE 20 | - 没有值 21 | - REG_SZ 22 | - 固定长度 Unicode 23 | - REG_EXPAND_SZ 24 | - 可变长度 Unicode 25 | - REG_BINARY 26 | - 任意长度二进制数据 27 | - REG_DWORD 28 | - 32 bit 数字 29 | - REG_DWORD_BIG_ENDIAN 30 | - 32 bit 数字,大端 31 | - REG_LINK 32 | - Unicode 符号链接,指向另一个注册表项 33 | - REG_MULTI_SZ 34 | - Unicode 字符串 35 | - REG_RESOURCE_LIST 36 | - 硬件资源描述 37 | - REG_FULL_RESOURCE_DESCRIPTOR 38 | - 硬件资源描述 39 | - REG_RESOURCE_REQUIREMENTS_LIST 40 | - 资源需求 41 | - REG_QWORD 42 | - 64 bit 数字 43 | 44 | root key 45 | ---------------------------------------- 46 | - HKEY_CURRENT_USER:和当前登陆用户有关的数据 47 | - AppEvents:事件关联 48 | - Console:控制台设定 49 | - Control Panel:控制面板 50 | - Environment:环境变量 51 | - EUDC:用户定义字符 52 | - Identities:Windows Mail账户信息 53 | - Keyboard Layout:键盘布局 54 | - Network:网络驱动信息 55 | - Printers:打印机 56 | - Software:软件 57 | - Volatile Environment:可变的环境变量 58 | - HKEY_USERS:所有用户有关的数据 59 | - HKEY_CLASSES_ROOT 60 | - 文件后缀关联 61 | - COM(Component Object Model)注册 62 | - UAC 63 | - HKEY_LOCAL_MACHINE:系统相关的数据 64 | - HKLM\BCD00000000 65 | - HKLM\COMPONENTS 66 | - HKLM\HARDWARE 67 | - HKLM\SAM 68 | - HKLM\SECURITY 69 | - HKLM\SOFTWARE 70 | - HKLM\SYSTEM 71 | - HKEY_PERFORMANCE_DATA:性能相关的数据 72 | - HKEY_CURRENT_CONFIG:当前配置文件 73 | -------------------------------------------------------------------------------- /source/os/windows/security/ident.rst: -------------------------------------------------------------------------------- 1 | 身份认证 2 | ======================================== 3 | 4 | 权限 5 | ---------------------------------------- 6 | - Administrators:管理员组,默认情况下,Administrators中的用户对计算机/域有不受限制的完全访问权 7 | - Power Users:高级用户组,Power Users 可以执行除了 Administrators 组之外的其他任何组任务 8 | - Users:普通用户组 9 | - Guests:来宾组,来宾跟普通Users的成员有同等访问权,但来宾帐户的限制更多 10 | - Everyone:所有的用户 11 | 12 | SID 13 | ---------------------------------------- 14 | - Windows使用SID来唯一表示安全主体 ,包括用户和组。Windows NT 6.x中, 系统服务也有SID标识。 15 | - 查看账户的SID 16 | - whoami / user 17 | - PsGetSid 18 | - user2sid 19 | 20 | - 从Windows Vista/Server 2008(NT 6.0)开始,每个服务程序都 有自己的SID,而账户的名称则为“NT SERVICE\<服务名称>” 21 | - 查看服务SID及其账户名称 22 | - sc.exe showsid 23 | - psgetsid 24 | 25 | 相关程序 26 | ---------------------------------------- 27 | 28 | Winlogon 29 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 30 | - 可信任的进程,负责管理与安全有关的用户交互 31 | - 协调登录过程,在登录时启动用户的第一个进程,处理注销过程,以管理其他各种与安全有关的操作,包括在登录时输入口令、更改口令、锁住/解锁工作站等。 32 | - 创建可用的桌面。 33 | - 向操作系统注册一个安全维护序列(SAS, Secure Attention Sequence),默认为Ctrl+Alt+Delete。 34 | - 维护工作站状态。 35 | - 实现超时处理。 36 | - 向GINA发送事件通知消息,提供可供GINA调用的各种接口函数。 37 | - 保证其操作对其他进程不可见,从而防止登录密码等信息被截获。 38 | 39 | GINA动态链接库 40 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 41 | - 提供了Winlogon用户标识和验证用户的输出函数。 42 | - WlxActivateUserShell、WlxDisplaySASNotice、WlxInitialize、WlxLoggedOnSAS、WlxLoggedOutSAS、WlxLogoff、WlxNegotiate、WlxScreenSaverNotify、WlxShutdown、WlxStartApplication、WlxWkstaLockedSAS 43 | - 微软提供的GINA是MSGINA.dll,但允许被用户替换来自行定 制系统的用户识别和身份验证。 44 | - [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\WindowsNT\CurrentVersion\Winlogon] "GinaDLL"="ginadll.dll" 45 | 46 | 身份验证程序包 47 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 48 | - 身份验证程序包的任务 49 | - 验证用户; 50 | - 为用户新建LSA登录会话; 51 | - 返回绑定到用户安全令牌中的SID。 52 | - 身份验证程序包位于DLL动态链接库中 53 | - 在系统启动期间被LSA所链接,接受输入的登录证书,通过验证 程序决定是否允许用户登录。 54 | - Windows安装的身份验证程序包 55 | - 独立(工作组)环境:MSV1_0, %SystemRoot%\System32\Msv1_0.dll 56 | - 域环境:Kerberos, %SystemRoot%\System32\Kerberos.dll 57 | 58 | LogonUI 59 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 60 | LogonUI,Logon user interface,登录用户接口 61 | 62 | - 为了保护Winlogon进程不崩溃,LogonUI由Winlogon按需启动,真正加载Credential provider,为用户提供验证身份的图形化界面。 63 | - LogonUI是用户模式下的进程,即 %SystemRoot%\System32\LogonUI.exe 64 | 65 | CP 66 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 67 | CP,Credential provider,凭证提供者 68 | 69 | - Credential provider是运行在LogonUI进程内的COM对象, 位于一些DLL文件中(触发SAS热键后由Winlogon按需启动 ),用来获取用户的用户名、密码、智能卡PIN码或者生物数据(比如指纹、视网膜信息) 70 | - 标准的CP是 %SystemRoot%\System32\authui.dll 和 %SystemRoot%\System32\SmartcardCredentialProvider.dll. 71 | -------------------------------------------------------------------------------- /source/os/windows/security/index.rst: -------------------------------------------------------------------------------- 1 | 安全机制 2 | ======================================== 3 | 4 | .. toctree:: 5 | :maxdepth: 2 6 | :caption: 目录: 7 | 8 | history 9 | acl 10 | ident 11 | policy 12 | virtual 13 | -------------------------------------------------------------------------------- /source/os/windows/security/policy.rst: -------------------------------------------------------------------------------- 1 | 安全策略 2 | ======================================== 3 | 4 | 本地安全策略 5 | ---------------------------------------- 6 | 7 | 账户策略 8 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 9 | 账户策略仅涉及和用户账户的凭据相关的设置。通过设置账户策略、可以让所有本地账户更加安全,同时要破解账户密码所需的时间更长,所需技术更高。 10 | 11 | - 账户策略的种类 12 | - 密码策略 13 | - 账户锁定策略 14 | 15 | 密码策略 16 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 17 | - 密码必须符合复杂性要求 18 | - 建议设置为"启用" 19 | - 密码长度最小值 20 | - 建议设置为“14” 21 | - 密码最短使用期限 22 | - 建议设置为“5天” 23 | - 密码最长使用期限 24 | - 建议设置为“30天” 25 | - 强制密码历史 26 | - 建议设置为“10个” 27 | - 用可还原的加密来存储密码 28 | - 建议设置为“禁用” 29 | 30 | 账户锁定策略 31 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 32 | - 账户锁定阈值 33 | - 建议设置为“3次” 34 | - 账户锁定时间 35 | - 建议设置为“30分钟”,可根据实际需要更改 36 | - 复位账户锁定计数器 37 | - 建议设置为“30分钟”,可根据实际需要更改 38 | 39 | 本地策略 40 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 41 | 本地策略中包含的全部是和账户无关的安全设置。通过设置本地策略,可以让Windows实现更严格的安全性,或者实现其他和安全有关的功能 42 | 43 | 本地策略的种类分为审核策略、用户权限分配、安全选项。 44 | 45 | 审核策略 46 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 47 | - 审核策略更改 48 | - 审核登录事件 49 | - 审核对象访问 50 | - 审核进程跟踪 51 | - 审核目录服务访问 52 | - 审核特权使用 53 | - 审核系统事件 54 | - 审核账户登录事件 55 | - 审核账户管理 56 | 57 | 组策略 58 | ---------------------------------------- 59 | 通过组策略(Group Policy)可以设置整个组织的集中化策略或分散式策略。 60 | 61 | 组策略对象 62 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 63 | - 组策略对象(Group Policy Object, GPO) 64 | - 组策略对象实际上就是组策略设置的集合。 65 | - 组策略对象包含: 66 | - 针对计算机的组策略设置 67 | - 应用在操作系统初始化和周期性更新循环过程中 68 | - 指定操作系统行为、桌面行为、安全性设置、计算机启动和关机指令、计算机赋予的应用程序选项以及应用程序设置 69 | - 针对用户的组策略设置 70 | - 应用在用户登录计算机和周期性更新循环的过程中 71 | - 指定操作系统行为、桌面行为、安全性设置、赋予和公布的应用程序选项、应用程序设置、文件夹的重定向选项以及用户登录和注销指令。 72 | 73 | 组策略对象与活动目录 74 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 75 | 组策略对象与活动目录的联合使用实现了策略的集中与分散管理,适应从小到大的各种网络规模。 76 | 77 | - 组策略对象能够链接到站点、域和组织单元,影响其中的用户和计算机。 78 | - 应用组策略对象的顺序和级别决定了用户和计算机实际所采用的组策略设置。 79 | 80 | 组策略对象的管理单元 81 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 82 | - 根节点 83 | - <组策略对象名称> [<域名称>]策略 84 | - 如:Default Domain Policy [SjtuInfosec.net] 策略 85 | - “本地计算机”策略 86 | - 第二层节点 87 | - 计算机配置 88 | - 用户配置 89 | - 第三层节点 90 | - 软件设置 91 | - Windows设置 92 | - 管理模板 93 | -------------------------------------------------------------------------------- /source/os/windows/security/virtual.rst: -------------------------------------------------------------------------------- 1 | 虚拟化安全 2 | ======================================== 3 | 4 | 在Windows 10中,微软在 Hyper-V 中加入了一系列新的虚拟化安全机制。 5 | 6 | - Device Guard 7 | - 提供 Hypervisor Code Integrity (HVCI) 机制 8 | - Hyper Guard 9 | - 保护关键的 内核 与 Hypervisor 相关代码与数据结构 10 | - Credential Guard 11 | - 防止敏感凭证被非授权访问泄露 12 | - Application Guard 13 | - 为Edge提供沙箱 14 | - Host Guardian and Shielded Fabric 15 | - 为虚拟机提供一个虚拟的 TPM (v-TPM) 16 | -------------------------------------------------------------------------------- /source/os/windows/services.rst: -------------------------------------------------------------------------------- 1 | 服务 2 | ======================================== 3 | 4 | 简介 5 | ---------------------------------------- 6 | 服务(Services)程序是后台运行的进程,常用来执行特定的任务,不需要和用户进行交互。比如自动更新服务、后台智能传输服务、事件日志服务等。 7 | 8 | 服务程序受Service Control Manager(SCM,即services.exe进程)所控制,其服务程序的配置数据位于 ``HKLM\System\CurrentControlSet\Services`` 。 9 | 10 | 服务通常由三个部分组成:服务应用、服务控制程序 (service control program, SCP)、服务控制管理器 (service control manager, SCM)。 11 | 12 | Windows提供了内置的SCP,可以启动、停止、继续运行程序。用户也可以自定义SCP程序来玩橙更细粒度的控制。服务程序是普通的Windows可执行程序,只是会有一些附加模块和SCM通信。 13 | 14 | Windows服务有三个名称,分别为在系统中执行的进程名、在注册表中的名称 (internal name),在服务管理工具中的名字(display name)。当服务没有设置display name时,使用internal name做为替代。 15 | 16 | 需要注意的是,服务进程和运行的服务并不是一一对应的关系,可能多个服务会共享一个进程。这种共享关系是在注册表中定义的。 17 | -------------------------------------------------------------------------------- /source/os/windows/terminology.rst: -------------------------------------------------------------------------------- 1 | 术语与缩写 2 | ======================================== 3 | 4 | SSDT 5 | ---------------------------------------- 6 | SSDT(System Services Descriptor Table)是系统服务描述符表,这个表把 Ring3 的 Win32 API 和 Ring0 的内核 API 联系起来。 7 | 8 | SSDT 并不仅仅只包含一个庞大的地址索引表,它还包含着一些其它有用的信息,诸如地址索引的基地址、服务函数个数等。 9 | 10 | 通过修改此表的函数地址可以对常用Windows函数及API进行Hook,从而实现对一些关心的系统动作进行过滤、监控的目的。 11 | 12 | 一些HIPS、防毒软件、系统监控、注册表监控软件往往会采用此接口来实现自己的监控模块。 13 | 14 | IDT 15 | ---------------------------------------- 16 | IDT(Interrupt Descriptor Table)是中断描述符表,是操作系统用于处理中断的。 17 | 18 | GDT 19 | ---------------------------------------- 20 | GDT,即全局描述表(GDT Global Descriptor Table)。 21 | 22 | LDT 23 | ---------------------------------------- 24 | LDT(Local Descriptor Table),即局部描述符表。 25 | 26 | 常见缩写 27 | ---------------------------------------- 28 | - Alpc: Advanced Local Inter-Process Communication 29 | - Cc: Common Cache 30 | - Cm: Configuration manager 31 | - Dbgk: Debugging Framework for User-Mode 32 | - Em: Errata Manager 33 | - Etw: Event Tracing for Windows 34 | - Ex: Executive support routines 35 | - FsRtl: File system driver run-time library 36 | - Hvl: Hypervisor Library Io I/O manager 37 | - Kd: Kernel Debugger 38 | - Ke: Kernel 39 | - Lsa: Local Security Authority 40 | - Mm: Memory manager 41 | - Nt: NT system services (most of which are exported as Windows functions) Ob Object manager 42 | - Pf: Prefetcher 43 | - Po: Power manager 44 | - Pp: PnP manager 45 | - Ps: Process support 46 | - Rtl: Run-time library 47 | - Se: Security 48 | - Sm: Store Manager 49 | - Tm: Transaction Manager 50 | - Vf: Verifier 51 | - Wdi: Windows Diagnostic Infrastructure Whea Windows Hardware Error Architecture Wmi Windows Management Instrumentation 52 | - Zw: Mirror entry point for system services 53 | -------------------------------------------------------------------------------- /source/os/windows/wmi.rst: -------------------------------------------------------------------------------- 1 | WMI 2 | ======================================== 3 | 4 | 简介 5 | ---------------------------------------- 6 | Windows Management Instrumentation (WMI) 是 Web-Based Enterprise Management (WBEM)的一个实现,从 Windows NT 4.0 开始出现在所有的 Windows 操作系统中,用于提供操作界面和对象模式以便访问有关操作系统、设备、应用程序和服务的管理信息。 7 | 8 | WMI由4个部分组成,分别为:management applications, WMI infrastructure, providers, and managed objects。 9 | 10 | 工具 11 | ---------------------------------------- 12 | 13 | wmic 14 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 15 | wmic 是一个与 WMI 进行交互的命令行工具,拥有大量的 WMI 对象的方便记忆的默认别名。 16 | 17 | wbemtest 18 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 19 | wbemtest 是一个带有图形界面的 WMI 诊断工具。它能够枚举对象实例、执行查询、注册事件、修改 WMI 对象和类,并且可以在本地或远程去调用方法。 20 | 21 | winrm 22 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 23 | winrm 是 WS-Management 协议的 Microsoft 实现,该协议为使用 Web 服务的本地计算机和远程计算机之间的通信提供了一种安全的方式。 24 | 25 | wmic 26 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 27 | wmic 是一个简单的 Linux 命令行工具,用于执行 WMI 查询。 28 | -------------------------------------------------------------------------------- /source/reverse/antidebug.rst: -------------------------------------------------------------------------------- 1 | 反调试 2 | ======================================== 3 | 4 | 常用技巧 5 | ---------------------------------------- 6 | - 随机化进程名 7 | - 检测调试状态 8 | -------------------------------------------------------------------------------- /source/reverse/brief.rst: -------------------------------------------------------------------------------- 1 | 简介 2 | ======================================== 3 | 逆向工程可以分为黑盒分析和白盒分析。黑盒分析通过给目标程序输入数据,并观察程序运行行为以构建软件行为模式的分析方式。白箱分析则通过分析程序代码,理解程序行为。 4 | -------------------------------------------------------------------------------- /source/reverse/dll.rst: -------------------------------------------------------------------------------- 1 | DLL 2 | ==================================== 3 | 4 | 简介 5 | ------------------------------------ 6 | dll是被映射到exe进程的地址空间中去,换句话说,它可以被认为寄生在exe之上,自己并不独立存在。 7 | 而对于需要独立执行的dll,Windows使用svchost.exe、dllhost.exe和rundll32.exe来执行这些dll。 8 | 9 | 10 | svchost.exe 11 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 12 | 13 | 官方的解释是 ``svchost.exe is a generic host process name for services that run from dynamic-link libraries.`` 14 | 15 | 16 | dllhost.exe 17 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 18 | 它的存在是为了容纳COM组件。 19 | 20 | rundll32.exe 21 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 22 | rundll是Windows系统自带的一个直接执行DLL中导出函数的小工具 23 | 24 | ref 25 | --------------------------------- 26 | 27 | https://zhuanlan.zhihu.com/p/30000572 -------------------------------------------------------------------------------- /source/reverse/index.rst: -------------------------------------------------------------------------------- 1 | 逆向工程 2 | ======================================== 3 | 4 | 5 | .. toctree:: 6 | :maxdepth: 2 7 | :caption: 目录: 8 | 9 | brief 10 | elf 11 | pe 12 | dll 13 | macho 14 | antidebug 15 | taint 16 | obfuscation 17 | -------------------------------------------------------------------------------- /source/reverse/macho.rst: -------------------------------------------------------------------------------- 1 | Mach-O 2 | ======================================== 3 | 4 | 参考链接 5 | ---------------------------------------- 6 | - `Overview of the Mach-O Executable Format `_ 7 | - `Mach Object Files `_ 8 | -------------------------------------------------------------------------------- /source/reverse/obfuscation.rst: -------------------------------------------------------------------------------- 1 | 代码混淆 2 | ======================================== 3 | 4 | 常用技术 5 | ---------------------------------------- 6 | - 基于AST做匿名化处理 7 | - 隐藏变量名、方法名、类名 8 | - 使用 NATIVE 代码 9 | - 编译时混淆 10 | - 字符串加密 11 | - 隐藏导入导出表 12 | - 控制流平坦化 13 | - 手工混淆 14 | - 插入垃圾指令 15 | - 虚拟化 16 | -------------------------------------------------------------------------------- /source/reverse/pe.rst: -------------------------------------------------------------------------------- 1 | PE 2 | ======================================== 3 | 4 | 简介 5 | ---------------------------------------- 6 | PE(全称Portable Executable)格式,是微软Win32环境可移植可执行文件(如exe、dll、vxd、sys、vdm等)的标准文件格式。 7 | 8 | Table 9 | ---------------------------------------- 10 | 每个PE文件在文件最开始的地方都有一个 import 和 export table。import table包含所有从dll中读取的函数,有一个.reloc 段来保存dll在内存中信息。 11 | 12 | 和linux不同,pe会优先加载同一个文件夹内的dll而不是去其他地方找。在开发者看来这省去了修改PATH的烦恼,避免了dll-hell,但是在攻击者看来这为一些绕过提供了方便。 13 | 14 | RVAs 15 | ---------------------------------------- 16 | PE-COFF的一个比较重要的概念是Relative Virtual Address(RVAs) 17 | RVAs是用来减少一些PE Loader需要做的工作的,简单的说,每个DLL都被加载到内存中的某个位置, 18 | 可以把RVA加到一个基址上去找想要的东西。 19 | 20 | Heaps 21 | ---------------------------------------- 22 | 在dll加载的时候,会调用一些初始函数,这些函数会用HeapCreate()来设置其自身的栈,然后用一个全局变量的指针来指向它。 23 | 24 | 大多数dll在内存中也有一个.data段来记录全局变量,因为有这么多的heap,堆溢出攻击会有点麻烦。 25 | 26 | 在linux中只会有一个栈溢出,但是在win中可能有几个栈同时溢出,这就增加了分析的难度 27 | 28 | 每个进程都有一个默认的堆,可以用GetDefaultHeap()来找到它,尽管这个heap并不一定是溢出的那一个。 29 | 30 | Thread 31 | ---------------------------------------- 32 | windows没有fork(),而是用CreateProcess,这个函数会起一个新的有自己内存空间的进程,子进程会继承父进程所有可继承的属性。 33 | 34 | DCOM 35 | ---------------------------------------- 36 | Distributed Common Object Model(DCOM)。windows有一个特点的是分发程序一般都是用binary,使得几乎所有程序都支持COM。 37 | 38 | COM可以用COM支持的任何一种语言完成,而且可以在其中进行无缝转换 39 | 要深入的了解DOM,需要了解IDL(Interface Description Language)文件。 40 | -------------------------------------------------------------------------------- /source/reverse/taint.rst: -------------------------------------------------------------------------------- 1 | 污点分析 2 | ======================================== 3 | 4 | 简介 5 | ---------------------------------------- 6 | 污点分析由 Dorothy E.Denning 在1976 年提出,这种方式将来自于输入流、文件、网络等外部数据以及由这些污点数据经过逻辑和算术运算而新生成的数据标记为污点数据。通过对污点数据进行跟踪分析,从而发现二进制程序中的问题。 7 | 8 | 污点分析根据分析流的不同可以分为基于数据流的污点分析与基于控制流的污点分析。 9 | 根据使用范围的不同可以分为用户级的污点分析与系统级的污点分析。 10 | -------------------------------------------------------------------------------- /source/stack/call.rst: -------------------------------------------------------------------------------- 1 | 调用机制 2 | ================================ 3 | 4 | 5 | 调用惯例 6 | -------------------------------- 7 | 8 | - cdecl 9 | - 函数调用方出栈 10 | - 传参从右至左入栈 11 | - 名称修饰使用下划线+函数名 12 | - stdcall 13 | - 函数本身出栈 14 | - 传参从右至左入栈 15 | - 名称修饰下划线+函数名+@+函数字节数 16 | - fastcall 17 | - 函数本身出栈 18 | - 传参头两个DWORD类型或者占更少字节的参数放入寄存器,其他的从右到左压栈 19 | - 名称修饰@+函数名+@+参数的字节数 20 | - pascal 21 | - 函数本身出栈 22 | - 传参从左至右入栈 23 | - 名称修饰复杂 24 | - naked call 25 | - 在特殊场合使用,不保护寄存器 26 | - thiscall 27 | - C++ 的特殊调用管理,称为thiscall,用于类成员函数的调用,特点随编译器不同而不同 28 | - VC的thiscall this指针存放于ecx,参数从右至左压栈 29 | - gcc的thiscall 和cdecl一样,只是将this看做函数的第一个参数 30 | -------------------------------------------------------------------------------- /source/stack/index.rst: -------------------------------------------------------------------------------- 1 | 栈相关漏洞 2 | ================================ 3 | 4 | 5 | .. toctree:: 6 | :maxdepth: 2 7 | :caption: 目录: 8 | 9 | call 10 | rop 11 | overflow 12 | -------------------------------------------------------------------------------- /source/stack/overflow.rst: -------------------------------------------------------------------------------- 1 | 栈溢出 2 | ========================== 3 | 4 | TODO 5 | -------------------------------------------------------------------------------- /source/stack/rop.rst: -------------------------------------------------------------------------------- 1 | ROP 2 | ================================= 3 | 4 | Return Orientated Programming 5 | 6 | 参考链接 7 | ------------------------------------- 8 | 9 | - `ROP `_ 10 | -------------------------------------------------------------------------------- /source/tools/compiler/clang.rst: -------------------------------------------------------------------------------- 1 | clang 2 | ======================================== 3 | -------------------------------------------------------------------------------- /source/tools/compiler/cmake.rst: -------------------------------------------------------------------------------- 1 | CMake 2 | ======================================== 3 | 4 | 运行 5 | ---------------------------------------- 6 | 运行CMake最基本的方法是通过CMake命令行程序。调用它的最简单方法是更改到build目录,并将生成器类型和源树位置的选项传递给CMake。例如: 7 | 8 | .. code-block:: shell 9 | 10 | mkdir build 11 | cd build 12 | cmake -G "Unix Makefiles" ../source 13 | 14 | 如果省略了-G选项,CMake将根据平台选择默认的生成器类型。 15 | 16 | 注意这里如果没有新建一个build目录也可以构建,这种方式被称为源内构建。这种方式下编译文件和源文件混在一起,增加了构建的困难,也难以创建干净的源,不推荐在任何情况下使用这种方式。 17 | 18 | 最小项目 19 | ---------------------------------------- 20 | 构建一个最小CMake项目的CMakeLists.txt文件如下: 21 | 22 | .. code-block:: cmake 23 | 24 | cmake_minimum_required(VERSION 3.2) 25 | project(App) 26 | add_executable(elf main.cpp) 27 | 28 | 注意CMake的命令名称也是不区分大小写的。 29 | 30 | 常用函数 31 | ---------------------------------------- 32 | 33 | cmake_minimum_required 34 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 35 | 函数原型为 ``cmake_minimum_required(VERSION major.minor[.patch[.tweak]])`` ,其中VERSION关键字必须始终出现,提供的版本详细信息必须有major.minor部分。 36 | 37 | project 38 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 39 | 每个CMake项目都应该包含一个project()命令,它应该在cmake_minimum_required()调用之后出现。 40 | 41 | 项目名称是必需的,只能是字母、数字、下划线(_)和连字符(-),通常只有字母和下划线在实践中使用。 42 | 43 | .. code-block:: cmake 44 | 45 | project( [LANGUAGES] [...]) 46 | project( 47 | [VERSION [.[.[.]]]] 48 | [LANGUAGES ...]) 49 | 50 | 其中LANGUAGES可以是 ``C`` / ``CXX`` / ``Fortran`` 等,在未给出参数时,默认为``C`` / ``CXX``。 51 | 52 | 构建目标 53 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 54 | .. code-block:: cmake 55 | 56 | add_executable(targetName [WIN32] [MACOSX_BUNDLE] 57 | [EXCLUDE_FROM_ALL] 58 | source1 [source2 ...] 59 | ) 60 | 61 | add_library(targetName [STATIC | SHARED | MODULE] 62 | [EXCLUDE_FROM_ALL] 63 | source1 [source2 ...] 64 | ) 65 | 66 | FLAGS 67 | ---------------------------------------- 68 | - ``CC`` 编译器 69 | - ``CXX`` C++ 编译器 70 | - ``LD`` 链接器 71 | - ``CFLAGS`` C 编译器的选项 72 | - ``CXXFLAGS`` C++ 编译器的选项 73 | - ``LDFLAGS`` 链接器的选项 74 | - ``LIBS`` 链接器要链接的库 75 | 76 | 参考链接 77 | ---------------------------------------- 78 | - `CMake Reference Documentation `_ 79 | - `Professional CMake `_ 80 | -------------------------------------------------------------------------------- /source/tools/compiler/index.rst: -------------------------------------------------------------------------------- 1 | 编译工具 2 | ======================================== 3 | 4 | .. toctree:: 5 | :maxdepth: 2 6 | :caption: 目录: 7 | 8 | gcc 9 | clang 10 | msvc 11 | cmake 12 | nasm 13 | -------------------------------------------------------------------------------- /source/tools/compiler/msvc.rst: -------------------------------------------------------------------------------- 1 | MSVC 2 | ======================================== 3 | Microsoft Visual C++是微软公司的C++开发工具,具有集成开发环境,可提供编辑C语言,C++以及C++/CLI等编程语言。 4 | 5 | MSVC的特点有:支持增量编译和增量链接;支持C++规范较快等。 6 | 7 | 参考链接 8 | ---------------------------------------- 9 | - `微软 MSVC 中文文档 `_ 10 | -------------------------------------------------------------------------------- /source/tools/compiler/nasm.rst: -------------------------------------------------------------------------------- 1 | nasm 2 | ======================================== 3 | 4 | 参考链接 5 | ---------------------------------------- 6 | - `NASM - The Netwide Assembler `_ 7 | -------------------------------------------------------------------------------- /source/tools/debuger/index.rst: -------------------------------------------------------------------------------- 1 | 调试器 2 | ======================================== 3 | 4 | .. toctree:: 5 | :maxdepth: 2 6 | :caption: 目录: 7 | 8 | gdb 9 | windbg 10 | trace 11 | misc 12 | -------------------------------------------------------------------------------- /source/tools/debuger/misc.rst: -------------------------------------------------------------------------------- 1 | 其他 2 | ======================================== 3 | 4 | 链接库 5 | ---------------------------------------- 6 | ldd 相关环境变量 7 | 8 | - ``LD_BIND_NOW`` 9 | - ``LD_DEBUG`` 10 | - ``LD_HWCAP_MASK`` 11 | - ``LD_LIBRARY_PATH`` 12 | - ``LD_TRACE_LOADED_OBJECTS`` 13 | - ``LD_WARN`` 14 | 15 | patchelf 16 | ---------------------------------------- 17 | - ``--add-needed `` 18 | - ``--allowed-rpath-prefixes `` 19 | - ``--force-rpath`` 20 | - ``--no-default-lib`` 21 | - ``--print-interpreter`` 22 | - ``--print-rpath`` 23 | - ``--print-soname`` 24 | - ``--remove-needed `` 25 | - ``--remove-rpath`` 26 | - ``--replace-needed `` 27 | - ``--set-interpreter `` 28 | - ``--set-rpath `` 29 | - ``--set-soname `` 30 | - ``--shrink-rpath`` 31 | -------------------------------------------------------------------------------- /source/tools/debuger/trace.rst: -------------------------------------------------------------------------------- 1 | trace工具 2 | ======================================== 3 | 4 | strace 5 | ---------------------------------------- 6 | 7 | ltrace 8 | ---------------------------------------- 9 | 10 | ptrace 11 | ---------------------------------------- 12 | 13 | dtrace 14 | ---------------------------------------- 15 | -------------------------------------------------------------------------------- /source/tools/debuger/windbg.rst: -------------------------------------------------------------------------------- 1 | Windbg 2 | ======================================== 3 | 4 | 命令行启动参数 5 | ---------------------------------------- 6 | - ``g`` 忽视第一个debug断点 7 | - ``p `` attach到pid为的程序 8 | 9 | 调试命令 10 | ---------------------------------------- 11 | - 单步调试 12 | - ``F11`` 单步,遇到函数跟进 (Step Into) 13 | - ``F10`` 单步,遇到函数跳过 (Step Over) 14 | - ``Shift + F11`` 跳出当前函数 (Step Out) 15 | - 执行到指定位置 16 | - ``g [地址|函数名]`` 执行到指定位置 17 | - ``gh [地址|函数名]`` 执行到指定位置,如遇到异常则中断 18 | - ``gn [地址|函数名]`` 执行到指定位置,如遇到异常则忽略 19 | - 断点 20 | - ``Ctrl+Break`` 中断当前运行 21 | - ``bl`` 列出已设置断点 22 | - ``be [断点ID]`` 激活断点 23 | - ``bd [断点ID]`` 禁用断点 24 | - ``bc [断点ID]`` 清除断点 25 | - ``bp [地址|函数名]`` 设置断点 26 | - 数据展示 27 | - ``d [地址]`` 显示内存数据 28 | - ``db [地址]`` 按字节显示内存数据 29 | - ``dd [地址]`` 按双字节显示内存数据 30 | - 数据编辑 31 | - ``e [地址] [数据]`` 修改任意内存地址的值 32 | - 栈的显示 33 | - ``k [x]`` 打印调用栈,x为需要回溯的栈帧数 34 | - ``kb [x]`` 打印调用栈,并额外显示3个传递给函数的参数 35 | - 模块显示 36 | - ``lm`` 列出已经读入的所有模块 37 | - ``lmvm [name]`` 查看模块的详细信息 38 | - ``x`` 查找符号的二进制地址 39 | - 反汇编功能 40 | - ``u`` 反汇编当前执行的后几条指令并显示 41 | - ``u [起始地址]`` 从指定的地址开始反汇编 42 | - ``u [起始地址] [终止地址]`` 反汇编指定区间的汇编代码 43 | - 重载 `.reload` 44 | - 帮助 `.help` 45 | - 清屏 `.cls` 46 | - 开启DML帮助 `.prefer_dml 1` 47 | - 设置符号地址 48 | - `.sympath ` 49 | - `.sympath+ srv**http://msdl.microsoft.com/download/symbols` 50 | - 进程信息 51 | - `.tlist` 52 | - `!process` 显示调试器当前运行进程信息 53 | - `!process 0` 显示进程列表 54 | - `!process ` 显示进程信息 55 | - `!peb
` 查看Process Enviroment Block 56 | - 线程信息 57 | - `~` 显示线程信息 58 | - `~ ` 切换 59 | - `!teb
` 查看TEB信息 60 | - `.ttime` 查看线程时间 61 | - 异常信息 62 | - `.exr` 63 | - `.exr -1` 约等于 `.lastevent` 64 | - `.bugcheck` 显示当前bug check的详细信息,用于调试crash 65 | - `!analyze` 分析最近的异常事件 66 | - 错误信息 67 | - `!error ` 获取错误码为eid的Win32错误信息 68 | - `!gle` get last error 69 | -------------------------------------------------------------------------------- /source/tools/document.rst: -------------------------------------------------------------------------------- 1 | 文档资料 2 | ======================================== 3 | 4 | 逆向工程 5 | ---------------------------------------- 6 | - `reverse engineering reference manual `_ 7 | - `x86-sok `_ 8 | 9 | 程序分析 10 | ---------------------------------------- 11 | - `Program Analysis Resources `_ 12 | 13 | 硬件 14 | ---------------------------------------- 15 | - `The Hackers Hardware Toolkit `_ 16 | - `Low Level PC/Server Attack & Defense `_ 17 | 18 | Windows 19 | ---------------------------------------- 20 | - `Windows SDK Data `_ Windows API listing in JSON format 21 | 22 | Linux 23 | ---------------------------------------- 24 | - `Linux insides `_ 25 | 26 | 漏洞利用 27 | ---------------------------------------- 28 | - `Awesome ARM Exploitation `_ 29 | 30 | 可信执行 31 | ---------------------------------------- 32 | - `TEE reversing `_ 33 | 34 | Fuzz 35 | ---------------------------------------- 36 | - `Awesome AFL `_ 37 | - `fuzzingbook `_ The Book "Generating Software Tests" 38 | 39 | 游戏安全 40 | ---------------------------------------- 41 | - `awesome game security `_ 42 | -------------------------------------------------------------------------------- /source/tools/index.rst: -------------------------------------------------------------------------------- 1 | 工具与资源 2 | ======================================== 3 | 4 | .. toctree:: 5 | :maxdepth: 2 6 | :caption: 目录: 7 | 8 | list/index 9 | booklist 10 | document 11 | reverse/index 12 | debuger/index 13 | compiler/index 14 | systool 15 | -------------------------------------------------------------------------------- /source/tools/list/android.rst: -------------------------------------------------------------------------------- 1 | Android 2 | ======================================== 3 | 4 | 分析工具 5 | ---------------------------------------- 6 | - `classyshark `_ Analyze any Android/Java based app or game 7 | - `jadx `_ Dex to Java decompiler 8 | - `jd-gui `_ Java Decompiler GUI 9 | - `dex2jar `_ Tools to work with android .dex and java .class files 10 | - `Apktool `_ tool for reverse engineering Android apk files 11 | - `JNI Helper `_ Find JNI function signatures in APK and apply to reverse tools 12 | 13 | 漏洞 14 | ---------------------------------------- 15 | - `qark `_ Tool to look for several security related Android application vulnerabilities 16 | 17 | 改机工具 18 | ---------------------------------------- 19 | - `Xposed `_ The native part of the Xposed framework 20 | - `Magisk `_ 21 | - `TaiChi `_ A framework to use Xposed module with or without Root/Unlock bootloader 22 | 23 | 流量分析 24 | ---------------------------------------- 25 | - `r0capture `_ 安卓应用层抓包通杀脚本 26 | 27 | 应用市场 28 | ---------------------------------------- 29 | - `AuroraStore `_ is an unofficial, FOSS client to Google's Play Store with an elegant design. Not only does Aurora Store download, update, and search for apps like the Play Store, it also empowers the user with new features. 30 | -------------------------------------------------------------------------------- /source/tools/list/compile.rst: -------------------------------------------------------------------------------- 1 | 编译 2 | ======================================== 3 | 4 | 编译工具 5 | ---------------------------------------- 6 | - `llvm `_ 7 | - `cmake `_ 8 | - `ninja `_ 9 | - `PeachPy `_ x86-64 assembler embedded in Python 10 | 11 | 交叉编译 12 | ---------------------------------------- 13 | - `buildroot `_ Buildroot, making embedded Linux easy 14 | - `musl cross `_ A small suite of scripts and patches for building musl libc cross compilers 15 | -------------------------------------------------------------------------------- /source/tools/list/demo.rst: -------------------------------------------------------------------------------- 1 | Demo 2 | ======================================== 3 | 4 | Hypervisor 5 | ---------------------------------------- 6 | - `Bitdefender Napoca Hypervisor `_ 7 | -------------------------------------------------------------------------------- /source/tools/list/exploit.rst: -------------------------------------------------------------------------------- 1 | 漏洞利用 2 | ======================================== 3 | 4 | 利用工具 5 | ---------------------------------------- 6 | - `pwntools `_ 7 | - `ROPgadget `_ 8 | 9 | AEG 10 | ---------------------------------------- 11 | - `rex `_ Shellphish's automated exploitation engine, originally created for the Cyber Grand Challenge 12 | - `Zeratool `_ About Automatic Exploit Generation (AEG) and remote flag capture for exploitable CTF problems 13 | - `HeapLayout `_ Source code for paper 'Automatic Heap Layout Manipulation for Exploitation' 14 | 15 | 利用技巧 16 | ---------------------------------------- 17 | - `CTF-pwn-tips `_ 18 | 19 | Anti-AV 20 | ---------------------------------------- 21 | - `GhostShell `_ 22 | - `DefenderCheck `_ Identifies the bytes that Microsoft Defender flags on 23 | - `BypassAV `_ This map lists the essential techniques to bypass anti-virus and EDR 24 | 25 | ShellCode 26 | ---------------------------------------- 27 | - `GhostShell `_ Malware indetectable, with AV bypass techniques, anti-disassembly, etc 28 | - `donut `_ Generates x86, x64, or AMD64+x86 position-independent shellcode that loads .NET Assemblies, PE files, and other Windows payloads from memory and runs them with parameters 29 | 30 | 特殊载荷生成 31 | ---------------------------------------- 32 | - `LNKUp `_ Generates malicious LNK file payloads for data exfiltration 33 | - `tricky lnk `_ Creates a .lnk file with unicode chars that reverse the file extension and adds a .txt to the end to make it appear as a textfile 34 | -------------------------------------------------------------------------------- /source/tools/list/firm.rst: -------------------------------------------------------------------------------- 1 | 嵌入式设备 2 | ======================================== 3 | 4 | IoT 5 | ---------------------------------------- 6 | - `awesome iot `_ 7 | - `IoTSecurity101 `_ 8 | - `awesome iot hacks `_ 9 | - `HomePWN `_ 10 | 11 | 仿真 12 | ---------------------------------------- 13 | - `firmadyne `_ Platform for emulation and dynamic analysis of Linux-based firmware 14 | - `FirmAE `_ Towards Large-Scale Emulation of IoT Firmware for Dynamic Analysis 15 | - `frankenstein `_ Broadcom and Cypress firmware emulation for fuzzing and further full-stack debugging 16 | 17 | 漏洞分析工具 18 | ---------------------------------------- 19 | - `FACT `_ The Firmware Analysis and Comparison Tool (FACT) 20 | - `firmwalker `_ Script for searching the extracted firmware file system for goodies 21 | - `Firmware Analysis Toolkit `_ 22 | - `fwanalyzer `_ 23 | - `Firmware Slap `_ Discovering vulnerabilities in firmware through concolic analysis and function clustering. 24 | 25 | BLE 26 | ---------------------------------------- 27 | - `btlejack `_ Bluetooth Low Energy Swiss-army knife 28 | 29 | UEFI 30 | ---------------------------------------- 31 | - `UEFITool `_ UEFI firmware image viewer and editor 32 | - `UEFI Firmware Parser `_ Parse BIOS/Intel ME/UEFI firmware related structures: Volumes, FileSystems, Files, etc 33 | - `UEFI RETool `_ A tool for UEFI firmware reverse engineering 34 | - `EFI DXE Emulator `_ EFI DXE Emulator and Interactive Debugger 35 | 36 | 固件分析 37 | ---------------------------------------- 38 | - `chipsec `_ Platform Security Assessment Framework 39 | - `flashrom `_ a utility for detecting, reading, writing, verifying and erasing flash chips 40 | -------------------------------------------------------------------------------- /source/tools/list/index.rst: -------------------------------------------------------------------------------- 1 | 工具列表 2 | ======================================== 3 | 4 | .. toctree:: 5 | :maxdepth: 2 6 | :caption: 目录: 7 | 8 | reverse 9 | dynamic 10 | compile 11 | exploit 12 | persistence 13 | firm 14 | virtual 15 | android 16 | fuzz 17 | sidechannel 18 | demo 19 | resources 20 | misc 21 | -------------------------------------------------------------------------------- /source/tools/list/misc.rst: -------------------------------------------------------------------------------- 1 | 其他 2 | ======================================== 3 | 4 | 静态工具 5 | ---------------------------------------- 6 | - `static GDB and GDBServer `_ 7 | - `statically compiled tools like Nmap and Socat `_ 8 | - `static binaries `_ 9 | - `Detect It Easy `_ 10 | 11 | 沙箱检测 12 | ---------------------------------------- 13 | - `wsb detect `_ enables you to detect if you are running in Windows Sandbox 14 | 15 | Malware Sample 16 | ---------------------------------------- 17 | - `malware samples `_ 18 | - `theZoo `_ 19 | - `MalwareSourceCode `_ Collection of malware source code for a variety of platforms in an array of different programming languages 20 | - `Al-Khaser `_ Public malware techniques used in the wild: Virtual Machine, Emulation, Debuggers, Sandbox detection 21 | 22 | 实验环境 23 | ---------------------------------------- 24 | - `ABD `_ Course materials for Advanced Binary Deobfuscation by NTT Secure Platform Laboratories 25 | 26 | 系统交互 27 | ---------------------------------------- 28 | - `PythonForWindows `_ is a base of code aimed to make interaction with Windows 29 | 30 | 环境 31 | ---------------------------------------- 32 | - `SystemExplorer `_ Windows System Explorer 33 | 34 | 套件 35 | ---------------------------------------- 36 | - `Sysinternals Suite `_ 37 | -------------------------------------------------------------------------------- /source/tools/list/persistence.rst: -------------------------------------------------------------------------------- 1 | 持久化 2 | ======================================== 3 | 4 | 运行环境信息收集 5 | ---------------------------------------- 6 | - `scanlimits `_ Tool to examine the behaviour of setuid binaries under constrained limits 7 | 8 | rootkit 9 | ---------------------------------------- 10 | - `KasperskyHook `_ Hook system calls on Windows by using Kaspersky's hypervisor 11 | - `MasterHide `_ 12 | 13 | 内核hook 14 | ---------------------------------------- 15 | - `EDRs `_ This repo contains information about EDRs that can be useful during red team exercise 16 | - `KDU `_ Kernel Driver Utility, 使用有漏洞的合法内核驱动完成操作 17 | 18 | 代码混淆 19 | ---------------------------------------- 20 | - `ConfuserEx `_ free protector for .NET applications 21 | - `Mangle `_ a tool that manipulates aspects of compiled executables (.exe or DLL) to avoid detection from EDRs 22 | 23 | 免杀 24 | ---------------------------------------- 25 | - `BypassAntiVirus `_ 远控免杀系列文章及配套工具 26 | - `DefenderCheck `_ Identifies the bytes that Microsoft Defender flags on. 27 | 28 | 无文件马 29 | ---------------------------------------- 30 | - `fireELF `_ Fileless Linux Malware Framework 31 | 32 | 后门 33 | ---------------------------------------- 34 | - `The Backdoor Factory `_ Patch PE, ELF, Mach-O binaries with shellcode 35 | 36 | 进程注入 37 | ---------------------------------------- 38 | - `Windows process injection methods `_ 39 | -------------------------------------------------------------------------------- /source/tools/list/red.rst: -------------------------------------------------------------------------------- 1 | 对抗 2 | ======================================== 3 | 4 | EDR 5 | ---------------------------------------- 6 | - `awesome edr bypass `_ 7 | -------------------------------------------------------------------------------- /source/tools/list/resources.rst: -------------------------------------------------------------------------------- 1 | 资源 2 | ======================================== 3 | 4 | 汇编 5 | ---------------------------------------- 6 | - `pcasm `_ PC Assembly Language book 7 | 8 | 论文集 9 | ---------------------------------------- 10 | - `paper collection `_ Academic papers related to fuzzing, binary analysis, and exploit dev 11 | - `Some Papers About Fuzzing `_ 12 | -------------------------------------------------------------------------------- /source/tools/list/sidechannel.rst: -------------------------------------------------------------------------------- 1 | 侧信道 2 | ======================================== 3 | 4 | Spectre / Meltdown 5 | ---------------------------------------- 6 | - `Meltdown Proof-of-Concept `_ This repository contains several applications, demonstrating the Meltdown bug 7 | - `Spectre & Meltdown Checker `_ 8 | -------------------------------------------------------------------------------- /source/tools/list/virtual.rst: -------------------------------------------------------------------------------- 1 | 虚拟化 2 | ======================================== 3 | 4 | 容器 5 | ---------------------------------------- 6 | - `runc `_ CLI tool for spawning and running containers according to the OCI specification 7 | - `sysbox `_ An open-source, next-generation "runc" that empowers rootless containers to run workloads such as Systemd, Docker, Kubernetes, just like VMs 8 | -------------------------------------------------------------------------------- /source/tools/reverse/ida.rst: -------------------------------------------------------------------------------- 1 | IDA 2 | ======================================== 3 | 4 | 快捷键 5 | ---------------------------------------- 6 | 7 | - ``;`` 添加注释 8 | - ``n`` 定义或修改名称 9 | - ``g`` 跳转到任意地方观察代码 10 | - ``Esc`` 回到跳转前位置 11 | 12 | -------------------------------------------------------------------------------- /source/tools/reverse/index.rst: -------------------------------------------------------------------------------- 1 | 逆向工具 2 | ======================================== 3 | 4 | .. toctree:: 5 | :maxdepth: 2 6 | :caption: 目录: 7 | 8 | ida 9 | objdump 10 | readelf 11 | -------------------------------------------------------------------------------- /source/tools/reverse/objdump.rst: -------------------------------------------------------------------------------- 1 | objdump 2 | ======================================== 3 | 4 | - ``-a`` 反汇编所有头信息 5 | - ``-d`` 反汇编所有包含指令的段 6 | - ``-D`` 反汇编所有段 7 | - ``-s`` 将所有段的内容以十六进制的格式打印 8 | - ``-S`` 将代码段反汇编的同时,将反汇编代码和源代码交替显示,该选项需要调试信息 9 | - ``-t`` 打印符号表 10 | - ``-C`` 将C++符号名逆向解析。 11 | - ``-l`` 反汇编代码中插入源代码的文件名和行号。 12 | - ``-j section`` 13 | - 仅反汇编指定的section 14 | - j可以有多个-j参数来选择多个section。 15 | -------------------------------------------------------------------------------- /source/tools/reverse/readelf.rst: -------------------------------------------------------------------------------- 1 | readelf 2 | ======================================== 3 | 4 | - ``-h`` 打印ELF的header 5 | - ``-S`` 打印ELF的Section 6 | - ``-s`` 打印ELF的符号表段 7 | -------------------------------------------------------------------------------- /source/tools/systool.rst: -------------------------------------------------------------------------------- 1 | 系统工具 2 | ======================================== 3 | 4 | ulimit 5 | ---------------------------------------- 6 | 7 | 参数 8 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 9 | - ``-a`` 列出所有当前资源极限 10 | - ``-c`` 设置core文件的最大值.单位:blocks 11 | - ``-d`` 设置一个进程的数据段的最大值.单位:kbytes 12 | - ``-f`` Shell 创建文件的文件大小的最大值,单位:blocks 13 | - ``-h`` 指定设置某个给定资源的硬极限。如果用户拥有 root 用户权限,可以增大硬极限。任何用户均可减少硬极限 14 | - ``-l`` 可以锁住的物理内存的最大值 15 | - ``-m`` 可以使用的常驻内存的最大值,单位:kbytes 16 | - ``-n`` 每个进程可以同时打开的最大文件数 17 | - ``-p`` 设置管道的最大值,单位为block,1block=512bytes 18 | - ``-s`` 指定堆栈的最大值:单位:kbytes 19 | - ``-S`` 指定为给定的资源设置软极限。软极限可增大到硬极限的值。如果 ``-H`` 和 ``-S`` 标志均未指定,极限适用于以上二者 20 | - ``-t`` 指定每个进程所使用的秒数,单位:seconds 21 | - ``-u`` 可以运行的最大并发进程数 22 | - ``-v`` Shell可使用的最大的虚拟内存,单位:kbytes 23 | 24 | 其中设置 ``unlimited`` 为取消内存限制 25 | -------------------------------------------------------------------------------- /source/virtual/cpu.rst: -------------------------------------------------------------------------------- 1 | CPU虚拟化 2 | ======================================== 3 | .. list-table:: CPU特性支持 4 | :header-rows: 1 5 | 6 | * - X86 64 Hypervisor 7 | - 是否开源 8 | - hypervisor 类型 9 | - 技术支持 10 | * - Xen 11 | - Y 12 | - Native 13 | - VT-x, AMD-V, EPT, RVI, VT-d, AMD-Vi 14 | * - KVM 15 | - Y 16 | - Hosted 17 | - VT-x, AMD-V, EPT, RVI, VT-d, AMD-Vi 18 | * - VMWare ESX 19 | - N 20 | - Native 21 | - VT-x, AMD-V, EPT, RVI, VT-d, AMD-Vi 22 | * - Hyper-V 23 | - N 24 | - Native 25 | - VT-x, AMD-V, EPT, RVI, VT-d, AMD-Vi 26 | * - VirtualBox 27 | - Y 28 | - Hosted 29 | - VT-x, AMD-V 30 | -------------------------------------------------------------------------------- /source/virtual/detect.rst: -------------------------------------------------------------------------------- 1 | 虚拟环境检测 2 | ======================================== 3 | 4 | 检测进程名 5 | ---------------------------------------- 6 | - Vmware 7 | - Vmtoolsd 8 | - Vmwaretrat 9 | - Vmwareuser 10 | - Vmacthlp 11 | - VirtualBox 12 | - vboxservice 13 | - vboxtray 14 | 15 | 检测注册表 16 | ---------------------------------------- 17 | - HKLM\SOFTWARE\Vmware Inc\Vmware Tools 18 | - HKEY_CLASSES_ROOT\Applications\VMwareHostOpen.exe 19 | - HKEY_LOCAL_MACHINE\SOFTWARE\Oracle\VirtualBox Guest Additions 20 | 21 | 硬盘文件检测 22 | ---------------------------------------- 23 | - VMware 24 | - C:\windows\System32\Drivers\Vmmouse.sys 25 | - C:\windows\System32\Drivers\vmtray.dll 26 | - C:\windows\System32\Drivers\VMToolsHook.dll 27 | - C:\windows\System32\Drivers\vmmousever.dll 28 | - C:\windows\System32\Drivers\vmhgfs.dll 29 | - C:\windows\System32\Drivers\vmGuestLib.dll 30 | - VirtualBox 31 | - C:\windows\System32\Drivers\VBoxMouse.sys 32 | - C:\windows\System32\Drivers\VBoxGuest.sys 33 | - C:\windows\System32\Drivers\VBoxSF.sys 34 | - C:\windows\System32\Drivers\VBoxVideo.sys 35 | - C:\windows\System32\vboxdisp.dll 36 | - C:\windows\System32\vboxhook.dll 37 | - C:\windows\System32\vboxoglerrorspu.dll 38 | - C:\windows\System32\vboxoglpassthroughspu.dll 39 | - C:\windows\System32\vboxservice.exe 40 | - C:\windows\System32\vboxtray.exe 41 | - C:\windows\System32\VBoxControl.exe 42 | 43 | 运行服务检测 44 | ---------------------------------------- 45 | - VMTools 46 | - Vmrawdsk 47 | - Vmusbmouse 48 | - Vmvss 49 | - Vmscsi 50 | - Vmxnet 51 | - vmx_svga 52 | - Vmware Tools 53 | 54 | mac地址前缀 55 | ---------------------------------------- 56 | - 00:05:69 (Vmware) 57 | - 00:0C:29 (Vmware) 58 | - 00:1C:14 (Vmware) 59 | - 00:50:56 (Vmware) 60 | - 08:00:27 (VirtualBox) 61 | 62 | 硬件 63 | ---------------------------------------- 64 | - CPU核心数 65 | - CPU温度 66 | - CPUID指令 67 | - MAC地址 68 | - 内存大小 69 | - 磁盘大小 70 | - 注册表和文件路径 71 | - 主板序列号 / 主机型号 72 | 73 | 文件系统 74 | ---------------------------------------- 75 | - TEMP目录下的文件数量 76 | - 最近打开的文件 77 | 78 | 指令 79 | ---------------------------------------- 80 | - 特权指令 81 | 82 | 参考资料 83 | ---------------------------------------- 84 | - `虚拟机检测技术剖析 `_ 85 | -------------------------------------------------------------------------------- /source/virtual/hypervisor.rst: -------------------------------------------------------------------------------- 1 | Hypervisor 2 | ======================================== 3 | 4 | 参考链接 5 | ---------------------------------------- 6 | - `Hypervisor From Scratch `_ 7 | -------------------------------------------------------------------------------- /source/virtual/index.rst: -------------------------------------------------------------------------------- 1 | 虚拟化 2 | ======================================== 3 | .. toctree:: 4 | :maxdepth: 2 5 | :caption: 目录: 6 | 7 | basic 8 | tech 9 | cpu 10 | mem 11 | hypervisor 12 | virtio 13 | libvirt 14 | vmware 15 | kvm/index 16 | xen 17 | qemu/index 18 | unicorn 19 | intel 20 | sec 21 | detect 22 | misc 23 | -------------------------------------------------------------------------------- /source/virtual/intel.rst: -------------------------------------------------------------------------------- 1 | Intel虚拟化技术 2 | ======================================== 3 | 4 | CPU虚拟化技术VT-X 5 | ---------------------------------------- 6 | Intel增加了虚拟机扩展指令集 VMX(Virtual Machine Extensions),该指令集包含了十条左右新增指令来支持与虚拟机向相关的操作,简称Intel VT-x技术。 7 | 8 | VT-x引入了根模式和非根模式两种操作模式,统称为VMX操作模式。 9 | 10 | 根模式是VMM所处的模式。所有指令都可运行,行为与正常IA32一样。兼容所有原有软件。 11 | 非根模式是客户机所处模式。所有敏感指令都会被重定义,使得他们不经虚拟化就直接运行或者通过陷入再模拟的方式处理。 12 | 13 | VT-x的VMCS能更好的支持虚拟化,VMCS保存在本地内存中的数据结构,包括 14 | 15 | - vCPU标识信息:标识vCPU属性 16 | - 虚拟寄存器信息:上下文环境保存 17 | - vCPU状态细信息 18 | - 额外寄存器/部件信息 19 | - 其他信息:优化字段等 20 | 21 | 每个VMCS对应一个vCPU,CPU每发生VM-Exit和VM-Entry时会自动查询和更新VMCS。VMM也可以通过指令来配置VMCS而影响vCPU。 22 | 23 | 扩展页表 24 | ---------------------------------------- 25 | EPT(Extended Page Table)扩展页表用于搭配VT-x使用。 26 | 27 | EPT页表存放在VMM内核空间,由VMM维护,当一个逻辑CPU处于非根模式下运行客户机代码时,使用的地址是客户机虚拟地址,而访问这个虚拟地址时,同样会发生地址的转换,这里的转换还没有设计到VMM层,和正常的系统一样,这里依然是采用CR3作为基址,利用客户机页表进行地址转换,只是到这里虽然已经转换成物理地址,但是由于是客户机物理地址,不等同于宿主机的物理地址,所以并不能直接访问,需要借助于第二次的转换,也就是EPT的转换。 28 | 29 | 不管是32位客户机还是64位客户机,统一按照64位物理地址来寻址。EPT页表是4级页表,页表的大小仍然是一个页即4KB,但是一个表项是8个字节,所以一张表只能容纳512个表项,需要9位来定位具体的表项。 30 | 31 | CPU虚拟化技术VT-d 32 | ---------------------------------------- 33 | Intel VT-d技术通过在北桥MCH引入DMA重映射硬件,以提供设备重映射和设备直接分配的功能。在启动VT-d的平台上,设备所有的DMA传输都会被DMA重映射硬件截获。根据设备对应的IO页表,硬件可以对DMA中的地址进行转换,使设备只能访问到规定的内存。 34 | 35 | SGX 36 | ---------------------------------------- 37 | 指令集扩展 (Software Guard Extensions, SGX)是Intel在2013年推出的技术,旨在以硬件安全为强制性保障,不依赖于固件和软件的安全状态,提供用户空间的可信执行环境。 38 | 39 | 参考链接 40 | ---------------------------------------- 41 | - `《SGX技术的分析和研究》阅读笔记 `_ 42 | -------------------------------------------------------------------------------- /source/virtual/kvm/basic.rst: -------------------------------------------------------------------------------- 1 | 简介 2 | ======================================== 3 | KVM (Kernel-Based Virtual Machine) 是基于内核的虚拟机,是Linux内核的一个可加载模块,通过调用Linux本身内核功能,实现对CPU的底层虚拟化和内存的虚拟化,使Linux内核成为虚拟化层。 4 | 5 | KVM必须依赖CPU提供的硬件虚拟化技术,以Intel、AMD为代表的硬件平台中很多虚拟化相关的硬件特性。 6 | 7 | 在普通的Linux系统中,进程一般有两种执行模式:内核模式和用户模式,在KVM环境中,增加了第三种模式:客户模式。KVM本身并不提供任何虚拟仿真功能,它仅仅是简单的提供的一个接口,接口位于 ``/dev/kvm`` ,用户空间通过 ioctl 使用此接口实现相关功能。 8 | 9 | - 用户模式(User Mode):主要处理I/O的模拟和管理,由QEMU实现。 10 | - 内核模式(Kernel Mode):主要处理特别需要高性能和安全相关的指令,如处理客户模式到内核模式的转换,处理客户模式下的I/O指令或其他特权指令引起的退出(VM-Exit),处理影子内存管理(shadow MMU)。 11 | - 客户模式(Guest Mode):主要执行guest OS中的大部分指令,I/O和一些特权指令除外。 12 | 13 | 历史 14 | ---------------------------------------- 15 | KVM虚拟机最初是由一个名为Qumranet的以色列创业公司作为他们的VDI产品的虚拟机开发的。 16 | 17 | KVM的开发人员并没有选择从底层开发Hypervisor,而是选择了基于Linux Kernel,通过加载新的模块从而使Linux Kernel本身变成一个Hypervisor。 18 | 19 | 2006年8月,在先后完成了基本功能、动态迁移以及主要的性能优化之后,Qumranet正式对外宣布了KVM的诞生并推向Linux内核社区。同年10月,KVM模块的源代码被正式接纳进入Linux Kernel,成为内核源代码的一部分。之后2007年2月发布的Linux 2.6.20是第一个带有KVM模块的Linux内核正式发布版本。 20 | 21 | 2008年,Qumranet被Red Hat收购。 22 | -------------------------------------------------------------------------------- /source/virtual/kvm/index.rst: -------------------------------------------------------------------------------- 1 | KVM 2 | ======================================== 3 | .. toctree:: 4 | :maxdepth: 2 5 | :caption: 目录: 6 | 7 | basic 8 | tool 9 | ref 10 | -------------------------------------------------------------------------------- /source/virtual/kvm/ref.rst: -------------------------------------------------------------------------------- 1 | 参考链接 2 | ======================================== 3 | - `Kernelgo KVM学习笔记 `_ 4 | -------------------------------------------------------------------------------- /source/virtual/kvm/tool.rst: -------------------------------------------------------------------------------- 1 | KVM工具集 2 | ======================================== 3 | -------------------------------------------------------------------------------- /source/virtual/libvirt.rst: -------------------------------------------------------------------------------- 1 | Libvirt 2 | ======================================== 3 | 4 | 简介 5 | ---------------------------------------- 6 | Libvirt是操作和管理虚拟机的一套工具,由实现管理接口的库文件、守护进程(libvirtd)、命令行工具(virsh)三个模块组成。Libvirt使用 C 语言开发,可以由不同语言调用。Libvirt以驱动的方式对VMM进行支持,对每种VMM提供一个Driver,VMM通过驱动和Libvirt进行通信。 7 | 8 | VMM支持 9 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 10 | Libvirt支持的VMM列表有很多,下面是其中的一部分: 11 | 12 | - Hyper-V 13 | - KVM 14 | - LXC 15 | - OpenVC 16 | - Parallels Workstation 17 | - PowerVM 18 | - QEMU 19 | - User-mode Linux (UML) 20 | - Virtualbox 21 | - VMware 22 | - Xen 23 | 24 | Libvirt API 25 | ---------------------------------------- 26 | Libvirt API可以分为虚拟机快照、虚拟机管理、事件、宿主机、网络接口、错误管理、其他设备管理等类型。虚拟机快照用于创建、删除和恢复快照。虚拟机管理提供创建、销毁、重启、迁移虚拟机等功能。事件是监控事件发生并处理的机制。宿主机API用于获取宿主机的信息,包括机器名、CPU状态等。网络接口提供对网络接口的操作。错误处理用于管理Libvirt运行时遇到的错误。其他设备提供对网络、PCI、USB、存储等设备的管理。 27 | -------------------------------------------------------------------------------- /source/virtual/mem.rst: -------------------------------------------------------------------------------- 1 | 内存虚拟化 2 | ======================================== 3 | 4 | 地址类型 5 | ---------------------------------------- 6 | - Guest虚拟地址 (Guest Virtual Address, GVA) 7 | - Guest物理地址 (Guest Physical Address, GPA) 8 | - Host虚拟地址 (Host Virtual Address, HVA) 9 | - Host物理地址 (Host Physical Address, HPA) 10 | 11 | EPT(Extended Page Table) 12 | ---------------------------------------- 13 | VT-x 提供了EPT技术,直接在硬件上支持了GVA->GPA->HPA的两次地址转换,降低了内存虚拟化的难度,提高了性能。 14 | -------------------------------------------------------------------------------- /source/virtual/misc.rst: -------------------------------------------------------------------------------- 1 | 其他 2 | ======================================== 3 | 4 | Wine 5 | ---------------------------------------- 6 | Wine (Wine Is Not an Emulator) 是一个能够在多种 POSIX-compliant 操作系统 (诸如 Linux,macOS 及 BSD 等) 上运行 Windows 应用的兼容层。Wine 不是像虚拟机或者模拟器一样模仿内部的 Windows 逻辑,而是將 Windows API 调用翻译成为动态的 POSIX 调用,免除了性能和其他一些行为的内存占用,让你能够干净地集合 Windows 应用到你的桌面。 7 | 8 | 参考链接 9 | ---------------------------------------- 10 | - `Wine `_ 11 | -------------------------------------------------------------------------------- /source/virtual/qemu/arch.rst: -------------------------------------------------------------------------------- 1 | 架构 2 | ---------------------------------------- 3 | QEMU 支持两种操作模式:用户模式仿真和系统模式仿真。用户模式仿真 允许一种架构的 CPU 构建的程序在另一种架构的 CPU 上执行,动态翻译/转换相应的指令/系统调用等。如果在相同架构的系统上进行用户模式仿真,可以实现近似本地的性能。 4 | 5 | 系统模式仿真允许对整个系统进行仿真,包括处理器和配套的外围设备。 6 | 7 | QEMU的优势在于其快速、可移植的动态翻译程序。动态翻译程序 允许在运行时将用于目标(Guest)CPU 的指令转换为用于主机 CPU,从而实现仿真。 8 | 9 | QEMU 实现动态翻译的方法是,首先将目标指令转换为微操作。这些微操作是一些编译成对象的 C 代码。然后构建核心翻译程序。它将目标指令映射到微操作以进行动态翻译。这不仅可产生高效率,而且还可以移植。 10 | 11 | QEMU 的动态翻译程序还缓存了翻译后的代码块,使翻译程序的内存开销最小化。当初次使用目标代码块时,翻译该块并将其存储为翻译后的代码块。QEMU 将最近使用的翻译后的代码块缓存在一个 16 MB 的块中。QEMU 甚至可以通过在缓存中将翻译后的代码块变为无效来支持代码的自我修改。 12 | -------------------------------------------------------------------------------- /source/virtual/qemu/basic.rst: -------------------------------------------------------------------------------- 1 | 背景 2 | ======================================== 3 | QEMU是一款开源的仿真执行工具,可以模拟运行多种CPU架构的程序或系统。当前支持的体系结构包括如ia32、x86-64、mips、 sparc、arm、risc-v等。同时QEMU也提供了大量对设备的仿真。 4 | 5 | 在执行时,QEMU会先以基本块(Basic Block)为单位,将目标指令经由TCG这一层翻译成宿主机的代码,得到TB(Translation Block),最终在主机上执行。 6 | 7 | 和虚拟化不同的是,仿真基本都是软件实现,宿主机和虚拟机可以是不同的架构。 8 | -------------------------------------------------------------------------------- /source/virtual/qemu/device.rst: -------------------------------------------------------------------------------- 1 | 外围设备 2 | ---------------------------------------- 3 | 将 QEMU 作为 PC 系统仿真器使用可提供各种外围设备。需要的标准外围设备包括硬件 Video Graphics Array (VGA) 仿真器、PS/2 鼠标和键盘、电子集成驱动器(Integrated Drive Electronics)硬盘和 CD-ROM 接口,以及软盘仿真。另外,QEMU 包括对 NE2000 Peripheral Controller Interconnect (PCI) 网络适配器、串行端口、大量的声卡和 PCI Universal Host Controller Interface (UHCI) Universal Serial Bus (USB) 控制器(带虚拟 USB 集线器)的仿真。Processor symmetric multiprocessing (SMP) 支持也得到了对 255 个 CPU 的支持。 4 | 5 | 除了仿真标准 PC 或 ISA PC(不带 PCI 总线)外,QEMU 还可以仿真其他非 PC 硬件,如 ARM Versatile 基线板(使用 926E)和 Malta million instructions per second (MIPS) 板。对于各种其他平台,包括 Power Macintosh G3 (Blue & White) 和 Sun-4u 平台,都能正常工作。 6 | -------------------------------------------------------------------------------- /source/virtual/qemu/event.rst: -------------------------------------------------------------------------------- 1 | 事件处理机制 2 | ======================================== 3 | 4 | 简介 5 | ---------------------------------------- 6 | QEMU是事件处理设计架构,所有的事件都在事件循环中被处理。实现基础就是Glib事件循环。Glib的核心是poll机制,通过poll检查用户注册的事件源,并执行对应的回调。 7 | 8 | 主事件循环 9 | ---------------------------------------- 10 | QEMU的主事件循环是 ``main_loop_wait()`` ,它执行以下任务: 11 | 12 | - 等待文件描述符变得可读或可写 13 | - 运行到期的计时器,计时器使用 ``qemu_mod_timer()`` 函数添加 14 | - 运行 bottom-halves 15 | 16 | 状态机 17 | ---------------------------------------- 18 | Glib对一个事件源的处理分为4个阶段:初始化、准备、poll和调度。每个阶段都提供了接口供用户注册处理函数,分别为prepare、query、check、dispatch,函数在事件后被调用。 19 | -------------------------------------------------------------------------------- /source/virtual/qemu/index.rst: -------------------------------------------------------------------------------- 1 | QEMU 2 | ======================================== 3 | .. toctree:: 4 | :maxdepth: 2 5 | :caption: 目录: 6 | 7 | basic 8 | arch 9 | event 10 | iothread 11 | device 12 | runtime 13 | qom 14 | qmp 15 | source 16 | sec 17 | misc 18 | opts 19 | ref 20 | -------------------------------------------------------------------------------- /source/virtual/qemu/iothread.rst: -------------------------------------------------------------------------------- 1 | iothread 2 | ======================================== 3 | 4 | 简介 5 | ---------------------------------------- 6 | 在早期的qemu版本,只存在一个主线程,同时负载客户虚拟机的指令执行和运行事件循两个任务。 7 | 8 | 线程执行客户机指令时,通过异常产生和信号量机制收走qemu线程控制权。接着通过执行非阻塞的 select 进行一次循环的迭代,之后就返回客户机指令的执行,并不停重复以上过程直到QEMU关闭。 9 | 10 | 这样的架构被称为non-iothread架构,这种架构存在着诸多问题,例如不能利用宿主机的多核能力、在运行SMP客户机的情况下会表现不佳、无法同时异步执行多个事件处理等。 11 | 12 | 之后QEMU在新版本中使用了新的架构,为每一个vCPU分配一个QEMU线程,以及一个专用的事件处理循环线程,这个模型被称为iothread。 13 | 14 | 在iothread架构中,各个vCPU线程可以并行的执行客户机指令,进而提供真正的SMP支持;iothread则负责运行事件处理循环。通过使用了一个全局的mutex互斥锁来维持线程同步。大多数时间里,vCPU在运行客户机指令,iothread则阻塞在select中。 15 | 16 | 这种方式使得IO处理能够完全脱离主线程,运行在多个不同的线程中,充分利用现代多核处理器的能力。 17 | -------------------------------------------------------------------------------- /source/virtual/qemu/misc.rst: -------------------------------------------------------------------------------- 1 | 其他 2 | ======================================== 3 | 4 | ioctl 5 | ---------------------------------------- 6 | 在QEMU-KVM中,用户空间的QEMU是通过 ioctl 与内核空间的KVM模块进行通讯的。 7 | 8 | TCG 9 | ---------------------------------------- 10 | TCG是Tiny Code Generator的简称,在QEMU中,它将虚拟出来的系统的指令转化成真正硬件支持的指令中的从中间代码到硬件支持的机器代码。 11 | -------------------------------------------------------------------------------- /source/virtual/qemu/opts.rst: -------------------------------------------------------------------------------- 1 | 常用选项 2 | ======================================== 3 | 4 | 用户模式 5 | ---------------------------------------- 6 | - ``-L`` 动态链接库前缀 7 | - ``-cpu model`` 设置CPU模型 8 | - ``-E var=value`` 设置环境变量 9 | - ``-g port`` gdb调试端口 10 | 11 | 系统模式 12 | ---------------------------------------- 13 | - ``-net`` 设置网络 14 | - ``-kernel`` 指定Kernel bzImage 15 | - ``-M`` 指定要仿真的开发板 16 | - ``-m`` 指定内存大小 17 | - ``-append cmdline`` 设置Linux内核命令行、启动参数 18 | - ``-initrd `` 使用 ``file`` 文件作为初始化ram disk 19 | - ``-nographic`` 非图形化启动,使用串口作为控制台 20 | -------------------------------------------------------------------------------- /source/virtual/qemu/qmp.rst: -------------------------------------------------------------------------------- 1 | QMP 2 | ======================================== 3 | 4 | 简介 5 | ---------------------------------------- 6 | QEMU对外提供了一个socket接口,称为qemu monitor,通过该接口,可以对虚拟机实例的整个生命周期进行管理,主要有如下功能 7 | 8 | - 状态查看、变更 9 | - 设备查看、变更 10 | - 性能查看、限制 11 | - 在线迁移 12 | - 数据备份 13 | - 访问内部操作系统 14 | -------------------------------------------------------------------------------- /source/virtual/qemu/qom.rst: -------------------------------------------------------------------------------- 1 | QOM 2 | ======================================== 3 | 4 | 简介 5 | ---------------------------------------- 6 | QOM (QEMU Object Module) 是用C语言实现的一种面向对象的编程模型,是设备模拟的基础,QEMU中所有的设备,包括CPU、内存、PCIe、外设都是基于QOM来实现的。 7 | -------------------------------------------------------------------------------- /source/virtual/qemu/ref.rst: -------------------------------------------------------------------------------- 1 | 参考链接 2 | ======================================== 3 | 4 | 官方材料 5 | ---------------------------------------- 6 | - `qemu `_ 7 | - `qemu wiki `_ 8 | - `qemu source code on github `_ 9 | - `QEMU Binaries for Windows and QEMU Documentation `_ 10 | - `QEMU Doc `_ 11 | - `QEMU, a Fast and Portable Dynamic Translator `_ 12 | - `QEMU’s documentation `_ 13 | 14 | wiki 15 | ---------------------------------------- 16 | - `QEMU internals by airbus `_ 17 | 18 | Blog 19 | ---------------------------------------- 20 | - `使用 QEMU 进行系统仿真 `_ 21 | - `QEMU(1) - QOM `_ 22 | - `QEMU Internals `_ 23 | - `QEMU Emulator User Documentation `_ 24 | 25 | 漏洞分析 26 | ---------------------------------------- 27 | - `QEMU 信息泄露漏洞 CVE-2015-5165 分析及利用 `_ 28 | - `qemu-pwn-cve-2019-6778堆溢出漏洞分析 `_ 29 | - `qemu-pwn-cve-2015-7504堆溢出漏洞分析 `_ 30 | - `VM escape - QEMU Case Study `_ 31 | - `Debugee in QEMU `_ 32 | 33 | 漏洞利用 34 | ---------------------------------------- 35 | - `qemu-vm-escape `_ exploit for CVE-2019-6778 36 | - `清道夫:误用“错误处理代码”导致的QEMU/KVM逃逸 `_ 37 | -------------------------------------------------------------------------------- /source/virtual/qemu/runtime.rst: -------------------------------------------------------------------------------- 1 | 启动流程 2 | ---------------------------------------- 3 | 4 | KVM交互 5 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 6 | - 获取到 KVM 句柄 7 | - 创建虚拟机,获取到虚拟机句柄 8 | - 为虚拟机映射内存,还有设备/信号处理的初始化 9 | - 创建 vCPU,并为 vCPU 分配内存空间 10 | - 创建 vCPU 个数的线程并运行虚拟机 11 | - 线程进入循环,并捕获虚拟机退出原因,做相应的处理 12 | 13 | TCG 模式 14 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 15 | - 启动 16 | - main 17 | - cpu_init 18 | - qemu_init_vcpu 19 | - qemu_tcg_init_vcpu 20 | - qemu_tcg_cpu_thread_fn 21 | - 主函数 22 | - cpu_exec 处理中断异常,找到代码翻译块,执行 23 | - tb_find 在Hash表中查找,如果找不到则调用tb_gen_code创建一个TB 24 | - tb_gen_code 分配一个新的TB 25 | - gen_intermediate_code 26 | - tcg_gen_code 将TCG代码转换成主机代码。 27 | - cpu_loop_exec_tb 28 | - cpu_tb_exec 执行TB主机代码 29 | - tcg_qemu_tb_exec 30 | 31 | 用户态 32 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 33 | 用户态的大部分代码都在 linux-user 目录下 34 | 35 | - linux-user/main.c main 36 | - linux-user/linuxload.c loader_exec 37 | - linux-user/elfload.c load_elf_binary 38 | - load_elf_image 39 | - load_elf_interp 40 | - linux-user//cpu_loop.c cpu_loop 41 | - accel/tcg/cpu-exec.c cpu_exec 42 | -------------------------------------------------------------------------------- /source/virtual/qemu/sec.rst: -------------------------------------------------------------------------------- 1 | 安全 2 | ======================================== 3 | 4 | 相关CVE 5 | ---------------------------------------- 6 | - CVE-2020-14364 7 | - CVE-2019-14378 8 | - CVE-2019-14835 9 | - CVE-2019-5049 10 | - CVE-2019-6778 tcp_emu 堆溢出 11 | - CVE-2015-7504 pcnet网卡堆溢出 12 | - CVE-2015-5165 信息泄露漏洞 13 | -------------------------------------------------------------------------------- /source/virtual/qemu/source.rst: -------------------------------------------------------------------------------- 1 | 源码结构 2 | ---------------------------------------- 3 | 主要文件 4 | 5 | - accel/tcg 6 | - cpu-exec.c 7 | - 寻找下一个二进制翻译代码块 8 | - 如果没有找到就请求得到下一个代码块,并且操作生成的代码块 9 | - translate-all.c 10 | - cpu_gen_code 函数,初始化真正代码生成 11 | - hw 12 | - 硬件目录 13 | - 主目录 14 | - vl.c 15 | - main 函数 16 | - main_loop 函数,条件判断 17 | - 最主要的模拟循环,虚拟机环境初始化,和 CPU 的执行 18 | - cpu-exec.c 19 | - cpu_exec 函数,主要的执行循环 20 | - 寻找下一个二进制翻译代码块 21 | - 如果没有找到就请求得到下一个代码块,并且操作生成的代码块 22 | - cpus.c 23 | - qemu_main_loop_start 函数,分时运行 CPU 核 24 | - exec-all.c 25 | - ``struct TranslationBlock`` 26 | - TB(二进制翻译代码块) 结构体 27 | - exec.c 28 | - target 29 | - 不同架构的对应目录 30 | - 将客户CPU架构的TBs转化成TCG中间代码 31 | - TCG前的前端 32 | - target//translate.c 33 | - 将 guest 代码翻译成不同架构的 TCG 操作码 34 | - target//cpu.h 35 | - CPU 状态结构体 36 | - tcg 37 | - tcg/tcg.c 38 | - 主要的 TCG 代码 39 | - tcg//tcg-target.c 40 | - 将 TCG 代码转化生成主机代码 41 | - TCG前的后端 42 | -------------------------------------------------------------------------------- /source/virtual/sec.rst: -------------------------------------------------------------------------------- 1 | 虚拟化安全 2 | ======================================== 3 | 4 | 安全问题 5 | ---------------------------------------- 6 | - 权限隔离 7 | - 资源隔离 8 | - 可用性 9 | - Spectre/Meltdown 10 | 11 | 攻击面 12 | ---------------------------------------- 13 | - hypervisor 14 | - 资源耗尽 15 | 16 | 安全机制 17 | ---------------------------------------- 18 | - Intel SGX 19 | 20 | 虚拟机漏洞 21 | ---------------------------------------- 22 | - 虚拟机逃逸 23 | - 拒绝服务攻击 24 | - 远程代码执行 25 | - 权限获取/提升 26 | - 敏感信息泄露 27 | -------------------------------------------------------------------------------- /source/virtual/tech.rst: -------------------------------------------------------------------------------- 1 | 虚拟化技术 2 | ======================================== 3 | 4 | 中断虚拟化 5 | ---------------------------------------- 6 | 中断从设备发送到CPU需要经过中断控制器,现代x86架构采用的中断控制器被称为APIC(Advanced Programmable Interrupt Controller)。APIC是伴随多核处理器产生的,所有的核共用一个I/O APIC,用于统一接收来自外部I/O设备的中断,而后根据软件的设定,格式化出一条包含该中断所有信息的Interrupt Message,发送给对应的CPU。 7 | -------------------------------------------------------------------------------- /source/virtual/unicorn.rst: -------------------------------------------------------------------------------- 1 | Unicorn 2 | ======================================== 3 | 4 | 背景 5 | ---------------------------------------- 6 | Unicorn基于QEMU,它提取了QEMU中与CPU模拟相关的核心代码,并在外层进行了包装,提供了多种语言的API接口。 7 | 8 | 参考链接 9 | ---------------------------------------- 10 | - `unicorn at github `_ 11 | - `unicorn `_ 12 | -------------------------------------------------------------------------------- /source/virtual/vmware.rst: -------------------------------------------------------------------------------- 1 | VMWare 2 | ======================================== 3 | 4 | 简介 5 | ---------------------------------------- 6 | VMWare是基于宿主模式的桌面虚拟软件,包括VMX驱动、ring0的VMM、ring3的用户态程序。 7 | 8 | VMware vSphere则是一个虚拟化方案,其核心是ESXi,ESXi独立安装在裸机上的操作系统(注意它不基于任何OS,它本身就是OS),通过它物理机的硬件资源被虚拟化为虚拟资源,之后再通过vCenter就能将安装了ESXi操作系统的物理机的资源进行整合,化为一个总的资源池,在这个资源池里面为各个部门划分不同大小的资源池方便其使用。 9 | 10 | 安全策略 11 | ---------------------------------------- 12 | 13 | vSphere 14 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 15 | ESXi通过以下功能提供附加VMKernel保护 16 | 17 | - 内存强化:将ESXi内核、用户模式应用程序及可执行组件(如驱动程序和库)位于无法预测的随机内存地址中。在将该功能与微处理器提供的不可执行的内存保护结合使用。 18 | - 内核模块完整性:数字签名确保由VMKernel加载的模块、驱动程序及应用程序的完整性和真实性。 19 | - 可信的平台模块:vSphere使用Intel可信的平台模块/受信任的执行技术(TPM/TXT),根据硬件信任根提供管理程序映像的远程证明。 20 | 21 | 虚拟机安全策略 22 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 23 | - 虚拟机常规保护 24 | - 包括安装防毒软件、配置客户机操作系统的日志记录级别等 25 | - 禁用虚拟机中不必要的功能 26 | - 移出不必要的硬件设别、禁用操作系统中未使用的服务、限制公开复制到剪贴板中的敏感数据、限制用户在虚拟机中运行命令、限制客户机操作系统写入主机内存等 27 | - 限制信息性消息从虚拟机流向VMX文件 28 | - 限制信息性消息从虚拟机流向VMX文件,从而避免填充数据存储和造成拒绝服务。 29 | -------------------------------------------------------------------------------- /source/virtual/xen.rst: -------------------------------------------------------------------------------- 1 | Xen 2 | ======================================== 3 | 4 | 历史 5 | ---------------------------------------- 6 | 20世纪90年代,伦敦剑桥大学的Ian Pratt和Keir Fraser在一个叫做Xenoserver的研究项目中,开发了Xen虚拟机。在这个时候还不具备对虚拟化技术的硬件支持,内核必须针对Xen做出特殊的修改才可以运行。 7 | 8 | 2002年Xen正式被开源。在先后推出了1.0和2.0版本之后,Xen开始被诸如Redhat、Novell和Sun的Linux发行版集成,作为其中的虚拟化解决方案。 9 | 10 | 2005年发布的Xen 3.0,开始正式支持Intel的VT技术和IA64架构,之后Xen虚拟机可以运行完全没有修改的操作系统。 11 | 12 | Xen Hypervisor 13 | ---------------------------------------- 14 | Xen Hypervisor是直接运行在硬件与所有操作系统之间的基本软件层。它负责为运行在硬件设备上的不同种类的虚拟机进行CPU调度和内存分配。Xen Hypervisor对虚拟机来说不单单是硬件的抽象接口,同时也控制虚拟机的执行,让他们之间共享通用的处理环境。 15 | 16 | Xen Hypervisor不负责处理诸如网络、外部存储设备、视频或其他通用的I/O处理。 17 | 18 | Xen Hypervisor的管理接口可通过Libxenctrl库调用,来实施管理功能。 19 | -------------------------------------------------------------------------------- /source/vulns/fmtstr.rst: -------------------------------------------------------------------------------- 1 | 格式化字符串 2 | ======================================== 3 | 4 | 概述 5 | ---------------------------------------- 6 | 类printf函数的最大的特点就是,在函数定义的时候无法知道函数实参的数目和类型。对于这种情况,可以使用省略号指定参数表。 7 | 8 | 带有省略号的函数定义中,参数表分为两部分,前半部分是确定个数、确定类型的参数,第二部分就是省略号,代表数目和类型都不确定的参数表,省略号参数表中参数的个数和参数的类型是事先的约定计算出来的,每个实参的地址(指针)是根据确定参数表中最后一个实参的地址算出来的。 9 | 10 | 这里涉及到函数调用时的栈操作。函数栈的栈底是高地址,栈顶是低地址。在函数调用时函数实参是从最后一个参数(最右边的参数)到第一个参数(最左边的参数)依次被压入栈顶方向。也就是说函数调用时,函数实参的地址是相连的,并且从左到右地址是依次增加的。 11 | 12 | 攻击原理 13 | ---------------------------------------- 14 | 因为类printf函数中省略号参数表中参数的个数和类型都是由类printf函数中的那个格式化字符串来决定的,所以攻击者可以利用编程者的疏忽或漏洞,巧妙构造格式化字符串,达到攻击目的。 15 | 16 | 举一个简单的例子,如果想输出一个字符串,可以使用 ``printf("%s", str)`` 或者 ``printf(str)`` 。而第二种写法是有漏洞的,如果攻击者输入 ``%d`` ``%x`` 等格式化字符,那么一个变量的参数值就从堆栈中取出。 17 | 18 | 常用字符 19 | ---------------------------------------- 20 | - ``%c`` 21 | - 输出字符,配上 ``%n`` 可用于向指定地址写数据 22 | - ``%d`` 23 | 输出十进制整数,配上 ``%n`` 可用于向指定地址写数据 24 | - ``%x`` 25 | - 输出16进制数据 26 | - ``%i$x`` 表示要泄漏偏移i处4字节长的16进制数据 27 | - ``%i$lx`` 表示要泄漏偏移i处8字节长的16进制数据,32bit和64bit环境下一样 28 | - ``%p`` 29 | - 输出16进制数据,与 ``%x`` 基本一样,只是附加了前缀0x,在32bit下输出4字节,在64bit下输出8字节,可通过输出字节的长度来判断目标环境是32bit还是64bit 30 | - ``%s`` 31 | - 输出的内容是字符串,即将偏移处指针指向的字符串输出,如 ``%i$s`` 表示输出偏移i处地址所指向的字符串,在32bit和64bit环境下一样,可用于读取GOT表等信息 32 | - ``%n`` 33 | - 将 ``%n`` 之前printf已经打印的字符个数赋值给偏移处指针所指向的地址位置 34 | - ``%100x%10$n`` 表示将0x64写入偏移10处保存的指针所指向的地址(4字节) 35 | - ``%$hn`` 表示写入的地址空间为2字节 36 | - ``%$hhn`` 表示写入的地址空间为1字节 37 | - ``%$lln`` 表示写入的地址空间为8字节,在32bit和64bit环境下一样 38 | - 有时,直接写4字节会导致程序崩溃或等候时间过长,可以通过 ``%$hn`` 或 ``%$hhn`` 来适时调整 39 | 40 | sinks 41 | ---------------------------------------- 42 | - printf 43 | - vprintf 44 | - cprintf 45 | - dprintf 46 | - fprintf 47 | - asprintf 48 | - snprintf 49 | - vdprintf 50 | - vfprintf 51 | - vsprintf 52 | - vasprintf 53 | - vsnprintf 54 | -------------------------------------------------------------------------------- /source/vulns/index.rst: -------------------------------------------------------------------------------- 1 | 其他漏洞 2 | ================================ 3 | 4 | 5 | .. toctree:: 6 | :maxdepth: 2 7 | :caption: 目录: 8 | 9 | fmtstr 10 | typeConfusion 11 | -------------------------------------------------------------------------------- /source/vulns/typeConfusion.rst: -------------------------------------------------------------------------------- 1 | Type Confusion 2 | ================================= 3 | 4 | 简介 5 | --------------------------------- 6 | 类型混淆的问题发生在程序使用一种类型分配或初始化诸如指针,对象或变量之类的资源,但在之后使用与原始类型不兼容的类型访问该资源的情况。 7 | 8 | 当程序使用不兼容类型访问资源时,可能会触发逻辑错误,因为资源没有预期的属性。在没有内存安全性的语言中,例如C和C++,类型混淆可能导致越界内存访问。 9 | 10 | 虽然在C中使用许多不同的嵌入对象类型解析数据时,这种漏洞经常与 ``union`` 相关联,但它可以存在于可以以多种方式解释相同变量或内存位置的任何应用程序中。 11 | 12 | 这个漏洞并不是C和C++独有的。PHP应用程序中的一些漏洞可以通过在期望标量时提供数组参数来触发,反之亦然。像Perl这样的语言,当变量被执行自动转换时,也可能包含这些问题。 13 | 14 | 示例 15 | --------------------------------- 16 | 17 | :: 18 | 19 | #define NAME_TYPE 1 20 | #define ID_TYPE 2 21 | 22 | struct MessageBuffer 23 | { 24 | int msgType; 25 | union { 26 | char *name; 27 | int nameID; 28 | }; 29 | }; 30 | 31 | 32 | int main (int argc, char **argv) { 33 | struct MessageBuffer buf; 34 | char *defaultMessage = "Hello World"; 35 | 36 | buf.msgType = NAME_TYPE; 37 | buf.name = defaultMessage; 38 | printf("Pointer of buf.name is %p\n", buf.name); 39 | /* This particular value for nameID is used to make the code architecture-independent. If coming from untrusted input, it could be any value. */ 40 | buf.nameID = (int)(defaultMessage + 1); 41 | printf("Pointer of buf.name is now %p\n", buf.name); 42 | if (buf.msgType == NAME_TYPE) { 43 | printf("Message: %s\n", buf.name); 44 | } 45 | else { 46 | printf("Message: Use ID %d\n", buf.nameID); 47 | } 48 | } 49 | --------------------------------------------------------------------------------