2023年12月22日 星期五

Bat/PowerShell 提權執行的指令

Bat/PowerShell 提權執行的指令



PowerShell

啟動一個新的進程並以管理員權限執行指定的命令

Start-Process 'cmd.exe' -ArgumentList "/c $cmdStr" -Verb RunAs



Bat 通常解法

批處理檔(.bat 檔)中實現類似的功能,事情就有些不同了,因為批處理檔沒有內建的提升權限命令。

一種解決方案是創建一個臨時的 VBScript 檔,這個腳本會觸發 UAC 提示以提升權限,然後執行您的批處理檔。這裡有一個例子:

  • 1. 創建一個 VBScript 檔案:
保存以下代碼到一個 .vbs 檔案,例如 elevate.vbs。這段代碼會以管理員身份執行一個指定的命令。
If WScript.Arguments.Count >= 1 Then
    Command = WScript.Arguments(0)
    Set Shell = CreateObject("Shell.Application")
    Shell.ShellExecute "cmd.exe", "/c " & Command, "", "runas", 1
End If


  • 2. 從批處理檔中調用這個 VBScript:
在您的 .bat 檔案中,使用以下命令來調用 elevate.vbs,並傳遞您想要以管理員權限執行的命令作為參數。
cscript //nologo elevate.vbs "您的命令"




進階手段

先利用執行內建需要管理員的程式來判斷是不是管理員

  1. 如果不是則委託給 PowerShell 重新讀取自己再次執行,並結束(並免重複執行自己)
  2. 如果已經是則繼續執行底下 bat

只需要將這行貼在首行即可

fltmc >nul || (set Admin=/x /d /c call "%~f0" %* & powershell -nop -c start cmd $env:Admin -verb runas; & exit /b)





2023年12月21日 星期四

PowerShell 如何讀取解析 Env/Properties 檔案

PowerShell 如何讀取解析 Env/Properties 檔案

實作做的功能包含了

  1. 自動讀取 “.env”, “.env.development”, “.env.production” 三個檔案,優先順序是後面覆蓋前面,同檔案間優先順序也是後面覆蓋前面
  2. 支援擴充功能使用斜線換行
  3. 支援擴充功能雙引號解析 PowerShell 變數


為什麼要拆分這麼多env檔案主要是兩個觀點

  1. 把連接資訊放在“.env.production”中避免部署設置時不小心動到連接資訊。
  2. 拆分development跟production,僅共用.env檔案這樣可以很好的區分開發機跟生產環境


範例 .env

A1="  AAA  
A2=  AAA  "
B1=" AAA "
B2=' AAA '
C1= \
arr1,\
arr2
D1="$($env:USERNAME)"
D2='$($env:USERNAME)'
Z=\
A\
B\
C\
D\


讀取用函式
ConvertFrom-Env.ps1

# 轉換 Env 文件
function ConvertFrom-Env {
    param (
        [string[]]$EnvFiles = @(".env", ".env.development", ".env.production"),
        [System.Text.Encoding]$Encoding = [System.Text.Encoding]::Default
    )

    # 使用有序字典保持讀取的順序
    $envVariables = [Ordered]@{}

    function ProcessLine {
        param (
            [string]$line
        )

        # 忽略註釋行
        if ($line -and -not $line.StartsWith("#")) {
            if ($line -match "^\s*([^#=]+?)\s*=\s*(.*)$") {
                $key = $matches[1].Trim()
                $value = $matches[2]
                if ($value -match '^"(.+)"$') {
                    # 處理雙引號包圍的值並展開字符串
                    $value = $matches[1] -replace '\\n', "`n" -replace '\\r', "`r" -replace '\\t', "`t"
                    $value = $ExecutionContext.InvokeCommand.ExpandString($value)
                } elseif ($value -match "^'(.+)'$") {
                    # 處理單引號包圍的值
                    $value = $matches[1]
                } else {
                    $value = $value.Trim()
                }

                # 將解析後的鍵值對加入字典
                $envVariables[$key] = $value
            }
        }
    }

    # 遍歷所有指定的文件
    foreach ($file in $EnvFiles) {
        if (Test-Path $file) {
            try {
                $reader = New-Object System.IO.StreamReader -ArgumentList $file, $Encoding
                try {
                    $currentLine = ''
                    while ($null -ne ($line = $reader.ReadLine())) {
                        $trimmedLine = $line.Trim()
                        if ($trimmedLine.EndsWith('\')) {
                            # 跨行值的處理
                            $currentLine += $trimmedLine.TrimEnd('\').TrimEnd()
                            continue
                        } else {
                            $currentLine += $trimmedLine
                        }
                        ProcessLine -line $currentLine
                        $currentLine = ''
                    }
                    # 處理跨行結尾在最一行時沒被處理的剩餘值
                    if ($currentLine) { ProcessLine -line $currentLine }
                } finally {
                    $reader.Close()
                }
            } catch {
                Write-Warning "無法讀取文件 '$file': $_"
            }
        }
    } # $envVariables = [PSCustomObject]$envVariables
    return $envVariables
} ConvertFrom-Env


代碼開源於此: hunandy14/ConvertFrom-Env (github.com)