C# Как P/ вызвать NtRaiseHardError

Следующий код C++ вызывает синий экран.

    #include "stdafx.h"
    #include <iostream>
    #include <string>
    #include <Windows.h>

    #pragma comment(lib, "ntdll.lib")


    using namespace std;


    EXTERN_C NTSTATUS NTAPI RtlAdjustPrivilege(ULONG, BOOLEAN, BOOLEAN, PBOOLEAN);

    EXTERN_C NTSTATUS NTAPI NtRaiseHardError(NTSTATUS, ULONG, ULONG, PULONG_PTR, ULONG, PULONG);

    int main(int argc, char **argv)
    {
        BOOLEAN bl;
        RtlAdjustPrivilege(19, TRUE, FALSE, &bl);
        unsigned long response;
        NtRaiseHardError(STATUS_ASSERTION_FAILURE, 0, 0, 0, 6, &response);
        return 0;
    }

Я хочу использовать C# для этого, поэтому я попытался использовать P/Invoke. Но это не работает. Проблема правильно в подписи NtRaiseHardError. Я ничего не нашел в Интернете (например, pinvoke.net не показывает NtRaiseHardError, потому что он недокументирован).
Вот что я попробовал:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Runtime.InteropServices;
    using System.IO;

    namespace BSCS
    {
        class Program
        {
            private static ulong STATUS_ASSERTION_FAILURE = 0xC0000420;

            static void Main(string[] args)
            {
                Console.WriteLine("Adjusting privileges");
                RtlAdjustPrivilege(19, true, false, out bool previousValue);
                Console.WriteLine("Triggering BSOD");
                NtRaiseHardError(STATUS_ASSERTION_FAILURE, 0, 0, 0, 6, out ulong oul);
                Console.WriteLine("Done");
            }

            [DllImport("ntdll.dll")]
            private static extern IntPtr RtlAdjustPrivilege(int Privilege, bool bEnablePrivilege, bool IsThreadPrivilege,
                out bool PreviousValue);

            [DllImport("ntdll.dll")]
            private static extern IntPtr NtRaiseHardError(ulong status, ulong ul, ulong ul2, ulong ul3, ulong ul4, out ulong oul);
        }
    }

1 ответ

Решение

Обе ваши декларации пинвока не верны. В основном ваше использование C# ulong который является 64-битным типом. C++ long тип 32 бит в Windows.

Я бы объявил их так

[DllImport("ntdll.dll")]
private static extern uint RtlAdjustPrivilege(
    int Privilege, 
    bool bEnablePrivilege, 
    bool IsThreadPrivilege,
    out bool PreviousValue
);

[DllImport("ntdll.dll")]
private static extern uint NtRaiseHardError(
    uint ErrorStatus, 
    uint NumberOfParameters, 
    uint UnicodeStringParameterMask, 
    IntPtr Parameters, 
    uint ValidResponseOption, 
    out uint Response
);

Я взял короткий путь с PULONG_PTR, Поскольку вы передаете нулевой указатель, его легче объявить как IntPtr и передать IntPtr.Zero,

Другие вопросы по тегам