none
SeBackupPrivilegeについて RRS feed

回答

  • Shared Sub Main(ByVal abc() As String)
        ModifyState("SeBackupPrivilege", True)
    
        '現在のコンソールに表示させる場合
        Dim psi As New ProcessStartInfo("whoami.exe", "/priv")
        psi.UseShellExecute = False
        Using p As Process = Process.Start(psi)
            p.WaitForExit()
        End Using
    
        'MsgBox で表示させる場合
        psi = New ProcessStartInfo("whoami.exe", "/priv")
        psi.UseShellExecute = False
        psi.RedirectStandardOutput = True
        Dim msg As String
        Using p As Process = Process.Start(psi)
            msg = p.StandardOutput.ReadToEnd()
            p.WaitForExit()
        End Using
        MsgBox(msg, MsgBoxStyle.Information Or MsgBoxStyle.SystemModal)
    
        Console.WriteLine("End!")
        Console.ReadKey()
    End Sub

    • 回答としてマーク Luky9 2019年7月4日 7:57
    2019年7月4日 7:15
  • .NET のソースに特権を操作している箇所があります。

    https://referencesource.microsoft.com/#mscorlib/system/security/accesscontrol/privilege.cs

    "SeTakeOwnershipPrivilege" の TakeOwnership のように、ダブルクリックすると使われている箇所が左のフレームに出てくるのですが、"SeBackupPrivilege" の Backup についてはダブルクリックしても出てこないので、定義はあるものの、残念ながら使われていないようです。

    あとは、6/12 に ShiroYuki_Mot さんが紹介してくださった記事(の英語版です)
    https://support.microsoft.com/en-us/help/318744/how-to-use-visual-basic-to-programmatically-change-ownership-of-a-file
    を見てゴリゴリ書いていくしかなさそうです。

    • 回答としてマーク Luky9 2019年7月4日 7:58
    2019年7月3日 8:18

  • https://support.microsoft.com/en-us/help/318744/how-to-use-visual-basic-to-programmatically-change-ownership-of-a-file
    この記事で必要なのは 

    Public Function ModifyState(Privilege As String, _
          Enable As Boolean) As Boolean

    の中身です。

    GetCurrentProcess
    OpenProcessToken
    LookupPrivilegeValue
    AdjustTokenPrivileges
    CloseHandle

    これら API の定義と使用している構造体については、.NET のソース(C#)を見て、VB.NET にコンバートしていけばよいです。

    出来上がったら

    ModifyState("SeBackupPrivilege", True)

    で特権が有効になり

    ModifyState("SeBackupPrivilege", False)

    で無効になります。
    • 回答としてマーク Luky9 2019年7月4日 7:58
    2019年7月3日 9:41
  • 「MyPrives.Privileges(0).Luid = PrivilegeId」でエラー発生しています。

    コンパイルエラーなのかコンパイル警告なのか実行時例外なのかすらわからないので、何のエラーかぐらいは書いて欲しかった所ですが…これは配列が未初期化なのが原因ですね。

    「If MyPrives.Privileges Is Nothing OrElse MyPrives.Privileges.Length = 0 Then」が真となる状況なら、未初期化による NullReferenceException (もしくは要素不足による IndexOutOfRangeException)になりそうです。

    TOKEN_PRIVILEGES 構造体の宣言に

    Public Sub New(count As Integer)
        PrivilegeCount = CUInt(count)
        Privileges = New LUID_AND_ATTRIBUTES(count - 1) {}
    End Sub

    というコンストラクタを追加しておき、利用時には

    'Dim MyPrives As TOKEN_PRIVILEGES
    Dim MyPrives As New TOKEN_PRIVILEGES(ANYSIZE_ARRAY)
    と書き換えれば、この点は解決されると思います。

    1. 今のコードだと、IntPtr 型や Boolean 型で宣言すべき場所で As Long 変数が使われているといった問題があります。データ型の指定ミスを減らすためにも、「Option Strict On」を必ず付与するようにしましょう。
    2. Or → OrElse への変更も忘れずに。
    3. OpenProcessToken の最後の引数は出力引数なので、「<Out> ByRef TokenHandle As IntPtr」のように Out 属性を付与した方がベターです。また、ここに渡す変数は IntPtr 型でなければなりません。
    4. AdjustTokenPrivileges の最後の引数も出力引数です。ここは「ByRef ReturnLength As IntPtr」では誤りで、正しくは「<Out> ByRef ReturnLength As Integer」として、Integer 型の変数を渡すようにします。ただし、最後の引数から値を受け取る必要が無い場合には、宣言を「ByVal ReturnLength As IntPtr」としておき、ここに IntPtr.Zero を渡すという方法が使えます。
    • 回答としてマーク Luky9 2019年7月4日 7:58
    2019年7月4日 2:20
  • 弁士さんの回答を読まれていないのでしょうか?

    アドバイスどおりにプログラムを修正して、管理者権限をつけて実行すれば動くはずですよ。

    • 回答としてマーク Luky9 2019年7月4日 7:58
    2019年7月4日 4:45
  • エラーコードは 998 ですね?

    Dim ex As New System.ComponentModel.Win32Exception(998)
    Debug.Print(ex.ToString())

    で、内容が確認できますが、「メモリ ロケーションへのアクセスが無効です。」なので、AdjustTokenPrivileges の宣言が間違っていると思われます。

    <DllImport("advapi32.dll", SetLastError:=True)>
    Shared Function AdjustTokenPrivileges(
                                          ByVal TokenHandle As IntPtr,
                                          ByVal DisableAllPrivileges As Boolean,
                                          ByRef NewState As TOKEN_PRIVILEGES,
                                          ByVal BufferLength As Integer,
                                          ByVal PreviousState As IntPtr,
                                          ByVal ReturnLength As IntPtr) As Boolean
    End Function
    
    Result = AdjustTokenPrivileges(hToken, False, MyPrives, 0, IntPtr.Zero, IntPtr.Zero)
    

    アドバイスどおりに書くと、こうなるはずです。

    • 回答としてマーク Luky9 2019年7月4日 7:58
    2019年7月4日 6:07
  • 1300 は「参照された特権またはグループのうち、一部の特権が呼び出し側に割り当てられていません。」です。

    管理者権限で実行していないだけでは?

    • 回答としてマーク Luky9 2019年7月4日 7:58
    2019年7月4日 6:35
  • Visual Studio の [ツール] メニューに [エラー検索] がある場合、そこから ErrLook.exe を起動できるようになっています。

    ちなみにエラーコード 1300 は WinError.h で定義されています。

    //
    // MessageId: ERROR_NOT_ALL_ASSIGNED
    //
    // MessageText:
    //
    // Not all privileges or groups referenced are assigned to the caller.
    //
    // 参照された特権またはグループのうち、一部の特権が呼び出し側に割り当てられていません。
    // 
    #define ERROR_NOT_ALL_ASSIGNED           1300L
    


    • 回答としてマーク Luky9 2019年7月4日 7:58
    2019年7月4日 6:41
  • どうやって特権が無い事を確認されたのでしょうか?
    特権が有効なのは、プロセスが生きている間だけなのですが。
    • 回答としてマーク Luky9 2019年7月4日 7:57
    2019年7月4日 7:02

すべての返信

  • .NET のソースに特権を操作している箇所があります。

    https://referencesource.microsoft.com/#mscorlib/system/security/accesscontrol/privilege.cs

    "SeTakeOwnershipPrivilege" の TakeOwnership のように、ダブルクリックすると使われている箇所が左のフレームに出てくるのですが、"SeBackupPrivilege" の Backup についてはダブルクリックしても出てこないので、定義はあるものの、残念ながら使われていないようです。

    あとは、6/12 に ShiroYuki_Mot さんが紹介してくださった記事(の英語版です)
    https://support.microsoft.com/en-us/help/318744/how-to-use-visual-basic-to-programmatically-change-ownership-of-a-file
    を見てゴリゴリ書いていくしかなさそうです。

    • 回答としてマーク Luky9 2019年7月4日 7:58
    2019年7月3日 8:18
  • どうすれば良いでしょうか。助けていただけますでしょうか。

    Luky9

    2019年7月3日 9:00

  • https://support.microsoft.com/en-us/help/318744/how-to-use-visual-basic-to-programmatically-change-ownership-of-a-file
    この記事で必要なのは 

    Public Function ModifyState(Privilege As String, _
          Enable As Boolean) As Boolean

    の中身です。

    GetCurrentProcess
    OpenProcessToken
    LookupPrivilegeValue
    AdjustTokenPrivileges
    CloseHandle

    これら API の定義と使用している構造体については、.NET のソース(C#)を見て、VB.NET にコンバートしていけばよいです。

    出来上がったら

    ModifyState("SeBackupPrivilege", True)

    で特権が有効になり

    ModifyState("SeBackupPrivilege", False)

    で無効になります。
    • 回答としてマーク Luky9 2019年7月4日 7:58
    2019年7月3日 9:41
  • ご返信ありがとうございます。下記の通りに実装しまたが 「MyPrives.Privileges(0).Luid = PrivilegeId」でエラー発生しています。vb.netに詳しい方いらしゃいましたら教えていただけますでしょうか。宜しくお願い致します。

    Imports System.Runtime.InteropServices
    Public Class Class1
        Const ANYSIZE_ARRAY As Integer = 1
        Const TOKEN_ADJUST_PRIVILEGES As Integer = &H20
        Const SE_PRIVILEGE_ENABLED As Integer = &H2

        <DllImport("kernel32.dll", EntryPoint:="CloseHandle", SetLastError:=True)>
        Private Shared Function CloseHandle(ByVal hObject As IntPtr) As <MarshalAsAttribute(UnmanagedType.Bool)> Boolean
        End Function

        <StructLayout(LayoutKind.Sequential)>
        Public Structure LUID
            Public LowPart As UInt32
            Public HighPart As UInt32
        End Structure

        <StructLayout(LayoutKind.Sequential)>
        Public Structure LUID_AND_ATTRIBUTES
            Public Luid As LUID
            Public Attributes As UInt32
        End Structure

        <StructLayout(LayoutKind.Sequential)>
        Public Structure TOKEN_PRIVILEGES
            Public PrivilegeCount As UInt32
            <MarshalAs(UnmanagedType.ByValArray, SizeConst:=ANYSIZE_ARRAY)>
            Public Privileges() As LUID_AND_ATTRIBUTES
        End Structure

        <DllImport("advapi32.dll", SetLastError:=True)>
        Shared Function LookupPrivilegeValue(ByVal lpSystemName As String, ByVal lpName As String, ByRef lpLuid As LUID) As Boolean
        End Function

        <DllImport("advapi32.dll", SetLastError:=True)>
        Shared Function OpenProcessToken(ByVal ProcessHandle As IntPtr, ByVal DesiredAccess As Integer, ByRef TokenHandle As IntPtr) As Boolean
        End Function

        <DllImport("advapi32.dll", SetLastError:=True)>
        Shared Function AdjustTokenPrivileges(ByVal TokenHandle As IntPtr, ByVal DisableAllPrivileges As Boolean, ByRef NewState As TOKEN_PRIVILEGES, ByVal BufferLength As Integer, ByRef PreviousState As TOKEN_PRIVILEGES, ByRef ReturnLength As IntPtr) As Boolean
        End Function

        Public Shared Function ModifyState(Privilege As String, Enable As Boolean) As Boolean
            Dim MyPrives As TOKEN_PRIVILEGES
            Dim PrivilegeId As LUID
            Dim hToken As Long
            Dim Result As Long
            Dim hProc As IntPtr = Process.GetCurrentProcess().Handle

            Result = OpenProcessToken(hProc, TOKEN_ADJUST_PRIVILEGES, hToken)
            If (Result = 0) Then
                ModifyState = False
                Exit Function
            End If

            Result = LookupPrivilegeValue(vbNullString, Privilege, PrivilegeId)
            If (Result = 0) Then
                ModifyState = False
                Exit Function
            End If

            MyPrives.Privileges(0).Luid = PrivilegeId
            MyPrives.PrivilegeCount = 1
            If (Enable) Then
                MyPrives.Privileges(0).Attributes = SE_PRIVILEGE_ENABLED
            Else
                MyPrives.Privileges(0).Attributes = 0
            End If

            Result = AdjustTokenPrivileges(hToken, False, MyPrives, 0, MyPrives, 0)
            If (Result = 0 Or Err.LastDllError <> 0) Then
                ModifyState = False
                Exit Function
            End If

            CloseHandle(hToken)
            ModifyState = True
        End Function

        Shared Sub Main(ByVal abc() As String)
            ModifyState("SeBackupPrivilege", True)
            Console.WriteLine("End!")
            Console.ReadKey()
        End Sub
    End Class


    Luky9

    2019年7月4日 1:40
  • 「MyPrives.Privileges(0).Luid = PrivilegeId」でエラー発生しています。

    コンパイルエラーなのかコンパイル警告なのか実行時例外なのかすらわからないので、何のエラーかぐらいは書いて欲しかった所ですが…これは配列が未初期化なのが原因ですね。

    「If MyPrives.Privileges Is Nothing OrElse MyPrives.Privileges.Length = 0 Then」が真となる状況なら、未初期化による NullReferenceException (もしくは要素不足による IndexOutOfRangeException)になりそうです。

    TOKEN_PRIVILEGES 構造体の宣言に

    Public Sub New(count As Integer)
        PrivilegeCount = CUInt(count)
        Privileges = New LUID_AND_ATTRIBUTES(count - 1) {}
    End Sub

    というコンストラクタを追加しておき、利用時には

    'Dim MyPrives As TOKEN_PRIVILEGES
    Dim MyPrives As New TOKEN_PRIVILEGES(ANYSIZE_ARRAY)
    と書き換えれば、この点は解決されると思います。

    1. 今のコードだと、IntPtr 型や Boolean 型で宣言すべき場所で As Long 変数が使われているといった問題があります。データ型の指定ミスを減らすためにも、「Option Strict On」を必ず付与するようにしましょう。
    2. Or → OrElse への変更も忘れずに。
    3. OpenProcessToken の最後の引数は出力引数なので、「<Out> ByRef TokenHandle As IntPtr」のように Out 属性を付与した方がベターです。また、ここに渡す変数は IntPtr 型でなければなりません。
    4. AdjustTokenPrivileges の最後の引数も出力引数です。ここは「ByRef ReturnLength As IntPtr」では誤りで、正しくは「<Out> ByRef ReturnLength As Integer」として、Integer 型の変数を渡すようにします。ただし、最後の引数から値を受け取る必要が無い場合には、宣言を「ByVal ReturnLength As IntPtr」としておき、ここに IntPtr.Zero を渡すという方法が使えます。
    • 回答としてマーク Luky9 2019年7月4日 7:58
    2019年7月4日 2:20
  • ご返信ありがとうございます。今は「Result = AdjustTokenPrivileges(hToken, False, MyPrives, 0, 0, 0)」にエラー発生しています。

    Option Strict On
    Imports System.Runtime.InteropServices
    Public Class Class1
        Const ANYSIZE_ARRAY As Integer = 1
        Const TOKEN_ADJUST_PRIVILEGES As Integer = &H20


        Const SE_PRIVILEGE_ENABLED As Integer = &H2

        <DllImport("kernel32.dll", EntryPoint:="CloseHandle", SetLastError:=True)>
        Private Shared Function CloseHandle(ByVal hObject As IntPtr) As <MarshalAsAttribute(UnmanagedType.Bool)> Boolean
        End Function

        <StructLayout(LayoutKind.Sequential)>
        Public Structure LUID
            Public LowPart As UInt32
            Public HighPart As UInt32
        End Structure

        <StructLayout(LayoutKind.Sequential)>
        Public Structure LUID_AND_ATTRIBUTES
            Public Luid As LUID
            Public Attributes As UInt32
        End Structure

        <StructLayout(LayoutKind.Sequential)>
        Public Structure TOKEN_PRIVILEGES
            Public PrivilegeCount As UInt32
            <MarshalAs(UnmanagedType.ByValArray, SizeConst:=ANYSIZE_ARRAY)>
            Public Privileges() As LUID_AND_ATTRIBUTES
            Public Sub New(count As Integer)
                PrivilegeCount = CUInt(count)
                Privileges = New LUID_AND_ATTRIBUTES(count - 1) {}
            End Sub

        End Structure

        <DllImport("advapi32.dll", SetLastError:=True)>
        Shared Function LookupPrivilegeValue(ByVal lpSystemName As String, ByVal lpName As String, ByRef lpLuid As LUID) As Boolean
        End Function

        <DllImport("advapi32.dll", SetLastError:=True)>
        Shared Function OpenProcessToken(ByVal ProcessHandle As IntPtr, ByVal DesiredAccess As Integer, <Out> ByRef TokenHandle As IntPtr) As Boolean
        End Function

        <DllImport("advapi32.dll", SetLastError:=True)>
        Shared Function AdjustTokenPrivileges(ByVal TokenHandle As IntPtr, ByVal DisableAllPrivileges As Boolean,
          NewState As TOKEN_PRIVILEGES, ByVal BufferLength As Long,
          ByVal PreviousState As Long, <Out> ByRef ReturnLength As Integer) As Boolean
        End Function

        Public Shared Function ModifyState(Privilege As String, Enable As Boolean) As Boolean
            Dim MyPrives As New TOKEN_PRIVILEGES(ANYSIZE_ARRAY)
            Dim PrivilegeId As LUID
            Dim hToken As IntPtr
            Dim Result As Boolean
            Dim hProc As IntPtr = Process.GetCurrentProcess().Handle

            Result = OpenProcessToken(hProc, TOKEN_ADJUST_PRIVILEGES, hToken)
            If (Result = False) Then
                ModifyState = False
                Exit Function
            End If

            Result = LookupPrivilegeValue(vbNullString, Privilege, PrivilegeId)
            If (Result = False) Then
                ModifyState = False
                Exit Function
            End If


            MyPrives.Privileges(0).Luid = PrivilegeId
            MyPrives.PrivilegeCount = 1
            If (Enable) Then
                MyPrives.Privileges(0).Attributes = SE_PRIVILEGE_ENABLED
            Else
                MyPrives.Privileges(0).Attributes = 0
            End If

            'If MyPrives.Privileges Is Nothing OrElse MyPrives.Privileges.Length = 0 Then
            Result = AdjustTokenPrivileges(hToken, False, MyPrives, 0, 0, 0)
            If (Result = False OrElse Err.LastDllError <> 0) Then
                    ModifyState = False
                    Console.WriteLine("AdjustTokenPrivileges failed with error code " & Err.LastDllError)
                    Exit Function
                End If
                'End If


                CloseHandle(hToken)
            ModifyState = True
        End Function

        Shared Sub Main(ByVal abc() As String)
            ModifyState("SeBackupPrivilege", True)
            Console.WriteLine("End!")
            Console.ReadKey()
        End Sub
    End Class


    • 編集済み Luky9 2019年7月4日 5:44
    2019年7月4日 3:04
  • 弁士さんの回答を読まれていないのでしょうか?

    アドバイスどおりにプログラムを修正して、管理者権限をつけて実行すれば動くはずですよ。

    • 回答としてマーク Luky9 2019年7月4日 7:58
    2019年7月4日 4:45
  • アドレス通りにしまたが Result = AdjustTokenPrivileges(hToken, False, MyPrives, 0, 0, 0)にエラー発生しています。「AdjustTokenPrivileges failed with error code 998」

    Luky9


    • 編集済み Luky9 2019年7月4日 5:43
    2019年7月4日 5:12
  • エラーコードは 998 ですね?

    Dim ex As New System.ComponentModel.Win32Exception(998)
    Debug.Print(ex.ToString())

    で、内容が確認できますが、「メモリ ロケーションへのアクセスが無効です。」なので、AdjustTokenPrivileges の宣言が間違っていると思われます。

    <DllImport("advapi32.dll", SetLastError:=True)>
    Shared Function AdjustTokenPrivileges(
                                          ByVal TokenHandle As IntPtr,
                                          ByVal DisableAllPrivileges As Boolean,
                                          ByRef NewState As TOKEN_PRIVILEGES,
                                          ByVal BufferLength As Integer,
                                          ByVal PreviousState As IntPtr,
                                          ByVal ReturnLength As IntPtr) As Boolean
    End Function
    
    Result = AdjustTokenPrivileges(hToken, False, MyPrives, 0, IntPtr.Zero, IntPtr.Zero)
    

    アドバイスどおりに書くと、こうなるはずです。

    • 回答としてマーク Luky9 2019年7月4日 7:58
    2019年7月4日 6:07
  • ご返信ありがとうございます。いまはエラーがないですがSeBackupPrivilegeは有効ならない状況です。



    Luky9



    • 編集済み Luky9 2019年7月4日 6:40
    2019年7月4日 6:28
  • 1300 は「参照された特権またはグループのうち、一部の特権が呼び出し側に割り当てられていません。」です。

    管理者権限で実行していないだけでは?

    • 回答としてマーク Luky9 2019年7月4日 7:58
    2019年7月4日 6:35
  • いまはエラーがないですがSeBackupPrivilegeは有効ならない状況です。

    Luky9

    2019年7月4日 6:41
  • Visual Studio の [ツール] メニューに [エラー検索] がある場合、そこから ErrLook.exe を起動できるようになっています。

    ちなみにエラーコード 1300 は WinError.h で定義されています。

    //
    // MessageId: ERROR_NOT_ALL_ASSIGNED
    //
    // MessageText:
    //
    // Not all privileges or groups referenced are assigned to the caller.
    //
    // 参照された特権またはグループのうち、一部の特権が呼び出し側に割り当てられていません。
    // 
    #define ERROR_NOT_ALL_ASSIGNED           1300L
    


    • 回答としてマーク Luky9 2019年7月4日 7:58
    2019年7月4日 6:41
  • すみません。管理者で実行したらエラーがないですがSeBackupPrivilegeは有効ならない状況です。本当に大変ですね。

    Option Strict On
    Imports System.Runtime.InteropServices
    Public Class Class1
        Const ANYSIZE_ARRAY As Integer = 1
        Const TOKEN_ADJUST_PRIVILEGES As Integer = &H20
        Const SE_PRIVILEGE_ENABLED As Integer = &H2

        <DllImport("kernel32.dll", EntryPoint:="CloseHandle", SetLastError:=True)>
        Private Shared Function CloseHandle(ByVal hObject As IntPtr) As <MarshalAsAttribute(UnmanagedType.Bool)> Boolean
        End Function

        <StructLayout(LayoutKind.Sequential)>
        Public Structure LUID
            Public LowPart As UInt32
            Public HighPart As UInt32
        End Structure

        <StructLayout(LayoutKind.Sequential)>
        Public Structure LUID_AND_ATTRIBUTES
            Public Luid As LUID
            Public Attributes As UInt32
        End Structure

        <StructLayout(LayoutKind.Sequential)>
        Public Structure TOKEN_PRIVILEGES
            Public PrivilegeCount As UInt32
            <MarshalAs(UnmanagedType.ByValArray, SizeConst:=ANYSIZE_ARRAY)>
            Public Privileges() As LUID_AND_ATTRIBUTES
            Public Sub New(count As Integer)
                PrivilegeCount = CUInt(count)
                Privileges = New LUID_AND_ATTRIBUTES(count - 1) {}
            End Sub
        End Structure

        <DllImport("advapi32.dll", SetLastError:=True)>
        Shared Function LookupPrivilegeValue(ByVal lpSystemName As String, ByVal lpName As String, ByRef lpLuid As LUID) As Boolean
        End Function

        <DllImport("advapi32.dll", SetLastError:=True)>
        Shared Function OpenProcessToken(ByVal ProcessHandle As IntPtr, ByVal DesiredAccess As Integer, <Out> ByRef TokenHandle As IntPtr) As Boolean
        End Function

        <DllImport("advapi32.dll", SetLastError:=True)>
        Shared Function AdjustTokenPrivileges(ByVal TokenHandle As IntPtr, ByVal DisableAllPrivileges As Boolean, ByRef NewState As TOKEN_PRIVILEGES, ByVal BufferLength As Integer, ByVal PreviousState As IntPtr, ByVal ReturnLength As IntPtr) As Boolean
        End Function
        Public Shared Function ModifyState(Privilege As String, Enable As Boolean) As Boolean
            Dim MyPrives As New TOKEN_PRIVILEGES(ANYSIZE_ARRAY)
            Dim PrivilegeId As LUID
            Dim hToken As IntPtr
            Dim Result As Boolean
            Dim hProc As IntPtr = Process.GetCurrentProcess().Handle

            Result = OpenProcessToken(hProc, TOKEN_ADJUST_PRIVILEGES, hToken)
            If (Result = False) Then
                ModifyState = False
                Exit Function
            End If

            Result = LookupPrivilegeValue(vbNullString, Privilege, PrivilegeId)
            If (Result = False) Then
                ModifyState = False
                Exit Function
            End If

            MyPrives.Privileges(0).Luid = PrivilegeId
            MyPrives.PrivilegeCount = 1
            If (Enable) Then
                MyPrives.Privileges(0).Attributes = SE_PRIVILEGE_ENABLED
            Else
                MyPrives.Privileges(0).Attributes = 0
            End If

            Result = AdjustTokenPrivileges(hToken, False, MyPrives, 0, IntPtr.Zero, IntPtr.Zero)
            If (Result = False OrElse Err.LastDllError <> 0) Then
                ModifyState = False
                Console.WriteLine("AdjustTokenPrivileges failed with error code " & Err.LastDllError)
                Exit Function
            End If

            CloseHandle(hToken)
            ModifyState = True
        End Function
        Shared Sub Main(ByVal abc() As String)
            If ModifyState("SeBackupPrivilege", True) Then
                Console.WriteLine("OK")
            End If
            Console.WriteLine("End!")
            Console.ReadKey()
        End Sub

    End Class


    Luky9


    • 編集済み Luky9 2019年7月4日 6:51
    • 回答の候補に設定 KOZ6.0 2019年7月5日 1:40
    2019年7月4日 6:47
  • どうやって特権が無い事を確認されたのでしょうか?
    特権が有効なのは、プロセスが生きている間だけなのですが。
    • 回答としてマーク Luky9 2019年7月4日 7:57
    2019年7月4日 7:02
  • 管理者権限でコマンドプロンプトで「whoami /priv」というコマンドで確認できます。元々無効でした。上のプログラムを実行したら有効なるのに無効ままでした。

    Luky9



    • 編集済み Luky9 2019年7月4日 7:08
    2019年7月4日 7:06
  • Shared Sub Main(ByVal abc() As String)
        ModifyState("SeBackupPrivilege", True)
    
        '現在のコンソールに表示させる場合
        Dim psi As New ProcessStartInfo("whoami.exe", "/priv")
        psi.UseShellExecute = False
        Using p As Process = Process.Start(psi)
            p.WaitForExit()
        End Using
    
        'MsgBox で表示させる場合
        psi = New ProcessStartInfo("whoami.exe", "/priv")
        psi.UseShellExecute = False
        psi.RedirectStandardOutput = True
        Dim msg As String
        Using p As Process = Process.Start(psi)
            msg = p.StandardOutput.ReadToEnd()
            p.WaitForExit()
        End Using
        MsgBox(msg, MsgBoxStyle.Information Or MsgBoxStyle.SystemModal)
    
        Console.WriteLine("End!")
        Console.ReadKey()
    End Sub

    • 回答としてマーク Luky9 2019年7月4日 7:57
    2019年7月4日 7:15
  • 理解していただけたようで何より。

    特権は、必要なときに有効にして、使い終わったら無効にしてください。

    あと3点ほど。

    (1) LookupPrivilegeValue や AdjustTokenPrivileges がエラーになると、トークンハンドルが開きっぱなしになるので、ちゃんと CloseHandle しましょう。

    (2) このような列挙体を作って

    Public Enum SePrivileges
        SeCreateTokenPrivilege
        SeAssignPrimaryTokenPrivilege
        SeLockMemoryPrivilege
        SeIncreaseQuotaPrivilege
        SeUnsolicitedInputPrivilege
        SeMachineAccountPrivilege
        SeTcbPrivilege
        SeSecurityPrivilege
        SeTakeOwnershipPrivilege
        SeLoadDriverPrivilege
        SeSystemProfilePrivilege
        SeSystemtimePrivilege
        SeProfileSingleProcessPrivilege
        SeIncreaseBasePriorityPrivilege
        SeCreatePagefilePrivilege
        SeCreatePermanentPrivilege
        SeBackupPrivilege
        SeRestorePrivilege
        SeShutdownPrivilege
        SeDebugPrivilege
        SeAuditPrivilege
        SeSystemEnvironmentPrivilege
        SeChangeNotifyPrivilege
        SeRemoteShutdownPrivilege
        SeUndockPrivilege
        SeSyncAgentPrivilege
        SeEnableDelegationPrivilege
        SeManageVolumePrivilege
        SeImpersonatePrivilege
        SeCreateGlobalPrivilege
        SeTrustedCredManAccessPrivilege
        SeReserveProcessorPrivilege
    End Enum

    Public Shared Function ModifyState(privilege As SePrivileges, Enable As Boolean) As Boolean
        Return ModifyState(privilege.ToString(), Enable)
    End Function

    のようにしておくと、

       ModifyState(SePrivileges.SeBackupPrivilege, True)

    のように使えるのでタイプミスが防げます。

    (3) API の宣言は NativeMethods クラスにまとめましょう。
    https://docs.microsoft.com/ja-jp/visualstudio/code-quality/ca1060-move-p-invokes-to-nativemethods-class?view=vs-2019
    2019年7月4日 11:17
  • もう一点。

    (4)  Dim hProc As IntPtr = Process.GetCurrentProcess().Handle

    Process クラスは Component なので Dispose() しましょう。

    もしくは GetCurrentProcess API を呼びます。

    特権の有効化/無効化を繰り返しはしないとは思いますが念のため。

    2019年7月5日 1:18