Google Project Zero

作者 1

本书的作者是 James Forshaw,也是著名的 Google Project Zero 成员之一。他负责维护很多开源的分析工具,同时自己也根据多年的经验总结出自己想要的工具。并在一些会议中分享,甚至是 open source。到目前,他已经是一位高级猎食者,从当初的破解游戏机,到揭秘操作系统中的复杂问题,具有十余年应用网络协议分析、利用经验。

会议描述
BlackHat国际公认的网络安全活动系列,提供最具技术性和相关性的信息安全研究
CanSecWest加拿大著名的国际信息安全会议,负责举办 Pwn2Own
Chaos Computer Conference由德国 CCC 组织,以其独特的社区文化、技术讨论和社会议题探讨而闻名

作者的经历非常 Nice! 有一个良好的家庭,无论做什么都鼓励孩子的家长。走入职场有 Richard Nea 这样不内耗的好 Leader(line manager) 同时发现了作者对 Security 领域有浓厚的兴趣并符合其性格。

在规划职业路径阶段认识了 Mike Jordon 在初创阶段进入到了 Context Information Security。与公司的创始团队学习,并培养其网络协议分析方面的技能,并开发了 Canape 等工具。这些不内耗的好 Leader,给了其充足的时间进行有前途的安全研究。


我之所以阅读这本书,是因为在我的生活中,几乎还未遇到和协议有关的事情(除了一些常见的场景,如 burp、nmap 这些基础的,或者一些涉及到流量分析的题目)。虽然我见过通过 Wireshark 来调试 API 的,但我认为这些远远不是 Wireshark 的全部功能。

在本书中虽然几乎都是用作者所开发的 Canape ,还包括了很多网络协议工具包,这些工具很多都是家喻户晓的,但成体系和系统性的学习,是我经历所缺少的部分。同时也希望提升自己在网络协议上面的见解,并扩充下眼界。


协议是一切的基础

基础 2

"对常见网络的构建和功能了解得越多,就越容易将这些知识应用于捕获、分析和利用新协议。" 这句话出在第一章的概述,小时候。我就对 IETF 非常崇拜,并不是因为他们的宣传,而是朴实无华的运行风格。

还记得第一次看到 IETF 的出版物,被 RFC 的简洁所震撼。这种朴实无华的风格,不仅简洁还充满了复古风味内容也相当丰富,记录了一个协议和提案标准的各类信息。以及协议提案的流程,该提案所经aaaa历过的所有环节依次公开。

一个标准的协议具有很多或很少的功能,但他们几乎或多或少符合下面六项特点中的一项:

功能描述
维护会话状态创建新的连接或终止连接
通过寻址识别节点数据需要传输到对应的节点,因此协议通过寻址来识别特定的节点或组
控制流量一次性通过网络传输的量是有限的。协议通过实施管理数据流,以提高吞吐减少延迟
保证传输数据的顺序将发送和接收到分散且混乱的数据重新排序,以保证数据的正确顺序
检测和纠正错误网络不是 100% 可靠的;数据可能会损坏。检测损坏并理想情况下纠正它非常重要
格式化和编码数据数据并不适合在网络中传输,例如将英语文本编码为二进制值;协议可以指定对数据进行编码甚至加密

我们都了解很多传输协议,这些协议是基础的。但很多时候,这些协议都是背后的一条条数据流,我们浏览网页,使用 APP 不需要思考这些是如何进行的,死记硬背不仅内耗自己,还花了很多时间,但在工作中几乎只有面试时才会用到。而基础章节中,作者总结出了自己的一套模型:

┌──────────────────────────────┐
│        Protocol model        │
│                              │
│  ┌────────────────────────┐  │
│  │     Content layer      │  │   I would like to get the file image.png
│  │     (File request)     │  │
│  └───────────▲────────────┘  │
│              │               │
│  ┌───────────▼────────────┐  │
│  │     Encoding layer     │  │   GET /image.png HTTP/1.1
│  │         (HTTP)         │  │
│  └───────────▲────────────┘  │
│              │               │
│  ┌───────────▼────────────┐  │
│  │    Transport layer     │  │   4500 0043 50d1 4000 8000 c0a8 0a6d
│  │        (TCP/IP)        │  │   d83a d544 40e0 0050 5dff a4e6 6ac2
│  └────────────────────────┘  │   ……
│                              │
└──────────────────────────────┘
协议模型描述
内容层 (文件请求)我想要一个 image.png 图片
编码层 (HTTP)GET /image.png HTTP/1.1
传输层 (TCP/IP)4500 0043 50d1 4000 8000 c0a8 0a6d
d83a d544 40e0 0050 5dff a4e6 6ac2 ……

