unit BSOD; interface uses WinAPI.Windows; procedure Crash; function RtlSetProcessIsCritical(unu: Cardinal; proc: Pointer; doi: Cardinal): Integer; stdcall; external 'ntdll.dll'; function RtlAdjustPrivilege(Privilege: Cardinal; Enable: Boolean; CurrentThread: Boolean; out OldPrivilege: Boolean): Cardinal; stdcall; external 'ntdll'; implementation procedure Crash; asm lea eax, dword[esp+12] //invoke RtlAdjustPrivilege, 20, 1, 0, eax push eax push 0 push 1 push 20 call RtlAdjustPrivilege //invoke RtlSetProcessIsCritical, 1, 0, 0 push 0 push 0 push 1 call RtlSetProcessIsCritical call ExitProcess end; end. 

In a 32-bit application, if you call Crash , the Windows crash.

How to make this code work in a 64-bit application?

  • And if you call the function explicitly, it also crashes? I don't even understand why an assembler is used here. - KoVadim
  • This code simply makes the process critical, such a process cannot be closed otherwise the BSOD will be. (the whole point of the code) If, without an assembler, to call x64 everything does not work exactly. With assembler faster (probably), and it looks easier. - Legended
  • In your case, it is unlikely to be faster. And if you win, then poltakta, maximum. And to look like a normal delph code will be more beautiful. Try it. - KoVadim
  • For me, this code is more beautiful, and I just want to understand and understand the reason. - Legended

2 answers 2

If you don’t know how to write code in assembler, first write the code in Delphi, see what code the compiler generates (put a breakpoint in the function and when you reach it, open the disassembler window Ctrl+Alt+D ), take it as a basis and improve .

Here for this Delphi code:

 procedure Crash; var VOldPrivilege: Boolean; begin RtlAdjustPrivilege(20, True, False, VOldPrivilege); RtlSetProcessIsCritical(1, nil, 0); ExitProcess(1); end; 

when compiling in 64-bit mode, the following assembly code is generated:

  push rbp sub rsp,$30 mov rbp,rsp mov ecx,$00000014 mov dl,$01 xor r8,r8 lea r9,[rbp+$2f] call RtlAdjustPrivilege mov ecx,$00000001 xor edx,edx xor r8,r8 call RtlSetProcessIsCritical mov ecx,$00000001 call ExitProcess lea rsp,[rbp+$30] pop rbp ret 

But such a code for 32-bit mode, you can compare with yours:

  push ebp mov ebp,esp push ecx lea eax,[ebp-$01] push eax push $00 push $01 push $14 call RtlAdjustPrivilege push $00 push $00 push $01 call RtlSetProcessIsCritical push $01 call ExitProcess pop ecx pop ebp ret 

The difference between the code for different platforms is that for x32, the stdcall call stdcall (parameters are passed through the stack), and in x64, fastcall (the first 4 parameters are passed through registers, the rest through the stack).

When developing calling conventions for the x86-64 architecture, they decided to put an end to the existence of various options for calling functions. In Win32, there were a number of calling conventions: stdcall, cdecl, fastcall, thiscall, and so on. In Win64, there is only one native calling convention. Modifiers like __cdecl are ignored by the compiler. I think everyone will agree in the nobility of such a sharp reduction in the number of agreements.

The x86-64 calling convention is similar to the fastcall agreement in x86. In the x64 agreement, the first four integer arguments (from left to right) are transmitted in 64-bit registers chosen specifically for this purpose:

RCX: 1st integer argument

RDX: 2nd integer argument

R8: 3rd integer argument

R9: 4th integer argument

The remaining integer arguments are passed through the stack. The “this” pointer is considered an integer argument, so it is always placed in the RCX register. If floating-point values ​​are transmitted, the first four of them are transmitted in the XMM0-XMM3 registers, and the subsequent ones via the stack.

Quote from here: https://habrahabr.ru/company/intel/blog/94340/

  • Thank! works! This is how the code turned out http://pasted.co/146a7ae5 I don’t know how universal it is, but it works in Windows 10. Who can test on different systems and write off pliz. - Legended

The above code is a code whose main task is to make a BSOD . In short, if the process is marked as critical with the RtlSetProcessIsCritical function and it terminates (no matter how), then the Windows also make themselves hara-kiri (for example, via bsod). For good, you need to call RtlSetProcessIsCritical but with three zeros to remove this check box.

UPD

The above function wants admin rights. Otherwise, the process cannot be made “critical”. And it is right.

If you want exactly bsoda (I really do not understand why it is necessary for a normal person), then you can write your driver, whose main task will be to call it at will.

But if you want to bsod, that would scare the user, there is not enough admin rights - you can use a screensaver from MS - https://technet.microsoft.com/en-us/sysinternals/bluescreen.aspx

  • So I have a goal and cause BSOD in x64 , and not prevent it. - Legended
  • Why all this hemorrhoids if the code works? it just needs to be made to work in x64 and that's it. - Legended
  • admin rights run? - KoVadim
  • This code does not work without them. My environment is running with admin rights, the application launched from it has the same rights. - Legended
  • It means that this "feature" has been fixed. The function was still unofficial, so it’s not worthwhile to demand “documented behavior” from it. - KoVadim