Code can not be changed(NtProtectVM ret. STATUS_SECTION_PROTECTION).
Code:
.data
pGdiGetSpoolMessage PVOID ?
RegionAddress PVOID 0
SynchLock BOOLEAN FALSE
RaiseLock BOOLEAN FALSE
.code
ThreadStartupRoutine proc UserParameter:PVOID
WaitLock:
cmp SynchLock,FALSE
je WaitLock
mov RaiseLock,FALSE
; Align 4, W.
push 0
push 0
push PAGE_SIZE
push RegionAddress
Call pGdiGetSpoolMessage
mov RaiseLock,TRUE
jmp WaitLock
ThreadStartupRoutine endp
%PERR macro
.if Eax != STATUS_INVALID_PAGE_PROTECTION
int 3
.endif
endm
%APIERR macro
.if !Eax
int 3
.endif
endm
$Gdi32 CHAR "Gdi32.dll",0
$Entry CHAR "GdiGetSpoolMessage",0
Entry proc
Local ClientId:CLIENT_ID
Local ThreadHandle:HANDLE
Local RegionSize:ULONG
Local OldProtect:ULONG
Local DllHandle:PVOID
invoke LoadLibrary, addr $Gdi32
%APIERR
invoke GetProcAddress, Eax, offset $Entry
%APIERR
mov pGdiGetSpoolMessage,eax
invoke RtlCreateUserThread, NtCurrentProcess, NULL, FALSE, 0, 0, 0, addr ThreadStartupRoutine, 0, addr ThreadHandle, addr ClientId
Synch:
mov RegionSize,PAGE_SIZE
mov RegionAddress,0
invoke ZwAllocateVirtualMemory, NtCurrentProcess, addr RegionAddress, 0, addr RegionSize, MEM_COMMIT, PAGE_READWRITE
mov SynchLock,TRUE
invoke ZwSuspendThread, ThreadHandle, NULL
invoke ZwFreeVirtualMemory, NtCurrentProcess, addr RegionAddress, addr RegionSize, MEM_RELEASE
test eax,eax
mov SynchLock,FALSE
jnz Raise
invoke ZwResumeThread, ThreadHandle, NULL
jmp Synch
Raise:
%PERR
; test for free.
invoke ZwFreeVirtualMemory, NtCurrentProcess, addr RegionAddress, addr RegionSize, MEM_RELEASE
%PERR
; test for change.
invoke ZwProtectVirtualMemory, NtCurrentProcess, addr RegionAddress, addr RegionSize, PAGE_NOACCESS, addr OldProtect
%PERR
; Unlock
invoke ZwResumeThread, ThreadHandle, NULL
@@:
cmp RaiseLock,FALSE
je @b
invoke ZwFreeVirtualMemory, NtCurrentProcess, addr RegionAddress, addr RegionSize, MEM_RELEASE
int 3
ret
Entry endp
Guard does not work for the region, which is described in TEB(StackBase & StackLimit).