ウクライナを標的にしたと報じられたPartyTicketランサムウェア、復号可能と判明
クラウドベースのエンドポイント、クラウドワークロード、アイデンティティ、データ保護の業界リーダーであるCrowdStrike Holdings, Inc.(NASDAQ: CRWD)の日本法人であるクラウドストライク 株式会社(本社:東京都港区、以下クラウドストライク)は本日、ウクライナの標的に対してデプロイされたランサムウェア「PartyTicket」に関する詳細情報をブログで紹介します。
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
暗号化の前に、ランサムウェアは
.[vote2024forjb@protonmail[.]com].encryptedJB
というフォーマットでファイル名を変更しています(バイナリに含まれているその他の政治的な内容からすると、「JB」はおそらく米国大統領、Joseph Bidenのイニシャルでしょう)。その後、ランサムウェアはコンテンツを暗号化されたデータで上書きします。PartyTicketはファイルの最初の9437184バイト(9.44 MB)だけを暗号化するでしょう。引数として渡されたファイルがこの容量を超えている場合は、超過分は暗号化されません。ファイルのコンテンツを暗号化した後、PartyTicketはRSAで暗号化されたAESキーをファイルの最後に追加します。
このランサムウェアはファイルの暗号化が開始する前に、read_me.htmlという名前のHTMLの脅迫メモをユーザーのデスクトップディレクトリに残します(図1)。メモの文章は、文法ミスが意図的なものでない限り、英語が堪能な人物によって書かれたものでも、チェックされたものでもないようです。
[caption id="attachment_114352" align="aligncenter" width="600"] 図1:脅迫メモ[/caption]
評価
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= 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の無料トライアルで最も高度な脅威に対抗する次世代アンチウイルスをご体験ください。