Tự build Malware Scanner cho Linux: Nhẹ, nhanh và linh hoạt với Python & YARA

Python tutorial - IT technology blog
Python tutorial - IT technology blog

Tại sao bạn nên tự build công cụ quét mã độc?

Nếu bạn từng thấy server Linux bỗng dưng “thở dốc” với CPU chạm đỉnh 100% do các tiến trình lạ như kinsing hay xmrig, bạn sẽ hiểu cảm giác bất lực khi tìm kiếm mã độc thủ công. Những script đào tiền ảo hoặc web shell hiện nay được ngụy trang cực kỳ tinh vi trong các thư mục /tmp hoặc /var/www/html.

Nhiều người chọn ClamAV, nhưng công cụ này thường ngốn từ 800MB đến hơn 1GB RAM chỉ để khởi động — một con số quá xa xỉ cho các VPS cấu hình thấp. Đây là lúc YARA tỏa sáng. Thay vì quét dựa trên chữ ký (signature) nặng nề, YARA cho phép bạn định nghĩa các quy tắc (rules) linh hoạt để nhận diện mã độc qua các mẫu đặc trưng. Nó giống như việc bạn đưa cho thám tử một bản mô tả chi tiết thay vì bắt họ học thuộc lòng danh sách hàng triệu tội phạm.

Kết hợp Python với yara-python, chúng ta sẽ có một hệ thống tự động hóa hoàn chỉnh. Bạn có thể quét định kỳ, lọc file theo dung lượng và bắn cảnh báo ngay về Telegram chỉ với vài chục dòng code.

Thiết lập môi trường làm việc

Để bắt đầu, server cần có sẵn Python 3. Quá trình cài đặt rất nhanh gọn, mất chưa đầy 2 phút trên các dòng máy Ubuntu hoặc Debian.

1. Cài đặt thư viện

# Cập nhật danh sách gói
sudo apt update

# Cài đặt công cụ build và header cho Python
sudo apt install -y build-essential python3-dev

# Cài đặt thư viện YARA cho Python
pip install yara-python

2. Định nghĩa quy tắc quét (YARA Rules)

Sức mạnh của scanner nằm ở bộ rule. Thay vì tự viết từ đầu, bạn có thể tận dụng các kho rule khổng lồ từ cộng đồng trên GitHub. Tuy nhiên, để bắt đầu, hãy tạo một file đơn giản tên webshell_rules.yar để tóm gọn các hàm PHP nguy hiểm:

rule Detect_Webshell_PHP {
    strings:
        $a = "eval(base64_decode"
        $b = "shell_exec"
        $c = "system($_GET"
    condition:
        any of them
}

Viết Script quét mã độc bằng Python

Chúng ta cần một script đủ thông minh để duyệt qua các thư mục nhưng không được làm sập server vì thiếu quyền truy cập hoặc quét phải các file rác quá lớn.

Logic xử lý chính

Trong thực tế, việc quét toàn bộ ổ cứng là không cần thiết. Tôi thường giới hạn file dưới 10MB để tối ưu tốc độ. Một script quét tốt cần xử lý mượt mà lỗi PermissionError khi đụng phải các file hệ thống nhạy cảm.

import yara
import os
import logging

# Ghi log để tiện tra cứu sau này
logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s - %(levelname)s - %(message)s',
    filename='scanner.log'
)

def compile_rules(rule_path):
    try:
        return yara.compile(filepath=rule_path)
    except yara.Error as e:
        print(f"Lỗi biên dịch rule: {e}")
        return None

def scan_directory(path, rules):
    print(f"[*] Đang rà soát: {path}")
    for root, _, files in os.walk(path):
        for file in files:
            file_path = os.path.join(root, file)
            try:
                # Chỉ quét file nhỏ hơn 10MB để tiết kiệm tài nguyên
                if os.path.getsize(file_path) > 10 * 1024 * 1024:
                    continue
                
                matches = rules.match(file_path)
                if matches:
                    msg = f"[!] Phát hiện nghi vấn: {file_path} (Rule: {matches})"
                    print(msg)
                    logging.warning(msg)
            except (PermissionError, OSError):
                continue

if __name__ == "__main__":
    rules = compile_rules('webshell_rules.yar')
    if rules:
        # Tập trung vào các khu vực nhạy cảm
        scan_directory('/var/www/html', rules)
        print("--- Hoàn tất quá trình quét ---")

Mẹo tối ưu với Regex

Mã độc hiện nay thường dùng kỹ thuật làm rối code (obfuscation). Do đó, bạn nên dùng Regex trong YARA rule để bắt các biến thể phức tạp. Đừng bao giờ chủ quan với Regex bạn vừa viết. Tôi thường dùng regex tester tại toolcraft.app để kiểm tra nhanh pattern. Công cụ này chạy ngay trên trình duyệt, giúp xác định chính xác pattern có khớp với mẫu shell code thực tế hay không trước khi nạp vào hệ thống.

Tự động hóa và Giám sát

Việc chạy script thủ công rất mất thời gian. Hãy để server tự làm việc đó vào lúc nửa đêm.

1. Lập lịch quét với Cron

Thời điểm 2 giờ sáng là lúc traffic thấp nhất, lý tưởng để quét mã độc. Hãy thêm dòng sau vào crontab -e:

0 2 * * * /usr/bin/python3 /root/scripts/scanner.py

2. Nhận cảnh báo tức thì qua Telegram

Thay vì đọc log mỏi mắt, hãy để script tự “nổ” tin nhắn về điện thoại khi thấy biến. Bạn chỉ cần thêm vài dòng code với thư viện requests:

import requests

def alert_telegram(message):
    token = "YOUR_BOT_TOKEN"
    chat_id = "YOUR_CHAT_ID"
    payload = {"chat_id": chat_id, "text": message}
    requests.post(f"https://api.telegram.org/bot{token}/sendMessage", data=payload)

3. Lưu ý về hiệu suất (Performance)

Nếu server của bạn đang chạy các dịch vụ quan trọng, hãy dùng lệnh nice hoặc ionice khi chạy script. Ví dụ: nice -n 19 python3 scanner.py. Điều này giúp hệ điều hành ưu tiên tài nguyên cho web server hoặc database trước, tránh tình trạng scanner làm gián đoạn dịch vụ của người dùng.

Tự xây dựng Malware Scanner không chỉ giúp bạn tiết kiệm chi phí mà còn là cách tuyệt vời để hiểu sâu về bảo mật Linux. Hãy bắt đầu từ những bộ rule đơn giản và nâng cấp dần theo nhu cầu thực tế nhé!

Share: