soffensive blog

Practical Reverse Engineering Exercise Solutions: Page 78 / Exercise 2

Exercise 2 of the ARM chapter has a rather short disassembly compared to the first exercise. Again, we are tasked with the decompilation of the provided function mystery2.

The disassembly is as follows:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
01:             mystery2
02: 28 B1         CBZ      R0, loc_C672

03: 90 F8 63 00   LDRB.W   R0, [R0,#0x63]
04: 00 38         SUBS     R0, #0
05: 18 BF         IT NE
06: 01 20         MOVNE    R0, #1
07: 70 47         BX              LR

08:             loc_C672
09: 01 20         MOVS     R0, #1
10: 70 47         BX              LR
11:             ; End of function mystery2

First of all, we notice that the function has been compiled in Thumb mode, as there are several instructions having a width of 16 bits, which is not possible in ARM mode. Furthermore, the instructions CBZ and IT are specific to Thumb mode and not available in ARM mode.

Practical Reverse Engineering Exercise Solutions: Page 78 / Exercise 1

This is the first blog post to a series of ARM challenges from the book Practical Reverse Engineering. In addition to the official ARM manual, the following web page turned out to be very helpful when solving the exercises, as it describes the different ARM instructions in great detail.

https://www.heyrick.co.uk/armwiki/Main_Page

Without further ado, let us explore the first function. The extract below shows the ARM disassembly of a function named mystery1, which we are supposed to decompile into C code.

Practical Reverse Engineering Exercise Solutions: Page 35 / Exercise 11

Read the Virtual Memory chapter in Intel Software Developer Manual, Volume 3 and AMD64 Architecture Programmer’s Manual, Volume 2: System Programming. Perform a few virtual address to physical address translations yourself and verify the result with a kernel debugger. Explain how data execution prevention (DEP) works.

For this exercise, we first have to set up a remote kernel debugging session. (see https://codemetrix.net/windows-kernel-debugging-setup/https://securityblog.gr/3253/debug-user-mode-processes-using-a-kernel-debugger/ and http://securityblog.gr/3023/windows-kernel-debugging/ for excellent explanations)

Practical Reverse Engineering Exercise Solutions: Page 35 / Exercise 10

Our task:

If the current privilege level is encoded in CS, which is modifiable by user-mode code, why can’t user-mode code modify CS to change CPL?

For a change, this is now a more theoretical than hands-on challenge. In order to address the exercise appropriately, we have to make sure we understood it correctly.

CS (code segment) is the CPU segment register that contains the current ring level in bits 0 and 1. This encoded level is also commonly referred to as CPL (current privilege level).

Practical Reverse Engineering Exercise Solutions: Page 35 / Exercise 9

Our task:

Sample L. Explain what function sub_1000CEA0 does and then decompile it back to C.

Here we have the function’s disassembly:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
                push    ebp
                mov     ebp, esp
                push    edi
                mov     edi, [ebp+8]
                xor     eax, eax
                or      ecx, 0FFFFFFFFh
                repne scasb
                add     ecx, 1
                neg     ecx
                sub     edi, 1
                mov     al, [ebp+0Ch]
                std
                repne scasb
                add     edi, 1
                cmp     [edi], al
                jz      short loc_1000CEC7
                xor     eax, eax
                jmp     short loc_1000CEC9

loc_1000CEC7:                       
                mov     eax, edi

loc_1000CEC9:              
                cld
                pop     edi
                leave
                retn
  endp

Firstly, the function takes two arguments, at ebp+0x8 (arg1) and ebp+0x0C (arg2) respectively. It follows the stdcall convention that arguments are pushed from right to left on the stack and the callee cleaning up the stack.

Practical Reverse Engineering Exercise Solutions: Page 35 / Exercise 8

Our task as formulated in exercise 8:

Sample H. Decompile sub_11732 and explain the most likely programming construct used in the original code.

The function’s disassembly:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
sub_1172E:
push    esi
mov     esi, [esp+8]
dec     esi
jz      short loc_1175F
dec     esi
jz      short loc_11755
dec     esi
jz      short loc_1174B
sub     esi, 9
jnz     short loc_1176B
mov     esi, [eax+8]
shr     esi, 1
add     eax, 0Ch
jmp     short loc_11767
; ---------------------------------------------------------------------------

loc_1174B:                             
mov     esi, [eax+3Ch]
shr     esi, 1
add     eax, 5Eh
jmp     short loc_11767
; ---------------------------------------------------------------------------

loc_11755:                           
mov     esi, [eax+3Ch]
shr     esi, 1
add     eax, 44h
jmp     short loc_11767
; ---------------------------------------------------------------------------

loc_1175F:                             
mov     esi, [eax+3Ch]
shr     esi, 1
add     eax, 40h

loc_11767:                             
        
mov     [ecx], esi
mov     [edx], eax

loc_1176B:                             
pop     esi
retn    4

Obviously, the sought-after programming construct in this case is a switch...case statement.