作者的这套网络模型,几乎概述了传输所涵盖的三个特点,即内容、寻址、传输等三个功能的概念化,因此适用于总结或对一个陌生的协议时的理解步骤。毕竟协议是可以自定义的,例如通过 Matrix 就可以自定义一个通信协议。

这一章节非常有意思,可以看一下原文 第一章:My Model for Network Protocol Analysis,给出了很多贴近该模型的案例。作者是一个不内耗的人,不会解说一堆 RFC 文件和 Wikipedia 中的内容,仅列举其作用和描述,让读者感兴趣的地方可以深入了解,并得出自己的见解。


流量捕获

捕获 2

针对流量的捕获分为主动和被动捕获,他们分别在不同的场景有不同的用处,对于主动捕获,甚至可以进行中间人攻击,如经常用到的 Burp Suite。

名称描述特点
被动捕获在线路上传输时提取数据,如 Wireshark不直接与流量交互
主动捕获干扰客户端应用程序与服务器之间的流量,类似 Burp 中通过代理进行拦截。直接与服务器之间的流量产生干扰甚至是拦截、篡改

除了 Wireshark 和 Burp,还有很多针对不同场景下会使用的工具,这里作者列举了几个我很感兴趣的场景,是不适用于被动捕获的:

  1. 在没有管理访问权限的系统或具有有限权限 shell 的移动设备上执行审计
  2. 只查看正在测试的应用程序的流量

作者演示了通过各种工具,从系统的工作原理来实现如何从本地应用程序提取网络流量的演示,这是我非常感兴趣的。其中有很多涉及到了操作系统原理和设计,想必这就是为什么要学操作系统设计和原理吧。

系统调用跟踪

许多现代系统提供了两种执行模式,分别为用户模式和内核模式。以提高系统的稳定性和安全性,保护系统免受不可信用户代码的影响。我体验过 Windows、Macos、Linux 这三个生态的系统,我的感受就是。

模式描述特点
用户模式操作系统普通应用程序和用户空间进程运行的模式权限限制
隔离
限制对系统资源的直接访问
日常应用程序的运行
内核模式操作系统核心代码,具有对系统资源的完全访问权限完全权限
关键操作
直接访问和控制系统资源
系统级调用

在 Windows 系统中,你是 Administrators;在 Linux 中,你是 Developers;而在 macOS 中,你只是一个普普通通的 User。这是我对这三个生态中系统执行模式的切身感受。

┌─────────────────────────────────────────────────┐                                 
│                                                 │                      ┌──────   ┐
│                                                 │                      │       S │
│   ┌────────────────────────┬────────────────┐   │                      │       e │
│   │                        │    Network     │   │                      │       r │
│   │         Kernel         │   subsystem    │◀──┼─────  Network  ──────┤       v │
│   │                        │                │   │                      │       i │
│   └────────────────────────┴─────────────▲──┘   │                      │       c │
│                                          │      │                      │       e │
│                                          │      │                      └──────   ┘
│                                                 │                                 
│                                          S      │                                 
│                                          y      │                                 
│                                          s      │                                 
│                                          t      │                                 
│                                          e      │                                 
│   ──────────   Kernel/User model    ──── m      │                                 
│                                                 │                                 
│                                          c      │                                 
│                                          a      │                                 
│                                          l      │                                 
│                                          l      │                                 
│                                                 │                                 
│                                          │      │                                 
│                                          │      │                                 
│   ┌──────────────────────────────────────┴──┐   │                                 
│   │                                         │   │                                 
│   │             System libraies             │   │                                 
│   │                                         │   │                                 
│   ├─────────────────────────────────────────┤   │                                 
│   │                                         │   │                                 
│   │                                         │   │                                 
│   │           Client application            │   │                                 
│   │                                         │   │                                 
│   │                                         │   │                                 
│   └─────────────────────────────────────────┘   │                                 
│                                                 │                                 
│                                                 │                                 
└─────────────────────────────────────────────────┘

当应用程序想要连接远程服务器时,应用程序会向操作系统内核发出系统调用以打开连接。之后应用程序读取和写入网络数据,因此我们可以通过监测这之间的过程,而实现对目标应用程序的网络捕获,作者给出了一个非常通俗易懂的图,简单的概括了这其中的一系列过程,简洁明了。

