find usermode func name from kernel mode and dll

Hi,

I am looking find the name of the function(foo here) and dll name also (if it originated from std dll) from which a usermode function (say foo1) made a syscall into kernel (say some driver).
Assuming that now we have the return address from current frame on the kernel function (say kfunc).

How can we (if possible) reliably find the name of the function & dll which made this system call ?

kd> kn

ChildEBP RetAddr

00 89c9ec0c 828781ea mydriver!kfunc
01 89c9ec0c 776f70b4 nt!KiFastCallEntry+0x12a
02 00c4f88c 76953aba ntdll!KiFastSystemCallRet
03 00c4f8c8 7690ea25 umodeapp!foo+0xc

Expected Result: function name: foo dll/exe: umodeapp

828781ea –> can we reliably use this address to find which function and dll from which this was called !!!

kd> kn

ChildEBP RetAddr

00 89c9ec0c 828781ea mydriver!kfunc
01 89c9ec0c 776f70b4 nt!KiFastCallEntry+0x12a
02 00c4f88c 76953aba ntdll!KiFastSystemCallRet
03 00c4f8c8 7690ea25 ntdll!ReadFile

Expected Result: function name:ReadFile dll/exe: ntdll.dll

The thing that i am more interested in is to figure out if or not an applicable tried to a make a direct systemcall using
technique similar to one mentioned in this article by filling the appropriate syscall id and making the call.

http://www.osronline.com/article.cfm?id=257

or it came via a some exported api from a standard dll like ntdll,kernel32,user32 etc.

thanks
spool

Hand off the thread ID to a user mode helper, and have it use
GetThreadContext and various module functions to determine this. Doing
this in the kernel depends in many cases on undocumented functions.

Don Burn
Windows Filesystem and Driver Consulting
Website: http://www.windrvr.com
Blog: http://msmvps.com/blogs/WinDrvr

xxxxx@gmail.com” wrote in message
news:xxxxx@ntdev:

> Hi,
>
> I am looking find the name of the function(foo here) and dll name also (if it originated from std dll) from which a usermode function (say foo1) made a syscall into kernel (say some driver).
> Assuming that now we have the return address from current frame on the kernel function (say kfunc).
>
> How can we (if possible) reliably find the name of the function & dll which made this system call ?
>
> kd> kn
> # ChildEBP RetAddr
> 00 89c9ec0c 828781ea mydriver!kfunc
> 01 89c9ec0c 776f70b4 nt!KiFastCallEntry+0x12a
> 02 00c4f88c 76953aba ntdll!KiFastSystemCallRet
> 03 00c4f8c8 7690ea25 umodeapp!foo+0xc
>
> Expected Result: function name: foo dll/exe: umodeapp
>
> 828781ea –> can we reliably use this address to find which function and dll from which this was called !!!
>
> kd> kn
> # ChildEBP RetAddr
> 00 89c9ec0c 828781ea mydriver!kfunc
> 01 89c9ec0c 776f70b4 nt!KiFastCallEntry+0x12a
> 02 00c4f88c 76953aba ntdll!KiFastSystemCallRet
> 03 00c4f8c8 7690ea25 ntdll!ReadFile
>
> Expected Result: function name:ReadFile dll/exe: ntdll.dll
>
> The thing that i am more interested in is to figure out if or not an applicable tried to a make a direct systemcall using
> technique similar to one mentioned in this article by filling the appropriate syscall id and making the call.
>
> http://www.osronline.com/article.cfm?id=257
>
> or it came via a some exported api from a standard dll like ntdll,kernel32,user32 etc.
>
> thanks
> spool

Thanks Don.

Going to usermode and doing the stuff there is not what i am looking for since i am afraid that this information might get modified/changed due to any xyz reason.

I am specifically interested in finding all this info from kernel mode only, without ever leaving the ring0 code. Can you be more specific in terms of the kmode tricks here be it undocumented or platform specific ?

The closest to documented is RtlCaptureContext to get the CONTEXT and
using PsSetLoadImageNotifyRoutine to set a routine to build a database
of modules. For the database you also need
PsSetCreateProcessNotifyRoutine so you can track processes. At that
point it gets ugly.

This is really a VERY STUPID IDEA since you are obviously trying to fix
an infected system from the inside, bottom line is that does not work.

Don Burn
Windows Filesystem and Driver Consulting
Website: http://www.windrvr.com
Blog: http://msmvps.com/blogs/WinDrvr

xxxxx@gmail.com” wrote in message
news:xxxxx@ntdev:

