카테고리 없음

EKOPARTY Crypto 300, Reversing 500 Writeup

진모씨 2015. 10. 27. 02:32

I participated the EKOPARTY CTF 2015 as solo, with YingyeoMan team name. The problems were really fun, and not too hard.

For crypto300 and reversing 500, yes, too. However I couldn't find a writeup, so wrote myself.


These challenges are connected challenges, and the order didn't matter.

I was given a zip file below with a VirtualBox VM configuration file, a Virtual Disk File, and the plugin for Virtual Machine Disk Image Encryption.


Challenge download

crypto300.zip


When I tried to run the virtual machine, it paused, and I couldn't restart the VM since it did again.



It was discovered that it runs on VirtualBox 5.0 and needs VirtualBox plugins.

I could download the plugin from virtualbox site.Wow, what an amazing feature it is!


Cracking the password


For crypto 300, it was needed to crack the password for the disk, and there was a open-source cracking tool, written in PHP, on github.

https://github.com/sinfocol/vboxdie-cracker/


And I used john the ripper to supply the word list, with FIFO.


mkfifo [wordlist]

./VBOXDIECracker.php [vmx file] [wordlist] &

john --incremental --stdout > [wordlist]

[+] Reading data from: $PATH

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

[+] Checking hard disk encryption for: ekokernel.vdi

[+] Hard disk is encrypted

[+] KeyStore encoded string:

U0NORQABQUVTLVhUUzI1Ni1QTEFJTjY0AAAAAAAAAAAAAAAAAABQQktERjItU0hB

MjU2AAAAAAAAAAAAAAAAAAAAAAAAAEAAAADQGfbiwaX/t8kk9NyKE+xMoMnWxXat

9kGJ/fs4Tb014CAAAAB8MP8Ky043t/ojIVewVAGnEv6Z7CurRWfTlq2lN8VLh9AH

AAAmQiRq+EJktDOorkdHroSe6r09Y7RJ90cQjNGcO/yLHdAHAABAAAAAOOlkHkC1

41LUUVQqZl12PXdL84P1DYN1uG4J+WAdAgW1AvzElHE+ReQdOVI8njOt4CaOWhw1

C1dZBoWR95YxhQ==

[+] KeyStore contents:

Header                        454e4353 (SCNE)

Version                       1

Algorithm                     AES-XTS256-PLAIN64

KDF                           PBKDF2-SHA256

Key length                    64

Final hash                    d019f6e2c1a5ffb7c924f4dc8a13ec4ca0c9d6c576adf64189fdfb384dbd35e0

PBKDF2 2 Key length           32

PBKDF2 2 Salt                 7c30ff0acb4e37b7fa232157b05401a712fe99ec2bab4567d396ada537c54b87

PBKDF2 2 Iterations           2000

PBKDF2 1 Salt                 2642246af84264b433a8ae4747ae849eeabd3d63b449f747108cd19c3bfc8b1d

PBKDF2 1 Iterations           2000

EVP buffer length             64

PBKDF2 2 encrypted password   38e9641e40b5e352d451542a665d763d774bf383f50d8375b86e09f9601d0205

                             b502fcc494713e45e41d39523c9e33ade0268e5a1c350b5759068591f7963185

john --incremental --stdout > wordlist

Press 'q' or Ctrl-C to abort, almost any other key for status

[+] Cracking finished, measured time: 20.4176 seconds

[!] KeyStore password found: angel


The tool shows that the password is "angel".




Ok, it shows login prompt. wtf?

hmm.. but we have a snapshot feature!


I captured a snapshot to .sav file and opened it with hex editor.

And tried to find the "login as" string.

Umm.. when I typed the username, it showed a weird prompt.

And it d said that it has "EKOPARTY Kernel!"


After crafting the snapshot file (RAM Dump), it showed the "login as" string, with "root", "root" string.

root string was repeated twice.

Then I guessed that root/root is password.

correct!


In fact, I found the reversed base64 string in dump (which could be found by ls -> cat secret_file.txt in terminal).

I reversed it and decoded the base64 string, and found the caesar-ciphered flag string.




You can find the flag from other writeup.


Reversing 500: Finding backdoor account


For reversing 500, I was requested to find the backdoor account for the OS. So I managed to reverse-engineer some instructions in disk itself.


The "root" password was in memory, so I analyzed the memory dump and it is like SYSLINUX + mboot.c32

(I didn't know the platform before. I searched and searched...)


I searched about debugging OS in virtualbox, and found that the builtin debugger supports debugging in console.

There were VBoxGDB which supported GDB stub for VirtualBox but it didn't work for me.


Anyway there were writecore command which made coredump, but it was ELF64.

I could open it with IDA x64 but the decompiled result was somewhat not accurate (the program was like it's for 32bit).


First I found the strings which were displayed, and found that there are a structure before string, describing the length and some other metadata information. The string itself didn't have a Xref.

But fortunately I could find the Xrefs for the structures in IDA.

The function was a bit large itself so I firstly thought that the function is about registering some strings for the program.

But I was wrong.

It used the structure to print the string to console.


There were many string structures in the memory, near there.

First I gathered information about the usage of string (without output routine. I just guessed.)

And found that the string printed out "login as" was used by terminal function.

The Xref shows that the function was used by initializer function, which said about some "IL2CPU" messages, used in COSMOS OS (I googled the string).

It describes that the .NET IL can be compiled with the program.


So, it was compiled .NET IL, to x86.

I didn't investigated whether it was JIT-Compiled or not because it would be already compiled and executed in native x86 code.

I just carefully looked the hex-rays string.


Ok, the terminal routine was like:

func terminal {

while(!login) {

    login as:

    input username

    (print some messages that scares hacker)

    password:

    input password

    if username: "root" and password: "root" then goto terminal

    if username: "ROOT" and strcmp_by_xor(password_xored_with_stream, target) == equals then goto flag 

}

terminal:

while(1) {

    input command as line

    calculate FNV Hash for command

    by hash, it categorizes some cases and compare the command with some predefined commands like "cat secret_file.txt", "uname -a"

    cat secret_file.txt prints the crypto300 flag.

    (reboot command reboots the system)

}

flag:

    AWESOME GUI SCREEN!!!

}


Well, that was a simple routine but it uses push-pop to transfer values between variables, and it was somekind awful.

Yeah. Some JIT sucks for reversers.

For comparing password with target, it seemed like using random stream with same seed, with each trial.

So I tried AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA for password.The target string structure had 0x1F length, which is 31 in decimal. And my string was xored with unknown values, but it was fixed (Of course!).


Once I found the compare routine for two string, I tried to set a breakpoint with bp command.

It used int3 breakpoint, but it didn't worked (it caused 0x0D CPU Exception).

Then I tried hardware breakpoint but it didn't worked for reading/execution breakpoint.

(For writing it worked. I didn't know why)

So I justed replaced the instruction with 0xEB 0xFE, which is jmp instruction to itself.

And for disabling, I just replaced it with original instruction.

0xEB 0xFE is two byte so it can be putted with ew instruction.

ew [addr] 0xfeeb


So I dumped two string in length 31, and xored, and xored with 0x41.

Then it shows the correct password. I typed it.

The password is: th3_B4ckd00r_k3y_f0r_d4_m4ch1n3

and the username is ROOT.


Umm.. but I don't have the script.

Maybe I wrote the script in python shell.


btw, tada!