DisARMing the Samsung S6E boot loader

Jonathan Levin, http://NewAndroidBook.com, 06/11/16

A while ago someone asked me for help with pointers on disassembling the Samsung 6E bootloader. I told him I'd get back to him, but with all my attention drawn into MOX*I for the big upcoming release, I didn't have much time to. Recently, however, while working on disassembling iOS's iBoot 64, I realized the same tool can be used for pretty much any ARM64 - including Samsung's sboot. So here is a writeup which shows the approach to disassembling pretty much any AArch64 boot loader, but Samsung's in particular. I'll also release a slide set on this after my MOSec talk on bootloaders at the beginning of July.

This example uses my disarm tool, which started its life as a simple command line opcode resolver, and is slowly becoming a full fledged disassembler. Yes, I could have used Capstone or something else - but A) I'd be bound by some crazy three or four letter license I don't understand and B) That would be cheating. Every instruction that is supported by disarm is an instruction I have read the full ARM documentation about. Maybe that's why still relatively few are :-P

Prereqs

Booting AArch64, in a nutshell

There are surprisingly little reference on the web to ARM's 64-bit boot process, though ARM themselves have superior documentation in the infocenter website. The architecture is quite different from the 32-bit architecture, which I've also covered in the reversing Aboot article on this website and in the book.

The first difference is that the processor boots into the most privileged exception level - EL3. This is somewhat akin to Intel's Ring 0, though in some ways more accurately following the ring model*. Think of it this way:

As with the Intel model, every ring has the abilities of its lesser rings, meaning EL0 ⊆ EL1 ⊆ EL2 ⊆ EL3. And, likewise, some instructions are only allowed at some exception levels. Moving in between the exception levels is performed by .. well.. exceptions! When an exception occurs, it automatically gets trapped by an exception vector of the higher level, which performs it and then returns back to the (less-privileged) origin level by means of a specialized instruction, ERET.

The processor has distinct register sets for each exception levels, which are separate from the normal set (i.e. not part of X0..X29,LR,SP,PC). As a general rule, when in Exception Level x, you have full power over your own ELx registers, as those of ELx-1, but not those of ELx+1 (if any), which are entirely invisible to you. It is this level of physical separation that forms the basis for all of ARM's security architecture.

sboot

Looking at the file with disarm we see:

0x00000000      0x00000010      DCD 0x10        ; ^P 
0x00000004      0xe99c208a      DCD 0xe99c208a  ; <8A> <9C> 
0x00000008      0x00000000      DCD 0x0 ;  
0x0000000c      0x00000000      DCD 0x0 ;  
0x00000010      0x14000002      B 0x18 
        -------------------------------
0x00000014      0x14000000      B 0x14 
        -------------------------------
0x00000018      0x58000a80      LDR X0, #336            ; 0x168 
0x0000001c      0xb9400000      LDR W0, [X0, #0] 
0x00000020      0xd2b00001      MOVZ X1, 0x8000, LSL #16  ; X1 = 0x8000000
0x00000024      0x6a01001f      __2DO 0x6a01001f 
0x00000028      0x54000740      B.EQ 0x110 
0x0000002c      0x58000a20      LDR X0, #324            ; 0x170 
0x00000030      0xb9400000      LDR W0, [X0, #0] 
0x00000034      0x7200001f      TST W0, #1 
0x00000038      0x540006c0      B.EQ 0x110 
0x0000003c      0x580009e0      LDR X0, #316            ; 0x178 
0x00000040      0xb9400000      LDR W0, [X0, #0] 
0x00000044      0x12000400      AND @TODO 
0x00000048      0x71000c1f      CMP W0, #3 
0x0000004c      0x540000c0      B.EQ 0x64 
0x00000050      0x58000980      LDR X0, #304            ; 0x180 
0x00000054      0xb9400000      LDR W0, [X0, #0] 
0x00000058      0x7200001f      TST W0, #1 
0x0000005c      0x54000040      B.EQ 0x64 
0x00000060      0x1400002c      B 0x110 

I'm sure IDA has a way to display this in branching view, but the version of IDA64 I used was so #@%#@$% I couldn't even get it to just perform the simple disassembly disarm does.

* - Intel based OSes normally don't use Ring 1 and 2, leaving only Ring 0 for kernel and Ring 3 for user. There is no real concept of "Secure Monitor" in the classic architecture, though Hypervisors can use "Ring -1"