diff --git a/Cargo.lock b/Cargo.lock index 594c571d..942b71d4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -19,9 +19,9 @@ checksum = "ee2a4ec343196209d6594e19543ae87a39f96d5534d7174822a3ad825dd6ed7e" [[package]] name = "aho-corasick" -version = "0.7.13" +version = "0.7.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "043164d8ba5c4c3035fec9bbee8647c0261d788f3474306f93bb65901cae0e86" +checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f" dependencies = [ "memchr", ] @@ -87,12 +87,6 @@ dependencies = [ "byteorder", ] -[[package]] -name = "base64" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3441f0f7b02788e948e47f457ca01f1d7e6d92c693bc132c22b087d3141c03ff" - [[package]] name = "bitflags" version = "1.2.1" @@ -902,6 +896,31 @@ dependencies = [ "winapi-build", ] +[[package]] +name = "lagotto" +version = "1.0.0" +dependencies = [ + "base64", + "chrono", + "clap", + "csv", + "dotenv", + "evtx", + "flate2", + "lazy_static", + "linked-hash-map", + "mopa", + "num_cpus", + "quick-xml 0.17.2", + "regex", + "serde", + "serde_derive", + "serde_json", + "slack-hook", + "tokio 1.3.0", + "yaml-rust", +] + [[package]] name = "lazy_static" version = "1.4.0" @@ -961,9 +980,9 @@ checksum = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00" [[package]] name = "memchr" -version = "2.3.3" +version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3728d817d99e5ac407411fa471ff9800a778d88a24685968b36824eaf4bee400" +checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a" [[package]] name = "memoffset" @@ -1543,14 +1562,13 @@ dependencies = [ [[package]] name = "regex" -version = "1.3.9" +version = "1.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c3780fcf44b193bc4d09f36d2a3c87b251da4a046c87795a0d35f4f927ad8e6" +checksum = "d07a8629359eb56f1e2fb1652bb04212c072a87ba68546a04065d525673ac461" dependencies = [ "aho-corasick", "memchr", "regex-syntax", - "thread_local", ] [[package]] @@ -1564,9 +1582,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.6.18" +version = "0.6.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26412eb97c6b088a6997e05f69403a802a92d520de2f8e63c2b65f9e0f47c4e8" +checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b" [[package]] name = "remove_dir_all" @@ -1583,7 +1601,7 @@ version = "0.9.24" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f88643aea3c1343c804950d7bf983bd2067f5ab59db6d613a08e05572f2714ab" dependencies = [ - "base64 0.10.1", + "base64", "bytes 0.4.12", "cookie", "cookie_store", @@ -1962,15 +1980,6 @@ dependencies = [ "syn", ] -[[package]] -name = "thread_local" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d40c6d1b69745a6ec6fb1ca717914848da4b44ae29d9b3080cbee91d72a69b14" -dependencies = [ - "lazy_static", -] - [[package]] name = "time" version = "0.1.44" @@ -2392,31 +2401,6 @@ dependencies = [ "winapi-build", ] -[[package]] -name = "yamato_event_analyzer" -version = "0.1.0" -dependencies = [ - "base64 0.12.3", - "chrono", - "clap", - "csv", - "dotenv", - "evtx", - "flate2", - "lazy_static", - "linked-hash-map", - "mopa", - "num_cpus", - "quick-xml 0.17.2", - "regex", - "serde", - "serde_derive", - "serde_json", - "slack-hook", - "tokio 1.3.0", - "yaml-rust", -] - [[package]] name = "yaml-rust" version = "0.4.4" diff --git a/Cargo.toml b/Cargo.toml index 6aa0afca..6a6b8d0d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] -name = "yamato_event_analyzer" -version = "0.1.0" +name = "lagotto" +version = "1.0.0" authors = ["akiranishikawa "] edition = "2018" @@ -13,7 +13,7 @@ serde = { version = "1.0", features = ["derive"] } serde_json = { version = "1.0"} serde_derive = "1.0" clap = "*" -regex = "1" +regex = "1.5.4" csv = "1.1" base64 = "*" flate2 = "1.0" diff --git a/README.md b/README.md index df132a7d..6175e10d 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,69 @@ -# YamatoEventAnalyzer -Yea! (Yamato Event Analyzer). Aiming to be the world's greatest Windows event log analysis tool! +# Lagotto +Aiming to be the world's greatest Windows event log analysis tool! 世界一のWindowsイベントログ解析ツールを目指しています! + + +# Platforms +Lagottoは下記のプラットフォーム上で実行できます。 +* Windows +* Linux +* macOS + +# Downloads +[Releases](https://github.com/Yamato-Security/YamatoEventAnalyzer/releases)からコンパイル済みの実行ファイルをダウンロードできます。 + +# Usage +## Commnad line option +```` +USAGE: + lagotto.exe [FLAGS] [OPTIONS] + +FLAGS: + --credits Prints credits + -h, --help Prints help information + --rfc-2822 Output date and time in RFC 2822 format. Example: Mon, 07 Aug 2006 12:34:56 -0600 + --slack Slack notification + -s, --statistics Prints statistics for event logs + -u, --utc Output time in UTC format(default: local time) + -V, --version Prints version information + +OPTIONS: + --csv-timeline Csv output timeline + -d, --directory Event log files directory + -f, --filepath Event file path + --human-readable-timeline Human readable timeline + -l, --lang Output language + -t, --threadnum Thread number +```` + +## Usage examples +* Windowsイベントログを一つ指定する +```` +lagotto.exe --filepath=eventlog.evtx +```` + +* Windowsイベントログが格納されているフォルダを指定する +```` +lagotto.exe --directory=.\evtx +```` + +* 結果をCSVファイルに出力する。 +```` +lagotto.exe --directory=.\evtx --csv-timeline lagotto.csv +```` + +# Rule files +LagottoではWindowsEventログを検知するルールをYAML形式で定義します。 + +ルールの記載方法については[RULEFILE.md](./doc/RULEFILE.md)を参照してください。 + +ルールファイルはrulesフォルダ内に設置します。 +rulesフォルダには組み込みルールファイルも設置されていますので、参考にしてください。 + +# How to compile from source files +下記のコマンドでビルドできます。 + +```` +cargo build +```` \ No newline at end of file diff --git a/doc/RULEFILE.md b/doc/RULEFILE.md new file mode 100644 index 00000000..a341be36 --- /dev/null +++ b/doc/RULEFILE.md @@ -0,0 +1,315 @@ +# ルールファイル +LagottoはWindowsEventログの検知ルールをYAML形式のファイルに記載します。 +単なる文字列一致だけでなく、正規表現やANDやOR等の条件を組み合わせることができ、複雑な検知ルールも表現できるようになっています。 +ここではその検知ルールの書き方について説明します。 + +# ルールファイルのフォーマット +ルールファイルのフォーマットは下記の通りです。 + +`````` +title: PowerShell Execution Pipeline +description: This rule detect powershell execution pipeline. +author: Zach Mathis +detection: + selection: + Event.System.EventID: 7040 + Event.System.Channel: System +falsepositives: + - unknown +level: medium +output: 'command=%CommandLine%' +creation_date: 2020/11/8 +updated_date: 2020/11/8 +`````` + +* title [required]: ルールファイルのタイトルを入力します。 +* description [optional]: ルールファイルの説明を入力します。 +* author [optional]: ルールファイルの作者を入力します。 +* detection [required]: 検知ルールを入力します。 +* falsepositives [optional]: 誤検知に関する情報を入力します。 +* level [optional]: リスクレベルを入力します。指定する値は`informational`,`low`,`medium`,`high`,`critical`のいづれかです。 +* output [required]: イベントログが検知した場合に表示されるメッセージを入力します。 +* creation_date [optional]: ルールファイルの作成日を入力します。 +* updated_date [optional]: ルールファイルの更新日を入力します。 + +# detectionの記法について +## detectionの基本 +まず、detectionの基本的な書き方について説明します。 + +### AND条件とOR条件の書き方 +AND条件を記載する場合はYAMLのハッシュを用いて記載します。 +下記のようにdetectionを記載すると、以下`両方の条件を満たす`イベントログを検知します。 +* EventIDが`7040`に完全一致する +* Channelが`System`に完全一致する + +`````` +detection: + selection: + Event.System.EventID: 7040 + Event.System.Channel: System +`````` + +OR条件を記載する場合は配列を利用します。 +下記のようにdetectionを記載すると、以下`いずれの条件を満たす`イベントログを検知します。 +* EventIDが`7040`に完全一致する +* Channelが`System`に完全一致する + +`````` +detection: + selection: + - Event.System.EventID: 7040 + - Event.System.Channel: System +`````` + +また、下記のように記載することもできます。 +この場合、以下`両方の条件を満たす`イベントログを検知します。 +* EventIDが`7040`又は`7041`に完全一致する +* Channelが`System`に完全一致する + +`````` +detection: + selection: + Event.System.EventID: + - 7040 + - 7041 + Event.System.Channel: System +`````` + +### eventkey +WindowsイベントログをXML形式で一部抜粋で出力すると、下記のようになります。ルールファイルの例に含まれる`Event.System.Channel`は、XMLの`System`を指しています。今回の例のように、XML形式のWindowsイベントログについて、入れ子になったXMLのタグに含まれる値をルールの条件に指定する場合、`.`でつなげて指定します。ルールファイルでは、この`.`でつなげた文字列をeventkeyと呼んでいます。 + +`````` + + + 7040 + System + + + Background Intelligent Transfer Service + 自動的な開始 + + +`````` + +### eventkeyのalias +`.`でつなげたeventkeyは長い文字列になってしまうことがあるため、Lagottoではeventkeyに対するエイリアスを使用できます。エイリアスは`config\eventkey_alias.txt`というファイルに定義されています。ファイルはCSV形式であり、aliasとevent_keyという列から構成されています。aliasにはエイリアスを定義し、event_keyには`.`でつなげたeventkeyを指定します。このエイリアスを用いると、最初に例に挙げたdetectionは以下のように書き換えることができます。 + +`````` +detection: + selection: + EventID: 7040 + Channel: System +`````` +### XMLの属性(attribute)をルールの条件にする方法 +WindowsEventログをXML形式で出力すると、XMLの属性に値が設定されている場合もあります。下記の例だと、ProviderタグのNameがXMLの属性です。 + +```````````` + + + + 4672 + 607469 + Security + + + +```````````` + +XMLの属性をeventkeyで指定するには、{eventkey}_attributes.{attribute_name}という形式で指定します。例えば、ProviderタグのName属性をルールファイルに指定する場合、下記のようになります。 + +`````` +detection: + selection: + Channel: Security + EventID: 4672 + Event.System.Provider_attributes.Name: 'Microsoft-Windows-Security-Auditing' +`````` + +### EventData +WindowsEventログをXML形式で出力すると、EventDataというタグが使用されている場合があります。(EventDataタグは様々なEventIDのログで頻繁に利用されます。)このEventDataにネストされたタグの名前は全て`Data`となっており、ここまで説明してきたeventkeyではSubjectUserSidやSubjectUserNameを区別することができません。 +```````````` + + + 5379 + + 607469 + Security + + + + S-1-1-11-1111111111-111111111-1111111111-1111 + lagotto + DESKTOP-LAGOTTO + 0x11111111 + + +```````````` + +この問題に対応するため、eventkeyで`Data`の代わりに`Name`に指定されている値をeventkeyに指定できるようになっています。例えば、EventData内のSubjectUserNameとSubjectDomainNameをルールの条件とする場合、下記のように記載します。 + +`````` +detection: + selection: + EventID: 7040 + Channel: System + Event.EventData.SubjectUserName: lagotto + Event.EventData.SubjectDomainName: DESKTOP-LAGOTTO +`````` + +### EventDataの特殊なパターン +EventDataというタグにネストされたタグの中には、Name属性が存在しないタグもあります。 +`````` + + + 5379 + Security + + + + Available + None + NewEngineState=Available PreviousEngineState=None SequenceNumber=9 HostName=ConsoleHost HostVersion=2.0 HostId=5cbb33bf-acf7-47cc-9242-141cd0ba9f0c EngineVersion=2.0 RunspaceId=c6e94dca-0daf-418c-860a-f751a9f2cbe1 PipelineId= CommandName= CommandType= ScriptName= CommandPath= CommandLine= + + +`````` + +上記のようなイベントログを検知する場合、`EventData`というeventkeyを指定します。この場合、EventDataタグにネストされているName属性の指定されてないタグのうち、いずれか一つでも一致するタグがあれば、条件に一致したものとして処理されます。 +`````` +detection: + selection: + Channel: Security + EventID: 5379 + EventData: None +`````` + +## パイプ +eventkeyにはパイプを指定することができます。ここまで説明した書き方では完全一致しか表現できませんでしたが、パイプを使うことでより柔軟な検知ルールを記載できるようになります。下記の例ではCommandLineの値が`yamato.*lagotto`という正規表現にマッチする場合、条件に一致したものとして処理されます。 + +`````` +detection: + selection: + EventID: 7040 + Channel: System + CommandLine|re: yamato.*lagotto +`````` + +使用できるパイプの一覧です。なお、v1.0.0時点では、複数のパイプをつなげて使用することはできません。 +* startswith: 先頭一致 +* endswith: 後方一致 +* contains: 部分一致 +* re: 正規表現(正規表現の処理にはregexクレートを使用しています。正規表現の詳細記法についてはhttps://docs.rs/regex/1.5.4/regex/を参照してください。) + +## ワイルドカード +eventkeyに対応する値にはワイルドカードを指定することができます。下記の例ではCommandLineがlagottoという文字列で始まっていれば、条件に一致したものとして処理されます。基本的にはsigmaルールのwildcardと同じ仕様になっています。 + +`````` +detection: + selection: + EventID: 7040 + Channel: System + CommandLine: lagotto* +`````` + +使用できるワイルドカードの一覧です。 +* `*`: 任意の0文字以上の文字列にマッチします。(内部的には`.*`という正規表現に変換されます。) +* `?`: 任意の1文字にマッチします。(内部的には`.`という正規表現に変換されます。) + +ワイルドカードを使用する場合、下記のルールに則って解釈されます。 +* ワイルドカード(`*`と`?`)をエスケープするにはバックスラッシュ(`/`)を使用します。 +* ワイルドカードの直前に文字としてのバックスラッシュ(`/`)を使用する場合、`\\*`又は`\\?`と記載してください。 +* バックスラッシュを単体で使う分にはエスケープ不要です。 + +## eventkeyにネストできるキーワード +eventkeyには特定のキーワードをネストさせることができます。下記の例ではCommandLineの値が`aa*bb`というワイルドカードにマッチした上で文字列長が10以上である場合、条件に一致したものと処理されます。 + +`````` +detection: + selection: + EventID: 7040 + Channel: System + CommandLine: + value: aa*bb + min_length: 10 +`````` + +現状では下記のキーワードを指定できます。 +* value: 文字列による一致(ワイルドカードやパイプを指定することもできます) +* min_length: 指定した文字数以上である場合、条件に一致したものとして処理されます。 +* regexes: 指定したファイルに記載された正規表現のリストにひとつでも一致すれば、`条件に一致した`ものとして処理されます。 +* whitelist: 指定したファイルに記載された正規表現のリストにひとつでも一致すれば、`条件に一致していない`ものとして処理されます。 + +### regexes.txtとwhitelist.txt +lagottoではregexesやwhitelistを使用した組み込みのルールを用意しており、それらのルールはregexes.txtとwhitelist.txtを参照しています。regexes.txtとwhitelist.txtを書き換えることで、参照する全てのルールの挙動を一度に変更することが可能です。 + +また、regexesやwhitelistに指定するファイルは、ユーザーが独自に作成することも可能です。作成する場合、regexes.txtとwhitelist.txtを参考にしてください。 + +## condition +これまでの記法を用いると、AND条件やOR条件を表現することができますが、ANDやOR等が複雑に入り組んだ条件を定義することは難しい場合があります。その場合、conditionというキーワードを使用することで、複雑な条件式を定義することができます。 + +`````` +detection: + selection_1: + EventID: 7040 + selection_2: + EventID: 7041 + selection_3: + Channel: System + selection_4: + CommandLine|contains: lsass.exe + selection_5: + CommandLine|contains: services.exe + selection_6: + ParentProcessName|contains: wininit.exe + + condition: ( selection_1 or selection_2 ) and selection_3 and ( selection_4 or selection_5 ) and ( not selection_6 ) +`````` + +conditionには以下のキーワードを使用することができます。 +* {expression1} and {expression2}: {expression1}と{expression2}のAND条件を表します。 +* {expression1} or {expression2}: {expression1}と{expression2}のOR条件を表します。 +* not {expression}: {expression}の条件式の真偽を逆転させます。 +* ( {expression} ) : {expression}の条件式を優先して評価します。数学等で現れる括弧と同じです。 + +なお、上記の例では、条件式をグルーピングするためにselection_1やselection_2といった名前を使用していますが、selectionというprefixを付ける必要はなく、ユーザーが任意の名前を定義できます。ただし、使用可能な文字は`\w`という正規表現にマッチする文字のみです。 + +## aggregation condition +上記で説明したconditionには、andやor条件だけでなく、検知したイベントログを集計するような機能も実装されています。この機能をaggregation conditionと呼んでおり、conditionの後にパイプでつなげて指定します。下記の例では、DestinationIpの値が3種類以上あるかどうかをSubjectUserName毎に判定する条件式になります。 + +`````` +detection: + selection: + EventID: 7040 + Channel: System + condition: selection | count(DestinationIp) by SubjectUserName >= 3 +`````` + +aggregation conditionは下記の形式で定義できます。なお、{number}には数値を指定します。 +* `count() {operator} {number}`: conditionのパイプ以前の条件に一致したログについて、一致したログ数が{operator}と{number}で指定した条件式を満たす場合に、条件に一致したものとして処理されます。 + +![](count1.png) + +* `count() by {eventkey_2} {operator} {number}`: conditionのパイプ以前の条件に一致したログを{eventkey_2}毎にグルーピングし、グルーピング毎に一致したログ数が{operator}と{number}で指定した条件式を満たす場合に、条件に一致したものとして処理されます。 + +![](count2.png) + +* `count({eventkey}) {operator} {number}`: conditionのパイプ以前の条件に一致したログについて、{eventkey}の値が何種類存在するか数えます。その数が{operator}と{number}で指定した条件式を満たす場合に、条件に一致したものとして処理されます。 + +![](count3.png) + +* `count({eventkey_1}) by {eventkey_2} {operator} {number}`: conditionのパイプ以前の条件に一致したログを{eventkey_2}毎にグルーピングし、そのグループ毎に{eventkey_1}の値が何種類存在するか数えます。そのグルーピング毎に数えた値が{operator}と{number}で指定した条件式を満たす場合に、条件に一致したものとして処理されます。 + +![](count4.png) + +また、上記のoperatorには下記を指定できます。 +* `==`: 指定された値と等しい場合、条件に一致したものと処理されます。 +* `>=`: 指定された値以上である場合、条件に一致したものと処理されます。 +* `>`: 指定された値より大きい場合、条件に一致したものと処理されます。 +* `<=`: 指定された値以下である場合、条件に一致したものと処理されます。 +* `<`: 指定された値より小さい場合、条件に一致したものと処理されます。 + +# outputの記法 +detectionの条件に一致した場合に、出力されるメッセージを指定できます。固定の文字列が出力できる他、eventkeyを%で囲むことにより、検知したログの値を表示することも可能です。下記の例では検知した際のメッセージにScriptBlockTextというeventkeyの値を使用しています。 + +`````` +output: 'command=%ScriptBlockText%' +`````` \ No newline at end of file diff --git a/doc/count1.png b/doc/count1.png new file mode 100644 index 00000000..7c9dfaac Binary files /dev/null and b/doc/count1.png differ diff --git a/doc/count2.png b/doc/count2.png new file mode 100644 index 00000000..79ec42e1 Binary files /dev/null and b/doc/count2.png differ diff --git a/doc/count3.png b/doc/count3.png new file mode 100644 index 00000000..176a5670 Binary files /dev/null and b/doc/count3.png differ diff --git a/doc/count4.png b/doc/count4.png new file mode 100644 index 00000000..ac4d80d9 Binary files /dev/null and b/doc/count4.png differ diff --git a/regexes.txt b/regexes.txt index f59a3792..a643b343 100644 --- a/regexes.txt +++ b/regexes.txt @@ -1,19 +1,17 @@ -Type,regex,string -0,^cmd.exe /c echo [a-z]{6} > \\\\.\\pipe\\[a-z]{6}$,Metasploit-style cmd with pipe (possible use of Meterpreter 'getsystem') -0,^%SYSTEMROOT%\\[a-zA-Z]{8}\.exe$,Metasploit-style %SYSTEMROOT% image path (possible use of Metasploit 'Native upload' exploit payload) -0,powershell.*FromBase64String.*IO.Compression.GzipStream,Metasploit-style base64 encoded/compressed PowerShell function (possible use of Metasploit PowerShell exploit payload) -0,DownloadString\(.http,Download via Net.WebClient DownloadString -0,mimikatz,Command referencing Mimikatz -0,Invoke-Mimikatz.ps,PowerSploit Invoke-Mimikatz.ps1 -0,PowerSploit.*ps1,Use of PowerSploit -0,User-Agent,User-Agent set via command line -0,[a-zA-Z0-9/+=]{500},500+ consecutive Base64 characters -0,powershell.exe.*Hidden.*Enc,Base64 encoded and hidden PowerShell command -# Generic csc.exe alert, comment out if experiencing false positives -0,\\csc\.exe,Use of C Sharp compiler csc.exe -0,\\csc\.exe.*\\Appdata\\Local\\Temp\\[a-z0-9]{8}\.cmdline,PSAttack-style command via csc.exe -# Generic cvtres.exe alert, comment out if experiencing false positives -0,\\cvtres\.exe.*,Resource File To COFF Object Conversion Utility cvtres.exe -0,\\cvtres\.exe.*\\AppData\\Local\\Temp\\[A-Z0-9]{7}\.tmp,PSAttack-style command via cvtres.exe -1,^[a-zA-Z]{22}$,Metasploit-style service name: 22 characters, [A-Za-z] -1,^[a-zA-Z]{16}$,Metasploit-style service name: 16 characters, [A-Za-z] \ No newline at end of file +^cmd.exe /c echo [a-z]{6} > \\\\.\\pipe\\[a-z]{6}$ +^%SYSTEMROOT%\\[a-zA-Z]{8}\.exe$ +powershell.*FromBase64String.*IO.Compression.GzipStream +DownloadString\(.http +mimikatz +Invoke-Mimikatz.ps +PowerSploit.*ps1 +User-Agent +[a-zA-Z0-9/+=]{500} +powershell.exe.*Hidden.*Enc +\\csc\.exe +\\csc\.exe.*\\Appdata\\Local\\Temp\\[a-z0-9]{8}\.cmdline +# Generic cvtres.exe alert +\\cvtres\.exe.* +\\cvtres\.exe.*\\AppData\\Local\\Temp\\[A-Z0-9]{7}\.tmp +^[a-zA-Z]{22}$ +^[a-zA-Z]{16}$ \ No newline at end of file diff --git a/rules/bitsjobs/1197_bitsjob.yaml b/rules/bitsjobs/1197_bitsjob.yaml index 7ce31f82..13f4e6d4 100644 --- a/rules/bitsjobs/1197_bitsjob.yaml +++ b/rules/bitsjobs/1197_bitsjob.yaml @@ -1,15 +1,12 @@ title: BitsJob description: Adversaries may abuse BITS jobs to persistently execute or clean up after malicious payloads. author: Yea -logsource: - product: windows detection: selection: Channel: Microsoft-Windows-Bits-Client/Operational EventID: 59 falsepositives: - unknown -level: medium output: 'Started bits job created. JobTitle:%JobTitle% URL:%Url%' creation_date: 2021/7/15 updated_date: 2021/7/15 diff --git a/rules/deep_blue_cli/powershell/4103.yml b/rules/deep_blue_cli/powershell/4103.yml index dbcbc022..3aaaefb5 100644 --- a/rules/deep_blue_cli/powershell/4103.yml +++ b/rules/deep_blue_cli/powershell/4103.yml @@ -1,8 +1,6 @@ title: PowerShell Execution Pipeline description: hogehoge author: Yea -logsource: - product: windows detection: selection: Channel: Microsoft-Windows-PowerShell/Operational @@ -13,7 +11,6 @@ detection: # condition: selection falsepositives: - unknown -level: medium output: 'command=%CommandLine%' creation_date: 2020/11/8 updated_date: 2020/11/8 diff --git a/rules/deep_blue_cli/powershell/4104.yml b/rules/deep_blue_cli/powershell/4104.yml index af55ec8f..16285b90 100644 --- a/rules/deep_blue_cli/powershell/4104.yml +++ b/rules/deep_blue_cli/powershell/4104.yml @@ -1,8 +1,6 @@ title: PowerShell Execution Remote Command description: hogehoge author: Yea -logsource: - product: windows detection: selection: Channel: Microsoft-Windows-PowerShell/Operational @@ -12,7 +10,6 @@ detection: # condition: selection falsepositives: - unknown -level: medium output: 'command=%ScriptBlockText%' creation_date: 2020/11/8 updated_date: 2020/11/8 diff --git a/rules/deep_blue_cli/security/1102.yml b/rules/deep_blue_cli/security/1102.yml index 9a042c62..515bee18 100644 --- a/rules/deep_blue_cli/security/1102.yml +++ b/rules/deep_blue_cli/security/1102.yml @@ -1,8 +1,6 @@ title: The Audit log file was cleared description: hogehoge author: Yea -logsource: - product: windows detection: selection: Channel: Security @@ -10,7 +8,6 @@ detection: # condition: selection falsepositives: - unknown -level: medium output: | Audit Log Clear The Audit log was cleared. diff --git a/rules/deep_blue_cli/security/4673.yml b/rules/deep_blue_cli/security/4673.yml index 6f32e10a..da2d50c4 100644 --- a/rules/deep_blue_cli/security/4673.yml +++ b/rules/deep_blue_cli/security/4673.yml @@ -1,8 +1,6 @@ title: Sensitive Privilede Use (Mimikatz) description: hogehoge author: Yea -logsource: - product: windows detection: selection: Channel: Security @@ -10,7 +8,6 @@ detection: # condition: selection | count(EventID) > 4 falsepositives: - unknown -level: medium output: | Sensitive Privilege Use Exceeds Threshold Potentially indicative of Mimikatz, multiple sensitive priviledge calls have been made. diff --git a/rules/deep_blue_cli/security/4674.yml b/rules/deep_blue_cli/security/4674.yml index 8a697d89..da84281d 100644 --- a/rules/deep_blue_cli/security/4674.yml +++ b/rules/deep_blue_cli/security/4674.yml @@ -1,8 +1,6 @@ title: An Operation was attempted on a privileged object description: hogehoge author: Yea -logsource: - product: windows detection: selection: Channel: Security @@ -12,7 +10,6 @@ detection: # condition: selection falsepositives: - unknown -level: medium output: | Possible Hidden Service Attempt User requested to modify the Dynamic Access Control (DAC) permissions of a service, possibly to hide it from view. diff --git a/rules/deep_blue_cli/security/4688.yml b/rules/deep_blue_cli/security/4688.yml index c52654e9..2a02a973 100644 --- a/rules/deep_blue_cli/security/4688.yml +++ b/rules/deep_blue_cli/security/4688.yml @@ -1,8 +1,6 @@ title: Command Line Logging description: hogehoge author: Yea -logsource: - product: windows detection: selection: Channel: Security @@ -11,7 +9,6 @@ detection: # condition: selection falsepositives: - unknown -level: medium output: 'CommandLine:%CommandLine% ParentProcessName:%ParentProcessName%' creation_date: 2020/11/8 updated_date: 2020/11/8 diff --git a/rules/deep_blue_cli/security/4720.yml b/rules/deep_blue_cli/security/4720.yml index d97fb88c..67eb3261 100644 --- a/rules/deep_blue_cli/security/4720.yml +++ b/rules/deep_blue_cli/security/4720.yml @@ -1,8 +1,6 @@ title: A user account was created. description: hogehoge author: Yea -logsource: - product: windows detection: selection: Channel: Security @@ -10,7 +8,6 @@ detection: # condition: selection falsepositives: - unknown -level: low output: 'New User Created UserName:%TargetUserName% SID:%TargetSid%' creation_date: 2020/11/8 updated_date: 2020/11/8 diff --git a/rules/deep_blue_cli/security/4728.yml b/rules/deep_blue_cli/security/4728.yml index c4d87ee7..efaf467a 100644 --- a/rules/deep_blue_cli/security/4728.yml +++ b/rules/deep_blue_cli/security/4728.yml @@ -1,8 +1,6 @@ title: A member was added to a security-enabled global group. description: hogehoge author: Yea -logsource: - product: windows detection: selection: Channel: Security @@ -11,7 +9,6 @@ detection: # condition: selection falsepositives: - unknown -level: low output: 'user added to global Administrators UserName: %MemberName% SID: %MemberSid%' creation_date: 2020/11/8 updated_date: 2020/11/8 diff --git a/rules/deep_blue_cli/security/4732.yml b/rules/deep_blue_cli/security/4732.yml index b83caf5a..20e48ca3 100644 --- a/rules/deep_blue_cli/security/4732.yml +++ b/rules/deep_blue_cli/security/4732.yml @@ -1,8 +1,6 @@ title: A member was added to a security-enabled local group. description: hogehoge author: Yea -logsource: - product: windows detection: selection: Channel: Security @@ -11,7 +9,6 @@ detection: # condition: selection falsepositives: - unknown -level: low output: 'user added to local Administrators UserName: %MemberName% SID: %MemberSid%' creation_date: 2020/11/8 updated_date: 2020/11/8 diff --git a/rules/deep_blue_cli/security/4756.yml b/rules/deep_blue_cli/security/4756.yml index eff845e1..bf979070 100644 --- a/rules/deep_blue_cli/security/4756.yml +++ b/rules/deep_blue_cli/security/4756.yml @@ -1,8 +1,6 @@ title: A member was added to a security-enabled universal group. description: hogehoge author: Yea -logsource: - product: windows detection: selection: Channel: Security @@ -11,7 +9,6 @@ detection: # condition: selection falsepositives: - unknown -level: low output: 'user added to universal Administrators UserName: %MemberName% SID: %MemberSid%' creation_date: 2020/11/8 updated_date: 2020/11/8 diff --git a/rules/deep_blue_cli/security/_4625.yml b/rules/deep_blue_cli/security/_4625.yml index 788da7fa..74e69c34 100644 --- a/rules/deep_blue_cli/security/_4625.yml +++ b/rules/deep_blue_cli/security/_4625.yml @@ -2,8 +2,6 @@ title: An account failed to log on description: hogehoge ignore: true author: Yea -logsource: - product: windows detection: selection: Channel: Security @@ -11,7 +9,6 @@ detection: # condition: selection | count(TargetUserName) > 3 falsepositives: - unknown -level: medium output: 'High number of logon failures for one account UserName:%event_data.SubjectUserName% Total logon faiures:%count%' creation_date: 2020/11/8 updated_date: 2020/11/8 diff --git a/rules/deep_blue_cli/security/_4648.yml b/rules/deep_blue_cli/security/_4648.yml index d48f4986..abf8c9d5 100644 --- a/rules/deep_blue_cli/security/_4648.yml +++ b/rules/deep_blue_cli/security/_4648.yml @@ -2,8 +2,6 @@ title: An account failed to log on description: hogehoge ignore: true author: Yea -logsource: - product: windows detection: selection: Channel: Security @@ -11,7 +9,6 @@ detection: # condition: selection | count(TargetUserName) > 3 falsepositives: - unknown -level: High output: 'Distributed Account Explicit Credential Use (Password Spray Attack)¥n The use of multiple user account access attempts with explicit credentials is ¥nan indicator of a password spray attack.¥nTarget Usernames:%TargetUserName$¥nAccessing Username: %SubjectUserName%¥nAccessing Host Name: %SubjectDomainName%' creation_date: 2020/11/8 updated_date: 2020/11/8 diff --git a/rules/deep_blue_cli/security/_4672.yml b/rules/deep_blue_cli/security/_4672.yml index 9fd97ce3..a92abfa3 100644 --- a/rules/deep_blue_cli/security/_4672.yml +++ b/rules/deep_blue_cli/security/_4672.yml @@ -2,8 +2,6 @@ title: Command Line Logging description: hogehoge ignore: true author: Yea -logsource: - product: windows detection: selection: Channel: Security @@ -12,7 +10,6 @@ detection: # condition: selection falsepositives: - unknown -level: medium output: 'CommandLine:%CommandLine% ParentProcessName:%ParentProcessName%' creation_date: 2020/11/8 updated_date: 2020/11/8 diff --git a/rules/deep_blue_cli/sysmon/1.yml b/rules/deep_blue_cli/sysmon/1.yml index 1c6f2c8c..6d02f890 100644 --- a/rules/deep_blue_cli/sysmon/1.yml +++ b/rules/deep_blue_cli/sysmon/1.yml @@ -1,8 +1,6 @@ title: Sysmon Check command lines description: hogehoge author: Yea -logsource: - product: windows detection: selection: Channel: Sysmon @@ -11,7 +9,6 @@ detection: # condition: selection falsepositives: - unknown -level: medium output: 'CommandLine=%CommandLine%¥nParentImage=%ParentImage%' creation_date: 2020/11/8 uodated_date: 2020/11/8 diff --git a/rules/deep_blue_cli/sysmon/7.yml b/rules/deep_blue_cli/sysmon/7.yml index fc043c1d..f7ae7a10 100644 --- a/rules/deep_blue_cli/sysmon/7.yml +++ b/rules/deep_blue_cli/sysmon/7.yml @@ -1,8 +1,6 @@ title: Check for unsigned EXEs/DLLs description: hogehoge author: Yea -logsource: - product: windows detection: selection: Channel: Sysmon @@ -11,7 +9,6 @@ detection: # condition: selection falsepositives: - unknown -level: low output: 'Message: Unsigned Image(DLL)¥n Result : Loaded by: %event_data.Image%¥nCommand : %event_data.ImageLoaded%' creation_date: 2020/11/8 uodated_date: 2020/11/8 diff --git a/rules/deep_blue_cli/system/104.yml b/rules/deep_blue_cli/system/104.yml index 597cbb48..25fce57f 100644 --- a/rules/deep_blue_cli/system/104.yml +++ b/rules/deep_blue_cli/system/104.yml @@ -1,8 +1,6 @@ title: The System log file was cleared description: hogehoge author: Yea -logsource: - product: windows detection: selection: Channel: System @@ -10,7 +8,6 @@ detection: # condition: selection falsepositives: - unknown -level: medium output: 'System Log Clear¥nThe System log was cleared.' creation_date: 2020/11/8 uodated_date: 2020/11/8 diff --git a/rules/deep_blue_cli/system/7030.yml b/rules/deep_blue_cli/system/7030.yml index 3af74a54..a31f3dd4 100644 --- a/rules/deep_blue_cli/system/7030.yml +++ b/rules/deep_blue_cli/system/7030.yml @@ -1,8 +1,6 @@ title: This service may not function properly description: hogehoge author: Yea -logsource: - product: windows detection: selection: Channel: System @@ -12,7 +10,6 @@ detection: # condition: selection falsepositives: - unknown -level: low output: 'Interactive service warning¥nService name: %ServiceName%¥nMalware (and some third party software) trigger this warning' creation_date: 2020/11/8 uodated_date: 2020/11/8 diff --git a/rules/deep_blue_cli/system/7036.yml b/rules/deep_blue_cli/system/7036.yml index ac5d0508..52226e5a 100644 --- a/rules/deep_blue_cli/system/7036.yml +++ b/rules/deep_blue_cli/system/7036.yml @@ -1,8 +1,6 @@ title: The ... service entered the stopped|running state description: hogehoge author: Yea -logsource: - product: windows detection: selection: Channel: System @@ -12,7 +10,6 @@ detection: condition: selection falsepositives: - unknown -level: low output: 'Suspicious Service Name¥nService name: %ServiceName%' creation_date: 2020/11/8 uodated_date: 2020/11/8 diff --git a/rules/deep_blue_cli/system/7040.yml b/rules/deep_blue_cli/system/7040.yml index 371ed498..d834ed1b 100644 --- a/rules/deep_blue_cli/system/7040.yml +++ b/rules/deep_blue_cli/system/7040.yml @@ -1,8 +1,6 @@ title: The start type of the Windows Event Log service was changed from auto start to disabled description: hogehoge author: Yea -logsource: - product: windows detection: selection: Channel: System @@ -14,7 +12,6 @@ detection: condition: selection falsepositives: - unknown -level: low output: 'Service name : %param1%¥nMessage : Event Log Service Stopped¥nResults: Selective event log manipulation may follow this event.' creation_date: 2020/11/8 uodated_date: 2020/11/8 diff --git a/rules/deep_blue_cli/system/7045.yml b/rules/deep_blue_cli/system/7045.yml index 7a574da0..60db511e 100644 --- a/rules/deep_blue_cli/system/7045.yml +++ b/rules/deep_blue_cli/system/7045.yml @@ -1,8 +1,6 @@ title: A service was installed in the system description: hogehoge author: Yea -logsource: - product: windows detection: selection: Channel: System @@ -15,7 +13,6 @@ detection: condition: selection falsepositives: - unknown -level: low output: 'New Service Created¥n%ImagePath¥nService name: %ServiceName%' creation_date: 2020/11/8 uodated_date: 2020/11/8 diff --git a/rules/kerberoast/as-rep-roasting.yml b/rules/kerberoast/as-rep-roasting.yml index 83d042be..e74452e2 100644 --- a/rules/kerberoast/as-rep-roasting.yml +++ b/rules/kerberoast/as-rep-roasting.yml @@ -1,8 +1,6 @@ title: AS-REP Roasting description: For each account found without preauthentication, an adversary may send an AS-REQ message without the encrypted timestamp and receive an AS-REP message with TGT data which may be encrypted with an insecure algorithm such as RC4. author: Yea -logsource: - product: windows detection: selection: Channel: Security @@ -11,7 +9,6 @@ detection: PreAuthType: 0 falsepositives: - unknown -level: medium output: 'Detected AS-REP Roasting Risk Actvity.' creation_date: 2021/4/31 updated_date: 2021/4/31 diff --git a/rules/kerberoast/kerberoasting.yml b/rules/kerberoast/kerberoasting.yml index 9f84ebc6..ec667457 100644 --- a/rules/kerberoast/kerberoasting.yml +++ b/rules/kerberoast/kerberoasting.yml @@ -1,8 +1,6 @@ title: Kerberoasting description: Adversaries may abuse a valid Kerberos ticket-granting ticket (TGT) or sniff network traffic to obtain a ticket-granting service (TGS) ticket that may be vulnerable to Brute Force. author: Yea -logsource: - product: windows detection: selection: Channel: Security @@ -11,7 +9,6 @@ detection: PreAuthType: 2 falsepositives: - unknown -level: medium output: 'Detected Kerberoasting Risk Activity.' creation_date: 2021/4/31 updated_date: 2021/4/31 diff --git a/rules/powershell/downgrade_attack.yml b/rules/powershell/downgrade_attack.yml index e35f299a..1b90b04b 100644 --- a/rules/powershell/downgrade_attack.yml +++ b/rules/powershell/downgrade_attack.yml @@ -1,8 +1,6 @@ title: PowerShell DownGradeAttack description: hogehoge author: Yea -logsource: - product: windows detection: selection: Channel: Windows PowerShell @@ -10,7 +8,6 @@ detection: EventData|re: '[\s\S]*EngineVersion=2\.0[\s\S]*' falsepositives: - unknown -level: medium output: 'Powershell DownGrade Attack Detected!!' creation_date: 2020/11/8 updated_date: 2020/11/8 diff --git a/src/detections/configs.rs b/src/detections/configs.rs index a321901e..9d346546 100644 --- a/src/detections/configs.rs +++ b/src/detections/configs.rs @@ -39,22 +39,20 @@ fn build_app<'a>() -> ArgMatches<'a> { } App::new(&program) - .about("Yea! (Yamato Event Analyzer). Aiming to be the world's greatest Windows event log analysis tool!") - .version("0.0.1") - .author("Author name ") + .about("Lagotto. Aiming to be the world's greatest Windows event log analysis tool!") + .version("1.0.0") + .author("Author name Yamato-Security(https://github.com/Yamato-Security/YamatoEventAnalyzer)") .setting(AppSettings::VersionlessSubcommands) - .arg(Arg::from_usage("-f --filepath=[FILEPATH] 'event file path'")) - .arg(Arg::from_usage("--attackhunt=[ATTACK_HUNT] 'Attack Hunt'")) - .arg(Arg::from_usage("--csv-timeline=[CSV_TIMELINE] 'csv output timeline'")) - .arg(Arg::from_usage("--human-readable-timeline=[HUMAN_READABLE_TIMELINE] 'human readable timeline'")) - .arg(Arg::from_usage("--rfc-2822 'output date and time in RFC 2822 format. Example: Mon, 07 Aug 2006 12:34:56 -0600'")) - .arg(Arg::from_usage("-l --lang=[LANG] 'output language'")) - .arg(Arg::from_usage("-u --utc 'output time in UTC format(default: local time)'")) - .arg(Arg::from_usage("-d --directory=[DIRECTORY] 'event log files directory'")) - .arg(Arg::from_usage("-s --statistics 'event statistics'")) - .arg(Arg::from_usage("-t --threadnum=[NUM] 'thread number'")) - .arg(Arg::from_usage("--slack 'slack notification'")) - .arg(Arg::from_usage("--credits 'Zachary Mathis, Akira Nishikawa'")) + .arg(Arg::from_usage("-f --filepath=[FILEPATH] 'Event file path'")) + .arg(Arg::from_usage("--csv-timeline=[CSV_TIMELINE] 'Csv output timeline'")) + .arg(Arg::from_usage("--rfc-2822 'Output date and time in RFC 2822 format. Example: Mon, 07 Aug 2006 12:34:56 -0600'")) + .arg(Arg::from_usage("-l --lang=[LANG] 'Output language'")) + .arg(Arg::from_usage("-u --utc 'Output time in UTC format(default: local time)'")) + .arg(Arg::from_usage("-d --directory=[DIRECTORY] 'Event log files directory'")) + .arg(Arg::from_usage("-s --statistics 'Prints statistics for event logs'")) + .arg(Arg::from_usage("-t --threadnum=[NUM] 'Thread number'")) + .arg(Arg::from_usage("--slack 'Slack notification'")) + .arg(Arg::from_usage("--credits 'Prints credits'")) .get_matches() } diff --git a/src/detections/rule/matchers.rs b/src/detections/rule/matchers.rs index 48a2aac6..81597167 100644 --- a/src/detections/rule/matchers.rs +++ b/src/detections/rule/matchers.rs @@ -72,7 +72,7 @@ impl LeafMatcher for MinlengthMatcher { /// 正規表現のリストが記載されたファイルを読み取って、比較するロジックを表すクラス /// DeepBlueCLIのcheck_cmdメソッドの一部に同様の処理が実装されていた。 pub struct RegexesFileMatcher { - regexes_csv_content: Vec>, + regexes_csv_content: Vec, } impl RegexesFileMatcher { @@ -107,15 +107,11 @@ impl LeafMatcher for RegexesFileMatcher { return Result::Err(vec![errmsg]); } - let csv_content = utils::read_csv(&value.unwrap()); - if csv_content.is_err() { - let errmsg = format!( - "cannot read regexes file. [key:{}]", - utils::concat_selection_key(key_list) - ); - return Result::Err(vec![errmsg]); + let regexes_csv_content = utils::read_txt(&value.unwrap()); + if regexes_csv_content.is_err() { + return Result::Err(vec![regexes_csv_content.unwrap_err()]); } - self.regexes_csv_content = csv_content.unwrap(); + self.regexes_csv_content = regexes_csv_content.unwrap(); return Result::Ok(()); } @@ -123,10 +119,8 @@ impl LeafMatcher for RegexesFileMatcher { fn is_match(&self, event_value: Option<&Value>) -> bool { //TODO Wildcardの場合、CaseInsensitiveなので、ToLowerする。 return match event_value.unwrap_or(&Value::Null) { - Value::String(s) => !utils::check_regex(s, 0, &self.regexes_csv_content).is_empty(), - Value::Number(n) => { - !utils::check_regex(&n.to_string(), 0, &self.regexes_csv_content).is_empty() - } + Value::String(s) => !utils::check_regex(s, &self.regexes_csv_content), + Value::Number(n) => !utils::check_regex(&n.to_string(), &self.regexes_csv_content), _ => false, }; } @@ -135,7 +129,7 @@ impl LeafMatcher for RegexesFileMatcher { /// ファイルに列挙された文字列に一致する場合に検知するロジックを表す /// DeepBlueCLIのcheck_cmdメソッドの一部に同様の処理が実装されていた。 pub struct WhitelistFileMatcher { - whitelist_csv_content: Vec>, + whitelist_csv_content: Vec, } impl WhitelistFileMatcher { @@ -170,15 +164,11 @@ impl LeafMatcher for WhitelistFileMatcher { return Result::Err(vec![errmsg]); } - let csv_content = utils::read_csv(&value.unwrap()); - if csv_content.is_err() { - let errmsg = format!( - "cannot read whitelist file. [key:{}]", - utils::concat_selection_key(key_list) - ); - return Result::Err(vec![errmsg]); + let whitelist_content = utils::read_txt(&value.unwrap()); + if whitelist_content.is_err() { + return Result::Err(vec![whitelist_content.unwrap_err()]); } - self.whitelist_csv_content = csv_content.unwrap(); + self.whitelist_csv_content = whitelist_content.unwrap(); return Result::Ok(()); } @@ -662,28 +652,16 @@ mod tests { // regexes.txtの中身と一致していることを確認 let csvcontent = &ancestor_matcher.regexes_csv_content; - assert_eq!(csvcontent.len(), 14); - - let firstcontent = &csvcontent[0]; - assert_eq!(firstcontent.len(), 3); - assert_eq!(firstcontent[0], "0"); + assert_eq!(csvcontent.len(), 17); assert_eq!( - firstcontent[1], + csvcontent[0], r"^cmd.exe /c echo [a-z]{6} > \\\\.\\pipe\\[a-z]{6}$" ); - assert_eq!( - firstcontent[2], - r"Metasploit-style cmd with pipe (possible use of Meterpreter 'getsystem')" - ); - let lastcontent = &csvcontent[13]; - assert_eq!(lastcontent.len(), 3); - assert_eq!(lastcontent[0], "0"); assert_eq!( - lastcontent[1], + csvcontent[14], r"\\cvtres\.exe.*\\AppData\\Local\\Temp\\[A-Z0-9]{7}\.tmp" ); - assert_eq!(lastcontent[2], r"PSAttack-style command via cvtres.exe"); } // whitelist.txtが読み込めることを確認 @@ -704,11 +682,11 @@ mod tests { assert_eq!(csvcontent.len(), 2); assert_eq!( - csvcontent[0][0], + csvcontent[0], r#"^"C:\\Program Files\\Google\\Chrome\\Application\\chrome\.exe""#.to_string() ); assert_eq!( - csvcontent[1][0], + csvcontent[1], r#"^"C:\\Program Files\\Google\\Update\\GoogleUpdate\.exe""#.to_string() ); } diff --git a/src/detections/utils.rs b/src/detections/utils.rs index edf45d91..2dcd5363 100644 --- a/src/detections/utils.rs +++ b/src/detections/utils.rs @@ -11,6 +11,7 @@ use regex::Regex; use serde_json::Value; use std::fs::File; use std::io::prelude::*; +use std::io::{BufRead, BufReader}; use std::str; use std::string::String; @@ -23,50 +24,30 @@ pub fn concat_selection_key(key_list: &Vec) -> String { }); } -pub fn check_regex( - string: &str, - r#type: usize, - regex_list: &Vec>, -) -> std::string::String { - let empty = "".to_string(); - let mut regextext = "".to_string(); +pub fn check_regex(string: &str, regex_list: &Vec) -> bool { for line in regex_list { - let type_str = line.get(0).unwrap_or(&empty); - if type_str != &r#type.to_string() { + if line.is_empty() { continue; } - let regex_str = line.get(1).unwrap_or(&empty); - if regex_str.is_empty() { - continue; - } - - let re = Regex::new(regex_str); + let re = Regex::new(line); if re.is_err() || re.unwrap().is_match(string) == false { continue; } - let text = line.get(2).unwrap_or(&empty); - if text.is_empty() { - continue; - } - - regextext.push_str(text); - regextext.push_str("\n"); + return true; } - return regextext; + return false; } -pub fn check_whitelist(target: &str, whitelist: &Vec>) -> bool { - let empty = "".to_string(); +pub fn check_whitelist(target: &str, whitelist: &Vec) -> bool { for line in whitelist { - let r_str = line.get(0).unwrap_or(&empty); - if r_str.is_empty() { + if line.is_empty() { continue; } - let r = Regex::new(r_str); + let r = Regex::new(line); if r.is_ok() && r.unwrap().is_match(target) { return true; } @@ -75,6 +56,21 @@ pub fn check_whitelist(target: &str, whitelist: &Vec>) -> bool { return false; } +pub fn read_txt(filename: &str) -> Result, String> { + let f = File::open(filename); + if f.is_err() { + let errmsg = format!("cannot open file. [file:{}]", filename); + return Result::Err(errmsg); + } + let reader = BufReader::new(f.unwrap()); + return Result::Ok( + reader + .lines() + .map(|line| line.unwrap_or(String::default())) + .collect(), + ); +} + pub fn read_csv(filename: &str) -> Result>, String> { let mut f = File::open(filename).expect("file not found!!!"); let mut contents: String = String::new(); @@ -165,18 +161,18 @@ mod tests { use crate::detections::utils; #[test] fn test_check_regex() { - let regexes = utils::read_csv("regexes.txt").unwrap(); - let regextext = utils::check_regex("\\cvtres.exe", 0, ®exes); - assert!(regextext == "Resource File To COFF Object Conversion Utility cvtres.exe\n"); + let regexes = utils::read_txt("regexes.txt").unwrap(); + let regextext = utils::check_regex("\\cvtres.exe", ®exes); + assert!(regextext == true); - let regextext = utils::check_regex("\\hogehoge.exe", 0, ®exes); - assert!(regextext == ""); + let regextext = utils::check_regex("\\hogehoge.exe", ®exes); + assert!(regextext == false); } #[test] fn test_check_whitelist() { let commandline = "\"C:\\Program Files\\Google\\Update\\GoogleUpdate.exe\""; - let whitelist = utils::read_csv("whitelist.txt").unwrap(); + let whitelist = utils::read_txt("whitelist.txt").unwrap(); assert!(true == utils::check_whitelist(commandline, &whitelist)); let commandline = "\"C:\\Program Files\\Google\\Update\\GoogleUpdate2.exe\""; diff --git a/src/main.rs b/src/main.rs index 4b26b728..3514f11b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,17 +2,17 @@ extern crate serde; extern crate serde_derive; use evtx::{EvtxParser, ParserSettings}; +use lagotto::detections::detection; +use lagotto::detections::detection::EvtxRecordInfo; +use lagotto::detections::print::AlertMessage; +use lagotto::omikuji::Omikuji; +use lagotto::{afterfact::after_fact, detections::utils}; +use lagotto::{detections::configs, timeline::timeline::Timeline}; use std::{ fs::{self, File}, path::PathBuf, vec, }; -use yamato_event_analyzer::detections::detection; -use yamato_event_analyzer::detections::detection::EvtxRecordInfo; -use yamato_event_analyzer::detections::print::AlertMessage; -use yamato_event_analyzer::omikuji::Omikuji; -use yamato_event_analyzer::{afterfact::after_fact, detections::utils}; -use yamato_event_analyzer::{detections::configs, timeline::timeline::Timeline}; // 一度にtimelineやdetectionを実行する行数 const MAX_DETECT_RECORDS: usize = 40000; diff --git a/whitelist.txt b/whitelist.txt index a6165f49..4a160ef0 100644 --- a/whitelist.txt +++ b/whitelist.txt @@ -1,3 +1,2 @@ -regex ^"C:\\Program Files\\Google\\Chrome\\Application\\chrome\.exe" ^"C:\\Program Files\\Google\\Update\\GoogleUpdate\.exe"