soffensive blog

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.

Small challenge from Gynvael Coldwin

Gynvael Coldwin posted a small challenge at the end of his last podcast on Windows Kernel Debugging with Artem Shishkin:

 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
Welcome back agent 1336.
No mail.
> mission --take
MISSION 012               goo.gl/qudiHJ             DIFFICULTY: ██░░░░░░░░ [2╱10]
┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅

Our agents managed to install a hardware keylogger in suspects computer. After
they retrieved it and dumped the recorded data, here is what showed up:

  58 f0 58 1b f0 1b 58 f0 58 44 f0 44 2d f0 2d 2d f0 2d 35 f0 35 41 f0 41 29
  f0 29 59 43 f0 43 f0 59 29 f0 29 23 f0 23 44 f0 44 31 f0 31 52 f0 52 2c f0
  2c 29 f0 29 1b f0 1b 4d f0 4d 24 f0 24 1c f0 1c 42 f0 42 29 f0 29 12 42 f0
  42 f0 12 24 f0 24 35 f0 35 32 f0 32 44 f0 44 1c f0 1c 2d f0 2d 23 f0 23 49
  f0 49

Could you help us decoded it to know what was typed?

Good luck!

---------------------------------------------------------------------------------

If you decode the answer, put it in the comments under this video! If you write
a blogpost / post your solution online, please add a link in the comments too!

P.S. I'll show/explain the solution on the stream in ~two weeks.

Our first guess was that the characters use some well-known encoding such as ASCII, but this turned out to be wrong assumption. In order to obtain some knowledge about the structure of the recorded data, we ran some statistical analysis of the different byte values:

Practical Reverse Engineering Exercise Solutions: Page 35 / Exercise 7

Exercise 7 on page 35:

Sample H. The function sub_10BB6 has a loop searching for something. First recover the function prototype and then infer the types based on the context. Hint: You should probably have a copy of the PE specification nearby.

Due to alignment issues, our routine is located at 10BB2 and has the following 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
sub_10BB2:

 mov     eax, [esp+4]   
 push    ebx    
 push    esi
 mov     esi, [eax+3Ch] 
 add     esi, eax   
 movzx   eax, word ptr [esi+14h]
 xor     ebx, ebx
 cmp     [esi+6], bx
 push    edi
 lea     edi, [eax+esi+18h]
 jbe     short loc_10BEB

loc_10BCE:                            
 push    [esp+0Ch+arg_4]
 push    edi
 call    ds:dword_169A4
 test    eax, eax
 pop     ecx
 pop     ecx
 jz      short loc_10BF3
 movzx   eax, word ptr [esi+6]
 add     edi, 28h
 inc     ebx
 cmp     ebx, eax
 jb      short loc_10BCE

loc_10BEB:                              
 xor     eax, eax

loc_10BED:                             
 pop     edi
 pop     esi
 pop     ebx
 retn    8

loc_10BF3:                             
                mov     eax, edi
                jmp     short loc_10BED

The PE file format and offsets have been described in detail here: http://www.sunshine2k.de/reversing/tuts/tut_pe.htm

Practical Reverse Engineering Exercise Solutions: Page 35 / Exercise 6

Exercise 6 on page 35 of the book Practical Reverse Engineering presents us with a malware samples.

These can be downloaded at the following page:

https://grsecurity.net/malware_research/

In this exercise, we are expected to have a look at the following routine sub_13842:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
.text:00013842 sub_13842      
.text:00013842                 mov     eax, [ecx+60h]
.text:00013845                 push    esi
.text:00013846                 mov     esi, [edx+8]
.text:00013849                 dec     byte ptr [ecx+23h]
.text:0001384C                 sub     eax, 24h
.text:0001384F                 mov     [ecx+60h], eax
.text:00013852                 mov     [eax+14h], edx
.text:00013855                 movzx   eax, byte ptr [eax]
.text:00013858                 push    ecx
.text:00013859                 push    edx
.text:0001385A                 call    dword ptr [esi+eax*4+38h]
.text:0001385E                 pop     esi
.text:0001385F                 retn

Firstly, we see that the function prototype takes two parameters, which are not saved on the stack but in the two registers ecx and edx. This can be deducted from the fact that these two registers are immediately referenced without prior initialization.