> Thanks Don.
>
> Going to usermode and doing the stuff there is not what i am looking for since i am afraid that this information might get modified/changed due to any xyz reason.
>
> I am specifically interested in finding all this info from kernel mode only, without ever leaving the ring0 code. Can you be more specific in terms of the kmode tricks here be it undocumented or platform specific ?

There is no way to do this. You maybe, just barely, be able to tell the
name of the executable from which the call came, perhaps even the DLL.
But the function name? No way. You would have to know the .pdb file for
the executable, and if a dll, for the dll. You would somehow have to call
the user-level library support for name resolution.

And what you will discover is that it came, most likely, from
kernel32.dll, which is remarkably uninteresting.

So you need to know how to parse the stack to find the call from which
kernel32.dll was called, which is a complex task, especially in 64-bit
code.

What problem are you trying to solve? How, for example, would knowing the
call came from other than ntdll.dll, help you in any way? And if you
think it will, I can probably fool your code anyway. You seem to be
interested in a solution to a non-problem, since the WIN32 kernel
interface assumes that any call into the kernel is going to present
untrustworthy data. If the parameters validate, what does it matter who
sent it?

Have you single-instruction-stepped from a breakpoint at a ReadFile call
to see everything it does? Do so, before thinking you are going to
discover anything meaningful even if you could determine where it came
from.
joe

Hi,

I am looking find the name of the function(foo here) and dll name also (if
it originated from std dll) from which a usermode function (say foo1) made
a syscall into kernel (say some driver).
Assuming that now we have the return address from current frame on the
kernel function (say kfunc).

How can we (if possible) reliably find the name of the function & dll
which made this system call ?

kd> kn

ChildEBP RetAddr

00 89c9ec0c 828781ea mydriver!kfunc
01 89c9ec0c 776f70b4 nt!KiFastCallEntry+0x12a
02 00c4f88c 76953aba ntdll!KiFastSystemCallRet
03 00c4f8c8 7690ea25 umodeapp!foo+0xc

Expected Result: function name: foo dll/exe: umodeapp

828781ea –> can we reliably use this address to find which function and
dll from which this was called !!!

kd> kn

ChildEBP RetAddr

00 89c9ec0c 828781ea mydriver!kfunc
01 89c9ec0c 776f70b4 nt!KiFastCallEntry+0x12a
02 00c4f88c 76953aba ntdll!KiFastSystemCallRet
03 00c4f8c8 7690ea25 ntdll!ReadFile

Expected Result: function name:ReadFile dll/exe: ntdll.dll

The thing that i am more interested in is to figure out if or not an
applicable tried to a make a direct systemcall using
technique similar to one mentioned in this article by filling the
appropriate syscall id and making the call.

http://www.osronline.com/article.cfm?id=257

or it came via a some exported api from a standard dll like
ntdll,kernel32,user32 etc.

thanks
spool


NTDEV is sponsored by OSR

For our schedule of WDF, WDM, debugging and other seminars visit:
http://www.osr.com/seminars

To unsubscribe, visit the List Server section of OSR Online at
http://www.osronline.com/page.cfm?name=ListServer

There are several ways to deal with a leaky roof. One is to put a bucket
under the leak. Another is to repair the roof. Yet another is to not let
the football team practice on the roof (read: not let ordinary users have
admin privileges)
joe

The closest to documented is RtlCaptureContext to get the CONTEXT and
using PsSetLoadImageNotifyRoutine to set a routine to build a database
of modules. For the database you also need
PsSetCreateProcessNotifyRoutine so you can track processes. At that
point it gets ugly.

This is really a VERY STUPID IDEA since you are obviously trying to fix
an infected system from the inside, bottom line is that does not work.

Don Burn
Windows Filesystem and Driver Consulting
Website: http://www.windrvr.com
Blog: http://msmvps.com/blogs/WinDrvr

xxxxx@gmail.com” wrote in message
> news:xxxxx@ntdev:
>
>> Thanks Don.
>>
>> Going to usermode and doing the stuff there is not what i am looking for
>> since i am afraid that this information might get modified/changed due
>> to any xyz reason.
>>
>> I am specifically interested in finding all this info from kernel mode
>> only, without ever leaving the ring0 code. Can you be more specific in
>> terms of the kmode tricks here be it undocumented or platform specific ?
>
>
> —
> NTDEV is sponsored by OSR
>
> For our schedule of WDF, WDM, debugging and other seminars visit:
> http://www.osr.com/seminars
>
> To unsubscribe, visit the List Server section of OSR Online at
> http://www.osronline.com/page.cfm?name=ListServer
>

