Xcode 7 Bitcode workflow and Security Evaluation

Source: Internet
Author: User

Xcode 7 Bitcode workflow and Security Evaluation

With the release of Xcode 7, Apple added a new feature Bitcode for Xcode [1 ]:

New features often mean new attack surfaces. This article first introduces Bitcode and Bitcode-related workflows. After familiarizing yourself with the Bitcode workflow, we will evaluate Bitcode-related attacks, finally, the test methods and current test results for each attack are introduced.
0x01 what is Bitcode
Simply put, Bitcode is a binary representation of a LLVM-IR on a disk. For more information about Bitcode, see [2]. Here we will use examples to give you a perceptual knowledge of Bitcode.
Write a simple C program to calculate the sum of two numbers. The Code is as follows:
Intadd (int a, int B)
{
Int c = a + B;
Return c;
}
Save the above program as add. c, and then compile the source program into Bitcode:
Clang-emit-llvm-c add. c-o add. bc
Execute the above command to generate add. bc. We use the binary editor to open the generated file and view the file content:

Because Bitcode is a binary representation of the LLVM-IR, for example, it is basically unreadable without understanding the encoding method. Here we convert Bitcode into text:
Llvm-dis add. bc-o add. ll
Open add. ll in a text editor and you can see that the LLVM-IR of the add function is as follows:
; ModuleID = 'add. bc'
Target datalayout = "e-m: o-i64: 64-f80: 128-n8: 16: 32: 64-S128"
Target triple = "x86_64-apple-macosx10.11.0"
; Function Attrs: nounwindsspuwtable
The following is the LLVM-IR for add ()
; You can note that many variables will be applied for this representation,
Interested parties can learn about Static Single Assignment (SSA)
Define i32 @ add (i32% a, i32 % B) #0 {
% 1 = alloca i32, align 4; the variable is 1-4 bytes, which is subsequently used to store parameter
% 2 = alloca i32, align 4; variable 2, 4 bytes space, which is subsequently used to store parameter B
% C = alloca i32, align 4; variable c, 4-byte space, subsequently used to store the Result c
Store i32 % a, i32 * % 1, align 4; save a to variable 1
Store i32 % B, i32 * % 2, align 4; save B to variable 2
% 3 = load i32, i32 * % 1, align 4; save number 1 to variable 3
% 4 = load i32, i32 * % 2, align 4; save Number 2 to variable 4
% 5 = addnsw i32 % 3, % 4; Save the sum of variable 3 and variable 4 to variable 5
Store i32 % 5, i32 * % c, align 4; save variable 5 to Result c
% 6 = load i32, i32 * % c, align 4; save Result c to variable 6
Ret i32 % 6; return variable 6
}
Comparing the source code with the added () function has been commented on the LLVM-IR said, we should have a perceptual knowledge of the LLVM-IR, below we take a look at the Bitcode workflow.
0x02 Workflow
Apple's workflow description:
When you archive for submission to the App Store, Xcode compiles your app into an intermediate representation. The App Store then compiles the bitcode down into the 64-or 32-bit executables as necessary.
The preceding workflow can be divided into two phases:
When uploading an application to the AppStore, Xcode uploads the corresponding Bitcode together.
AppStore recompiles Bitcode into executable programs for users to download.
The complete workflow related to Bitcode is divided into the following issues or sub-processes and described separately:
WhereistheBitcode?
Embedding Bitcode
Method for generating executable programs from Bitcode
WhereistheBitcode?
According to Apple's description, Bitcode is generated only in Archive, so a test project is created:

Run Archive and view the generated package structure:

After analysis, the Bitcode is not directly found in the above directory, and then check the generated MachO. Use MachOView to load the generated MachO. The result is as follows:

The final executable program contains segments and sections related to LLVM. Continue to view the corresponding Section information:

For example, Section _ bundle stores an xar document, extracts the xar document, and then uses the following command to unbind the document:
Undo:
Xar-x-f XXX. xar
After unzipping, you can see the Bitcode file.
Summary: The Bitcode corresponding to the program is packaged into an xar document by Xcode and embedded into the MachO file.

The following describes how to embed Bitcode in MachO.
Embedding Bitcode
Method 1
By comparing the Archive and non-Archive compilation parameters, we can find that by adding the compilation parameter-fembed-bitcode at the position shown in, Xcode can also embed Bitcode in MachO during normal Compilation:

