Go言語入門:よくある質問 -Implementation Vol.5-

スポンサーリンク
Go言語入門:よくある質問 -Implementation Vol.5- ノウハウ
Go言語入門:よくある質問 -Implementation Vol.5-
この記事は約13分で読めます。
よっしー
よっしー

こんにちは。よっしーです(^^)

本日は、Go言語のよくある質問 について解説しています。

スポンサーリンク

背景

Go言語を学んでいると「なんでこんな仕様になっているんだろう?」「他の言語と違うのはなぜ?」といった疑問が湧いてきませんか。Go言語の公式サイトにあるFAQページには、そんな疑問に対する開発チームからの丁寧な回答がたくさん載っているんです。ただ、英語で書かれているため読むのに少しハードルがあるのも事実で、今回はこのFAQを日本語に翻訳して、Go言語への理解を深めていけたらと思い、これを読んだ時の内容を備忘として残しました。

Implementation

なぜウイルススキャンソフトウェアが、Goディストリビューションやコンパイル済みバイナリが感染していると判断するのか?

これは、特にWindowsマシンでよく発生する現象で、ほぼ常に誤検知です。商用ウイルススキャンプログラムは、他の言語からコンパイルされたものほど頻繁に見かけないGoバイナリの構造に混乱することがよくあります。

Goディストリビューションをインストールしたばかりで、システムが感染していると報告する場合、それは確実に間違いです。本当に徹底的に確認するには、ダウンロードページのチェックサムとダウンロードしたものを比較することでダウンロードを検証できます。

いずれにせよ、報告が誤りだと思われる場合は、ウイルススキャナーの提供元にバグを報告してください。時間が経てば、ウイルススキャナーもGoプログラムを理解できるようになるかもしれません。

解説

この問題は何について説明しているの?

Goでプログラムを作ってコンパイルすると、こんな警告が出ることがあります:

⚠️ Windows Defender
脅威が検出されました: Trojan:Win32/Wacatac.B!ml
ファイル: hello.exe

「え!? ウイルス!? 自分で作ったプログラムなのに!?」

安心してください。これはほぼ100%誤検知(false positive)です。

基本的な用語
  • 誤検知 (false positive): 実際には問題ないのに、問題があると誤って検出すること
  • ウイルススキャナー: ウイルスやマルウェアを検出するソフト
  • バイナリ: コンパイル後の実行ファイル
  • チェックサム: ファイルの「指紋」のようなもの、改ざん検出に使う
  • ヒューリスティック検査: 既知のウイルスパターンではなく、「怪しい動作」を検出する方法
なぜGoのバイナリが誤検知されるのか?
理由1: 見慣れない構造

ウイルススキャナーの学習:

たくさん見たもの:
  C/C++でコンパイルされたプログラム
  .NET Framework プログラム
  Visual Studioで作られたプログラム
    ↓
  これらは「正常」と学習

あまり見ないもの:
  Goでコンパイルされたプログラム
    ↓
  「怪しい!?」と判断

例え:

警察犬が学習しているもの:
  犬、猫、人間 → 安全
  
初めて見るもの:
  カピバラ → 「何これ!? 危険かも!」

実際には無害なのに、見慣れないから警戒してしまう。

理由2: 静的リンク

前の質問で学んだように、Goは静的リンク:

Goのバイナリ:
┌────────────────────┐
│ あなたのコード    │
│ + ランタイム      │
│ + 全ての依存      │  ← 大きい、自己完結
└────────────────────┘

一般的なプログラム:
┌──────────┐
│ コード   │  ← 小さい、外部依存
└──────────┘
     ↓
  システムDLL

ウイルススキャナーの判断:

「このプログラム、システムDLLを使わない...」
「全部自分で持ってる...」
「マルウェアがよくやる手口だ!」
→ 誤検知!
理由3: 実行時の特殊な動作

Goのランタイムは独特:

  • 独自のスケジューラ
  • 独自のメモリ管理
  • 独自のスタック管理

ウイルススキャナー:

「通常のプログラムと動きが違う...」
「怪しい...」
→ 誤検知!
理由4: UPX圧縮

バイナリサイズを小さくするためにUPXで圧縮すると:

upx --best hello.exe

ウイルススキャナー:

「実行ファイルが圧縮されている!」
「マルウェアがよく使う手法!」
→ 誤検知率UP!

実際、マルウェアは検出を逃れるために圧縮を使うことがあります。

