STATUS_ACCESS_VIOLATION

Hi,

I’m playing about with hooking into NtOpenFile() but I’ve got a little
problem.

My function basically copies the UNICODE_STRING containing the file name and
then calls the real NtOpenFile
with this string rather than the one passed to it. However, the call to the
real NtOpenFile returns with 0xC0000005
which maps to STATUS_ACCESS_VIOLATION.
Okay - so it didn’t like me pointing to memory I allocated with
ExAllocatePool(). My current guess is that this
memory needs to be put into the processes memory map - but (a) is this
correct? and (b) if so, how do I do
that (or is there a better way to allocate the memory)?

NTSTATUS NewNtOpenFile(DWORD a1,DWORD a2,DWORD a3,DWORD a4,DWORD a5,DWORD
a6)
{
NTSTATUS rc;
UNICODE_STRING *newFileName;
UNICODE_STRING *oldFileName;

oldFileName=(UNICODE_STRING
*)(((POBJECT_ATTRIBUTES)a3)->ObjectName);

/* Allocate memory for newFileName */
newFileName=ExAllocatePool(NonPagedPool,sizeof(UNICODE_STRING));

newFileName->Buffer=ExAllocatePool(NonPagedPool,sizeof(WCHAR)*((oldFileName-

MaximumLength)+1));

/* Copy oldFileName to newFileName, setting Length and Maximum
length as well */
uscopy(newFileName,oldFileName);

/* Use newFileName rather than oldFileName */
((POBJECT_ATTRIBUTES)a3)->ObjectName=newFileName;

/* Call the real NTOpenFile */
rc=((NTSTATUS
(*)(DWORD,DWORD,DWORD,DWORD,DWORD,DWORD))orig_call[79])(a1,a2,a3,a4,a5,a6);

/* Move it back in case the subsystem gets funny */
((POBJECT_ATTRIBUTES)a3)->ObjectName=oldFileName;

/* Free memory */
ExFreePool(newFileName->Buffer);
ExFreePool(newFileName);

return rc;
}

Regards

Stuart

I can’t comment on the need to have the memory in
the processes space, but a easy way to handle this
is to use the Rtl Heap functions. The native API
example at www.sysinternals.com will give you the
definitions. These functions will allocate memory
in the current processes user space.

Don Burn

----- Original Message -----
From: “Stuart Adamson”
To: “NT Developers Interest List”
Sent: Monday, July 10, 2000 10:29 AM
Subject: [ntdev] STATUS_ACCESS_VIOLATION

> Hi,
>
> I’m playing about with hooking into NtOpenFile() but I’ve got a little
> problem.
>
> My function basically copies the UNICODE_STRING containing the file name
and
> then calls the real NtOpenFile
> with this string rather than the one passed to it. However, the call to
the
> real NtOpenFile returns with 0xC0000005
> which maps to STATUS_ACCESS_VIOLATION.
> Okay - so it didn’t like me pointing to memory I allocated with
> ExAllocatePool(). My current guess is that this
> memory needs to be put into the processes memory map - but (a) is this
> correct? and (b) if so, how do I do
> that (or is there a better way to allocate the memory)?
>
> NTSTATUS NewNtOpenFile(DWORD a1,DWORD a2,DWORD a3,DWORD a4,DWORD a5,DWORD
> a6)
> {
> NTSTATUS rc;
> UNICODE_STRING newFileName;
> UNICODE_STRING oldFileName;
>
> oldFileName=(UNICODE_STRING
> )(((POBJECT_ATTRIBUTES)a3)->ObjectName);
>
> /
Allocate memory for newFileName /
> newFileName=ExAllocatePool(NonPagedPool,sizeof(UNICODE_STRING));
>
>
newFileName->Buffer=ExAllocatePool(NonPagedPool,sizeof(WCHAR)
((oldFileName-
> >MaximumLength)+1));
>
> /
Copy oldFileName to newFileName, setting Length and Maximum
> length as well /
> uscopy(newFileName,oldFileName);
>
> /
Use newFileName rather than oldFileName /
> ((POBJECT_ATTRIBUTES)a3)->ObjectName=newFileName;
>
> /
Call the real NTOpenFile /
> rc=((NTSTATUS
>
(
)(DWORD,DWORD,DWORD,DWORD,DWORD,DWORD))orig_call[79])(a1,a2,a3,a4,a5,a6);
>
> /
Move it back in case the subsystem gets funny /
> ((POBJECT_ATTRIBUTES)a3)->ObjectName=oldFileName;
>
> /
Free memory */
> ExFreePool(newFileName->Buffer);
> ExFreePool(newFileName);
>
> return rc;
> }
>
>
>
> Regards
>
> Stuart
>
> —
> You are currently subscribed to ntdev as: xxxxx@acm.org
> To unsubscribe send a blank email to $subst(‘Email.Unsub’)
>

