Skip to content


Folders and files

Last commit message
Last commit date

Latest commit


Repository files navigation

DEFCON 2019 Quals LCARS000

Build Status

This challenge contains 3 flags.

LCARS is a micro kernel that could load and run multiple apps.


LCARS000: v0.2 LCARS022: v0.4 LCARS333: v0.5


Services are loaded from the filesystem during booting process. They are just static executable loaded at constant address. They can not be modified.


Launching other services and interacting with user. The first (only) service executed from kernel.



Parsing and loading packed binaries.


Handling all cryptography operations.

Supported opreations:


Supported keys:

  1. CRYPTO_KEY_ROOT # from './root.key'
  2. CRYPTO_KEY_PROVISION # hardcoded 'O' * 32
  3. CRYPTO_KEY_USER # set by user
  4. CRYPTO_KEY_SESSION # from '/dev/urandom'


Applets are loaded by loader.sys, they are packed into a special file format.

They could be signed by system or platform keys or unsigned.

They could be encrypted by root, provision, user or session keys.

Security Contexts

Tasks are running in different security contexts:

  1. CTX_KERNEL # unconfined
  2. CTX_SYSTEM_APP # signed by system key AND encrypted by root key
  3. CTX_PLATFORM_APP # signed by platform key AND encrypted by provision key
  4. CTX_UNTRUSTED_APP # unsigned OR encrypted by user key

Tasks can only run into lower privileges.

Kernel services

  1. ECHO
  4. WAIT
  5. POST
  6. OPEN
  7. EXEC
  8. RUNAS


Level1: Information Leak in shared memory

Tasks talk to the kernel through unix sockets, parameters are passed through shared memory. A task can access shared memory of any process, but only has write permission to its own shared memory.

Since the loader.sys has to communicate with crypto.sys in order to verify and decrypt apps, the encrypted app and its decryption parameters are present in the shmem of loader.sys, the decrypted app is present in the shmem of crypto.sys.

The hacker could write some shellcode to dump shared memory and find the flag1 in flag1.papp.

Level2: Logic issue in signature verificaion

Each executable pages are ENCRYPTED THEN SIGNED. In the verification process the loader does check if encryption mode and parameters are bound to the signed page.

The hacker should have some signed pages from the previous stage. He could modify the IV used in AES-CBC decryption to change the first 16 bytes of signed page. By mapping controlled data page after current stack, he can use ROP to open/read/write flag2.txt.

In this level, hacker gains code execution as PLATFORM_APP.

flag1.papp is required for this level. Hacker should have solved Level1 before Level2.

Level3: OOB read uninitialized memory

Loader records all loaded memory pages. It will unmap all pages on error. Uninitialized .BSS data will be accessed due to an off-by-one bug. This is not a very serious problem unless the hacker maps the page just after .BSS section.

Now the hacker gains the ability to unmap arbitrary pages. Notice that it does not give direct code execution primitive because after unmapping the hacker has no way to do mapping. Unmapping .text/.stack/.data will cause segfault immediately.

The intended solution is to unmap the SHARED memory and replace it with PRIVATE memory. This will not affect control flow of current program, but breaks the IPC mechanism. By unmapping local shared memory, remote process will not see any update of the message content. By unmapping remote shared memory, local process will see arbitrary message response. Now the crypto verfication is totally comproised and hacker gains code execution as SYSTEM_APP.

Untrusted user can not talk to the loader directly. The hacker should have at least PLATFORM_APP privilege to talk to the loader to do unmapping and remapping. Hacker should have solved Level2 before Level3.

Level3+: Race condition in message forwarding

The kernel never gurantees that the consitency in message forwarding. There are race conditions if the message reciever does not match the intended one. This is partially mitigated by enforcing message reciever is alive and cleaning up message queue of any dead task.

However, the message will be forwarded if the task dies and its pid is quickly reused. The sender has no way to tell if the reciever is still valid.

One possible exploit is to send request to the crypto without recieving the response while keeping crypto engine busy. A new loader with same pid will see the crypto engine in a broken state.

The exploit leverages bugs in message processing so PLATFORM_APP privilege is required.

Backdoor1: fd leak

In v0.2, the kernel process close fds upto 1024, but the default limit of files is more than 1024. Untrusted apps can spray the fd by creating a lot of files. Then new tasks are able to hijack unix sockets between kernel and other task with higher privilege.

Fixed in v0.3

Backdoor2: uninitalized top

top is used for allocating from shared memory, is located at the beginning of data segment. It is always initialized for services, but not for apps, since the data segments are not signed and completely controlled by user.

The only signed app available to users is flag1.papp. So this is not a severe bug and it is probably not exploitable.

Fixed in v0.4

Backdoor3: arbitrary mmap

The loader is supposed to be able to mmap to arbitrary address only if the address is not in use. I (and a few other hackers) just assumed mmap to exsiting pages with MMAP_FIXED will fail. This is WRONG.

A common exploit is to use mmap to replace current stack. This gives a few teams much easier solution to SYSTEM_APP privilege. However, it only affects versions used in Level1 and Level2, and its difficulty is between the intended solutions of these levels, so it's not so bad.

Fixed in v0.5