Hi Joseph,
Thanks for your inputs too.

Answering/Questions inline:

There is no way to do this. You maybe, just barely, be able to tell the name of the executable from which the call came, perhaps even the DLL. But the function name? No way. You would have to know the .pdb file for the executable, and if a dll, for the dll. You would somehow have to call the user-level library support for name resolution. And what you will discover is that it came, most likely, from kernel32.dll, which is remarkably uninteresting. So you need to know how to parse the stack to find the call from which kernel32.dll was called, which is a complex task, especially in 64-bit code.



What problem are you trying to solve? How, for example, would knowing the call came from other than ntdll.dll, help you in any way?


It is sort of a sandboxed mechanism for a specific problem i am solving.

On top of this, i am also exploring the possibilities, if i am called into my kernel code then, would it be possible for me to lock the callstack till usermode and prevent from any modification to these parameters.
>

And if you think it will, I can probably fool your code anyway.



You seem to be interested in a solution to a non-problem, since the WIN32 kernel interface assumes that any call into the kernel is going to present untrustworthy data. If the parameters validate, what does it matter who sent it? Have you single-instruction-stepped from a breakpoint at a ReadFile call to see everything it does? Do so, before thinking you are going to discover anything meaningful even if you could determine where it came from.

< I know that i am trying to achieve too many things here but i want to understand clearly all the possibilities,drawbacks and deadends before i actually believe it is not achievible anyways. (Documented or undocumented). It is a new learning for me as well.
>

Thanks again for valuable inputs here

- spool

On 20-May-2012 11:23, xxxxx@gmail.com wrote:

< I know that i am trying to achieve too many things here but i want to understand clearly all the possibilities,drawbacks and deadends before i actually believe it is not achievible anyways. (Documented or undocumented). It is a new learning for me as well.

Some of likely possibilities are that your adversaries will be quite
clever and know more than you can achieve by this exercise. Do you have
“plan B” for this?
– pa

> Hi Joseph,

Thanks for your inputs too.

Answering/Questions inline:

There is no way to do this. You maybe, just barely, be able to tell the
name of the executable from which the call came, perhaps even the DLL. But
the function name? No way. You would have to know the .pdb file for the
executable, and if a dll, for the dll. You would somehow have to call the
user-level library support for name resolution. And what you will discover
is that it came, most likely, from kernel32.dll, which is remarkably
uninteresting. So you need to know how to parse the stack to find the call
from which kernel32.dll was called, which is a complex task, especially in
64-bit code.

> call stack looked a bit achievable on x86 and on 64-bit it is indeed a
> daunting task>
>
> What problem are you trying to solve? How, for example, would knowing the
> call came from other than ntdll.dll, help you in any way?
>
> > in deciding to fail the call, if someone directly made a system call.
> Since in my code, i know that if it comes from a specific
> dll(ntdll,kernel32 etc), then i know that this will be a genuine call and
> not spoofed. Because using the direct syscall the spurious/insecure
> application can have more control over the parameters to APIs compared to
> via normal path.
>

Why do you believe this? There is no basis for this conclusion. EVERY
kernel call is assumed to be delivering untrustworthy information, and all
parameters are verified. While there are interesting anti-malware
features of putting calls inline, they can’t “spoof” anything, because all
calls to the kernel require validation. I can call ntdll.dll to used the
(mostly-undocumented) raw API, and you would see it as a call from
ntdll.dll, so would presumably verify that it was good. Even if its
intention was bad (I used to teach a security course where I showed some
very interesting things you can do with the undocumented API that are not
doable from the official API). The point here is that you would be
creating a very complex solution to a non-problem, because the concept of
“spoofing” is completely inoperative here. You gain nothing, and I would
be more inclied to use the raw API, which you could not detect anyway,
because the calls would be from ntdll.dll. So the solution offers only
complexity without solving any security issue whatsoever. All those
layers of system callness ypu see are only so programmers don’t have to
write sysenter instructions; there are no meaningful validations done alng
those paths, and all validation is done AFTER the sysenter has transferred
control into the kernel. v

Do you have an actual example of your alleged “spoofed” call that does
damage? If you actually have one, I suspect that I can do the same thing
in a fashion that your alleged solution would think of as acceptable. If
you are merely thinking “someone could spoof a kernel call by hand-coding
a sysenter” then you really don’t understand how the kernel works. There
is absolutely nothing special about ntll.dll or kernel32.dll or any of the
other dlls you think are on the approved list that makes what they do
“more secure” than if I write a sysenter myself in my code.
****

