Calling Nt function from ntdll.dll in Win32 environment, C++
Asked Answered
S

1

5

I want to call some Nt function from ntdll.dll, I'm doing that like this above.

For calling: NtTestAlert() , you need typical ntcall kernel routine, accessable via int 2Eh. ( from here I got Nt functions http://undocumented.ntinternals.net/ )

Code is also unfinished, I'm getting:

*error C2664: '_ntcall' : cannot convert parameter 1 from 'int' to 'MESS (_stdcall )'

#include <iostream>
#include <windows.h>
#include <Ntsecapi.h>

using namespace std;

typedef int(__stdcall MESS)(unsigned int);

void __ntcall(MESS *msg)
{
    __asm
    {
        int 2Eh;
    }
}

int main(void)
{
    MESS *me = 0;
    int result = 0;

    HINSTANCE__ *hModule= LoadLibrary(L"C:\\Windows\\System32\\ntdll.dll");

    if(hModule != 0)
    {
        me = (MESS*)GetProcAddress(hModule, "NtTestAlert");

        if(me != 0)
        {
            unsigned int type = 1;

            result = (__ntcall((*me)(type)));
        }
        else
        {
            cout << "Error Load function!" << endl;
        }

        FreeLibrary(hModule);
    }
    else
    {
        cout << "Error load Dll!" << endl;
    }

    return 0;
}
Staunch answered 9/4, 2012 at 15:26 Comment(0)
S
12

You simply call the function whose pointer you retrieve. The int 2Eh is an old (and since XP SP2 outdated) method of making system calls. When calling (just via the normal means) an NTDLL function that is what goes on underneath. You need not care about that.

Side-note: you seem to confuse some more concepts. NtTestAlert doesn't take a parameter.

NTSYSAPI NTSTATUS NTAPI NtTestAlert();

so that would translate to (your MESS type):

typedef NTSTATUS(__stdcall *TFNNtTestAlert)();

An example based on yours:

#include <iostream>
#include <windows.h>
#include <tchar.h>
#include <Ntsecapi.h>

using namespace std;

typedef NTSTATUS (__stdcall *TFNNtTestAlert)();
// NTSTATUS is LONG, in case that isn't defined in the above headers

int main(void)
{
    HMODULE hModule=GetModuleHandle(TEXT("ntdll.dll"));

    if(hModule != 0)
    {
        TFNNtTestAlert pfnNtTestAlert = (TFNNtTestAlert)GetProcAddress(hModule, "NtTestAlert");

        if(pfnNtTestAlert != 0)
        {
            result = pfnNtTestAlert();
        }
        else
        {
            cout << "Error Load function!" << endl;
            return 1;
        }
    }
    else
    {
        cout << "Error load Dll!" << endl;
        return 2;
    }

    return 0;
}

System call mechanism:

the syscall mechanism in Windows used int 2Eh at some point (and now sysenter) to pass the parameters on the user mode stack, the index of the syscall and then invoke the dispatcher. This then transitions the thread into kernel mode, where the parameters from the user mode stack are checked and then the handling proceeds. This is a very rough outline. I suggest you read Gary Nebbett's book on the topic.

Scotney answered 9/4, 2012 at 15:29 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.