Go言語で作成したプログラムがWindows Defenderに「Wacatac!ml」と誤検知される件と回避方法
こんなことあるんだ😲という豆知識記事です。
似たような事象の人のヒントになればと。
経緯
Mac上でGo言語でコマンドラインプログラムを作成して、配布用にWindowsバイナリをクロスコンパイルしてGitHub Releaseにあげて、Windows側でダウンロードして実行するとWindows Defender君に 「Wacatac!mlだ!」 と怒られファイルをローカルで削除されてしまいました。
環境詳細
- ソースビルドはMac M1 darwin/arm64
- goのバージョン等は go1.19
- Windows向けバイナリは
GOOS=windows GOARCH=amd64 go build -trimpath -ldflags '-s -w' -o
オプションで作成 - Windowsバージョンは10Pro 21H2
Wacatac!ml とは?
マルウェアの一種のようですが誤検知の記事もちらほらあるようです
自作ソフトがMicrosoft Defenderから Trojan:Win32/Wacatac.B!mlとして判定を受けてしまいました。 ↓の記事タイトル
Go言語でDefendeの誤検知にひっかかった箇所
ファイルのソースを一部コメントアウトしていき、コンパイルー>動作確認を繰り返して特定していきました。
f, err := os.Create(filePath)
if err != nil {
log.Fatal(err)
}
w := csv.NewWriter(f)
for _, record := range records {
if err := w.Write(record); err != nil {
log.Fatal(err)
}
}
w.Flush() //<--------!!!!これ!!!!!!!
CSVファイルを作成する箇所で、メモリ上の配列を1行ずつファイルに書き込んでいき最後にFlushする箇所がどうもひっかかっていそうなのがわかりました。
回避策
goのAPIリファレンスにflushを直接使わないサンプルがあるのでそちらにコードを変更します
f, err := os.Create(filePath)
if err != nil {
log.Fatal(err)
}
w := csv.NewWriter(f)
//https://pkg.go.dev/encoding/csv#Writer.Write
//w.write + w.Flush するとWindowsDefenderが誤検知するのでw.WriteAllを使う
err = w.WriteAll(records) // calls Flush internally
if err != nil {
log.Fatalln(err)
}
if err := w.Error(); err != nil {
log.Fatalln("error writing csv:", err)
}
推測されるDefenderにひっかかっている理由
flushの内部のメモリ間のコピー処理=build-in関数のcopyあたりがチェックにひっかかっていると推測されますが、どこが誤検知されているかはDefender君が教えてくれるわけではないので推測の粋をでません。
結論
今回はw.writeをw.WriteAllに変更することでw.Flush()を呼び出さずに誤検知を回避することができましたが、プログラムの構成によってはデータをメモリに貯めっぱなしにすることも難しいと思うため別の回避方法は検討する必要はありそうです。なんにせよ開発機はMacの場合にGo言語で気軽にWindows向けにクロスコンパイルできるとは言ってもこういったセキュリティ絡みの強化があるご時世ではWindows側の動作確認はちゃんとしないとトラブルになるな感じました。クロスコンパイルしてバイナリだけ配置して動作確認せずとも「たぶん動くでしょ」というわけにはいかないんだなと。
Discussion