> It is sort of a sandboxed mechanism for a specific problem i am solving.

But it does not solve any problem worth worrying about. If you think
there is a problem, I’d first need to se a detailed example of one of
these “spoofed” calls. There is nothing important that such calls can
bypass. ACLs, thread privileges, address validity, etc. are all checked
IN THE KERNEL for each system call. In fact, one of the older performance
improvements was to move parts of the WIN32 API into the kernel. Turns
out that in NT4 there were “Win32” calls of the form A(x, y, z) which in
one of the user-level DLLs was done as calls of the form NtSomething(x,
y); NtSomethingElse(x, z, result_of_previous_call); NtYetMore(result1,
result2, y, z); and these were now moved enyirely ino yhe kernel for
performance reasons. The problem was that the existing implementation
required three ring-crossings. It was not the cost of the ring3-ring0
transition; it was the fact that on each ring transition, ALL THE
PARAMETERS HAD TO BE VERIFIED, each time, because every return to ring3
meant a potential security compromise. So the kernel is already designed
and built to avoid the kind of spoofing you think can be a problem. Your
efforts will add nothing to this.

>
> On top of this, i am also exploring the possibilities, if i am called into
> my kernel code then, would it be possible for me to lock the callstack
> till usermode and prevent from any modification to these parameters.
>>
>
> And if you think it will, I can probably fool your code anyway.
>
> > parameters, that is another challenge i would like to tackle, assuming
> that hooking into ntdll,kernel32 func require admin priviledges already>

I think you don’t understand what is meant by “hooking”. Rootkit-style
hooking means all bets are off, and therefore your whole solution is
irrelevant. And there’s nothing that can be done in user space, with or
without admin privileges, that would produce a parameter list that would
bypass the existing validation.

>
> You seem to be interested in a solution to a non-problem, since the WIN32
> kernel interface assumes that any call into the kernel is going to
> present untrustworthy data. If the parameters validate, what does it
> matter who sent it? Have you single-instruction-stepped from a breakpoint
> at a ReadFile call to see everything it does? Do so, before thinking you
> are going to discover anything meaningful even if you could determine
> where it came from.
>
> < I know that i am trying to achieve too many things here but i want to
> understand clearly all the possibilities,drawbacks and deadends before i
> actually believe it is not achievible anyways. (Documented or
> undocumented). It is a new learning for me as well.
>>

The whole idea is a dead end, because it is an attempt to solve a
nonexistent problem using an irrelevant and probably
impossible-to-implement mechanism. The major failure here is an
absolutely unfounded belief that a hand-coded kernel call can “spoof” its
parameters so that something usafe can be accomplished.

If I were a malware writer, the only reason I would do this is to disguise
the fact that I was doing something like using the raw API, because a
program reading the PE-format file (for Win32; I forget what the file
representation is called for Win64) would see import records for
NtSomeReallyEsotericFunction, which might lead me to suspect the code is
doing soething odd. BUT, unless I have stupidly been running with admin
privileges, if I call that function, standard rights administration and
parameter validation will either permit it (and by your own definition,
since it’s coming from ntdll.dll, you will approve it anyway) or it will
be rejected by the kenel (in which case, your efforts will have been
pointless). If I hand-code it inline, if the parameters are bad, it will
be rejected anyway, and all I have avoided is the import-record-check,
which is not particularly reliable anyway (I can always call
GetProcAddress and avoid the import record).

I think you have invented a problem where none exists. If you have a
counterexample that demonstrates this, then we can disuss that, and I can
probably show how I could make it work anyway.
****
>
> Thanks again for valuable inputs here
>
> - spool
>
> —
> NTDEV is sponsored by OSR
>
> For our schedule of WDF, WDM, debugging and other seminars visit:
> http://www.osr.com/seminars
>
> To unsubscribe, visit the List Server section of OSR Online at
> http://www.osronline.com/page.cfm?name=ListServer
>

> >achievable on x86 and on 64-bit it is indeed a daunting task>

Yes, but finding the trap (not call!) frame is not such, you just need to look at some undoc structures in KTHREAD.

Let’s look:

1) you need to parse PE binaries from Windows kernel.
2) the kernel does have this support, but it is undoc.
3) so, your only chances are a) use undoc stuff in the kernel or b) write your own PE parser.