よくある誤検知のパターン
パターン1: Go本体のインストール時

シナリオ:

1. go1.21.windows-amd64.msi をダウンロード
2. インストール実行
3. Windows Defenderが警告:
   「Trojan:Win32/Wacatac が検出されました」

これは間違いです! 公式サイトからダウンロードしたGoは安全です。

パターン2: 自作プログラムのコンパイル直後

シナリオ:

1. hello.go を作成
2. go build hello.go
3. hello.exe が生成される
4. すぐに削除される!
5. 「脅威を削除しました」と通知

あなたのプログラムが削除された! でも、ウイルスではありません。

パターン3: ネットワーク機能を使うプログラム
package main

import (
    "net/http"
    "fmt"
)

func main() {
    resp, _ := http.Get("https://example.com")
    fmt.Println(resp.Status)
}

ウイルススキャナー:

「ネットワーク通信している!」
「外部と通信するプログラム!」
「怪しい!」
→ 誤検知!
対処方法
方法1: ウイルススキャナーの例外設定

Windows Defender の場合:

  1. Windows セキュリティを開く
  2. ウイルスと脅威の防止
  3. 設定の管理
  4. 除外セクション
  5. 除外の追加または削除

追加する除外:

フォルダ: C:\Program Files\Go
フォルダ: C:\Users\YourName\go
フォルダ: C:\Users\YourName\Projects

注意: 本当に安全なフォルダだけを除外してください!

方法2: チェックサムで検証

公式ダウンロードの確認:

# ダウンロードしたファイルのチェックサム
certutil -hashfile go1.21.windows-amd64.msi SHA256

出力例:

SHA256 hash of go1.21.windows-amd64.msi:
a1b2c3d4e5f6...

公式サイトと比較:

https://go.dev/dl/
→ Checksums を確認
→ 一致すれば安全!
方法3: 段階的な対応

ステップ1: 冷静に判断

質問1: 公式サイトからダウンロードした?
  → YES: ほぼ確実に誤検知

質問2: 自分で書いたコード?
  → YES: ほぼ確実に誤検知

質問3: 怪しいサイトからダウンロード?
  → YES: 本当に危険かも!

ステップ2: 検証

1. チェックサムを確認
2. VirusTotalでスキャン(オンラインサービス)
3. 複数のスキャナーで確認

ステップ3: 報告

1. ウイルススキャナー提供元に誤検知を報告
2. Goコミュニティにも報告(GitHub Issue)
VirusTotal での確認方法

VirusTotal: 複数のウイルススキャナーで一度にチェックできるサービス

1. https://www.virustotal.com にアクセス
2. ファイルをアップロード
3. 結果を確認:
   
   例:
   60個のスキャナー中:
   - 58個: 問題なし
   - 2個: 検出
   
   → 誤検知の可能性が高い

注意:

  • 機密情報を含むプログラムはアップロードしない
  • アップロードしたファイルは公開される
各ウイルススキャナーでの報告方法
Windows Defender (Microsoft)
1. Windows セキュリティを開く
2. 保護の履歴
3. 該当する検出を見つける
4. 「誤検知として報告」をクリック

または:

https://www.microsoft.com/en-us/wdsi/filesubmission
Avast
https://www.avast.com/false-positive-file-form.php
AVG
https://www.avg.com/en-us/false-positive-file-form
Kaspersky
https://opentip.kaspersky.com/
なぜこの問題が起きるのか(技術的詳細)
Goバイナリの特徴

1. 大きなバイナリサイズ

通常のC/C++プログラム: 数十KB
Goプログラム: 数MB

ウイルススキャナー:
「大きい = たくさんコードが詰まっている」
「マルウェアかも?」

2. 独特なバイナリ構造

PE (Portable Executable) ヘッダー:
- Goは独自のセクション配置
- 通常と異なるエントリーポイント
- カスタムローダー

ウイルススキャナー:
「見慣れない構造...」

3. ランタイムの動的動作

実行時:
- メモリを動的に確保
- スタックを動的に拡張
- ゴルーチンを作成・破棄

ウイルススキャナー:
「動的な動作が多い...」
「マルウェアっぽい?」
実際の対処例
例1: 簡単なHTTPサーバー

コード:

package main

import (
    "fmt"
    "net/http"
)

func handler(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "Hello, World!")
}

func main() {
    http.HandleFunc("/", handler)
    http.ListenAndServe(":8080", nil)
}

