I have read a few similar entries but nothing that asks my specific question…
On x86 we have some inline assembly code that basically calls things like ZwTerminateThread, ZwProtectVirtualMemory via int 2eh.
I am trying to understand if this is possible on x64 platforms like Windows 2008 and Windows 7 as these functions are not exported…however using the masm file and syscall instead of int 2eh causes bad things to happen (Vmware stack kernel faults).
Basically the masm file contains functions that perform the
mov r10, rcx
mov eax, [dynamic syscall entry value found from ntdll exports]
syscall
ret
Any thoughts?
.> Any thoughts?
The only thought that may get into one’s head is that you need to restructure your driver and to avoid
calling functions via SSDT - this is really bad design which is not guaranteed to be portable across platforms and may be broken by a slightest system update even if it works OK on the OS version where it had been tested…
Why don’t you want just to introduce a helper UM app that will do all UM tasks in the UM upon driver’s request??? It seems to be the most reasonable thing to do here…
Anton Bassov
wrote in message news:xxxxx@ntdev…
> I have read a few similar entries but nothing that asks my specific
> question…
>
> On x86 we have some inline assembly code that basically calls things like
> ZwTerminateThread, ZwProtectVirtualMemory via int 2eh.
>
> I am trying to understand if this is possible on x64 platforms like
> Windows 2008 and Windows 7 as these functions are not exported…however
> using the masm file and syscall instead of int 2eh causes bad things to
> happen (Vmware stack kernel faults).
>
> Basically the masm file contains functions that perform the
>
> mov r10, rcx
> mov eax, [dynamic syscall entry value found from ntdll exports]
> syscall
> ret
>
> Any thoughts?
Do you need these syscalls in user or kernel mode?
At least for some calls, have done that in kernel mode; works under VMware
as well.
However, as Anton pointed out, this is risky.
Though the syscall indexes seem to stay fixed for previous NT versions
(as listed in http://www.metasploit.com/users/opcode/syscalls.html )
they may deliberately break this in newer kernels?
–pa
There is certainly no guarantee that there will be any particular ordering here. This is way off into “at risk of breaking without notice” land.
-----Original Message-----
From: xxxxx@lists.osr.com [mailto:xxxxx@lists.osr.com] On Behalf Of Pavel A.
Sent: Wednesday, August 05, 2009 8:57 PM
To: Windows System Software Devs Interest List
Subject: Re:[ntdev] x64 driver attempt to do syscall from masm
wrote in message news:xxxxx@ntdev…
> I have read a few similar entries but nothing that asks my specific
> question…
>
> On x86 we have some inline assembly code that basically calls things like
> ZwTerminateThread, ZwProtectVirtualMemory via int 2eh.
>
> I am trying to understand if this is possible on x64 platforms like
> Windows 2008 and Windows 7 as these functions are not exported…however
> using the masm file and syscall instead of int 2eh causes bad things to
> happen (Vmware stack kernel faults).
>
> Basically the masm file contains functions that perform the
>
> mov r10, rcx
> mov eax, [dynamic syscall entry value found from ntdll exports]
> syscall
> ret
>
> Any thoughts?
Do you need these syscalls in user or kernel mode?
At least for some calls, have done that in kernel mode; works under VMware
as well.
However, as Anton pointed out, this is risky.
Though the syscall indexes seem to stay fixed for previous NT versions
(as listed in http://www.metasploit.com/users/opcode/syscalls.html )
they may deliberately break this in newer kernels?
–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
> Though the syscall indexes seem to stay fixed for previous NT versions
IWell, you can obtain index dynamically by parsing ntdll.dll, so that changing indexes does not really pose a problem unless they deliberately change syscall convention (for example, put service index into EDX
and make EAX point to parameters)
The real problem is that if function is exported by the kernel via SSDT but not via IAT (which means it is not supposed to be called by drivers,) the OS may check PreviousMode in ETHREAD right in function’s code - even if does not CURRENTLY do it there is no guarantee that is keeps on skipping these checks in all subsequent OS releases. If you decide to fool this part by getting function’s address from SSDT and calling it directly by its address, rather than going via the system call dispatcher, you may get an error when the target function discovers that pointer or handle parameters refer to the kernel address space…
Anton Bassov
Yes: Why in the world do you want to do this.
Aside from that, not very much.
I don’t think he IS attempting to call functions via the SSDT. He’s trying to hand-code the standard system service call stub: Args in registers, execute SYSCALL instruction, resulting in an orderly and protected transition into kernel mode.
Nothing to do with the SSDT here as far as I can tell… except that Windows will use it, like it always does, to dispatch the request.
Peter
OSR
> Args in registers, execute SYSCALL instruction, resulting in an orderly and protected
transition into kernel mode.
The only question is why someone would want to do it from the UM if he can simply call the target function by its name, in the first place. Furthermore, no matter what you do in the UM, you are not going to get kernel stack corruption.
Therefore, it is obvious that he tries to do it from the KM. Apparently, what he wants to do here is to call a function that is exposed only via SSDT, and do it from the KM - otherwise the whole exercise just would not make sense. Look at the functions he mentions - they are not exported via ntoskrnl.exe’s IAT but are exported by ntdll.dll .
Therefore, what he tries to do here is to re-enter the system service dispatcher. The reason why he crashes is plainly obvious as well - he tries to use SYSCALL instruction, and you cannot execute the it
from the kernel mode. In order to do something like that he has either to use INT 0x2E or simply call
INT 0x2E handler as a function after pushing CS and flags on the stack. Please pay a special attention to the fact that his code that works on x86 relies upon INT 2E, rather than sysenter - if he tried sysenter on x86 he would get exactly the same result that he gets here …
Anton Bassov
Maybe. Maybe we’ll be so lucky that the OP will tell us what he’s trying to do in a bit more detail.
We could be speculating for the rest of our lives…
Peter
OSR
Peter,
We could be speculating for the rest of our lives…
Actually, there is nothing new here - after all, this is how all these “long rambling threads” normally start…
Anton Bassov
Sorry I had not replied to any of the responders questions but the initial response was unhelpful so I had delayed checking back.
Yes I am attempting to execute these non-exported functions from kernel mode and having a user mode app do these tasks is not ideal.
The 32 bit equivalent driver uses the int 2e method but my impression was that this would not work on x64. However from Anton’s last response it appears possible?
As Peter mentioned I am not attempting to use SSDT hooks in this case…as finding the table given PatchGuard’s protections will be cumbersome.
Hopefully this answers any follow on questions and queries for any “int 2e” knowledge on x64 windows?
xxxxx@yahoo.com wrote:
Sorry I had not replied to any of the responders questions but the initial response was unhelpful so I had delayed checking back.
Yes I am attempting to execute these non-exported functions from kernel mode and having a user mode app do these tasks is not ideal.
The 32 bit equivalent driver uses the int 2e method but my impression was that this would not work on x64. However from Anton’s last response it appears possible?
Well, the 64-bit Win 7 ntdll APIs use the sysenter instruction.
–
Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.
> Well, the 64-bit Win 7 ntdll APIs use the sysenter instruction.
Actually, starting from XP, sysenter is being used for both 32-bit and 64-bit OS versions - IIRC, W2K is the last OS version where ntdll relies upon software interrupt…
Anton Bassov
wrote in message news:xxxxx@ntdev…
>> Well, the 64-bit Win 7 ntdll APIs use the sysenter instruction.
>
> Actually, starting from XP, sysenter is being used for both 32-bit and
> 64-bit OS versions - IIRC, W2K is the last OS version where ntdll relies
> upon software interrupt…
>
> Anton Bassov
Why sysenter? the OP wants to call non-exported syscalls from kernel mode.
( Sorry, can’t post a code sample - it belongs to my last employer.
All I can say - this is doable, but not thru int 2e, neither patches nor SST
hooks, the verifier is happy. )
–pa
> Why sysenter?
This is because Tim is speaking about ntdll. Therefore, I just point out that this is not really indicative how ntdll
enters the kernel…
All I can say - this is doable,
This is understandable - otherwise there would be no native routine in Zw form that ntoskrnl.exe exports…
but not thru int 2e,
…but still via INT 0x2E handler, right - instead of making INT instruction you push CS and flags on the stack
and call dispatcher via 'call 'instruction. IIRC, this is how native routine in Zw form that ntoskrnl.exe exports
do things - they call service dispatcher as a function
Anton Bassov
Well the int 2e handler is still usable in xp, and 2k3 AFAIK (at least the x86 version)
However doing the same in x64 doesn’t crash but it doesn’t appear to do anything. However maybe I am not doing it correctly…I push args to function, store syscall number in rax and lea rdx with the address of the first arg then make the int 2e call.
…but still via INT 0x2E handler, right - instead of making INT instruction you push CS and flags on the > stack and call dispatcher via 'call 'instruction. IIRC, this is how native routine in Zw form that >ntoskrnl.exe exports do things - they call service dispatcher as a function
What should the CS and flags registers look like when they are pushed?
Also where does someone call if all they know is the syscall id?
…this is doable
Encouraging…however losing time and steam in search…
Anton suggests to duplicate an exported Zw stub and modify/use it for your
own purposes. If you aren’t familiar with the difference between the Zw
and Nt variants, read this article:
http://www.osronline.com/article.cfm?id=257
On Wed, 12 Aug 2009 14:52:55 +0200, wrote:
> Well the int 2e handler is still usable in xp, and 2k3 AFAIK (at least
> the x86 version)
>
> However doing the same in x64 doesn’t crash but it doesn’t appear to do
> anything. However maybe I am not doing it correctly…I push args to
> function, store syscall number in rax and lea rdx with the address of
> the first arg then make the int 2e call.
>
>> …but still via INT 0x2E handler, right - instead of making INT
>> instruction you push CS and flags on the > stack and call dispatcher
>> via 'call 'instruction. IIRC, this is how native routine in Zw form
>> that >ntoskrnl.exe exports do things - they call service dispatcher as
>> a function
>
> What should the CS and flags registers look like when they are pushed?
>
> Also where does someone call if all they know is the syscall id?
>
>> …this is doable
>
> Encouraging…however losing time and steam in search…
Dude! Get right! You’re trying to do something that’s obviously unsupported and that the designers of the system clearly didn’t want you to do. So, you should expect to “lose” a LOT of time in searching.
I’m confused. I guess I don’t understand what problem you’re having. I mean… we’re TRYING to help you (well, most of us are).
First: Just throw away the old “int 2e” junk. Forget about it. There are vestiges left in the OS for “backward compatibility” but that’s really it. Maybe the ones in x64 work, maybe they don’t. I don’t know. That’s not the current way it’s done anyhow, as you know, so never mind.
Givens: You apparently KNOW the system service ID of the function you want to call. I *assume* you know how to write x64 function in assembler, with the appropriate prefix and such for exceptional handling.
So: You code-up the call of a well documented ZwXxxx system service in your driver. Let’s take, oh, ZwCreateFile. You disassemble that code. That’ll show you how the Zw form of a system service is invoked. Sweet! To check your understanding, code-up a call to a different well-documented system service, say ZwClose or ZwWriteFile or even (why not live a little?) BOTH! Disassemble these. Compare results. Draw conclusions.
Follow pattern, substituting (1) The system service code of the function YOU want to invoke, and (2) The number and types of arguments that YOU want to pass.
Custom ZwXxxx invocation from kernel-mode: Finished.
Either it’s that simple or I’m entirely missing what you’re asking. Either one is possible, of course.
Or perhaps that’s as “unhelpful” as the initial response(s) you got to your question?
Peter
OSR
Thanks Peter…I had sort of forged down the path you describe…however I am hitting some bumps that are expected but curious about what to do…
Yes I can write an x64 assembler function…but not sure about the “prefix and such for exception handling”
Here is my thought…taking ZwOpenThread as an example…disassembles to the following on my 2k8 x64 system:
nt!ZwOpenThread:
fffff800016a0d80 488bc4 mov rax,rsp fffff800
016a0d83 fa cli
fffff800016a0d84 4883ec10 sub rsp,10h fffff800
016a0d88 50 push rax
fffff800016a0d89 9c pushfq fffff800
016a0d8a 6a10 push 10h
fffff800016a0d8c 488d056d360000 lea rax,[nt!KiServiceLinkage (fffff800
016a4400)]
fffff800016a0d93 50 push rax fffff800
016a0d94 b8f8000000 mov eax,0F8h
fffff800016a0d99 e9a22e0000 jmp nt!KiServiceInternal (fffff800
016a3c40)
fffff800`016a0d9e 6690 xchg ax,ax
So I need some way to find nt!KiServiceLinkage, nt!KiServiceInternal and modify the 0F8 syscall number to use the one I find in case it is a different system.
My assumption is I can calculate the addresses for the Ki* functions, lea and jmp to the calculated addresses but substitute for a far jmp instead.
Does this seem reasonable?
Also passing the args should be taken care of by the caller to my asm function…as that is what appears to happen for the available Zw calls.
For the record all responses have been helpful.
xxxxx@yahoo.com wrote:
…
So I need some way to find nt!KiServiceLinkage, nt!KiServiceInternal and modify the 0F8 syscall number to use the one I find in case it is a different system.
My assumption is I can calculate the addresses for the Ki* functions, lea and jmp to the calculated addresses but substitute for a far jmp instead.
Does this seem reasonable?
Reasonable? Hell, no. The REASONABLE path is to call ZwOpenThread
directly and forget about vectoring through the service table by hand.
I don’t know what you think you’re going to save through this route, but
it’s almost certainly a false optimization.
–
Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.
I was giving ZwOpenThread as an example of the disassembly…when if you read the whole thread you would see I am interested in non-exported functions such as ZwTerminateThread and ZwProtectVirtualMemory.
Thanks.