CrowdStrike Blog:ウクライナを標的にしたと報じられた PartyTicketランサムウェア、復号可能と判明 | ScanNetSecurity
2023.02.01(水)

CrowdStrike Blog:ウクライナを標的にしたと報じられた PartyTicketランサムウェア、復号可能と判明

本日、ウクライナの標的に対してデプロイされたランサムウェア「PartyTicket」に関する詳細情報をブログで紹介します。

脆弱性と脅威 脅威動向
CrowdStrike Blog:ウクライナを標的にしたと報じられた PartyTicketランサムウェア、復号可能と判明
CrowdStrike Blog:ウクライナを標的にしたと報じられた PartyTicketランサムウェア、復号可能と判明 全 2 枚 拡大写真

 2022 年 2 月 23 日、ウクライナの組織を標的とした破壊的な攻撃が行われました。業界のレポートによると、被害に遭ったいくつかの企業や組織において、PartyTicket(または HermeticRansom)という Go言語で書かれたランサムウェアが検知されました(注1)。他に、CrowdStrike のインテリジェンスチームが DriveSlayer(HermeticWiper)として追跡する同系の高度なワイパー型攻撃も確認されています。

 PartyTicketランサムウェアを分析したところ、ファイルの暗号化は表面的なもののようです。暗号化キーの初期化を正しく行っていないため、拡張子が .encryptedJB の暗号化ファイルであれば復元できることがわかりました。

●技術分析

 PartyTicketランサムウェアの検体には、4dc13bb83a16d4ff9865a51b3e4d24112327c526c1392e14d56f20d6f4eaf382 という SHA256ハッシュがあります。cdir.exe、cname.exe、connh.exe、intpub.exe というファイル名と関連があることが確認されています。

 Go言語の 1.10.1バージョンで書かれたランサムウェアの検体には、voteFor403、C:/projects/403forBiden/wHiteHousE、primaryElectionProcess といった米国の政治システムを示す記号が多数含まれています。

 このランサムウェアはすべてのドライブレターで実行を繰り返し、各ドライブ内とサブフォルダー内のファイルを再帰的に列挙します。ただし、Windows および Program Files の文字列を含むファイルパスや、C:\Documents and Settings(Windows XP より新しい Windowsバージョンでは、C:\Users)のフォルダパスは除きます。以下の拡張子の付いたファイルを暗号化の対象として選びます。

acl、avi、bat、bmp、cab、cfg、chm、cmd、com、contact、crt、css、dat、dip、dll、doc、docx、dot、encryptedjb、epub、exe、gif、htm、html、ico、in、iso、jpeg、jpg、mp3、msi、odt、one、ova、pdf、pgsql、png、ppt、pptx、pub、rar、rtf、sfx、sql、txt、url、vdi、vsd、wma、wmv、wtv、xls、xlsx、xml、xps、zip

 前述のパスに該当しない、これらの拡張子の各ファイルパスについて、ランサムウェアが自身のインスタンスを実行元と同じディレクトリにコピーしてコマンドラインで実行し、ファイルパスを引数として渡します。親のランサムウェアプロセスは、クローンにランダムな UUID で名前を付けます。これはパブリックライブラリ(注2)が生成したもので、現在のタイムスタンプおよび感染したホストのネットワークアダプターの MACアドレスが使用されます。

 マルウェアの開発者は Go の WaitGroup処理で並列処理機能を実装しようとしたようですが、おそらくコーディングエラーのため、ランサムウェアは大量のスレッド(列挙したファイルパスごとに 1 つ)を作成し、選択したファイルの数と同じ回数分、自身のバイナリをカレントディレクトリにコピーします。すべての暗号化スレッドの終了後、コマンドラインから元のバイナリが消去されます。

 検体がファイルパスを引数として受け取ると、Galois/Counter Mode(GCM)の AES を使用してファイルを暗号化します。AESキーは Go の randパッケージの Intn関数で生成されます。文字列 1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ 内のオフセットを選択することで 32バイトのキーを生成します。もう 1 つ別のコーディングエラーと思われますが、キーの生成後に Intn関数のシードが更新されています。つまり、バイナリとクローンが実行されるたび、同じ AESキーが生成されています。ホスト上で暗号化されたすべてのファイルには同じ暗号化キーが使用されており、対応する PartyTicket の検体のキーで復号化が可能です。このエラーを活用して暗号化ファイルを復元するためのスクリプトを GitHub の CrowdStrike のレポジトリに掲載しています。

 AES暗号化キーはファイルごとに RSA-OAEP で暗号化されており、以下のパラメータのパブリックRSAキーを使用しています。

