Windows 7 x86 perform a direct system call using sysenter


I'm trying to write some program to directly call a system call without going through ntdll.dll

My code ( Visual Studio syntax...):

#include <windows.h>

int main()
        push arg1
        push arg2
        push arg3
        mov eax,syscall_id
        mov edx,esp
        _emit 0xf
        _emit 0x34 //sysenter opcodes...

When the program tries to execute the sysenter instruction the program crash with this access violation:

CALL DWORD PTR DS:[EAX+EDX*4] // Access Violation when reading [00000128]

EAX == 0x00000000
EDX == 0x0000004D

I tried to put a hw breakpoint using a kernel debugger in the desired system call and the execution flow is not reaching there...

I guess the problem has something to do with stack order/depth.

Thanks a lot!


I guess the problem was that i was trying to execute a win32k system call without loading user32 and gdi32 dlls.

just added:


and problem solved..

If anyone has a better idea why this happens without loading those dlls , i will be pleased to know :)

asked on Stack Overflow Nov 3, 2013 by John Smith • edited Nov 3, 2013 by John Smith

1 Answer


SYSENTER and SYSEXIT opcodes do not behave as normal call/ret opcodes.

Both SYSENTER and SYSEXIT peform jumps to predefined addresses (one in the kernel space and the other in the user space).

Specifically, SYSEXIT is set to jump to KiFastSystemCallRet in ntdll. Usually the system procedures exported in ntdll call KiFastSystemCall, instead of directly using SYSENTER. Let's look on the KiFastSystemCall and KiFastSystemCallRet in ntdll:

KiFastSystemCall:     mov edx, esp
KiFastSystemCallRet:  retn

Your code would result in a system procedure returning from the kernel to a RETN instruction, meaning returning to whatever address you have in arg3. I have no idea why loading user32 and gdi32 changes anything, maybe it has to do with the value of arg3.

Anyway, the safest way to calling a kernel system procedure on your own is using KiFastSystemCall. You could also writing your own code, bearing in mind that that first opcode when returning from kernel-mode would be RETN, so your code would need to have the return address at the top of the stack.

answered on Stack Overflow Sep 5, 2014 by Adam

User contributions licensed under CC BY-SA 3.0