1 of 40

Flare-On 5 #12

A trip into bootkits and esoteric ISAs

dp_1, November 16th 2018

2 of 40

Who am I

Dario Petrillo, 19 y/o

Studying Computer Engineering @ Sapienza

Capturing flags with TheRomanXpl0it and mHACKeroni

Mainly a reverse engineer

@dario_petrillo

dp1

3 of 40

Flare what?

Annual reverse engineering competition held by Fireye

12 challenges in roughly increasing order of difficulty

Six weeks to solve them all

4 of 40

Flare what?

5 of 40

#12: Suspicious floppy disk

“Now for the final test of your focus and dedication. We found a floppy disk that was given to spies to transmit secret messages. The spies were also given the password, we don't have that information, but see if you can figure out the message anyway. You are saving lives.”

6 of 40

A first look

7 of 40

A first look

8 of 40

A first look

9 of 40

infohelp.exe

Trivially simple program:

> Write password into key.dat

> Print message from message.dat

10 of 40

infohelp.exe

Trivially simple program:

Basically does nothing!

> Write password into key.dat

> Print message from message.dat

11 of 40

Diving deeper

Something must be intercepting calls to disk

The boot sector is different from an original WinME floppy

12 of 40

Diving deeper

Something must be intercepting calls to disk

The boot sector is different from an original WinME floppy

Smells like a bootkit!

13 of 40

Bootkit behaviour

infohelp.exe

int 13h

Data on disk

14 of 40

Bootkit behaviour

infohelp.exe

int 13h

Data on disk

Bootkit

15 of 40

Bootsector analysis

16 of 40

Bootsector analysis

> Reserve RAM

17 of 40

Bootsector analysis

> Reserve RAM

> Copy payload

18 of 40

Bootsector analysis

> Reserve RAM

> Copy payload

> Install as int 13h handler

19 of 40

The interrupt handler

20 of 40

The interrupt handler

Disk write

> Save key�

21 of 40

The interrupt handler

Disk write

> Save key�

Disk read

> Hide from OS

> Check flag�

22 of 40

Password checker

Two small functions

Looks easy right?

23 of 40

Subleq

One Instruction Set Computer

Subtract A from B and jump to C if result is less than or equal to zero

It’s turing complete!

subleq A, B, C

24 of 40

Subleq

0

1

3

2

5

4

8

7

6

10

9

11

12

13

1

9

2

IP

25 of 40

Subleq

0

1

3

2

5

4

8

7

6

10

9

11

12

13

A

B

1

9

2

26 of 40

Subleq

0

1

3

2

5

4

8

7

6

10

9

11

12

13

A

B-A

1

9

2

27 of 40

Subleq

0

1

3

2

5

4

8

7

6

10

9

11

12

13

≤ 0

> 0

A

1

9

2

B-A

28 of 40

Subleq: higher level instructions

subleq A, A, 0

memory[A] = 0

subleq 0, 0, ADDR

jump to ADDR

subleq A, 0, 0

subleq 0, B, 0

subleq 0, 0, 0

memory[B] += memory[A]

subleq B, B, 0

subleq A, 0, 0

subleq 0, B, 0

subleq 0, 0, 0

memory[B] = memory[A]

29 of 40

RSSB

Reverse subtract and skip if borrow

Uses an accumulator register ACC

Subtract ACC from A and skip the next instruction if the result is negative

Turing complete, but even more limited

rssb A

30 of 40

RSSB

0

1

3

2

5

4

8

7

6

3

IP

ACC

A

31 of 40

RSSB

0

1

3

2

5

4

8

7

6

3

IP

A-ACC

A-ACC

32 of 40

RSSB

0

1

3

2

5

4

8

7

6

3

IP

A-ACC

A-ACC

< 0

≥ 0

33 of 40

Making it readable

After a lot of bad code...

34 of 40

Making it readable: subleq

Relatively small, ~600 instructions

Reduced to 70 (~8.5 times less) lines then manually reversed

35 of 40

Making it readable: subleq

Relatively small, ~600 instructions

Reduced to 70 (~8.5 times less) lines then manually reversed

It’s a RSSB vm

36 of 40

Making it readable: rssb

~9000 instructions reduced to 230 lines (~39 times less!)

Many instructions are still quite long, time for a bit of manual reversing:

5746 RSSB acc

5747 var_2908 = var_2894;

5761 RSSB acc

5762 var_2908 *= 2;

5805 var_2908 *= 2;

5848 var_2908 *= 2;

5891 var_2908 *= 2;

5934 var_2908 *= 2;

5977 var_2908 += var_2894;

var_2908 = var_2894 * 33

37 of 40

Making it readable: rssb’s xor

An XOR takes ~2000 instructions!

Inputs: A, B

result = 0

for(i = 0; i < 16; i++)

{

tmpA = 0, tmpB = 0

if(A < 0) tmpA = 1

if(B < 0) tmpB = 1

tmp = 0

if(tmpA + tmpB == 1) tmp = 1

A = A * 2

B = B * 2

result = result * 2 + tmp

}

result = A ^ B

38 of 40

Making it readable: flag checker

res = [64639, 62223, ...]

bool check(word *flag, word len)

{

hash = sum(flag.split('@')[0]) + len(flag) * 3072

for(int i = 0; i < 15; i++)

{

pair = (flag[2 * i + 1] - 32) * 128 + (flag[2 * i] - 32)

idx = i * 33

if((idx ^ pair) + hash == res[i]) total -= i

}

return total == -105

}

39 of 40

Making it readable: flag checker

Invert the algorithm (bruteforce the hash) and get the flag:

Av0cad0_Love_2018@flare-on.com

40 of 40

Thank you!

Questions?

Full subleq/rssb analysis code is available at https://github.com/dp1/flareon5-12