Modulus (N): 0xcbb94cb189a638b51e7cfe161cd92edb7145ecbd93989e78c94f8c15c61829286fd834d80c931daed4ac4aba14835fd3a6721602bcaa7193245fc6cf8e1d3261460ff3f1cbae3d44690beb989adee69ac486a932ee44dbdf0a44e772ab9822a16753cd08bdbb169f866f722114ee69c0cf1588fdaf8f7efd1c3ed243786078593f9b0cd867bab2b170c1843660d16e2181ae679137e2650551a41631398e027206e22a55858c741079ceafd50d5bd69546d4d52f5a33b0a576e1750d3f83afa1ce4403d768cbd670b443f61794b44705a8b1132c0c0ce77dbd04053ba20aec9baf23944270f10d16ad0727ed490c91c7f469278827c20a3e560f7c84015f7e1b
Exponent (E): 0x10001

 暗号化の前に、ランサムウェアは
<original file name>.[vote2024forjb@protonmail[.]com].encryptedJB というフォーマットでファイル名を変更しています(バイナリに含まれているその他の政治的な内容からすると、「JB」はおそらく米国大統領、Joseph Biden のイニシャルでしょう)。その後、ランサムウェアはコンテンツを暗号化されたデータで上書きします。PartyTicket はファイルの最初の 9437184バイト(9.44 MB)だけを暗号化するでしょう。引数として渡されたファイルがこの容量を超えている場合は、超過分は暗号化されません。ファイルのコンテンツを暗号化した後、PartyTicket は RSA で暗号化された AESキーをファイルの最後に追加します。

 このランサムウェアはファイルの暗号化が開始する前に、read_me.html という名前の HTML の脅迫メモをユーザーのデスクトップディレクトリに残します(図1)。メモの文章は、文法ミスが意図的なものでない限り、英語が堪能な人物によって書かれたものでも、チェックされたものでもないようです。

図1:脅迫メモ

●評価

 CrowdStrike のインテリジェンスチームは、現時点では PartyTicket攻撃が名の知れた攻撃者によって行われたとは考えていません。

 このランサムウェアには実装エラーが含まれており、暗号化が遅く、復号化することができます。このエラーから、マルウェアの作成者は Go で書くのに慣れていない、または、おそらく開発時間が限られていたためにマルウェアを十分にテストしていないということが示唆されます。特に PartyTicket は、低レベルの NTFS の構文解析アルゴリズムを使用した DriveSlayer のレベルにさえ達していません。相対的に完成度が低く、政治的なメッセージを含むこと、デプロイのタイミング、ウクライナの組織を標的としたものであることから、通常のランサムウェアのような身代金要求としてではなく、DriveSlayer攻撃に便乗して使用されたと思われます。

●YARAシグネチャ

 以下の YARAルールを使用して PartyTicket を検知することができます。

rule CrowdStrike_PartyTicket_01 : ransomware golang
{
meta:
copyright = "(c) 2022 CrowdStrike Inc."
description = "Detects Golang-based crypter"
version = "202202250130"
last_modified = "2022-02-25"
strings:
$ = ".encryptedJB" ascii
$start = { ff 20 47 6f 20 62 75 69 6c 64 20 49 44 3a 20 22 }
$end = { 0a 20 ff }
condition:
uint16(0) == 0x5A4D and uint32(uint32(0x3C)) == 0x00004550 and
for 1 of ($end) : ( @start < @ and @start + 1024 > @) and
all of them
}