コンパイル:

go build -o server.exe server.go

Windows Defender の反応:

脅威: Trojan:Win32/Casdet!rfn
状態: 削除されました

対処:

# 1. 除外フォルダに追加
# 2. 再ビルド
go build -o server.exe server.go

# 3. 実行
./server.exe
# → 問題なく動作!
例2: コマンドラインツール

コード:

package main

import (
    "fmt"
    "os"
)

func main() {
    if len(os.Args) < 2 {
        fmt.Println("Usage: tool <filename>")
        return
    }
    
    data, _ := os.ReadFile(os.Args[1])
    fmt.Println(string(data))
}

誤検知の理由:

  • ファイルシステムアクセス
  • コマンドライン引数の処理

対処:

  • プロジェクトフォルダを除外設定
  • ウイルススキャナーに報告
予防策
1. 開発フォルダを除外設定

推奨構成:

C:\Users\YourName\
  ├── go\           ← Go modules キャッシュ
  └── Projects\     ← 開発フォルダ
      ├── project1\
      ├── project2\
      └── ...

除外設定:
  C:\Users\YourName\go
  C:\Users\YourName\Projects
2. リアルタイムスキャンの調整

Windows Defender:

設定 → ウイルスと脅威の防止
→ リアルタイム保護
→ (必要に応じて)一時的に無効化

注意: 開発中のみ、安全な環境で!

3. ビルドフラグの調整
# デバッグ情報を含める(誤検知率が下がることも)
go build -ldflags="-s -w" main.go

# または、通常ビルド
go build main.go

実は、デバッグ情報を削除すると誤検知が増えることも…

コミュニティの取り組み
Go チームの対応
1. ウイルススキャナー企業に連絡
2. Goバイナリの特徴を説明
3. 誤検知データベースに追加してもらう

進行中ですが、完全解決には時間がかかります。

ユーザーができること
1. 誤検知を報告
   → ウイルススキャナー企業
   → Goのissue tracker

2. データを共有
   → どのスキャナーで検出されたか
   → どんなプログラムか

3. 忍耐強く待つ
   → 時間とともに改善される
まとめ
Goバイナリの誤検知について
  1. ほぼ確実に誤検知
    • 公式からのダウンロード
    • 自作プログラム
    • 特にWindows環境
  2. 原因:
    • 見慣れない構造
    • 静的リンク
    • 独特なランタイム動作
  3. 対処法:
    • 除外設定
    • チェックサム確認
    • 報告
実用的なアドバイス
状況対応優先度
Go本体のインストール除外設定 + チェックサム確認🔴 高
開発中のプログラムプロジェクトフォルダを除外🔴 高
配布用プログラムデジタル署名🟡 中
誤検知の報告スキャナー企業に連絡🟢 低
やるべきこと

すぐに:

  1. ✅ 開発フォルダを除外設定
  2. ✅ Go インストールフォルダを除外設定
  3. ✅ チェックサムで公式ダウンロードを確認

余裕があれば:

  1. ⭐ VirusTotalで確認
  2. ⭐ ウイルススキャナーに誤検知を報告
  3. ⭐ Goコミュニティに情報共有
やってはいけないこと

ウイルススキャナーを完全に無効化 → 本当の脅威から無防備に

怪しいサイトからGoをダウンロード → 本当にウイルスの可能性

すべてのプログラムを信用 → 自分で書いたコードのみ信用

長期的な展望
現在:
  Goは比較的新しい
  ウイルススキャナーが学習中

数年後:
  Goがより普及
  誤検知が減少
  
将来:
  ほとんど問題なし?

時間とともに、ウイルススキャナーも進化し、Goバイナリを正しく認識できるようになるはずです。

重要な心構え:

  • 😱 パニックにならない
  • 🔍 冷静に確認する
  • 📝 必要なら報告する
  • 💪 開発を続ける!

この問題は、Goが「新しくて優れている」ことの副作用とも言えます。ウイルススキャナーが追いついていないだけで、あなたのプログラムは安全です。適切な対処をすれば、開発には全く支障ありません!

おわりに 

本日は、Go言語のよくある質問について解説しました。

よっしー
よっしー

何か質問や相談があれば、コメントをお願いします。また、エンジニア案件の相談にも随時対応していますので、お気軽にお問い合わせください。

それでは、また明日お会いしましょう(^^)

コメント

タイトルとURLをコピーしました