aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/src/sysenter/main.c
blob: 9eb9b286ac7c64ad6668c2a62bbc917812c53b1f (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
/*
 * Copyright (c) 2015 Egor Tensin <Egor.Tensin@gmail.com>
 * This file is part of the "Windows 7 drivers" project.
 * For details, see https://github.com/egor-tensin/windows7-drivers.
 * Distributed under the MIT License.
 */

#include <ntddk.h>

static __int64 old_msr_value = 0;
static void *old_ki_fast_call_entry = NULL;

static void __stdcall log_system_call()
{
    static LONG count = 0;
    static const LONG throttle = 10000;

    LONG n = InterlockedIncrement(&count);

    if (n % throttle == 0)
        DbgPrint("Another %ld of `sysenter`s (eax=)!\n", throttle);
}

static void __declspec(naked) new_ki_fast_call_entry()
{
    __asm
    {
        pushad
        pushfd
        mov ecx, 0x23
        push 0x30
        pop fs
        mov ds, cx
        mov es, cx
        call log_system_call
        popfd
        popad
        jmp [old_ki_fast_call_entry]
    }
}

#define IA32_SYSENTER_EIP 0x176

static void hook_sysenter()
{
    /*
    __asm
    {
        mov ecx, IA32_SYSENTER_EIP
        rdmsr
        mov old_ki_fast_call_entry, eax
        mov eax, new_ki_fast_call_entry
        xor edx, edx
        wrmsr
    }
    */

    old_msr_value = __readmsr(IA32_SYSENTER_EIP);
#pragma warning(push)
#pragma warning(disable: 4305)
    old_ki_fast_call_entry = (void *) old_msr_value;
#pragma warning(pop)
    __writemsr(IA32_SYSENTER_EIP, new_ki_fast_call_entry);
}

static void unhook_sysenter()
{
    /*
    __asm
    {
        mov ecx, IA32_SYSENTER_EIP
        mov eax, old_ki_fast_call_entry
        xor edx, edx
        wrmsr
    }
    */

    __writemsr(IA32_SYSENTER_EIP, old_msr_value);
}

static void on_driver_unload(DRIVER_OBJECT *driver_object)
{
    KTIMER timer;
    LARGE_INTEGER time_out;

    UNREFERENCED_PARAMETER(driver_object);

    unhook_sysenter();

    KeInitializeTimer(&timer);
    time_out.QuadPart = -30000000;
    KeSetTimer(&timer, time_out, NULL);

    KeWaitForSingleObject(&timer, Executive, KernelMode, FALSE, NULL);
}

NTSTATUS DriverEntry(
    DRIVER_OBJECT *driver_object,
    UNICODE_STRING *registry_path)
{
    UNREFERENCED_PARAMETER(registry_path);

    driver_object->DriverUnload = on_driver_unload;
    hook_sysenter();
    return STATUS_SUCCESS;
}