Vistaの新機能、UACは昇格ダイアログのおかげで権限を(予め低くしたところから)上げるほうばかり目が行きますが、逆に下げる機能もあります。誰がそんな機能を使うかというと、Internet Explorerです。VistaのIE7にある保護モードはそれを使って通常より権限を低くした制限の強い状態で動かすというものです。これはこれで日本語IMEがまともに使えない(IMEで登録した単語が変換できない:Vista & IE7トラブルウォッチング)などの弊害もあるわけですが。

IEがやっているということは、当然自分でそういうプロセスを作ることも可能です。というわけで、ABからコマンドプロンプトを低い権限で動かすサンプルです。あ、申し遅れましたが、この権限の高い低いのことは整合性レベル(Integrity Level)と呼びます。

#console
'XP以上
Declare Function CreateWellKnownSid Lib "advapi32" (
    WellKnownSidType As WELL_KNOWN_SID_TYPE,
    DomainSid As PSID,
    pSid As PSID,
    ByRef cbSid As DWord
) As BOOL
'NT
Declare Function OpenProcessToken Lib "advapi32" (
    ProcessHandle As HANDLE,
    DesiredAccess As DWord,
    ByRef TokenHandle As HANDLE
) As BOOL
'NT4
Declare Function DuplicateTokenEx Lib "advapi32" (
    hExistingToken As HANDLE,
    DesiredAccess As DWord,
    lpTokenAttributes As *SECURITY_ATTRIBUTES,
    ImpersonationLevel As SECURITY_IMPERSONATION_LEVEL,
    TokenType As TOKEN_TYPE,
    ByRef hNewToken As HANDLE
) As BOOL
'NT
Declare Function SetTokenInformation Lib "advapi32" (
    TokenHandle As HANDLE,
    TokenInformationClass As TOKEN_INFORMATION_CLASS,
    ByRef TokenInformation As Any,
    TokenInformationLength As DWord
) As BOOL
'NT
Declare Function GetLengthSid Lib "advapi32" (
    pSid As PSID
) As DWord
'NT3.51
Declare Function CreateProcessAsUser Lib "advapi32" Alias "CreateProcessAsUserA" (
    hToken As HANDLE,
    lpApplicationName As PCSTR,
    lpCommandLine As PCSTR,
    lpProcessAttributes As *SECURITY_ATTRIBUTES,
    lpThreadAttributes As *SECURITY_ATTRIBUTES,
    bInheritHandles As Long,
    dwCreationFlags As DWord,
    lpEnvironment As VoidPtr,
    lpCurrentDirectory As PCSTR,
    ByRef lpStartupInfo As STARTUPINFO,
    ByRef lpProcessInformation As PROCESS_INFORMATION
) As BOOL

Function CreateLowProcess(cmdLine As PCTSTR) As Boolean
    Dim sidSize = SECURITY_MAX_SID_SIZE As DWord
    Dim sidBuf[ELM(SECURITY_MAX_SID_SIZE)] As Byte
    Dim pIntegritySid = sidBuf As PSID
    If CreateWellKnownSid(WinLowLabelSid,
        0, pIntegritySid, sidSize) = FALSE Then

        Return False
    End If

    Dim hToken As HANDLE
    If OpenProcessToken(GetCurrentProcess(),
        MAXIMUM_ALLOWED, hToken) Then

        Dim hNewToken As HANDLE
        If DuplicateTokenEx(hToken, MAXIMUM_ALLOWED,
            0, SecurityImpersonation, TokenPrimary, hNewToken) Then

            Dim til As TOKEN_MANDATORY_LABEL
            til.Label.Attributes = SE_GROUP_INTEGRITY
            til.Label.Sid = pIntegritySid
            If SetTokenInformation(hNewToken, TokenIntegrityLevel, til,
                SizeOf (TOKEN_MANDATORY_LABEL)
                + GetLengthSid(pIntegritySid)) Then

                Dim pi As PROCESS_INFORMATION
                Dim si As STARTUPINFO
                si.cb = Len(si)
                If CreateProcessAsUser(hNewToken, 0, cmdLine,
                    0, 0, FALSE, 0, 0, 0, si, pi) Then

                    CreateLowProcess = True
                    CloseHandle(pi.hProcess)
                    CloseHandle(pi.hThread)
                Else
                    CreateLowProcess = False
                End If
            End If
            CloseHandle(hNewToken)
        End If
        CloseHandle(hToken)
    End If
End Function

If CreateLowProcess("C:\\Windows\\System32\\cmd.exe") = False Then
    Print ActiveBasic.Windows.HResultToString(GetLastError())
    System.Console.ReadLine()
End If

Vista以上で動かすと、NTFSドライブにことごとく書き込みができません。カレントディレクトリをMy Documentsなどにしてもecho Hello > hello.txtなどが「アクセスが拒否されました。」と言われてしまいます。ごく一部のディレクトリだけ書き込みが許可されていたはずですが、省略します。 Proess ExplorerでIntegrity LevelがLowと表示されている様子 このとおり、Process Explorerで見ても整合性レベルがLowであることが確認できます。

ちなみに、CreateWellKnownSidの引数WinLowLabelSidが整合性レベル低の指定です。WinMediumLabelSid(中)とWinHighLabelSid(高)もあります。昇格済みの高で動いているプロセスから、通常の中で動くプロセスを作るなどといった応用も考えられます。もちろん逆はできないですよ。さすがに昇格ダイアログの回避はできません。


スポンサード リンク

この記事のカテゴリ