Hello,

I would just like to comment on why you are getting
the STATUS_ACCESS_VIOLATION error.

The int 2eh handler stores the caller mode (user
mode/kernel mode) in one field in KTEB. The mode is
calculated by looking at the code selector of the
caller (on stack).

Each system call implementation performs various kinds
of parameter validations if the caller mode is user
mode. This is to protect operating system from
crashing due to invalid parameters being passed by the
user mode code.

One of the parameter validation check makes sure that
all the pointers passed to the kernel mode code are
lying in user address space (below 2GB). If the
parameter is pointer to structure then individual
structure members are also probed for validity.

Now in your hook, you are allocating a piece of
memory, which will be allocated from kernel space
(above 2GB) and then you are passing this pointer to a
old NtOpenFile function. Hence, NtOpenFile sees it as
a kernel space pointer being passed from the user mode
code. Hence returns you STATUS_ACCESS_DENIED.

You can solve this problem by allocating memory from
user space using the ZwAllocateVirtualMemory system
call or Rtlxx functions to allocate from heap.

-Prasad

— Stuart Adamson
wrote:
> Hi,
>
> I’m playing about with hooking into NtOpenFile() but
> I’ve got a little
> problem.
>
> My function basically copies the UNICODE_STRING
> containing the file name and
> then calls the real NtOpenFile
> with this string rather than the one passed to it.
> However, the call to the
> real NtOpenFile returns with 0xC0000005
> which maps to STATUS_ACCESS_VIOLATION.
> Okay - so it didn’t like me pointing to memory I
> allocated with
> ExAllocatePool(). My current guess is that this
> memory needs to be put into the processes memory map
> - but (a) is this
> correct? and (b) if so, how do I do
> that (or is there a better way to allocate the
> memory)?
>
> NTSTATUS NewNtOpenFile(DWORD a1,DWORD a2,DWORD
> a3,DWORD a4,DWORD a5,DWORD
> a6)
> {
> NTSTATUS rc;
> UNICODE_STRING newFileName;
> UNICODE_STRING oldFileName;
>
> oldFileName=(UNICODE_STRING
> )(((POBJECT_ATTRIBUTES)a3)->ObjectName);
>
> /
Allocate memory for newFileName /
>
>
newFileName=ExAllocatePool(NonPagedPool,sizeof(UNICODE_STRING));
>
>
newFileName->Buffer=ExAllocatePool(NonPagedPool,sizeof(WCHAR)
((oldFileName-
> >MaximumLength)+1));
>
> /
Copy oldFileName to newFileName, setting Length
> and Maximum
> length as well /
> uscopy(newFileName,oldFileName);
>
> /
Use newFileName rather than oldFileName /
> ((POBJECT_ATTRIBUTES)a3)->ObjectName=newFileName;
>
> /
Call the real NTOpenFile /
> rc=((NTSTATUS
>
(
)(DWORD,DWORD,DWORD,DWORD,DWORD,DWORD))orig_call[79])(a1,a2,a3,a4,a5,a6);
>
> /
Move it back in case the subsystem gets funny /
> ((POBJECT_ATTRIBUTES)a3)->ObjectName=oldFileName;
>
> /
Free memory */
> ExFreePool(newFileName->Buffer);
> ExFreePool(newFileName);
>
> return rc;
> }
>
>
>
> Regards
>
> Stuart
>
> —
> You are currently subscribed to ntdev as:
> xxxxx@yahoo.com
> To unsubscribe send a blank email to
> $subst(‘Email.Unsub’)
>

=====
Prasad S. Dabak
Director of Engineering, Windows NT/2000 Division
Cybermedia Software Private Limited
http://www.cybermedia.co.in
Co-author of the book “Undocumented Windows NT”
ISBN 0764545698

__________________________________________________
Do You Yahoo!?
Get Yahoo! Mail – Free email you can access from anywhere!
http://mail.yahoo.com/

