26번 API 참조 문서. InitiateSystemShutdown API에 대한 문서를 작성하던 도중, SE_SHUTDOWN_PRIVILEGE 특권을 활성화시켜주지 않아서 시스템 종료가 되지 않았다.


그렇다고 AdjustTokenPrivilege 등의 API를 선언해주기는 귀찮고.. 

그러던 도중 System.Diagnostics.Process 클래스에서 본 EnterDebugMode 메서드가 생각이 났다.

System.Diagnostics.Process.EnterDebugMode() 메서드는 호출 스레드에 SE_DEBUG_PRIVILEGE 특권을 활성화해주는데 혹시나 해서 Process 클래스를 디스어셈블해서 본 결과 EnterDebugMode 메서드는 아래와 같이 코딩되어 있었다.

public static void EnterDebugMode()
{
    if (ProcessManager.IsNt)
    {
        Process.SetPrivilege("SeDebugPrivilege"2);
    }
}


Process 클래스 내에 선언되어 있는 SetPrivilege 메서드는 private static 으로 접근 한정자가 지정되어 있어, Reflection을 이용하면 되지 않을까? 라는 생각을 했고.. 다음과 같이 코드를 짜보았다.

public static void SetPrivilege(String privilegeName, Int32 state) {
    Assembly asm = Assembly.GetAssembly(typeof(System.Diagnostics.Process));
    if ( asm == null ) return;
    
    Type t = asm.GetType("System.Diagnostics.Process");
    if ( t == null ) return;

    MethodInfo mi = t.GetMethod("SetPrivilege", BindingFlags.Static | BindingFlags.NonPublic);
    if ( mi == null ) return;
    
    Object[] parameters = {privilegeName, state};
    mi.Invoke(null, parameters);
}


이 코드에 대해서 간단하게 설명을 하자면, System.Diagnostics.Process 클래스가 속해있는 어셈블리를 가져오고 그 어셈블리에서 System.Diagnostics.Process 클래스의 형식을 가져오고.. 가져온 형식에서 SetPrivilege라는 공용 멤버가 아니고(=NonPublic) 정적으로 정의된(=Static) 메서드의 정보를 가져오도록 했다. (=MethodInfo)


그리고 가져온 메서드 정보가 유효하다면, privilegeName, state 두 개의 매개 변수를 넘겨줌으로써 private 로 선언된 SetPrivilege 메서드를 호출해본 결과, 대 성공이다 :)


잠시 후에 InitiateSystemShutdown API에 대한 문서도 올리겠지만, 이런 간단한 방법으로도 특권을 활성화시킬 수 있다는 것을 알려주고자 이 글을 쓴 것이다.


도움이 되기 바람!!


* P.S. SetPrivilege 메서드의 VB.NET 선언은 다음과 같다.

Public Shared Sub SetPrivilege(privilegeName As String, state As Int32)
    Dim asm As Assembly = Assembly.GetAssembly(GetType(System.Diagnostics.Process))
    If asm Is Nothing Then
        Return
    End If

    Dim t As Type = asm.GetType("System.Diagnostics.Process")
    If t Is Nothing Then
        Return
    End If

    Dim mi As MethodInfo = t.GetMethod("SetPrivilege", BindingFlags.Static Or BindingFlags.NonPublic)
    If mi Is Nothing Then
        Return
    End If

    Dim parameters As Object() = {privilegeName, state}
    mi.Invoke(Nothing, parameters)
End Sub


* P.S. 2. 특권 활성화는 state의 값을 '2' 로 비활성화는 '0' 으로 값을 주면 된다.

+ Recent posts