Method 2
Method 1 is very convenient, but IDE does a lot of work, so it is not easy to understand the specific process. Next we compile the executable file by ourselves. The executable program generated from the source code is mainly divided into two processes: Compilation and linking. to control these two processes, the following describes the configuration of Makefile and the parameters used in these two processes.
When using Makefile to compile iOS programs, some general configurations are as follows for your reference:
SDK_iOS: =$ (shell xcodebuild-version-sdkiphoneos Path)
CC_iOS: =$ (shell xcrun -- sdkiphoneos -- find clang)
LD_iOS: = $ (CC_iOS)
SYS_ROOT =-isysroot $ (SDK_iOS)
SDK_SETTINGS_iOS = $ (SYS_ROOT)-I $ (SDK_iOS)/usr/include-I $ (SDK_iOS)/usr/local/include
MIN_VER_iOS =-miphoneos-version-min = 8.0
ARCH_iOS =-arch arm64
Take main. m as an example to describe the required parameters for compilation:
CC_FLAGS_COMMON =-fblocks-std = gnu99-fobjc-arc-g-fembed-bitcode
CC_FLAGS =-x objective-c $ (ARCH_iOS) $ (CC_FLAGS_COMMON)
COMPILE_iOS_OBJ = $ (CC_iOS) $ (MIN_VER_iOS) $ (SDK_SETTINGS_iOS) $ (CC_FLAGS)
 
$ (COMPILE_iOS_OBJ)-c main. m-o main. o
Link main. o, AppDelegate. o, and ViewController. oto the executable program parameters:
LDFLAGS = $ (SYS_ROOT )\
-Dead_strip \
-Fembed-bitcode \
-Fobjc-arc-fobjc-link-runtime
LINK_iOS_BIN = $ (LD_iOS) $ (ARCH_iOS) $ (MIN_VER_iOS) $ (LDFLAGS)
LDFLAGS_CUSTOM =-framework Foundation-framework UIKit
$ (LINK_iOS_BIN) $ (LDFLAGS_CUSTOM) AppDelegate. oViewController. omain. o-oXBCTest
You can use the make command to embed Bitcode into an executable program by slightly modifying the Makefile snippet.
Method 3
In this method, we will further break down the above steps. The specific process is as follows:
Source code --> Bitcode --> xar --> executable program
Source code --> Bitcode
In this process, we compile the source code of the iOS application into Bitcode. The following uses main. m as an example to describe the parameters used:
CC_FLAGS_COMMON_BC =$ (CC_FLAGS_COMMON)
COMPILE_iOS_32_BC = $ (CC_iOS)-PC3-x objective-c $ (CC_FLAGS_COMMON_BC)-triple thumbv7-apple-ios8.0.0-disable-llvm-optzns-target-abiapcs-gnu-mfloat-abi soft $ (SYS_ROOT)
COMPILE_iOS_64_BC = $ (CC_iOS)-PC3-x objective-c $ (CC_FLAGS_COMMON_BC)-triple arm64-apple-ios8.0.0-disable-llvm-optzns-target-abidarwinpcs $ (SYS_ROOT)
 
$ (COMPILE_iOS_64_BC)-emit-llvm-bcmain.m-o main. bc
After completing this process, we can get three Bitcode files:
Main. bc
AppDelegate. bc
ViewController. bc
Bitcode --> xar
In this step, we will package the three Bitcode files obtained above into an xar document. There is nothing special about packaging. It should be noted that it must be compatible with the xar generated by Xcode. The specific parameters are as follows:
Generation:
Xar -- toc-cksum none-c-f BC. xarmain. bcAppDelegate. bcViewController. bc
Xar --> executable program
To simplify the process, we will jump out of Makefile and use Xcode to clear the following compilation parameters:

Copy the generated BC. xar file to the root directory of the test project:

Edit the Other Linker Flags of the Project Settings and add:-Wl,-sectcreate ,__ LLVM ,__ bundle, $ (SRCROOT)/BC. xar, for example:

Compile the program and view the generated MachO file. You can see that Bitcode has been added to MachO.
As mentioned above, we have introduced the method of embedding Bitcode in MachO, which corresponds to the first process: "When uploading an application to AppStore, Xcode uploads the corresponding Bitcode together ", the second process is described below.
Method for generating executable programs from Bitcode
The second process is: "AppStore will recompile Bitcode into executable programs for users to download ". The second process is performed on Apple's Server. We cannot directly obtain the details, but it should all be based on the same tool chain. We can simulate this process.
Extract Bitcode from MachO
After the AppStore obtains the uploaded IPA, it first needs to extract the xar file containing Bitcode from the MachO file in the IPA. In Xcode's tool chain, segedit can be used to extract sections from MachO. The specific parameters for extracting xar are as follows:
Segedit./XBCTest-extract "_ LLVM" "_ bundle" Embedded-BC.xar
After the xar is extracted, unlock the xar:
Undo:
Xar-x-f Embedded-BC.xar
Obtain the following Bitcode files:

You can also use the llvm-dis tool to process the above file into a readable form to understand the content of each file.
Generate executable programs
After Bitcode is available, you need to compile Bitcode into an executable program. There are two steps: Compile Bitcode into an Object file and link the Object file to the executable program.

 

Compile Bitcode into an Object file
The Makefile snippets are as follows:
COMPILE_iOS_BC_2_OBJ = $ (CC_iOS) $ (MIN_VER_iOS) $ (SYS_ROOT) $ (ARCH_iOS)
 
