Powershellとautorunsで自動起動をチェックする

Microsoftが無料で提供しているSysinternalsツールのAutorunsを使って、Powershellで自動実行の確認をする。
私はPowershellをランチャーとして使っているので、起動時に組み込んでみた。



関数

function Watch-AutoRuns() {
        $baseFile = ((Get-Alias autoruns).Definition) + '.xml'
        $tempFile = ((Get-Alias autoruns).Definition) + '.t.xml'
        autoruns -a -v -f -x * > $tempFile

        $arn = [xml](Get-Content $baseFile)
        $arnt = [xml](Get-Content $tempFile)
        $switch = !(Test-Path $baseFile)

        if($switch) {
                foreach($i in $arnt.autoruns.item) {
                        if($i.itemname.length -gt 0) {
                                $i
                        }
                }
        } else {
                foreach($i in $arnt.autoruns.item) {
                        $nodelist = $arn.SelectNodes('autoruns/item[itemname="'+$i.itemname+'" and location="'+$i.location+'"]')
                        $diff = $true
                        foreach($j in $nodelist) {
                                $diff = $false
                                foreach($p in (Get-Member -InputObject $j -MemberType property | Select-Object Name)) {
                                        if($j.item($p.Name).'#text' -ne $i.item($p.Name).'#text') {
                                                $diff = $true
                                        }
                                }
                                if(!$diff) {
                                        break
                                }
                        }
                        if($diff) {
                                if($i.itemname.length -gt 0) {
                                        if($nodelist.count -le 0) {
                                                Write-Host 'new'
                                        } else {
                                                Write-Host 'diff'
                                        }
                                        $i
                                        Write-Host
                                        Write-Host
                                        $switch = $true
                                }
                        } else {
                                #Write-Host 'same ' + $i.itemname
                        }
                }
        }

        while($switch) {
                Write-Host 'OK?(y/n)'
                Write-Host " or `$arn.SelectNodes('autoruns/item[itemname=`"`" and location=`"`"]')"
                $res = Read-Host '?'
                if($res.ToLower().StartsWith('y')) {
                        if(Test-Path $baseFile) {
                                Remove-Item $baseFile
                        }
                        Copy-Item $tempFile -Destination $baseFile
                        $switch = $false
                } elseif($res.ToLower().StartsWith('n')) {
                        $switch = $false
                } else {
                        Invoke-Expression $res
                }
        }
        Remove-Item $tempFile

}

依存

autorunsがインストールされていること
http://technet.microsoft.com/ja-jp/sysinternals/bb963902.aspx


autorunsという別名定義があること

set-alias -name autoruns -value c:\tools\utility\SysinternalsSuite\autorunsc.exe

(パスはそれぞれの環境にあわせてください)


autorunsのあるフォルダーに

  • 問題ない自動実行のリスト autorunsc.exe.xml
  • 現在の自動実行のリスト(テンポラリー) autorunsc.exe.t.xml

を作成して良いこと


起動時チェックは、起動時に実行される部分に以下を書きました。

start powershell -Verb runas -ArgumentList -Command,"Watch-AutoRuns"

これで、変更がなければ自動的に閉じて、ある場合は「OK?」と出て止まるすんぽーです。
管理者権限がないと見られない部分はチェックしないなら、「-Verb runas」は不要。

解説

autorunsのオプションは関数の最初にあるように「-a -v -f -x *」。


XML形式なので、[xml]にキャストするとオブジェクトになるという、Powershell便利!


問題のない自動実行リストとの比較では、XPathでitemnameとlocationの一致を見ています。


差異のチェックは、減った場合は検出できません。
増えたか変更があった場合に検出します。
検出した場合は「OK?」と聞いてくるので、「y」と答えれば現在のリストを問題のない自動実行リストとします。
変更があり「diff」と出た場合に、元の設定を見るには、
「$arn.SelectNodes('autoruns/item[itemname="" and location=""]')」をコピーして、itemnameとlocationを埋めてやれば見られます。


これでautorunsで検出する範囲は、異変があれば気づけます。
検出できない範囲、、、例えばrootkit的なものは無理ですね。


初回は全てを検出してしまうので、とりあえずOKして、autoruns.exeを使ってじっくり確認することをおすすめします。