> From: Prasad Dabak [mailto:xxxxx@yahoo.com]

Each system call implementation performs various kinds
of parameter validations if the caller mode is user
mode. This is to protect operating system from
crashing due to invalid parameters being passed by the
user mode code.

I guessed it was something related to this. Thanks for
the explanation - it nicely filled in the gaps.

You can solve this problem by allocating memory from
user space using the ZwAllocateVirtualMemory system
call or Rtlxx functions to allocate from heap.

Just having had a look at the prototype for ZwAllocateVirtualMemory
I can see how that should work and I’ll give it a go tonight. Thanks.

A look at ntddk.lib suggests that the functions
RtlEnumProcessHeaps(DWORD,DWORD)
and RtlGetProcessHeaps(DWORD,DWORD) could be used to get a handle
for a heap of the process that could be then passed to RtlAllocateHeap().
However, I can’t find any docs on these two functions - I’d guess one
parameter must be the process id and the other a pointer to a block of
memory
to which handles to the heaps are to be put - have these been documented
anywhere?

Regards

Stuart

Actually, you can just use RtlCreateHeap to create another
heap for the process.

Don Burn

----- Original Message -----
From: “Stuart Adamson”
To: “NT Developers Interest List”
Sent: Tuesday, July 11, 2000 7:28 AM
Subject: [ntdev] Re: STATUS_ACCESS_VIOLATION

> > From: Prasad Dabak [mailto:xxxxx@yahoo.com]
> > Each system call implementation performs various kinds
> > of parameter validations if the caller mode is user
> > mode. This is to protect operating system from
> > crashing due to invalid parameters being passed by the
> > user mode code.
>
> I guessed it was something related to this. Thanks for
> the explanation - it nicely filled in the gaps.
>
> > You can solve this problem by allocating memory from
> > user space using the ZwAllocateVirtualMemory system
> > call or Rtlxx functions to allocate from heap.
>
> Just having had a look at the prototype for ZwAllocateVirtualMemory
> I can see how that should work and I’ll give it a go tonight. Thanks.
>
> A look at ntddk.lib suggests that the functions
> RtlEnumProcessHeaps(DWORD,DWORD)
> and RtlGetProcessHeaps(DWORD,DWORD) could be used to get a handle
> for a heap of the process that could be then passed to RtlAllocateHeap().
> However, I can’t find any docs on these two functions - I’d guess one
> parameter must be the process id and the other a pointer to a block of
> memory
> to which handles to the heaps are to be put - have these been documented
> anywhere?
>
> Regards
>
>
> Stuart
>
> —
> You are currently subscribed to ntdev as: xxxxx@acm.org
> To unsubscribe send a blank email to $subst(‘Email.Unsub’)
>

> with this string rather than the one passed to it. However, the call to
the

real NtOpenFile returns with 0xC0000005
which maps to STATUS_ACCESS_VIOLATION.

Call ZwOpenFile or ZwCreateFile instead. They set the previous mode in the
TLS to KernelMode - while NtOpenFile will not update the previous mode - it
will be UserMode.
The body of NtOpenFile will ProbeFor/Read/Write the parameters if the
previous mode is UserMode. The probe will raise this very exception if a
kernel pointer is passed there.

In a few words - in the kmode code, use Zwxxx functions or int 2Eh, not
Ntxxx.

Max

> From: Maxim S. Shatskih [mailto:xxxxx@storagecraft.com]

> real NtOpenFile returns with 0xC0000005
> which maps to STATUS_ACCESS_VIOLATION.

Call ZwOpenFile or ZwCreateFile instead. They set the
previous mode in the
TLS to KernelMode - while NtOpenFile will not update the
previous mode - it
will be UserMode.
The body of NtOpenFile will ProbeFor/Read/Write the parameters if the
previous mode is UserMode. The probe will raise this very
exception if a
kernel pointer is passed there.

But by calling ZwOpenFile I’m bypassing any code in the
real NtOpenFile which to my understanding checks that the
incoming parameters are valid - hence I have to implement
this and any other code that MS may decide to put into this
layer in the future which seems like a Bad Thing to me.

It also means that if anything else has hooked into this syscall
then I will bypass that as well ;(

If I were trying to open a file for the drivers own use then
I would agree with you - but I’m not - I’m opening the file
for a userland process so the correct solution is to make sure
a pass a valid pointer to a usermode address.

Stuart