网络编程的基础

大多时候,我们在学习各类 code 语言的时。或多或少都会接触网络编程,比如耳熟能详的 Socket。这就要说到 IP 协议的首个实现是在 Berkeley Software Distribution(BSD) 完成的。因此在网络通信领域中,就离不开 Berkeley Sockets,它作为网络编程的基础,提供了不同主机之间进行网络通信的标准接口。

它主要定义了一系列的系统调用,允许应用程序通过网络发送和接收数据。广为人知的就是 close()、connect()、socket()、listen()、send(), 这些 Berkeley_sockets 被纳入 POSIX 标准的一部分。

不同平台之间的捕获

平台应用描述
LinuxStrace跟踪系统调用和信号
macOSDTrace跟踪系统调用, 可用于许多类 Unix 系统
WindowsProcess MonitorWindows TEAM 提供的交互非常 Nice 的进程监视器

让我意外的是,Microsoft 的进程监视工具非常方便,它提供了应用程序在建立网络通信时的必要信息。同时还能捕获当前调用堆栈的状态,以确定在应用程序中建立网络连接的位置。对二进制文件进行逆向工程以制定网络协议时,这将变得很重要。

主动捕获

"主动捕获可能是分析和利用应用程序网络协议最有价值的技术",这一章节告诉我们,编写一个属于自己的网络代理有多么重要。这个程序要实现流量重定向到代理,同时以更加可观的形式输出 (虽然作者提供了自己写的代理库,但已经年久失修了)。

太阳底下没有新鲜事 3

太阳底下没有新鲜事

开篇作者直接抛出了一句谚语:“太阳底下没有新鲜事 (There is nothing new under the sun)” 并告诉读者这句谚语在协议结构方式方面非常适用。二进制和文本协议遵循常见的模式和结构,一旦理解,就可以很容易地应用于任何新协议。

一些进制的基础

我属于是那种从来没有体系过学习的,之前读书的时候还会自己算一下 16 进制,但现在也都忘记了。很庆幸的是作者给出了非常清晰易懂的描述,以及图文结合的方式讲解二进制协议的结构。

类型描述特点
二进制协议以二进制格式传输数据高效性
紧凑性
复杂性
依赖性
文本协议以人类可读的形式传输数据(如 ASCII 或 UTF-8)可读性
效率低
灵活性(容错性和可扩展性)

我们都知道二进制就是 0 和 1,处理单个位很难,因此在计算机中。通常以八位(Bit)为一组,8 bit 即一个字节(byte). 在网络和通信中,通常使用 octet 来确保每个单位确实是 8 位。

                                                                
                  Bit 7/MSB                                     
                                                                
                   ^                                            
                   |                                            
                 +---+---+---+---+---+---+---+---+              
  Bit format:    | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 1 |   = 0x41/65  
                 +---+---+---+---+---+---+---+---+              
                                               |                
                                               v                
                                                                
 Octet format: 0x41                      Bit 0/LSB

首先我们要做的就是,区分位编号方向。如果没有特殊说明,应该按照从左到右的方式来读取位编号。即最高有效位(MSB)在左侧,最低有效位(LSB)在右侧。这种方式是最常见的(常见于大多数计算机体系结构,如 x86 和 ARM)

数值数据

数值数据就是表示数字的数据值,是指适用不同的方式存储或描述一个数字。比如上图就将二进制,以十进制和十六进制的方式表达。0x41 是这个二进制数的十六进制表示方法;65 是这个二进制数的十进制表示方法。

这些基础的知识有很多,甚至有的人可以口算,而不需要用到转换器。但在大模型发展的今天,我们只需要 copy 就可以知道其中的信息甚至帮我们翻译成人类可读的形式。再加上 Wireshark 也会帮我们将一些人类不可读的进制转换成十六进制,也会将一些未使用加密的传输暴露在阳光之下。因此我认为全书重要的信息是,协议结构 与逆向。

前者可以知道这是什么协议魔改的,后者可以通过逆向工程知道其运转的逻辑,从而找出问题所在。也就是说,我们当看到一个 Wireshark 中看到一个流量请求中,要根据其 Type 来识别出该协议的具体 握手过程 来识别出加密套件。

之后,我们需要通过逆向工程不断的进行断点,以及指令的输出。观看程序的变化以及影响,结合 OWASP 常见漏洞进行分析,以发现程序的弱点与信息的变化。我想我会从 The IDA Pro Book 这本书中找到我想要的。