rule CrowdStrike_PartyTicket_02 : PartyTicket golang
{
meta:
copyright = "(c) 2022 CrowdStrike Inc."
description = "Detects Golang-based PartyTicket ransomware"
version = "202202250130"
last_modified = "2022-02-25"
strings:
$s1 = "voteFor403"
$s2 = "highWay60"
$s3 = "randomiseDuration"
$s4 = "subscribeNewPartyMember"
$s5 = "primaryElectionProces"
$s6 = "baggageGatherings"
$s7 = "getBoo"
$s8 = "selfElect"
$s9 = "wHiteHousE"
$s10 = "encryptedJB"
$goid = { ff 20 47 6f 20 62 75 69 6c 64 20 49 44 3a 20 22 71 62 30 48 37 41 64 57 41 59 44 7a 66 4d 41 31 4a 38 30 42 2f 6e 4a 39 46 46 38 66 75 70 4a 6c 34 71 6e 45 34 57 76 41 35 2f 50 57 6b 77 45 4a 66 4b 55 72 52 62 59 4e 35 39 5f 4a 62 61 2f 32 6f 30 56 49 79 76 71 49 4e 46 62 4c 73 44 73 46 79 4c 32 22 0a 20 ff }
$pdb = "C://projects//403forBiden//wHiteHousE"
condition:
(uint32(0) == 0x464c457f or (uint16(0) == 0x5a4d and uint16(uint32(0x3c)) == 0x4550)) and 4 of ($s*) or $pdb or $goid

●PartyTicket で暗号化されたファイルを復号化するためのスクリプト

 AESキー生成における前述の実装エラーにより、PartyTicket による暗号化に使用された AESキーを復元することができます。以下の Go のスクリプトによって、PartyTicket の検体
4dc13bb83a16d4ff9865a51b3e4d24112327c526c1392e14d56f20d6f4eaf382 を使って暗号化されたファイルを復号化できます。このスクリプトは“-p”フラグによって複合化するファイルを引数として受け取り、復号化した出力を同じディレクトリ内の“decrypted.bin”に保存します。このスクリプトはコンパイルして実行することも、Go の実行パッケージで実行することもできます。Go の go1.16.6 のバージョンを使用してテストされました。

package main

import (
"crypto/aes"
"crypto/cipher"
"encoding/hex"
"fmt"
"os"
"flag"
)

func main() {

encrypted_filepath := flag.String("p", "encrypted.bin", "Path to encrypted file")
flag.Parse()

fmt.Printf("Decrypting file : %s\n", *encrypted_filepath)
key_bytes := []byte("6FBBD7P95OE8UT5QRTTEBIWAR88S74DO")
key := hex.EncodeToString(key_bytes)
fmt.Printf("Decryption key : %s\n", key_bytes)

dat, err := os.ReadFile(*encrypted_filepath)
if err != nil {
fmt.Println("Unable to open file, please supply path of encrypted file with flag -p, default file path is ./encrypted.bin")
os.Exit(3)
}

decrypted_filepath := "decrypted.bin"
filecontents := dat
encrypted_contents := filecontents[:len(filecontents) - 288]
enc_size := len(encrypted_contents)
bsize := 1048604
cycles := enc_size / bsize

if cycles == 0{

encrypted := hex.EncodeToString(encrypted_contents)
decrypted := decrypt(encrypted, key)
write_output(decrypted_filepath, decrypted)
} else {
for i:=0; i<cycles; i++ { if i >= 9 {
start := 9 * bsize
end := enc_size
data := string(encrypted_contents[start:end])
write_output(decrypted_filepath, data)
break
}
block_start := i * bsize
block_end := (i+1) * bsize
if block_end > enc_size{
block_end := enc_size
encrypted:=hex.EncodeToString(encrypted_contents[block_start:block_end])
decrypted := decrypt(encrypted, key)
write_output(decrypted_filepath, decrypted)

}

encrypted:=hex.EncodeToString(encrypted_contents[block_start:block_end])
decrypted := decrypt(encrypted, key)
write_output(decrypted_filepath, decrypted)
}
}

fmt.Printf("Decrypted file written to : %s\n", decrypted_filepath)

}

func write_output(filepath string, data string) {
f, err := os.OpenFile(filepath, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
if err != nil {
panic(err)
}
byte_data := []byte(data)
f.Write(byte_data)
f.Close()
}

func decrypt(encryptedString string, keyString string) (decryptedString string) {

key, _ := hex.DecodeString(keyString)
enc, _ := hex.DecodeString(encryptedString)

block, err := aes.NewCipher(key)
if err != nil {
panic(err.Error())
}
aesGCM, err := cipher.NewGCM(block)
if err != nil {
panic(err.Error())
}
nonceSize := aesGCM.NonceSize()
nonce, ciphertext := enc[:nonceSize], enc[nonceSize:]
plaintext, err := aesGCM.Open(nil, nonce, ciphertext, nil)
if err != nil {
panic(err.Error())
}

return fmt.Sprintf("%s", plaintext)
}

[注]

1.https[:]//symantec-enterprise-blogs.security[.]com/blogs/threat-intelligence/ukraine-wiper-malware-russia

2.https[:]//pkg.go.dev/github[.]com/satori/go.uuid#NewV1

●追加のリソース

・ウクライナに対するサイバー攻撃の詳細については、こちらをご覧ください。Lessons Learned From Successive Use of Offensive Cyber Operations Against Ukraine and What May Be Next(ウクライナに対する一連のサイバー攻撃の教訓と今後の予測)

・CrowdStrike Falcon が DriveSlayer およびワイパー型攻撃に対して継続的に行っている防御については、こちらをご参照ください。CrowdStrike Falcon Protects from New Wiper Malware Used in Ukraine Cyberattacks(CrowdStrike Falcon、ウクライナへのサイバー攻撃で使用された新たなワイパー型マルウェアから保護)

・WhisperGate に関する CrowdStrike Intelligence のブログ記事をご覧ください。Technical Analysis of the WhisperGate Malicious Bootloader(WhisperGate不正ブートローダーの技術分析)

・パワフルでクラウドネイティブな CrowdStrike Falconプラットフォームをウェブサイトの製品のページでご紹介しています。

完全な機能を搭載した CrowdStrike Falcon Prevent の無料トライアルで最も高度な脅威に対抗する次世代アンチウイルスをご体験ください。

※この資料は、米国時間 2022 年 3 月 1 日に発表された CrowdStrike のインテリジェンスチームによるブログの抄訳です。

*原文は CrowdStrike Blog サイト掲載 :https://www.crowdstrike.com/blog/how-to-decrypt-the-partyticket-ransomware-targeting-ukraine/

《Intelligence Team Research & Threat Intel (CrowdStrike)》

関連記事

この記事の写真

/

特集

PageTop

アクセスランキング

  1. IPA、セキュリティ予算獲得「経営層説得」ツール公開

    IPA、セキュリティ予算獲得「経営層説得」ツール公開

  2. 複数の条件満たすことでDBへの侵入許す恐れ、フォレンジック調査の結果を公表

    複数の条件満たすことでDBへの侵入許す恐れ、フォレンジック調査の結果を公表

  3. カジュアルファッション取り扱いアダストリアのサーバへ不正アクセス、100万件の個人情報が流出した可能性

    カジュアルファッション取り扱いアダストリアのサーバへ不正アクセス、100万件の個人情報が流出した可能性

  4. チューリッヒ「スーパー自動車保険」加入者の情報が漏えい、外部委託業者が不正アクセス被害

    チューリッヒ「スーパー自動車保険」加入者の情報が漏えい、外部委託業者が不正アクセス被害

  5. ユービーセキュア・NRIセキュア・GSXの3社でクラウド型Webアプリケーション診断ツールを開発

    ユービーセキュア・NRIセキュア・GSXの3社でクラウド型Webアプリケーション診断ツールを開発

  6. Proofpoint Blog 第21回「夢は(オマエの財布から)ガッポリ、北朝鮮の“スタートアップ”APT「TA444」とは?」

    Proofpoint Blog 第21回「夢は(オマエの財布から)ガッポリ、北朝鮮の“スタートアップ”APT「TA444」とは?」

  7. DX推進 重視する人材「情報セキュリティ担当」最多47.9%

    DX推進 重視する人材「情報セキュリティ担当」最多47.9%

  8. ISC BINDに複数の脆弱性

    ISC BINDに複数の脆弱性

  9. Apache HTTP Server 2.4に複数の脆弱性

    Apache HTTP Server 2.4に複数の脆弱性

  10. システムに代理登録する際 委託事業者が患者情報を誤入力、別人に登録完了メール送信

    システムに代理登録する際 委託事業者が患者情報を誤入力、別人に登録完了メール送信

ランキングをもっと見る