PDA

View Full Version : The Old New Thing: Why you shouldn't allocate usermode memory from PsSetLoadImageNot


Piotr Bania Chronicles
September 29th, 2010, 05:18
I'm describing this little story here because back in the days i have
experienced this problem and i couldn't find a solution and reasonable
explanation online. I guess for some of my readers this is quite obvious
however maybe it will help some less experienced people.


The PsSetLoadImageNotifyRoutine routine registers a driver-supplied
callback that is subsequently notified whenever an image is loaded (or
mapped into memory). When the callback is registered the system calls
the load-image notify routine whenever an executable image is mapped
into virtual memory, whether in system space or user space, before the
execution of the image begins. Additionally, the system calls this
routine when a DLL image is mapped into user-space virtual memory. [1]

Appending to MSDN [1](?) the callbacks routines operate at the
PASSIVE_LEVEL IRQL. So what if you want to allocate some r3 memory (for
various purposes) when the new image is being loaded? Assuming that the
ZwAllocateVirtualMemory also runs at PASSIVE_LEVEL everything should be
just fine. However it's not.


Continue reading ("http://www.piotrbania.com/all/articles/allocate_deadlock.txt")


http://blog.piotrbania.com/2010/09/old-new-thing-why-you-shouldnt-allocate.html

Indy
October 10th, 2010, 22:36
This is a classical problem of free resources. Access to a resource is determined by the SFN. Necessary to lower the SFN to a level lower than in MmMapViewOfSection(address space will be unlocked, UNLOCK_ADDRESS_SPACE macro). This problem is easily solved by using graphs(CFG).

GPE engine release:
http://files.virustech.org/indy/Code/+GPE/ ("http://files.virustech.org/indy/Code/+GPE/")
http://indy-vx.narod.ru/Bin/GPE.zip ("http://indy-vx.narod.ru/Bin/GPE.zip")

Pseudocode:
Code:
; Routine() -> ... -> Notify().

Initialize:
Graph = CreateGraph(@Routine, NL = 1)

Notify:
Frame:PSTACK_FRAME
Frame = rEbp
Do
if CheckIpBelongToGraph(Graph, Frame.Ip)
Tls = AllocateTls()
Tls.Ip = Frame.Ip
Frame.Ip = @2ndDispatch()
End
endif
Frame = Frame.Next
Loop END_OF_CHAIN

2ndDispatch:
Payload()
Ip = Tls.Ip
FreeTls(Tls)
Jmp Ip

Directly notifier:
Code:
; Описатель графа.
;
GP_SNAPSHOT_EX struct
Mdl PMDL ? ; Дескриптор буфера.
Snap GP_SNAPSHOT <>
; Ip - Адрес разбираемой процедуры.
; GpBase - Базовый адрес буфера с графом(MDL.MappedSystemVa).
; GpLimit - Лимит графа(размер + GpBase).
GP_SNAPSHOT_EX ends
PGP_SNAPSHOT_EX typedef ptr GP_SNAPSHOT_EX

; Стековый фрейм для PspCreateProcess().
; o Используется только STACK_FRAME, структура может меняться(не имеет значения.
;
PS_STACK_FRAME struct
Frame STACK_FRAME <>
ProcessHandle HANDLE ?
DesiredAccess ACCESS_MASK ?
ObjectAttributes POBJECT_ATTRIBUTES ?
ParentProcess HANDLE ?
Flags ULONG ?
SectionHandle HANDLE ?
DebugPort HANDLE ?
ExceptionPort HANDLE ?
JobMemberLevel ULONG ?
PS_STACK_FRAME ends
PPS_STACK_FRAME typedef ptr PS_STACK_FRAME

; NTSTATUS
; PspCreateProcess(
; OUT PHANDLE ProcessHandle,
; IN ACCESS_MASK DesiredAccess,
; IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
; IN HANDLE ParentProcess OPTIONAL,
; IN ULONG Flags,
; IN HANDLE SectionHandle OPTIONAL,
; IN HANDLE DebugPort OPTIONAL,
; IN HANDLE ExceptionPort OPTIONAL,
; IN ULONG JobMemberLevel
; );

; +
; Выполняет раскрутку SFC и находим стековый фрейм принадлежащий PspCreateProcess() и загружает в найденный фрейм линк на хэндлер.
; o Учитываем изоляцию ISR.
; Параметры:
; pLoadImageNotify2ndDispatch - ссылка на хэндлер, вызываемый при возврате из PspCreateProcess().
; ChainDispatch - ссылка на переменную в TLS, принимающую оригинальный адрес возврата из PspCreateProcess().
; (При возврате из PspCreateProcess() управление получит хэндлер LoadImageNotify2ndDispatch(), он должен выполнить обработку и вернуть управление на [ChainDispatch].
;
xLoadImageNotifyRoutine:
%GET_CURRENT_GRAPH_ENTRY
xLoadImageNotifyRoutineInternal proc Snapshot:PGP_SNAPSHOT_EX, pLoadImageNotify2ndDispatch:PVOID, ChainDispatch:PVOID
Local Caller:GP_CALLER
mov ecx,Snapshot
lea eax,Caller
lea ecx,GP_SNAPSHOT_EX.Snap[ecx]
push eax
push KernelMode
push NULL
push ecx
%GPCALL GP_FIND_CALLER_BELONG_TO_SNAPSHOT
test eax,eax
mov edx,Caller.Frame ; ~PspCreateProcess()
mov ecx,pLoadImageNotify2ndDispatch
.if Zero?
mov edx,STACK_FRAME.Next[edx]
xchg PS_STACK_FRAME.Frame.Ip[edx],ecx
mov edx,ChainDispatch
mov dword ptr [edx],ecx
.endif
ret
xLoadImageNotifyRoutineInternal endp

wasm.ru