In any case, this is severe undoc land, and MS usually does not even want to hear about writing such SW.


Maxim S. Shatskih
Windows DDK MVP
xxxxx@storagecraft.com
http://www.storagecraft.com

Are you able to get the backtrace of user mode stack?

Just get the list of modules loaded in the process. You can build your own per-process database as described above, but I beleive there is a better way: need to look into GetModuleHanle code for example.

Once you have the list of module base addresses and size, you can walk the stack trace to find from which module the call is made.

Anatoly.

On 20-May-2012 14:49, xxxxx@gmail.com wrote:

Are you able to get the backtrace of user mode stack?

Just get the list of modules loaded in the process. You can build your own per-process database as described above, but I beleive there is a better way: need to look into GetModuleHanle code for example.

Once you have the list of module base addresses and size, you can walk the stack trace to find from which module the call is made.

Anatoly.

It is definitely possible from kernel mode: Process Monitor does it -
but it belongs to Microsoft and thus is on the back side of Undocumented.

If I read the OP correctly, the problem is not about validation of a
system call vs Win32 API at all. The OP has some “magic DLL” that
creates a magic key, which, when sent via ioctl or other driver request,
opens a tiny door in the OP’s driver.
The OP’s concern is that adversary can forge this key without his DLL.

Regards,
– pa

Well, if this is, indeed, the case, then the OP’s scheme firmly belong in “faulty by design” class of solutions…

Anton Bassov

But there are several problems with this idea. First, the idea that the
call must come from a limited number of “good guys” is silly, because as
far as the kernel is concerned, EVERYTHING up to the sysenter is untrusted
code. So it will check everything. Now, to access a driver, I need to
call ReadFile, WriteFile or DeviceIoControl, and I can call those anyway;
I don’t need to “spoof” anything. A driver that would cause damage unless
the API is called from a “trusted” DLL is an failed design, because if it
matters, then the driver has created a security hole. So again, it is an
attempt to create a complex mechanism to solve a nonexistent problem, or
one which has been artificially created due to bad driver design.

As I have said in several posts, I think the OP has no clue as to how the
kernel works, or how it has to assume that every single call from user
space is a possible attack. The concept of “spoofing” makes no sense.
joe

On 20-May-2012 14:49, xxxxx@gmail.com wrote:
> Are you able to get the backtrace of user mode stack?
>
> Just get the list of modules loaded in the process. You can build your
> own per-process database as described above, but I beleive there is a
> better way: need to look into GetModuleHanle code for example.
>
> Once you have the list of module base addresses and size, you can walk
> the stack trace to find from which module the call is made.
>
> Anatoly.

It is definitely possible from kernel mode: Process Monitor does it -
but it belongs to Microsoft and thus is on the back side of Undocumented.

If I read the OP correctly, the problem is not about validation of a
system call vs Win32 API at all. The OP has some “magic DLL” that
creates a magic key, which, when sent via ioctl or other driver request,
opens a tiny door in the OP’s driver.
The OP’s concern is that adversary can forge this key without his DLL.

Regards,
– pa


NTDEV is sponsored by OSR

For our schedule of WDF, WDM, debugging and other seminars visit:
http://www.osr.com/seminars

To unsubscribe, visit the List Server section of OSR Online at
http://www.osronline.com/page.cfm?name=ListServer

xxxxx@gmail.com wrote:



You can find the addresses, but you can’t find the function names. That
information is simply not stored in memory. It’s in the debugging
symbol files. There might not even BE symbol files for the user
executables and DLLs, and there certainly won’t be for malware. Even if
there were, you wouldn’t know where to find them.


Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.

> information is simply not stored in memory. It’s in the debugging

symbol files.

And, without frame pointer omission debug info, you cannot reliably walk the stack.


Maxim S. Shatskih
Windows DDK MVP
xxxxx@storagecraft.com
http://www.storagecraft.com

You can find the function names if they are in the export/import tables.
Windbg defaults to exports when it fails to find .pdb.

And depending on the calling conventions you may not be able to find the
return address without the PDB files. Modern compilers don’t use stack
frames the way they used to.

Don Burn
Windows Filesystem and Driver Consulting
Website: http://www.windrvr.com
Blog: http://msmvps.com/blogs/WinDrvr

xxxxx@gmail.com” wrote in
message news:xxxxx@ntdev:

> You can find the function names if they are in the export/import tables.
> Windbg defaults to exports when it fails to find .pdb.

Don, does this apply to windows modules as well? i.e. kernel32, user32, advapi …