33 KiB
33 KiB
In [ ]:
%cd ~/lab/day1_labs
import pandas as pd
# Mở bộ HỌC (50 tin có nhãn) và bộ THI (10 tin lách luật của bài M1)
hoc = pd.read_csv("Manual_SOC_Dataset.csv")
thi = pd.read_csv("Evasion_Dataset.csv")
# Đặt tên ngắn cho 5 cột của file: mã tin, kênh, người gửi, nội dung, nhãn đúng (lừa đảo / an toàn)
hoc.columns = thi.columns = ["ma", "kenh", "nguoi_gui", "noi_dung", "nhan"]
# Đếm mỗi loại nhãn có bao nhiêu tin
print("BỘ HỌC (Manual_SOC_Dataset.csv):", len(hoc), "tin")
print(hoc.nhan.value_counts().to_string())
print("\nBỘ THI (Evasion_Dataset.csv):", len(thi), "tin")
print(thi.nhan.value_counts().to_string())
# In 2 tin đầu của mỗi loại nhãn (cắt 70 ký tự cho gọn)
print("\nVài tin mẫu trong bộ học (2 tin mỗi loại):")
for noi_dung, nhan in hoc.groupby("nhan").head(2)[["noi_dung", "nhan"]].values:
print(" ", nhan, "|", noi_dung[:70])In [ ]:
# Mượn công cụ TF-IDF của thư viện máy học scikit-learn
from sklearn.feature_extraction.text import TfidfVectorizer
# 3 câu ví dụ (có thể sửa chữ trong ngoặc kép để thử câu của mình)
cau = ["chuyển khoản gấp vào tài khoản này",
"chiều nay họp tại phòng họp lớn",
"bấm vào link này để nhận quà"]
# Máy tự lập từ điển từ 3 câu, rồi biến mỗi câu thành một hàng số (điểm của từng từ)
tfidf = TfidfVectorizer()
bang_so = tfidf.fit_transform(cau)
tu_dien = tfidf.get_feature_names_out()
print("Từ điển máy tự tạo (" + str(len(tu_dien)) + " từ):", list(tu_dien))
# Với mỗi câu: in các từ có điểm > 0, điểm cao xếp trước
for i in range(len(cau)):
print("\nCâu", i + 1, ":", cau[i])
diem = bang_so[i].toarray()[0]
for tu, d in sorted(zip(tu_dien, diem), key=lambda x: -x[1]):
if d > 0:
print(f" {tu:8s} {d:.2f}")In [ ]:
%%bash
cd ~/lab/day1_labs
# Học từ 50 tin (Manual_SOC_Dataset.csv), thi trên 10 tin lách luật (Evasion_Dataset.csv)
python ml_classifier.pyIn [ ]:
%cd ~/lab/day1_labs
import pandas as pd
# Công cụ TF-IDF (chữ -> số) và thuật toán Naive Bayes
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.naive_bayes import MultinomialNB
hoc = pd.read_csv("Manual_SOC_Dataset.csv")
thi = pd.read_csv("Evasion_Dataset.csv")
# Đặt tên ngắn cho 5 cột: mã tin, kênh, người gửi, nội dung, nhãn đúng
hoc.columns = thi.columns = ["ma", "kenh", "nguoi_gui", "noi_dung", "nhan"]
# Lập từ điển + biến 50 tin học thành số
tfidf = TfidfVectorizer()
X_hoc = tfidf.fit_transform(hoc.noi_dung)
# Nhãn -> số: 1 = lừa đảo, 0 = an toàn
y_hoc = hoc.nhan.str.contains("Lừa đảo").astype(int)
# Naive Bayes học
mo_hinh = MultinomialNB().fit(X_hoc, y_hoc)
# predict_proba = xác suất của từng tin; [:, 1] = cột xác suất "lừa đảo"
xac_suat = mo_hinh.predict_proba(tfidf.transform(thi.noi_dung))[:, 1]
for ma, tin, p in zip(thi.ma, thi.noi_dung, xac_suat):
# Trên 50% -> kết luận lừa đảo
ket_luan = "LỪA ĐẢO" if p >= 0.5 else "an toàn"
print(f"{ma} | khả năng lừa đảo {p:4.0%} -> {ket_luan:7s} | {tin[:55]}")In [ ]:
%%bash
cd ~/lab/day1_labs
# Đảo vai: HỌC từ 10 tin lách luật, THI trên 50 tin cũ
python ml_classifier.py --train Evasion_Dataset.csv --test Manual_SOC_Dataset.csv
# Đếm nhãn trong 10 tin vừa dùng để học (iloc[:, -1] = cột cuối cùng = nhãn)
python -c "import pandas as pd; print(pd.read_csv('Evasion_Dataset.csv').iloc[:, -1].rename('nhan').value_counts().to_string())"In [ ]:
%%bash
cd ~/lab/day1_labs
# Tạo file đề thi: chép dòng tiêu đề từ file có sẵn, rồi thêm 4 tin (3 an toàn, 1 lừa đảo)
head -1 Manual_SOC_Dataset.csv > ~/lab/my_test_M2.csv
cat >> ~/lab/my_test_M2.csv <<'EOF'
T-01,Email,hr@company.com,Chiều nay 3h họp toàn công ty tại phòng họp lớn. Mọi người nhớ mang laptop.,An toàn (Benign)
T-02,Zalo,Mẹ,Con ơi tối nay về ăn cơm nhé mẹ nấu canh chua.,An toàn (Benign)
T-03,Email,IT,Hệ thống email sẽ bảo trì từ 22h đến 23h tối nay. Không cần làm gì thêm.,An toàn (Benign)
T-04,SMS,Ngân hàng,Tài khoản của bạn bị khóa. Bấm vào link xac-minh-ngay.com và nhập mã OTP để mở khóa.,Lừa đảo (Phishing)
EOF
# Học từ 50 tin như cũ, thi trên 4 tin vừa tạo
python ml_classifier.py --test ~/lab/my_test_M2.csvIn [ ]:
%%bash
# Tìm mọi dòng log có mã phiên (session) 54613b5cec67 trong ngày 22/09
grep '"54613b5cec67"' /opt/csai/data/honeypot_m1/cowrie.json.2026-09-22In [ ]:
%%bash
cd ~/lab/day1_labs
# Part A: nạp 30 ngày log, lọc kết nối, ghép tên phần mềm theo session, tách ngày/giờ, lưu bảng sạch
python Lab_M2_Part_A_Clean.pyIn [ ]:
%%bash
cd ~/lab/day1_labs
# Part B: đọc bảng sạch, vẽ 5 biểu đồ (lưu ảnh vào out_m2/) và in 1 dòng số liệu cho mỗi biểu đồ
python Lab_M2_Part_B_Visualize.py
# Xem tên 5 file ảnh vừa tạo
ls out_m2In [ ]:
# Hiện các biểu đồ trong out_m2/ ngay dưới ô này
import glob, os
from IPython.display import Image, display
for f in sorted(glob.glob(os.path.expanduser('~/lab/day1_labs/out_m2/*.png'))):
print(f)
display(Image(filename=f, width=800))In [ ]:
%cd ~/lab/day1_labs
import pandas as pd
# Mở bảng sạch của Part A (mỗi hàng = 1 kết nối)
d = pd.read_csv("cleaned_honeypot_data.csv")
# Tên phần mềm ngắn gọn: "SSH-2.0-Go" -> "Go", "SSH-2.0-PuTTY_Release_0.84" -> "PuTTY"; không khai báo -> "unknown"
d["phan_mem"] = d.client_version.str.extract(r"^SSH-[\d.]+-([A-Za-z]+)")[0].fillna("unknown")
# Gom mọi kết nối của cùng một IP thành MỘT hàng; mỗi cột là một đặc trưng:
bang = d.groupby("src_ip").agg(
so_ket_noi=("src_ip", "size"), # tổng số kết nối
so_ngay=("date", "nunique"), # xuất hiện bao nhiêu ngày khác nhau
so_khung_gio=("hour", "nunique"), # hoạt động trong bao nhiêu giờ khác nhau của ngày (tối đa 24)
phan_mem=("phan_mem", lambda s: s.mode()[0]), # phần mềm dùng nhiều nhất
)
# Trung bình mỗi ngày hoạt động kết nối bao nhiêu lần
bang["ket_noi_moi_ngay"] = (bang.so_ket_noi / bang.so_ngay).round(1)
print("Bảng đặc trưng:", len(bang), "IP x", len(bang.columns), "đặc trưng")
# 5 IP kết nối nhiều nhất
print("\n5 IP kết nối nhiều nhất:")
print(bang.sort_values("so_ket_noi", ascending=False).head(5).to_string())
# 5 IP chọn ngẫu nhiên (random_state=1: lần nào chạy cũng ra cùng 5 IP)
print("\n5 IP chọn ngẫu nhiên:")
print(bang.sample(5, random_state=1).to_string())In [ ]:
%%bash
cd ~/lab/day1_labs
# Top 5 IP chiếm bao nhiêu phần tổng số kết nối? (cộng số kết nối của 5 IP đầu, chia cho tổng; 0.25 = 25%)
python -c "import pandas as pd; d=pd.read_csv('cleaned_honeypot_data.csv'); print(d.src_ip.value_counts().head(5).sum()/len(d))"
# Ngày bùng nổ 20/09: chỉ giữ kết nối của ngày đó, rồi lấy 3 IP kết nối nhiều nhất
python -c "import pandas as pd; d=pd.read_csv('cleaned_honeypot_data.csv'); print(d[d.date=='2026-09-20'].src_ip.value_counts().head(3))"In [ ]:
%cd ~/lab/day1_labs
import pandas as pd
d = pd.read_csv("cleaned_honeypot_data.csv")
# Rút gọn tên phần mềm: "SSH-2.0-Go" -> "Go"; kết nối không khai báo -> "unknown"
d["phan_mem"] = d.client_version.str.extract(r"^SSH-[\d.]+-([A-Za-z]+)")[0].fillna("unknown")
# Với mỗi IP: đếm số phần mềm KHÁC NHAU nó đã dùng (bỏ qua "unknown")
so_phan_mem = d[d.phan_mem != "unknown"].groupby("src_ip").phan_mem.nunique()
print("Số IP chỉ dùng 1 phần mềm: ", (so_phan_mem == 1).sum())
print("Số IP dùng từ 2 phần mềm trở lên:", (so_phan_mem >= 2).sum())
# 5 IP đổi nhiều phần mềm nhất, kèm danh sách phần mềm (", ".join = nối thành một dòng)
print("\nTOP 5 IP đổi nhiều phần mềm nhất:")
for ip in so_phan_mem.sort_values(ascending=False).head(5).index:
cac_pm = d[(d.src_ip == ip) & (d.phan_mem != "unknown")].phan_mem.unique()
print(f" {ip:16s} {len(cac_pm)} phần mềm: {', '.join(sorted(cac_pm))}")In [ ]:
%cd ~/lab/day1_labs
import pandas as pd
d = pd.read_csv("cleaned_honeypot_data.csv")
# Với mỗi IP: đếm số GIỜ khác nhau (0-23, giờ UTC) mà nó có kết nối
so_gio = d.groupby("src_ip").hour.nunique()
print("Số IP hoạt động ĐỦ 24 giờ trong ngày:", (so_gio == 24).sum())
print("Số IP chỉ hoạt động trong 1 giờ: ", (so_gio == 1).sum())
# Các IP đủ 24 giờ chiếm bao nhiêu phần trăm tổng số kết nối? (.isin = "nằm trong danh sách")
ip_24h = so_gio[so_gio == 24].index
print(f"-> {len(ip_24h)} IP 'không bao giờ ngủ' tạo ra {d.src_ip.isin(ip_24h).mean():.0%} tổng số kết nối")In [ ]:
%cd ~/lab/day1_labs
import pandas as pd
# ===== SỬA DÒNG NÀY: ngày muốn soi (theo ngày UTC như Part B), trong khoảng 2026-08-24 .. 2026-09-22 =====
NGAY_CAN_SOI = "2026-09-20"
d = pd.read_csv("cleaned_honeypot_data.csv")
# Lọc các kết nối của đúng ngày đó (cột date do Part A tạo)
mot_ngay = d[d.date == NGAY_CAN_SOI]
# Trung bình mỗi ngày = tổng kết nối / số ngày khác nhau
tb = len(d) / d.date.nunique()
print(f"Ngày {NGAY_CAN_SOI}: {len(mot_ngay)} kết nối = gấp {len(mot_ngay) / tb:.1f} lần trung bình ({tb:.0f}/ngày), từ {mot_ngay.src_ip.nunique()} IP")
# Cắt số cuối của IP -> dải /24, đếm số kết nối của mỗi dải trong ngày đó
dai = mot_ngay.src_ip.str.rsplit(".", n=1).str[0] + ".0/24"
print("TOP 3 dải mạng trong ngày:")
print(dai.rename("dai_mang").value_counts().head(3).to_string())
# Dải đứng đầu chiếm bao nhiêu phần trăm số kết nối của ngày
print(f"-> dải đứng đầu chiếm {dai.value_counts().iloc[0] / len(mot_ngay):.0%} số kết nối của ngày")