Slide 1

Slide 1 text

萬 ⽤ 劫 持 本 地 提 权 情報滲透 越 級 注 入 PS C:\> [System.Convert]::ToBase64String([Sy ext.Encoding]::UTF8.GetByte cmd.exe /c "dir" 414141414141414141 AAAAAAAAAAAAAAAAAAAAAA [email protected] 遠程後⾨ 網軍⾏動 Duplicate Paths Attack: Get Elevated Privilege from Forged Identities

Slide 2

Slide 2 text

$_whoami #Windows #Reversing #Pwn #Exploit • Master degree at CSIE, NTUST • Security Researcher - chrO.ot • Speaker - BlackHat, DEFCON, VXCON, HITCON • 30cm.tw • Hao's Arsenal • [email protected]

Slide 3

Slide 3 text

[email protected] 1. UAC Design > Privilege Duplicate > Double Trust Auth 2. Issues > Path Normalization 3. A Combo, inject unlimited agents $_cat ./agenda

Slide 4

Slide 4 text

[email protected] 〉〉〉UAC Design

Slide 5

Slide 5 text

[email protected] $_cat ./uac

Slide 6

Slide 6 text

[email protected] $_cat ./uac

Slide 7

Slide 7 text

[email protected] $_cat ./uac

Slide 8

Slide 8 text

[email protected] $_cat ./uac

Slide 9

Slide 9 text

[email protected] $_cat ./uac $ svchost.exe -k netsvcs -p -s Appinfo

Slide 10

Slide 10 text

說到創建Process事情, 對作業系統主要就是兩個問題: (⼀)程式碼要擺哪裡 (⼆)執⾏緒該怎麼執⾏

Slide 11

Slide 11 text

syscall Ring0 Ring3 Parent Process (A.) CreateProcess Child Process (B.) Child Proess Created, EXE File Mapped, Gained the Same Privilege and New Thread pointed to RtlUserThreadStart (C.) Kernel Create a new Thread: RtlUserThreadStart →LdrInitializeThunk →LdrpInitializeProcess (D.) Jump into AddressOfEntry

Slide 12

Slide 12 text

AppInfo!RAiLaunchAdminProcess syscall Ring0 Ring3 Parent Process (A.) RunAs, CreateProcessAsUser or CreateProcessWithToken UAC Service (B.) Send a task by RPC message to UAC service for creating a different privilege child process RPC Priv Auth (C.) verify new process is qualified or not Child Process Task Cancelled Y N (D.) Child process is created by CreateProcessAsUser with specific token by Parent Process

Slide 13

Slide 13 text

syscall Ring0 Ring3 Parent Process (A.) RunAs, CreateProcessAsUser or CreateProcessWithToken (B.) Send a task by RPC message to UAC service for creating a different privilege child process RPC (C.) verify new process is qualified or not Child Process Task Cancelled Y N (D.) Child process is created by CreateProcessAsUser with specific token by Parent Process AppInfo!RAiLaunchAdminProcess UAC Service Priv Auth UAC Protection Logic

Slide 14

Slide 14 text

Some points about UAC protection we're interested in: • How the UAC process verifies processes get higher privilege • Security issues • Bypassing Vectors syscall Ring0 Ring3 Parent Process (A.) RunAs, CreateProcessAsUser or CreateProcessWithToken UAC Service (B.) Send a task by RPC message to UAC service for creating a different privilege child process RPC Priv Auth (C.) verify new process is qualified or not Child Process Task Cancelled Y N (D.) Child process is created by CreateProcessAsUser with specific token by Parent Process AppInfo!RAiLaunchAdminProcess

Slide 15

Slide 15 text

[email protected] 只好⾃⼰動⼿逆向 QQ 當你以爲拜 Google ⼤神有解答, 但卻沒有。

Slide 16

Slide 16 text

if you can see me, remember it's discovered by reversing and not talked about on Internet. I have no idea it's correct or not :/

Slide 17

Slide 17 text

[email protected] $_exec RunAs

Slide 18

Slide 18 text

[email protected] void __fastcall RAiLaunchAdminProcess( struct _RPC_ASYNC_STATE *rpcStatus, RPC_BINDING_HANDLE rpcBindingHandle, wchar_t *exePath, wchar_t *fullCommand, int dwCreationFlags, LPVOID lpEnvironment, wchar_t *lpCurrentDirectory, unsigned __int16 *a8, struct _APPINFO_STARTUPINFO *lpStartupInfo, __int64 a10, int millSecond, struct _PROCESS_INFORMATION *lpProcessInformation, unsigned int *a13)

Slide 19

Slide 19 text

Slide 20

Slide 20 text

Slide 21

Slide 21 text

Slide 22

Slide 22 text

Slide 23

Slide 23 text

Slide 24

Slide 24 text

[email protected] $_./trustAuth_A

Slide 25

Slide 25 text

[email protected] void AipCheckSecurePFDirectory(_UNICODE_STRING *exePath, uint *trustedFlag, __int64 caseSenstive) { *trustedFlag |= 0x2000u; int pos = 0; do { // \??\C:\Program Files\Windows Defender, \??\C:\Program Files (x86)\Windows Defender // \??\C:\Program Files\Windows Journal, \??\C:\Program Files (x86)\Windows Journal // \??\C:\Program Files\Windows Media Player, \??\C:\Program Files (x86)\Windows Media Player // \??\C:\Program Files\Windows Multipoint Server if ( RtlPrefixUnicodeString(&(&g_IncludedPF)[2 * pos], exePath, caseSenstive = true) ) break; ++pos; } while ( pos < 8 ); if ( pos != 8 ) *trustedFlag_1 |= 0x4000u; // 0x4000, trusted windows system application } $_./trustAuth_A

Slide 26

Slide 26 text

[email protected] $_./trustAuth_A

Slide 27

Slide 27 text

[email protected] $_./trustAuth_A

Slide 28

Slide 28 text

[email protected] // \??\C:\Windows\System32\Sysprep\sysprep.exe // \??\C:\Windows\System32\inetsrv\InetMgr.exe int index = 0, pos = 0; while ( !RtlEqualUnicodeString( g_IncludedXmtExe[index ++], exeUni_FullPath, true) ); if (index < 2) { if ( AipMatchesOriginalFileName(exeUni_FullPath) ) { tmpTrustFlagToAdd |= (0x800000u | 0x200000u); trustedFlag = tmpTrustFlagToAdd; } else { tmpTrustFlagToAdd |= (0x400000u | 0x200000u); trustedFlag = tmpTrustFlagToAdd; } } else ... $_./trustAuth_A

Slide 29

Slide 29 text

[email protected] else { // \??\C:\Windows\SysWow64\ // \??\C:\Windows\System32\ for (pos = 0; pos < 2; pos++) if ( RtlPrefixUnicodeString(g_IncludedSysDir[pos], exeUni_FullPath, true) ) break; if (pos != 2) { tmpTrustFlagToAdd |= 0x200000u; trustedFlag = tmpTrustFlagToAdd; } } $_./trustAuth_A

Slide 30

Slide 30 text

[email protected] $_./trustAuth_B

Slide 31

Slide 31 text

[email protected] $_./trustAuth_B

Slide 32

Slide 32 text

[email protected] filemappingPtr = CreateFileMappingW(exeFileHandle, 0i64, 0x11000002, 0, ...); if ( filemappingPtr ) { exeRawData = MapViewOfFile(filemappingPtr, 4u, 0, 0, 0i64); if ( exeRawData ) if ( LdrResSearchResource(exeRawData, &buf, 3i64, 48i64 ..., 64) >= 0 ) { actCtx = CreateActCtxW(&Dst); if ( actCtx != -1i64 ) { if ( QueryActCtxSettingsW( 0, actCtx, 0i64, L"autoElevate", &pvBuffer, ...) ) // pvBuffer = (wchar_t*)L"true" // tryAutoElevFlag = ( 't' - 'T'(0x54) & 0xffdf ) == 0 --> case insentive tryAutoElevFlag = ((pvBuffer - 'T') & 0xFFDF) == 0; ... if ( tryAutoElevFlag ) goto markedAutoElev; $_./trustAuth_B

Slide 33

Slide 33 text

[email protected] tryToVerify: ... tryAutoElevFlag = false; filemappingPtr = CreateFileMappingW(exeFileHandle, 0i64, 0x11000002, 0, ...); if ( filemappingPtr ) { exeRawData = MapViewOfFile(filemappingPtr, 4u, 0, 0, 0i64); if ( exeRawData ) if ( LdrResSearchResource(exeRawData, &buf, 3i64, 48i64 ..., 64) >= 0 ) { actCtx = CreateActCtxW(&Dst); if ( actCtx != -1i64 ) { if ( QueryActCtxSettingsW( 0, actCtx, 0i64, L"autoElevate", &pvBuffer, ...) ) // pvBuffer = (wchar_t*)L"true" // tryAutoElevFlag = ( 't' - 'T'(0x54) & 0xffdf ) == 0 --> case insentive tryAutoElevFlag = ((pvBuffer - 'T') & 0xFFDF) == 0; ... if ( tryAutoElevFlag ) goto markedAutoElev; markedAutoElev: if ( _wcsicmp(L"mmc.exe", *mmc) ) { // autoElev request marked flag *trustFlag |= 0x1010000u; goto bye; } // ... chk for the arguments for mmc $_./trustAuth_B

Slide 34

Slide 34 text

[email protected] $_./trustAuth_B

Slide 35

Slide 35 text

Slide 36

Slide 36 text

Slide 37

Slide 37 text

Slide 38

Slide 38 text

Slide 39

Slide 39 text

[email protected] AiLaunchProcess: Create Suspended Consent Process by CreateProcessAsUserW

Slide 40

Slide 40 text

[email protected] AiLaunchProcess: Create Suspended Consent Process by CreateProcessAsUserW AipVerifyConsent: Verify consent not patched by ReadProcessMemory

Slide 41

Slide 41 text

[email protected] AiLaunchProcess: Create Suspended Consent Process by CreateProcessAsUserW AipVerifyConsent: Verify consent not patched by ReadProcessMemory

Slide 42

Slide 42 text

[email protected] Consent process gets awake, checks the "trustFlag", and decides to display alert UI or not.

Slide 43

Slide 43 text

[email protected] AiLaunchProcess: Create Suspended Consent Process by CreateProcessAsUserW AipVerifyConsent: Verify consent not patched by ReadProcessMemory

Slide 44

Slide 44 text

Slide 45

Slide 45 text

Slide 46

Slide 46 text

[email protected] High Priv Low Priv Priv Low to High Timeline

Slide 47

Slide 47 text

[email protected] NtOpenProcess RpcImpersonateClient High Priv Low Priv NtDuplicateToken(-2) RpcRevertToSelf RpcImpersonateClient ExeFileHandle = CreateFileW $p = ToDosName(GetLongPathNameW(pathInput)) TrustAuth_A($p) TrustAuth_B($p) RpcRevertToSelf AiLaunchConsentUI AiLaunchProcess(pathInput)

Slide 48

Slide 48 text

[email protected] NtOpenProcess RpcImpersonateClient High Priv Low Priv NtDuplicateToken(-2) RpcRevertToSelf RpcImpersonateClient ExeFileHandle = CreateFileW $p = ToDosName(GetLongPathNameW(pathInput)) TrustAuth_A($p) TrustAuth_B($p) RpcRevertToSelf AiLaunchConsentUI AiLaunchProcess(pathInput)

Slide 49

Slide 49 text

[email protected] NtOpenProcess RpcImpersonateClient High Priv Low Priv NtDuplicateToken(-2) RpcRevertToSelf RpcImpersonateClient ExeFileHandle = CreateFileW $p = ToDosName(GetLongPathNameW(pathInput)) TrustAuth_A($p) TrustAuth_B($p) RpcRevertToSelf AiLaunchConsentUI AiLaunchProcess(pathInput)

Slide 50

Slide 50 text

[email protected] NtOpenProcess RpcImpersonateClient High Priv Low Priv NtDuplicateToken(-2) RpcRevertToSelf RpcImpersonateClient ExeFileHandle = CreateFileW $p = ToDosName(GetLongPathNameW(pathInput)) TrustAuth_A($p) TrustAuth_B($p) RpcRevertToSelf AiLaunchConsentUI AiLaunchProcess(pathInput)

Slide 51

Slide 51 text

[email protected] 〉〉〉Issue

Slide 52

Slide 52 text

[email protected] NtOpenProcess RpcImpersonateClient High Priv Low Priv NtDuplicateToken(-2) RpcRevertToSelf RpcImpersonateClient ExeFileHandle = CreateFileW $p = ToDosName(GetLongPathNameW(pathInput)) TrustAuth_A($p) TrustAuth_B($p) RpcRevertToSelf AiLaunchConsentUI AiLaunchProcess(pathInput)

Slide 53

Slide 53 text

[email protected] > TenableSecurity: UAC Bypass by Mocking Trusted Directories by David Wells > Google Project Zero: The Definitive Guide on Win32 to NT Path Conversion by James Forshaw > MSDN Developer Blog: Path Normalization by Jeremy Kuhne Path Format Overview by Jeremy Kuhne /?path_Normaliz

Slide 54

Slide 54 text

[email protected] /?path_Format DOS Paths (2.0) C:\Test\Foo.txt A full volume name. If it doesn't start with all 3 characters it is considered to be partially qualified or relative to the current directory.

Slide 55

Slide 55 text

[email protected] /? UNC Paths \\Server\Share\Test\Foo.txt start with two separators. The first component is the host name (server), which is followed by the share name. path_Format

Slide 56

Slide 56 text

[email protected] /? DOS Device Paths \\.\C:\Test\Foo.txt path_Format \\?\C:\Test\Foo.txt \\.\UNC\Server\Share\Test\Foo.txt \\?\UNC\Server\Share\Test\Foo.txt

Slide 57

Slide 57 text

[email protected] • Identifying the Path and Legacy Devices • Applying the Current Directory • Canonicalizing Separators • Evaluating Relative Components • Trimming Characters • Skipping Normalization /?path_Normaliz Path Normalization by Jeremy Kuhne

Slide 58

Slide 58 text

[email protected] • Identifying the Path and Legacy Devices • Applying the Current Directory • Canonicalizing Separators • Evaluating Relative Components • Trimming Characters • Skipping Normalization /?path_Normaliz Path Normalization by Jeremy Kuhne If the path doesn't end in a separator, all trailing periods and \x20 will be removed. If the last segment is simply a single or double period it falls under the relative components rule above. This rule leads to the possibly surprising ability to create a directory with a trailing space. You simply need to add a trailing separator to do so.

Slide 59

Slide 59 text

[email protected] • Identifying the Path and Legacy Devices • Applying the Current Directory • Canonicalizing Separators • Evaluating Relative Components • Trimming Characters • Skipping Normalization /?path_Normaliz Path Normalization by Jeremy Kuhne An important exception- if you have a device path that begins with a question mark instead of a period. It must use the canonical backslash- if the path does not start with exactly \\?\ it will be normalized.

Slide 60

Slide 60 text

[email protected] NtOpenProcess RpcImpersonateClient High Priv Low Priv NtDuplicateToken(-2) RpcRevertToSelf RpcImpersonateClient ExeFileHandle = CreateFileW $p = ToDosName(GetLongPathNameW(pathInput)) TrustAuth_A($p) TrustAuth_B($p) RpcRevertToSelf AiLaunchConsentUI AiLaunchProcess(pathInput) /?Issue

Slide 61

Slide 61 text

[email protected] $p = RtlDosPathNameToRelativeNtPathName_U_WithStatus( GetLongPathNameW(pathInput) ) /?trustAuth_A

Slide 62

Slide 62 text

[email protected] RtlDosPathNameToRelativeNtPathName_U_WithStatus( GetLongPathNameW(L"C:\sea\food \seafood.exe") ) RtlDosPathNameToRelativeNtPathName_U_WithStatus( L"C:\sea\food\seafood.exe" ) $p = L"\??\C:\sea\food\seafood.exe" /?trustAuth_A AiLaunchProcess(L"C:\sea\food \seafood.exe")

Slide 63

Slide 63 text

[email protected] RtlDosPathNameToRelativeNtPathName_U_WithStatus( GetLongPathNameW(L"C:\Windows \System32\a.exe") ) RtlDosPathNameToRelativeNtPathName_U_WithStatus( L"C:\Windows\System32\a.exe" ) $p = L"\??\C:\Windows\System32\a.exe" /?trustAuth_A AiLaunchProcess(L"C:\Windows \System32\a.exe")

Slide 64

Slide 64 text

[email protected] RtlDosPathNameToRelativeNtPathName_U_WithStatus( GetLongPathNameW(L"C:\Windows \System32\a.exe") ) RtlDosPathNameToRelativeNtPathName_U_WithStatus( L"C:\Windows\System32\a.exe" ) $p = L"\??\C:\Windows\System32\a.exe" /?trustAuth_A AiLaunchProcess(L"C:\Windows \System32\a.exe") We have no privilege to write files inside C:\Windows\System32 due to Windows DACL But it's okay for us to create a dictionary "Windows\x20" via the \\?\ prefix to avid Path Normalization

Slide 65

Slide 65 text

[email protected] 〉〉〉Combo

Slide 66

Slide 66 text

[email protected] • TrustAuth_A - Path Normalization Issues → \\?\ prefix to bypass • TrustAuth_B - Whitelisted EXE Files with Trusted Signature - AutoElevated Marked EXE Files → DLL Side-Loading Tricks to hijack AutoElevated Marked EXE Files /?attack Vectors

Slide 67

Slide 67 text

[email protected] $_payload?

Slide 68

Slide 68 text

[email protected] $_Siofra github.com/Cybereason/siofra

Slide 69

Slide 69 text

Slide 70

Slide 70 text

Slide 71

Slide 71 text

$_ DEMO

Slide 72

Slide 72 text

[email protected] • TrustAuth_A used for verifying child process launched from a trustable dircctory • if trusted, TrustAuth_B check child process signed with legal signature or marked as AutoElevate • Consent.exe launched, and the UAC prompt pops up if child process isn't full trusted • TrustAuth_A/B is an extra design. The different paths between verification and Forking Process lead to EoP $_./Recap

Slide 73

Slide 73 text

萬 ⽤ 劫 持 本 地 提 权 情報滲透 越 級 注 入 PS C:\> [System.Convert]::ToBase64String([Sy ext.Encoding]::UTF8.GetByte cmd.exe /c "dir" 414141414141414141 AAAAAAAAAAAAAAAAAAAAAA [email protected] 遠程後⾨ 網軍⾏動 Thanks! Slide Github @aaaddress1 Facebook