[NTAPI] RtlSetProcessIsCritical - 프로세스 강제 종료 시 BSOD(블루스크린)을 발생시키도록 한다
안녕하세요. 오랜 만에 간단한 팁을 써보게 되네요. ^^ 오늘 소개할 NTAPI는 RtlSetProcessIsCritical 로, 이 API는 자신의 프로세스를 winlogon.exe와 같은 Critical Process로 설정하는 함수입니다. 따라서 프로세스를 강제로 종료하게 되면 블루스크린을 유발하게 됩니다.
이를 악용한다면 한없이 악용할 수도 있겠지만, 반대로 좋은 쪽으로 사용한다면 보안 프로세스에서 비정상적인 종료를 방지할 때 사용할 수도 있을 것입니다. 위험한 함수이니 만큼 제가 특별히 안전하게 사용할 수 있는 함수를 하나 만들었습니다.
Option Explicit
' ### 특권 활성화 코드
Private Declare Function RtlAdjustPrivilege Lib "ntdll" ( _
ByVal Privilege As Long, _
ByVal bEnablePrivilege As Long, _
ByVal IsThreadPrivilege As Long, _
ByRef PreviousValue As Long _
) As Long
' ### 임계 프로세스 설정
Private Declare Function RtlSetProcessIsCritical Lib "ntdll" ( _
ByVal NewValue As Long, _
ByRef OldValue As Long, _
ByVal IsWinlogon As Long _
) As Long
' ### 미처리 예외 핸들러 설정
Private Declare Function SetUnhandledExceptionFilter Lib "kernel32.dll" ( _
ByVal lpTopLevelExceptionFilter As Long _
) As Long
' ### 스레드 관련 API
Private Declare Function CreateThread Lib "kernel32.dll" ( _
ByRef lpThreadAttributes As Any, _
ByVal dwStackSize As Long, _
ByVal lpStartAddress As Long, _
ByRef lpParameter As Any, _
ByVal dwCreationFlags As Long, _
ByRef lpThreadId As Long _
) As Long
Private Declare Function WaitForSingleObject Lib "kernel32.dll" ( _
ByVal hHandle As Long, _
ByVal dwMilliseconds As Long _
) As Long
Private Declare Function GetExitCodeThread Lib "kernel32.dll" ( _
ByVal hThread As Long, _
ByRef lpExitCode As Long _
) As Long
Private Declare Function CloseHandle Lib "kernel32.dll" ( _
ByVal hObject As Long _
) As Long
Private Const INFINITE& = &HFFFFFFFF
Private Const WAIT_OBJECT_0& = 0&
Private Const SeDebugPrivilege& = 20&
Private OldSEH As Long, OldValue As Long, Protected As Boolean
Public Function ProtectProcess() As Boolean
On Error GoTo Failed
' ### 이미 보호되어 있다면 탈출
If Protected Then ProtectProcess = True: Exit Function
' ### IDE인 경우 탈출
If App.LogMode = 0& Then Exit Function
' ### 디버그 특권을 얻는다.
If RtlAdjustPrivilege(SeDebugPrivilege, 1&, 0&, 0&) >= 0& Then
' ### 미처리 예외 핸들러 설정
' ### (API 쓰다가 무슨 일이 생길지 모르므로...)
OldSEH = SetUnhandledExceptionFilter(AddressOf SafeSEH)
' ### 임계 프로세스 설정
If RtlSetProcessIsCritical(1&, OldValue, 0&) >= 0& Then
Protected = True: ProtectProcess = True
End If
End If
Failed:
End Function
Public Sub RestoreProcess()
On Error GoTo Failed
' ### 원상태로 복구
SetUnhandledExceptionFilter OldSEH
RtlSetProcessIsCritical OldValue, 0&, 0&
Protected = False
Failed:
End Sub
Private Function SafeSEH(ByVal pvExceptPointer As Long) As Long
' ### 원상태로 복구
RestoreProcess
' ### 정상적인 처리를 위해 이전 예외 처리기 함수를 호출해준다.
If OldSEH Then
Dim hThread As Long, retVal As Long
hThread = CreateThread(ByVal 0&, 0&, OldSEH, ByVal pvExceptPointer, 0&, 0&)
If WaitForSingleObject(hThread, INFINITE) = WAIT_OBJECT_0 Then
If GetExitCodeThread(hThread, retVal) Then
SafeSEH = retVal
End If
End If
CloseHandle hThread
End If
End Function
모듈에 위와 같이 선언한 후, 폼의 코드부에서 다음과 같이 선언해주시면 됩니다.
Option Explicit
Private Sub Form_Load()
ProtectProcess
End Sub
Private Sub Form_Unload(Cancel As Integer)
RestoreProcess
End Sub
첫댓글 궁금한거요.. 끄면 프로세스보호가 해제되는것 같은데 그럼 의미가 없잖아요... 못끄게 하려는 건데...
ㅎㅎ... 강제로 작업 관리자 등에서 끄려고 할때만 유효해요. 바이러스의 경우 폼의 종료 단추 자체가 없기 때문에 정상 종료가 불가능해지겠죠? ^^;
리눅스에서 Wine으로 실행시켜도 블루스크린 떠요??
역시 수학쟁이님임... 완전 윈도 분석 쌈박하시네 ㅎㅎ
저기요 그렇다면 블루스크린이 안뜨고 다른 프로세스를 종료하도록 할려면 어떻게하나요
그런데요.
저거 보니 세마포어(?) 아닌가요?
그리고 대체 어떤 원리로 블루스크린이 뜨죠?
수학쟁이님 이거 윈7에서 관리자 권한 없이 실행하려고 사용자계정 UAC 최하로 설정하고 실행하면 91 런타임 오류가 뜨는데 방법이 없을까요?