News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests

Main Menu

Need Sysenter tips

Started by Mondragon, August 18, 2017, 03:40:44 PM

Previous topic - Next topic

Mondragon

Hello,

I've been doing a lot of research and study of the Windows kernel and for fun, I wanted to try and write some assembly which calls sysenter directly rather than using the Ntdll.dll stuff in order to learn about the system service dispatch table and how it interacts with usermode.

However, I can't really find a concrete example on implementing the sysenter or int 0x2e in code and the other implications behind it such as how to pass arguments to the SSDT call. Could anyone point me in the right direction or give any tips? Thanks.

aw27

Quote from: Mondragon on August 18, 2017, 03:40:44 PM
Hello,

I've been doing a lot of research and study of the Windows kernel and for fun, I wanted to try and write some assembly which calls sysenter directly rather than using the Ntdll.dll stuff in order to learn about the system service dispatch table and how it interacts with usermode.

However, I can't really find a concrete example on implementing the sysenter or int 0x2e in code and the other implications behind it such as how to pass arguments to the SSDT call. Could anyone point me in the right direction or give any tips? Thanks.
Hello Mondragon,
I published a Code Project article which may give you a good introduction on these matters.
Note the following sparse points:
1) SSDT service numbers may vary between Windows releases.
2) the edx register points to the list of arguments.
3) In x64, the instruction is syscall and the 1st 4 arguments are passed in registers, remaining on the stack.

I have no test sample right now, but it is uncomplicated.

Mondragon

aw27,

Thanks a lot, just got done reading and it cleared up a few things! :eusa_clap:

Some of the comments were scarier than the article... But thats probably because my idea of after-work fun is reading the Windows Internals book :P

So it seems basically 2 things are needed to pull this off:

1. The address of the beginning of the stack

2. The Dispatch ID of the func.

Using these 2 things, the kernel will call up the function and pass it the arguments. Only question I got now is, how is the return for the kernel function handled ie passing a return from the kernel func back to user mode? Or am I having a late-night brain fart and this isn't even necessary?

Thanks again! I feel like this info is pretty scarce, especially when compared to all the javascript stuff out now haha.

aw27

Quote from: Mondragon on August 18, 2017, 05:32:37 PM
Only question I got now is, how is the return for the kernel function handled ie passing a return from the kernel func back to user mode? Or am I having a late-night brain fart and this isn't even necessary?

I am not fresh on the subject, so I am not willing to give you information that may not be correct.
The idea I have now now, and may be wrong, is that you need to push the return address on the stack because sysenter will not do that.
BTW, when you have something working please post here.  :t

jj2007

Quote from: Mondragon on August 18, 2017, 05:32:37 PMOnly question I got now is, how is the return for the kernel function handled ie passing a return from the kernel func back to user mode?

The pointer to the return address is passed in edx, together with any other parameters:KiFastSystemCall:
mov edx, esp
sysenter
retn


Btw you have an interesting project there, what are you trying to achieve?

Mondragon

Aha! That makes sense!

I'm trying to learn how to do this so I can write some proof-of-concepts first and then who knows, maybe write my own API or something. I'm a security researcher so the more knowledge of stuff like this, the better when it comes to understanding malware and stuff.

hutch--

Mondragon,

Do us a favour and be very careful what you post on this subject as unfortunately there are always lurkers interested in using this low level access to write trojans, rootkits and viruses. We have been stung so many times with people desperate to learn how to write malicious code that any system low level access is subject to abuse.

I would also ask other members to exercise care here as any blowback of illegal code gets pointed at me and I will actively support any country's security agency in tracking down anyone who tries to post crap in here.

aw27

#7
Quote from: hutch-- on August 19, 2017, 08:20:27 AM
I would also ask other members to exercise care here as any blowback of illegal code gets pointed at me and I will actively support any country's security agency in tracking down anyone who tries to post crap in here.
@hutch
Ok!

@Mondragon

This is a complete working example which will make a sysenter call to retrieve the number of processors.
NOTE1: It will only run on a 32 bit operating system (Will not run on Wow64)
NOTE2: the system service 105h is only suitable for Windows 7 - 32 bit and it was only tested on Windows 7 - 32 bit. For other editions look here  (function NtQuerySystemInformation). I have not tested.
NOTE3: The point that is usually disregarded is that the stacked arguments begin 8 bytes above top of stack.


.686

.model Flat, stdcall
option Casemap :None


includelib \masm32\lib\kernel32.lib
ExitProcess proto STDCALL :dword
includelib \masm32\lib\msvcrt.lib
printf proto C :ptr, :vararg

_SYSTEM_BASIC_INFORMATION struct 4
    Reserved1 byte 24 dup (?)
    Reserved2 dword 4 dup (?)
    NumberOfProcessors sbyte ?
_SYSTEM_BASIC_INFORMATION ends

.data
format0 db "Number of processors: %d retlen: %x retval: %04x",13,10,0


.code

main proc
LOCAL basicinfo :  _SYSTEM_BASIC_INFORMATION
LOCAL _retlen : dword

mov _retlen,0
lea eax, _retlen
push eax
push sizeof basicinfo
lea eax, basicinfo
push eax
push 0
mov eax, 105h ; Value for Windows 7=0x105! NOT tested, but for Windows 10 1507=0x009a 1511=0x009a 1607=0x009b
push offset @f
push offset @f ; The convention is that the stacked arguments begin 8 bytes above top of stack
mov edx, esp
sysenter
@@:
add esp, 20
invoke printf, addr format0, basicinfo.NumberOfProcessors, _retlen, eax
invoke ExitProcess,0

main endp

end main


Number of processors: 4 retlen: 2c retval: 0000



aw27

#8
For people interested, I have also produced an example of using SYSCALL. The procedure is completely different than the one for SYSENTER.

morgot

Hello AW,
why you need to use this lines:
push offset @f
push offset @f  ?

Why only two arguments (two pushes)? Does it depend on the number of function parameters or not?
Sorry for the bad English