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
>