$ (COMPILE_iOS_BC_2_OBJ)-c 1-o 1.o
$ (COMPILE_iOS_BC_2_OBJ)-c 2-o 2.o
$ (COMPILE_iOS_BC_2_OBJ)-c 3-o 3.o
$ (COMPILE_iOS_BC_2_OBJ)-c 4-o 4.o
Link an Object file to an executable program
The Makefile snippets are as follows:
LDFLAGS = $ (SYS_ROOT )\
-Dead_strip \
-Fobjc-arc-fobjc-link-runtime
LINK_iOS_BIN = $ (LD_iOS) $ (ARCH_iOS) $ (MIN_VER_iOS) $ (LDFLAGS)
LDFLAGS_CUSTOM =-framework Foundation-framework UIKit
$ (LINK_iOS_BIN) $ (LDFLAGS_CUSTOM) 1.o 2.o 3.o 4.o-oXBCTest
As shown above, we have re-generated the executable program XBCTest from Bitcode.
0x03 attack surface
Let's first review Bitcode's local workflow: Xcode uploads the MachO embedded with Bitcode to the AppStore. Through analysis, we can find that there are two problems:
The consistency between MachO and the embedded Bitcode. That is, whether the Bitcode of program B can be embedded into program.
Whether the AppStore trusts Xcode and does not check consistency issues, thus allowing MalformedMachO to be uploaded to the AppStore.
After analyzing the possible problems, we think that if the Bitcode process and function are defective, the two goals can be threatened: common users and apple.
Common User
Bitcode is transparent to common users, so users cannot be directly attacked through its vulnerabilities. However, consistency may pose A threat to common users. Imagine: If program A submitted for AppStore review embeds Bitcode containing malicious code, normal users may download programs containing malicious code from the AppStore.
For this attack method, we call it Bitcode Injection. The following describes the implementation method of this attack and our test results.
Apple
As a result, MalformedMachO can be uploaded to Apple's server. Compared with the previous one, Apple's server mainly requires two additional operations: Unlocking xar and compiling Bitcode. If these two processes have problems, the DoS can be generated on the Apple Server, and the DoS can cause arbitrary code execution on the Apple Server.
In addition, Bitcode was originally a kind of serialization form of LLVM-IR, and LLVM-IR is a kind of intermediate form, has not been directly exposed before, and is now fully open, and is a binary format, this is very prone to problems. The process of generating executable files from Bitcode consists of the following sub-processes:
Platform-independent IR-based code optimization.
The Platform of IR is related and legal.
Optimization and code generation related to the platform.
These are the internal processes of the compiler. For various reasons, the traditional tests on the compiler mainly focus on the front-end Parser and Lexer, now some intermediate or back-end processes with Bitcode are also exposed. If the above process has a problem, the worst result is that the compiler's instruction generation can be controlled.
The above is an analysis of the attack. Later, we will introduce the ideas for testing xar and Bitcode, as well as the problems found.
0x04 BitcodeInjection
The above section describes how to implement BitcodeInjection in the Bitcode workflow, but the method mentioned above is not concise enough. Here we will introduce a simpler method, the main idea is to use Xcode to the maximum extent. The specific implementation steps of this method are as follows:
Build a project XBCTest using Xcode:

Copy the project XBCTest to obtain the project XBCTest2:

Modify the source code of the XBCTest2 project and embed malicious code:

Archive Project XBCTest2:


Obtain MachO and use segedit to extract xar containing Bitcode from MachO:

1
2
Extract xar:
Segedit./XBCTest-extract "_ LLVM" "_ bundle" BC. xar
Modify the link tag of the Project XBCTest and embed the extracted xar: BC. xar into the MachO file of the Project XBCTest.
Disable the Bitcode feature of the project XBCTest, Archive and upload it to the AppStore:

During the test, we did not embed malicious code. Instead, we found two completely different applications on the internet, Embedded One Bitcode into another MachO, and submitted it to the AppStore.
When you submit an application to the AppStore, you can perform two checks: static analysis is performed by Xcode locally; after the application is submitted, the Apple Server checks the application. However, applications constructed using Bitcode Injection can perform the following two checks:


After a long review, our application was rejected because our application and description were inconsistent. In the description, our application should look like the following:

 


However, after Apple's reviewers install the program, it looks like this:

There are at least three problems:
The BitcodeInjection method we use is correct.
Apple's reviewers reviewed the program compiled from Bitcode.
Consistency depends on human flesh. If the embedded malicious code does not affect the UI, it is possible to bypass the review.
0x05 Test xar
Ideas
Perform a fuzzy test on xar. The data generation method is based on the standard xar document for variation.
Test Results
Currently, some null pointers are used to solve the reference issue in Fuzz.
0x06 Test clang
Ideas
Perform a fuzzy test on the Bitcode-to-Object function in clang, and generate test data by means of variation.
Test Results
Through Fuzz of clang, we found some problems related to heap damage.
0x07 Summary
The Xcode 7 bitcode feature has opened a huge attacking surface, Apple shoshould do something to narrow it, for example: checking the bitcode is identical to the relatedMachO file.
In the above section, we have introduced in detail the attack surface and the test ideas for each attack. We hope these will be helpful for you to study Bitcode-related attack surface and security.
 

 

 

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.