Serangan manipulasi objek kernel langsung (DKOM) pada penyedia ETW.

Potret tampilan samping seorang pria menatap layar komputer saat bekerja larut malam

Penulis

Ruben Boonen

CNE Capability Lead, Adversary Services

IBM X-Force

Dalam postingan ini, peretas ofensif IBM Security X-Force Red menganalisis bagaimana penyerang, dengan hak istimewa yang ditingkatkan, dapat menggunakan akses mereka untuk menyimulasikan kemampuan pasca-eksploitasi Windows Kernel. Selama beberapa tahun terakhir, akun publik semakin menunjukkan bahwa penyerang yang kurang mahir menggunakan teknik ini untuk mencapai tujuan mereka. Oleh karena itu penting bagi kami untuk menyoroti kemampuan ini dan mempelajari lebih lanjut tentang dampak potensialnya. Secara khusus, dalam postingan ini, kami akan mengevaluasi bagaimana pasca-eksploitasi Kernel dapat digunakan untuk membutakan sensor ETW dan mengikatnya kembali ke sampel malware yang diidentifikasi di dunia nyata tahun lalu.

Pengantar

Seiring waktu, mitigasi keamanan dan telemetri deteksi pada Windows telah meningkat secara substansial. Ketika kemampuan ini dikombinasikan dengan solusi deteksi titik akhir & respon (EDR) yang dikonfigurasi dengan baik, mereka dapat mewakili penghalang yang signifikan terhadap pasca-eksploitasi. Penyerang menghadapi biaya konstan untuk mengembangkan dan mengulangi taktik, teknik, dan prosedur (TTP) untuk menghindari heuristik deteksi. Tim Adverse Simulation di IBM Security X-Force menghadapi masalah yang sama ini. Tim kami ditugaskan untuk mensimulasikan kemampuan ancaman tingkat lanjut di beberapa lingkungan terbesar dan paling keras. Kombinasi solusi keamanan yang disetel dengan baik dan tim Pusat Operasi Keamanan (SOC) yang terlatih dengan baik dapat sangat membebani teknik operasi. Dalam beberapa kasus, penggunaan TTP tertentu menjadi benar-benar tak terpakai dalam rentang tiga hingga empat bulan (biasanya terkait dengan tumpukan teknologi tertentu).

Penyerang dapat memilih untuk memanfaatkan eksekusi kode di Kernel Windows untuk memanipulasi beberapa perlindungan ini atau untuk sepenuhnya menghindari sejumlah sensor di user-land. Demonstrasi pertama yang dipublikasikan mengenai kemampuan ini adalah pada tahun 1999 di Majalah Phrack. Dalam tahun-tahun berikutnya ada sejumlah kasus yang dilaporkan di mana aktor ancaman (TA) menggunakan rootkit Kernel untuk pasca-eksploitasi. Beberapa contoh yang lebih lama termasuk Derusbi Family dan Lamberts Toolkit.

Secara tradisional, jenis kemampuan ini sebagian besar terbatas pada TA tingkat lanjut. Namun, dalam beberapa tahun terakhir, kami telah melihat lebih banyak penyerang komoditas menggunakan primitif eksploitasi Bring Your Own Vulnerable Driver (BYOVD) untuk memfasilitasi tindakan pada titik akhir. Dalam beberapa kasus, teknik-teknik ini cukup primitif, terbatas pada tugas-tugas sederhana, tetapi ada juga demonstrasi yang lebih mampu.

Pada akhir September 2022, riset dari ESET merilis white paper tentang kemampuan Kernel yang digunakan oleh Lazarus TA dalam sejumlah serangan terhadap entitas di Belgia dan Belanda untuk tujuan eksfiltrasi data. Makalah ini menjabarkan sejumlah primitif Manipulasi Objek Kernel Langsung (DKOM) yang digunakan payload untuk membutakan telemetri OS/AV/EDR. Jarang tersedia riset publik tentang teknik ini. Mendapatkan pemahaman yang lebih menyeluruh tentang teknik pasca-eksploitasi Kernel sangat penting untuk pertahanan. Argumen klasik naif yang sering terdengar adalah bahwa penyerang dengan hak istimewa yang tinggi dapat melakukan apa saja, jadi mengapa kita harus memodelkan kemampuan dalam skenario itu? Ini adalah pendirian yang lemah. Penjaga keamanan perlu memahami kemampuan apa yang dimiliki penyerang ketika mereka memiliki akses yang lebih tinggi, sumber data mana yang tetap dapat diandalkan (dan mana yang tidak), opsi penahanan apa yang ada dan bagaimana teknik canggih dapat dideteksi (bahkan jika kemampuan untuk melakukan deteksi tersebut tidak ada). Dalam postingan ini saya akan fokus secara khusus tentang melakukan patching pada struktur Kernel Event Tracing for Windows (ETW) untuk merender penyedia menjadi tidak efektif atau tidak dapat dioperasikan. Saya akan memberikan beberapa latar belakang tentang teknik ini, menganalisis bagaimana penyerang dapat memanipulasi struktur Kernel ETW, dan membahas mekanisme untuk menemukan struktur ini. Akhirnya, saya akan meninjau bagaimana teknik ini diterapkan oleh Lazarus dalam payload mereka.

Berita teknologi terbaru, didukung oleh insight dari pakar

Tetap terinformasi tentang tren industri yang paling penting—dan menarik—tentang AI, otomatisasi, data, dan di luarnya dengan buletin Think. Lihat Pernyataan Privasi IBM®.

Terima kasih! Anda telah berlangganan.

Langganan Anda akan disediakan dalam bahasa Inggris. Anda akan menemukan tautan berhenti berlangganan di setiap buletin. Anda dapat mengelola langganan atau berhenti berlangganan di sini. Lihat Pernyataan Privasi IBM® kami untuk informasi lebih lanjut.

ETW DKOM

ETW adalah fasilitas penelusuran berkecepatan tinggi yang dibangun ke dalam sistem operasi Windows. Ini memungkinkan pencatatan peristiwa dan aktivitas sistem oleh aplikasi, driver, dan sistem operasi, memberikan visibilitas terperinci ke dalam perilaku sistem untuk debugging, analisis kinerja, dan diagnostik keamanan.

Pada bagian ini, saya akan memberikan gambaran tingkat tinggi tentang Kernel ETW dan permukaan serangan terkaitnya. Ini akan membantu untuk memiliki pemahaman yang lebih baik tentang mekanisme yang terlibat dalam memanipulasi penyedia ETW dan efek terkait dari manipulasi tersebut.

Permukaan serangan Kernel ETW

Para peneliti dari Binarly memberikan ceramah di BHEU 2021, yang membahas permukaan serangan umum ETW di Windows. Ikhtisar model ancaman digambarkan di bawah ini.

diagram alur yang menunjukkan pemodelan ancaman ETW
Gambar 1 – Veni, No Vidi, No Vici: Attacks on ETW Blind EDR Sensors (Binarly)

Dalam postingan ini, kami fokus pada permukaan serangan ruang Kernel.

bagan yang menunjukkan dan menggambarkan serangan pada penyedia ETW mode kernel
Gambar 2 — Veni, No Vidi, No Vici: Attacks on ETW Blind EDR Sensors (Binarly)

Posting ini hanya mempertimbangkan serangan dalam kategori serangan pertama yang ditunjukkan pada “Gambar 2”, di mana pelacakan dinonaktifkan atau diubah dalam beberapa cara.

Sebagai catatan peringatan, ketika mempertimbangkan struktur buram pada Windows, selalu penting untuk diingat bahwa ini dapat berubah, dan pada kenyataannya sering berubah di seluruh versi Windows. Ini sangat penting ketika menyumbat data Kernel, karena kesalahan kemungkinan akan berujung pada Blue Screen of Death (BSoD), lakukan dengan aman!

Inisialisasi

Penyedia kernel didaftarkan menggunakan nt!EtwRegister, sebuah fungsi yang diekspor oleh ntoskrnl. Versi fungsi yang didekompilasi dapat dilihat di bawah ini.

tangkapan layar kode untuk dekompilasi nt!EtwRegister
Gambar 3 – Dekompilasi nt!EtwRegister

Inisialisasi penuh terjadi dalam fungsi EtwpRegisterKMProvider bagian dalam, tetapi ada dua langkah utama di sini:

  • ProviderId adalah pointer ke GUID 16-byte. GUID ini statis di seluruh sistem operasi, sehingga dapat digunakan untuk mengidentifikasi penyedia yang sedang diinisialisasi.
  • RegHandle adalah alamat memori yang menerima pointer ke struktur _ETW_REG_ENTRY pada panggilan yang berhasil. Struktur data ini dan beberapa properti bersarangnya menyediakan jalan untuk memanipulasi penyedia ETW sesuai riset dari Binarly.

Mari kita daftar secara singkat struktur yang disorot Binarly pada slide mereka pada Gambar 2.

ETW_REG_ENTRY

Daftar lengkap 64-bit struktur _ETW_REG_ENTRY ditunjukkan di bawah ini. Detail tambahan tersedia di blog Geoff Chappell di sini. Struktur ini juga dapat d jelajahi lebih lanjut pada ProyekVergilius.

// 0x70 bytes (sizeof)
// Win11 22H2 10.0.22621.382
struct _ETW_REG_ENTRY
{
    struct _LIST_ENTRY RegList;                           //0x0
    struct _LIST_ENTRY GroupRegList;                      //0x10
    struct _ETW_GUID_ENTRY* GuidEntry;                    //0x20
    struct _ETW_GUID_ENTRY* GroupEntry;                   //0x28
    union
    {
        struct _ETW_REPLY_QUEUE* ReplyQueue;              //0x30
        struct _ETW_QUEUE_ENTRY* ReplySlot[4];            //0x30
        struct
        {
            VOID* Caller;                                 //0x30
            ULONG SessionId;                              //0x38
        };
    };
    union
    {
        struct _EPROCESS* Process;                        //0x50
        VOID* CallbackContext;                            //0x50
    };
    VOID* Callback;                                       //0x58
    USHORT Index;                                         //0x60
    union
    {
        USHORT Flags;                                     //0x62
        struct
        {
            USHORT DbgKernelRegistration:1;               //0x62
            USHORT DbgUserRegistration:1;                 //0x62
            USHORT DbgReplyRegistration:1;                //0x62
            USHORT DbgClassicRegistration:1;              //0x62
            USHORT DbgSessionSpaceRegistration:1;         //0x62
            USHORT DbgModernRegistration:1;               //0x62
            USHORT DbgClosed:1;                           //0x62
            USHORT DbgInserted:1;                         //0x62
            USHORT DbgWow64:1;                            //0x62
            USHORT DbgUseDescriptorType:1;                //0x62
            USHORT DbgDropProviderTraits:1;               //0x62
        };
    };
    UCHAR EnableMask;                                     //0x64
    UCHAR GroupEnableMask;                                //0x65
    UCHAR HostEnableMask;                                 //0x66
    UCHAR HostGroupEnableMask;                            //0x67
    struct _ETW_PROVIDER_TRAITS* Traits;                  //0x68
};

ETW_GUID_ENTRY

Salah satu entri bersarang dalam _ETW_REG_ENTRY adalah GuidEntry, yang merupakan struktur _ETW_GUID_ENTRY. Informasi lebih lanjut tentang struktur yang tidak terdokumentasi ini dapat ditemukan di blog Geoff Chappell di sini dan di Proyek Vergilius.

// 0x1a8 bytes (sizeof)
// Win11 22H2 10.0.22621.382
struct _ETW_GUID_ENTRY
{
    struct _LIST_ENTRY GuidList;                          //0x0
    struct _LIST_ENTRY SiloGuidList;                      //0x10
    volatile LONGLONG RefCount;                           //0x20
    struct _GUID Guid;                                    //0x28
    struct _LIST_ENTRY RegListHead;                       //0x38
    VOID* SecurityDescriptor;                             //0x48
    union
    {
        struct _ETW_LAST_ENABLE_INFO LastEnable;          //0x50
        ULONGLONG MatchId;                                //0x50
    };
    struct _TRACE_ENABLE_INFO ProviderEnableInfo;         //0x60
    struct _TRACE_ENABLE_INFO EnableInfo[8];              //0x80
    struct _ETW_FILTER_HEADER* FilterData;                //0x180
    struct _ETW_SILODRIVERSTATE* SiloState;               //0x188
    struct _ETW_GUID_ENTRY* HostEntry;                    //0x190
    struct _EX_PUSH_LOCK Lock;                            //0x198
    struct _ETHREAD* LockOwner;                           //0x1a0
};

TRACE_ENABLE_INFO

Akhirnya, salah satu entri bersarang dalam _ETW_GUID_ENTRY adalah ProviderEnableInfo yang merupakan struktur _TRACE_ENABLE _INFO. Untuk informasi lebih lanjut tentang elemen struktur data ini, Anda dapat merujuk ke  dokumentasi resmi Microsoft dan Proyek Vergilius. Pengaturan dalam struktur ini secara langsung mempengaruhi operasi dan kemampuan penyedia.

// 0x20 bytes (sizeof)
// Win11 22H2 10.0.22621.382
struct _TRACE_ENABLE_INFO
{
    ULONG IsEnabled;                                       //0x0
    UCHAR Level;                                           //0x4
    UCHAR Reserved1;                                       //0x5
    USHORT LoggerId;                                       //0x6
    ULONG EnableProperty;                                  //0x8
    ULONG Reserved2;                                       //0xc
    ULONGLONG MatchAnyKeyword;                             //0x10
    ULONGLONG MatchAllKeyword;                             //0x18
};

Memahami penggunaan handle registrasi

Sementara beberapa latar belakang teoritis bagus, selalu menjadi praktik terbaik untuk melihat penggunaan contoh konkret untuk mendapatkan pemahaman yang lebih dalam tentang suatu topik. Mari kita pertimbangkan secara singkat sebuah contoh. Sebagian besar penyedia Kernel ETW penting diinisialisasi di dalam, nt!EtwpInitialize, yang tidak diekspor. Melihat ke dalam fungsi ini mengungkapkan sekitar lima belas penyedia.

Tangkapan layar kode untuk dekompilasi parsial nt!EtwpInitialize
Gambar 4 — nt!EtwpInitialize dekompilasi parsial

Mengambil entri Microsoft-Windows-Threat-Intelligence (EtwTi) sebagai contoh, kita dapat memeriksa parameter ThreatIntProviderGuid global untuk memulihkan GUID untuk penyedia ini.

Tangkapan layar kode untuk GUID Penyedia EtwTi
Gambar 5 — GUID Penyedia EtwTi

Mencari GUID ini secara online akan segera mengungkapkan bahwa kami dapat memulihkan nilai yang benar (f4e1897c-bb5d-5668-f1d8-040f4d8dd344).

Mari kita lihat contoh di mana parameter handle registrasi, EtwThreatIntProvRegHandle, digunakan dan menganalisis caranya digunakan. Satu tempat di mana handle direferensikan adalah nt!EtwTiLogDriverObjectUnLoad. Dari nama fungsi ini, kita dapat memahami bahwa itu dimaksudkan untuk menghasilkan peristiwa ketika objek driver diturunkan oleh Kernel.

Tangkapan layar kode untuk dekompilasi nt!EtwTiLogDriverUnload
Gambar 6 – Dekompilasi nt!EtwTiLogDriverUnload

Fungsi nt!EtwEventEnabled dan nt!EtwProviderEnabled keduanya dipanggil di sini dengan memasukkan handle registrasi sebagai salah satu argumen. Mari kita lihat salah satu sub-fungsi ini untuk memahami lebih dalam apa yang sebenarnya terjadi.

Tangkapan layar kode untuk dekompilasi nt!EtwProviderEnable
Gambar 7 – Dekompilasi nt!EtwProviderEnable

Memang ini agak sulit untuk diikuti. Namun, aritmatika pointer tidak terlalu penting. Mari kita fokus pada bagaimana fungsi ini memproses handle pendaftaran. Tampaknya fungsi tersebut memvalidasi sejumlah properti struktur _ETW_REG_ENTRY dan sub-strukturnya seperti properti GuidEntry.

struct _ETW_REG_ENTRY
{
    …
    struct _ETW_GUID_ENTRY* GuidEntry;                    //0x20
    …
}

Dan properti GuidEntry->ProviderEnableInfo.

struct _ETW_GUID_ENTRY
{
    …
    struct _TRACE_ENABLE_INFO ProviderEnableInfo;         //0x60
    …
}

Fungsi tersebut kemudian masuk ke pemeriksaan berbasis level yang serupa. Akhirnya, fungsi mengembalikan true atau false untuk menunjukkan apakah penyedia diaktifkan untuk pencatatan peristiwa pada tingkat dan kata kunci tertentu. Rincian lebih lanjut tersedia dengan menggunakan dokumentasiresmi Microsoft.

Kita dapat melihat bahwa ketika penyedia diakses melalui handle registrasinya, integritas struktur tersebut menjadi sangat penting bagi operasi penyedia. Sebaliknya, jika penyerang mampu memanipulasi struktur tersebut, mereka dapat mempengaruhi aliran kontrol pemanggil untuk menghentikan atau menghilangkan peristiwa yang tidak direkam.

Menyerang handle registrasi

Melihat kembali permukaan serangan yang dinyatakan Binarly dan bersandar pada analisis ringan kami, kami dapat mengajukan beberapa strategi untuk mengganggu pengumpulan peristiwa.

  • Seorang penyerang dapat membuat NULL pointer _ETW_REG_ENTRY. Setiap fungsi yang mereferensikan handle registrasi akan mengasumsikan bahwa penyedia belum diinisialisasi.
  • Penyerang dapat membuat NULL pointer_ETW_REG_ENTRY- >GuidEntry - > ProviderEnableInfo. Hal ini seharusnya secara efektif menonaktifkan kemampuan pengumpulan penyedia karena ProviderEnableInfo adalah sebuah pointer ke struktur _TRACE_ENABLE_INFO yang menguraikan bagaimana penyedia seharusnya beroperasi.
  • Seorang penyerang dapat menimpa properti dari  struktur data  _ETW_REG_ENTRY->GuidEntry->ProviderEnableInfo untuk memanipulasi konfigurasi penyedia.
    • IsEnabled: Setel ke 1 untuk mengaktifkan peristiwa penerimaan dari penyedia atau untuk menyesuaikan pengaturan yang digunakan saat menerima peristiwa dari penyedia. Setel ke 0 untuk menonaktifkan peristiwa penerimaan dari penyedia.
    • Level: Nilai yang menunjukkan tingkat maksimum peristiwa yang Anda inginkan untuk ditulis oleh penyedia. Penyedia biasanya menulis sebuah peristiwa jika level peristiwa kurang dari atau sama dengan nilai ini, selain memenuhi kriteria MatchAnyKeyword dan MatchAllKeyword.
    • MatchAnyKeyword: Bitmask 64-bit dari kata kunci yang menentukan kategori peristiwa untuk ditulis penyedia. Penyedia biasanya menulis peristiwa jika bit kata kunci peristiwa cocok dengan salah satu bit yang ditetapkan dalam nilai ini atau jika peristiwa tidak memiliki bit kata kunci yang ditetapkan, selain memenuhi kriteria Level dan MatchAllKeyword.
    • MatchAllKeyword: Bitmask 64-bit dari kata kunci yang membatasi peristiwa untuk ditulis oleh penyedia. Penyedia biasanya menulis peristiwa jika bit kata kunci acara cocok dengan semua bit yang ditetapkan dalam nilai ini atau jika acara tidak memiliki bit kata kunci yang ditetapkan, selain memenuhi kriteria Level dan MatchAnyKeyword.

Teknik pencarian kernel

Kini kita memiliki pemahaman yang bagus tentang bentuk serangan DKOM pada ETW. Mari kita asumsikan bahwa penyerang memiliki kerentanan yang memberikan Kernel Read/Write primitif, seperti yang dilakukan malware Lazarus dalam kasus ini dengan memuat driver yang rentan. Yang masih kurang adalah cara untuk menemukan handle registrasi ini.

Saya akan menguraikan dua teknik utama untuk menemukan handle ini dan menunjukkan varian dari salah satu yang digunakan oleh Lazarus dalam payload Kernel mereka.

Bypass KASLR tingkat integritas sedang (MedIL)

Pertama, mungkin penting untuk menjelaskan bahwa meskipun ada Kernel ASLR, ini bukan batas keamanan untuk penyerang lokal jika mereka dapat mengeksekusi kode di MedIL atau lebih tinggi. Ada banyak cara untuk membocorkan pointer Kernel yang hanya dibatasi dalam skenario sandbox atau LowIL. Untuk latar belakang Anda dapat melihat I Got 99 Problems But a Kernel Pointer Ain't One oleh Alex Ionescu, banyak dari teknik ini masih berlaku hingga saat ini.

Alat pilihan di sini adalah ntdll!NtQuerySystemInformation dengan kelas SystemModuleInformation:

internal static UInt32 SystemModuleInformation = 0xB;

[DllImport(“ntdll.dll”)]
internal static extern UInt32 NtQuerySystemInformation(
    UInt32 SystemInformationClass,
    IntPtr SystemInformation,
    UInt32 SystemInformationLength,
    ref UInt32 ReturnLength);

Fungsi ini mengembalikan alamat dasar langsung dari semua modul yang dimuat di ruang Kernel. Pada titik itu, dimungkinkan untuk mengurai modul-modul tersebut pada disk dan mengonversi offset file mentah ke alamat virtual relatif dan sebaliknya.

public static UInt64 RvaToFileOffset(UInt64 rva, List<SearchTypeData.IMAGE_SECTION_HEADER> sections)
{
    foreach (SearchTypeData.IMAGE_SECTION_HEADER section in sections)
    {
        if (rva >= section.VirtualAddress && rva < section.VirtualAddress + section.VirtualSize)
        {
            return (rva – section.VirtualAddress + section.PtrToRawData);
        }
    }
    return 0;
}

public static UInt64 FileOffsetToRVA(UInt64 fileOffset, List<SearchTypeData.IMAGE_SECTION_HEADER> sections)
{
    foreach (SearchTypeData.IMAGE_SECTION_HEADER section in sections)
    {
        if (fileOffset >= section.PtrToRawData && fileOffset < (section.PtrToRawData + section.SizeOfRawData))
        {
            return (fileOffset – section.PtrToRawData) + section.VirtualAddress;
        }
    }
    return 0;
}

Penyerang juga dapat memuat modul-modul ini ke dalam proses user-land mereka menggunakan panggilan API pustaka beban standar (misalnya, ntdll!LdrLoadDll). Melakukan hal itu akan menghindari komplikasi konversi offset file ke RVA dan kembali. Namun, dari sudut pandang keamanan operasional (OpSec) ini tidak ideal karena dapat menghasilkan lebih banyak telemetri deteksi.

Metode 1: Rantai gadget

Jika memungkinkan, ini adalah teknik yang saya sukai karena membuat kebocoran lebih portabel di seluruh versi modul karena mereka kurang terpengaruh oleh perubahan patch. Kelemahannya adalah Anda bergantung pada rantai gadget yang ada untuk objek yang ingin Anda bocorkan.

Mempertimbangkan penanganan pendaftaran ETW, mari kita ambil Intelijen Ancaman Microsoft Windows sebagai contoh. Di bawah ini Anda dapat melihat panggilan lengkap ke nt!EtwRegister.

Tangkapan layar kode untuk pembongkaran CALL penuh nt!EtwRegister
Gambar 8 – Pembongkaran CALL lengkap nt!EtwRegister

Di sini kita ingin membocorkan pointer ke pegangan registrasi, EtwThreatIntProvRegHandle. Seperti yang terlihat dimuat ke param_4 pada baris pertama Gambar 8. Pointer ini diselesaikan ke global dalam bagian .data dari modul Kernel. Karena panggilan ini terjadi dalam fungsi yang tidak diekspor, kami tidak dapat membocorkan alamatnya secara langsung. Sebagai gantinya, kita harus melihat di mana global ini direferensikan dan melihat apakah itu digunakan dalam fungsi yang alamatnya dapat bocor.

tangkapan layar kode untuk nt! referensi nt!EtwThreatIntProvRegHandle
Gambar 9 – Referensi nt!EtwThreatIntProvRegHandle

Menjelajahi beberapa entri ini dengan cepat mengungkapkan kandidat di nt!KeInsertQueueApc.

tangkapan layar kode untuk dekompilasi parsial nt!KeInsertQueueApc
Gambar 10 – Dekompilasi nt!KeInsertQueueApc

Ini adalah kandidat yang bagus karena beberapa alasan:

  • nt!KeInsertQueueApc adalah fungsi yang diekspor. Ini berarti kita dapat membocorkan alamat langsungnya menggunakan bypass KASLR. Kemudian kita dapat menggunakan kerentanan Kernel kita untuk membaca data di alamat itu.
  • Global digunakan pada awal fungsi. Ini sangat membantu karena itu berarti kita kemungkinan besar tidak perlu membangun logika penguraian instruksi yang kompleks untuk menemukannya.

Melihat perakitan menunjukkan tata letak berikut.

tangkapan layar kode untuk pembongkaran parsial nt!KeInsertQueueApc
Gambar 11 – nt! Pembongkaran sebagian nt!KeInsertQueueApc

Membocorkan handle registrasi ini kemudian menjadi mudah. Kami membaca array byte menggunakan kerentanan kami, dan mencari instruksi mov R10 pertama untuk menghitung offset virtual relatif dari variabel global. Perhitungannya akan menjadi seperti ini:

Int32 pOffset = Marshal.ReadInt32((IntPtr)(pBuff.ToInt64() + i + 3));
hEtwTi = (IntPtr)(pOffset + i + 7 + oKeInsertQueueApc.pAddress.ToInt64());

Dengan handle registrasi, maka dimungkinkan untuk mengakses struktur data _ETW_REG_ENTRY.

Secara umum, rantai gadget semacam itu dapat digunakan untuk membocorkan berbagai struktur data Kernel. Namun, perlu ditunjukkan bahwa tidak selalu mungkin untuk menemukan rantai gadget seperti itu dan kadang-kadang rantai gadget mungkin memiliki beberapa tahap kompleks. Misalnya, kemungkinan rantai gadget untuk membocorkan konstan entri direktori halaman (PDE) dapat terlihat seperti ini.

MmUnloadSystemImage -> MiUnloadSystemImage -> MiGetPdeAddress

Faktanya, analisis sepintas dari pegangan pendaftaran ETW mengungkapkan bahwa sebagian besar tidak memiliki rantai gadget yang sesuai yang dapat digunakan seperti dijelaskan di atas.

Metode 2: Pemindaian memori

Pilihan utama lainnya untuk membocorkan handle pendaftaran ETW ini adalah dengan menggunakan pemindaian memori, baik dari memori Kernel langsung atau dari modul pada disk. Ingatlah bahwa ketika memindai modul pada disk mungkin untuk mengonversi offset file ke RVA.

Pendekatan ini terdiri dari mengidentifikasi pola byte yang unik, memindai pola-pola tersebut, dan akhirnya melakukan beberapa operasi pada offset kecocokan pola. Mari kita lihat lagi nt!EtwpInitialize untuk memahami hal ini dengan lebih baik:

Tangkapan layar kode untuk dekompilasi parsial nt!EtwpInitialize
Gambar 12 — Dekompilasi parsial nt!EtwpInitialize

Semua lima belas panggilan ke nt!EtwRegister sebagian besar digabungkan bersama dalam fungsi ini. Strategi utama di sini adalah untuk menemukan pola unik yang muncul sebelum pemanggilan pertama ke nt!EtwRegister dan pola kedua yang muncul setelah pemanggilan terakhir ke nt!EtwRegister. Ini tidak terlalu rumit. Salah satu trik yang dapat digunakan untuk meningkatkan portabilitas adalah dengan membuat pemindai pola yang mampu menangani string byte kartu liar. Ini adalah tugas yang diserahkan kepada pembaca.

Setelah indeks start dan stop diidentifikasi, mungkin untuk melihat semua instruksi di antaranya.

  • Instruksi CALL potensial dapat diidentifikasi berdasarkan opcode untuk CALL yaitu 0xe8.
  • Selanjutnya, pembacaan berukuran DWORD digunakan untuk menghitung offset relatif dari instruksi CALL potensial.
  • Offset ini kemudian ditambahkan ke alamat relatif dari CALL dan ditambah dengan lima (ukuran instruksi rakitan).
  • Akhirnya, nilai baru ini dapat dibandingkan dengan nt!EtwRegister untuk menemukan semua lokasi CALL yang valid.

Setelah semua instruksi CALL ditemukan, mungkin untuk mencari mundur dan mengekstrak argumen fungsi. Pertama, GUID yang mengidentifikasi penyedia ETW dan kedua, alamat pegangan pendaftaran. Dengan informasi ini, kita dapat melakukan serangan DKOM yang terinformasi pada handle registrasi untuk mempengaruhi operasi penyedia yang diidentifikasi.

Patching ETW Lazarus

Saya mendapatkan sampel FudModle DLL yang disebutkan di whitepaper ESET dan menganalisisnya. DLL ini memuat driver Dell rentan yang ditandatangani (dari sumber daya yang enkode XOR inline) dan kemudian menguji driver untuk melakukan patch pada banyak struktur Kernel untuk membatasi telemetri pada host.

Tangkapan layar kode untuk hash FudModule Lazarus
Gambar 13 — Lazarus FudModule hash

Sebagai bagian akhir dari posting ini, saya ingin mengulas strategi yang digunakan Lazarus untuk menemukan handle registrasi Kernel ETW. Ini adalah variasi pada metode pemindaian yang sudah kita bahas di atas.

Di awal fungsi pencarian, Lazarus menyelesaikan nt!EtwRegister dan menggunakan alamat ini untuk memulai pemindaian

Tangkapan layar kode untuk dekompilasi pencarian ETW parsial Lazarus FudModule
Gambar 14 – Dekompilasi pencarian ETW parsial Lazarus FudModule

Keputusan ini agak aneh karena bergantung pada di mana fungsi itu ada dalam kaitannya dengan tempat fungsi dipanggil. Posisi relatif fungsi dalam modul dapat bervariasi dari versi ke versi karena kode baru dapat diperkenalkan, dihapus, atau diubah. Namun, karena cara modul dikompilasi, diharapkan fungsi mempertahankan urutan yang relatif stabil. Ada asumsi ini adalah pengoptimalan kecepatan pencarian.

Ketika mencari referensi untuk nt!EtwRegister di ntoskrnl, tampaknya tidak banyak entri yang terlewatkan dengan menggunakan teknik ini. Lazarus mungkin juga telah melakukan analisis tambahan untuk menentukan bahwa entri yang terlewat tidak penting atau tidak perlu di-patch. Entri yang terlewat ditandai di bawah ini. Menggunakan strategi ini memungkinkan Lazarus untuk melewati 0x7b1de0 byte saat melakukan pemindaian yang mungkin merupakan jumlah yang tidak sepele jika pemindai lambat.

Tangkapan layar kode untuk Instans panggilan ke nt!EtwRegister
Gambar 15 — Contoh panggilan ke nt!EtwRegister

Selain itu, saat memulai pemindaian, lima pencocokan pertama akan dilewati sebelum mulai merekam handle registrasi. Bagian dari fungsi pencarian ditunjukkan di bawah ini.

Tangkapan layar kode untuk dekompilasi pencarian ETW parsial Lazarus FudModule
Gambar 16 — Dekompilasi pencarian ETW parsial Lazarus FudModule

Kodenya agak tumpul, tetapi kami mendapatkan sorotan plotnya. Kode tersebut mencari panggilan ke nt!EtwRegister, mengekstrak handle registrasi, mengonversi handle ini ke alamat aktif menggunakan bypass KASLR, dan menyimpan pointer dalam array yang disisihkan untuk tujuan ini di dalam struktur konfigurasi malware (dialokasikan pada saat inisialisasi).

Akhirnya, mari kita lihat apa yang dilakukan Lazarus untuk menonaktifkan penyedia ini.

Tangkapan layar kode untuk handle registrasi ETW NULL Lazarus FudModule
Gambar 17 – Handle egistrasi NULL ETW Lazarus FudModule

Ini sebagian besar masuk akal, apa yang dilakukan Lazarus di sini adalah membocorkan variabel global yang kita lihat sebelumnya dan kemudian mengganti pointer di alamat itu dengan NULL. Ini secara efektif menghapus referensi ke struktur data _ETW_REG_ENTRY jika ada.

Saya tidak sepenuhnya puas dengan teknik yang ditampilkan karena beberapa alasan:

  • Payload tidak menangkap GUID penyedia sehingga tidak dapat membuat keputusan cerdas apakah harus atau tidak harus mengganti handle registrasi penyedia.
  • Keputusan untuk memulai pemindaian pada offset di dalam ntoskrnl tampaknya patut dipertanyakan, karena offset pemindaian dapat bervariasi, tergantung pada versi ntoskrnl.
  • Melewatkan 5 pencocokan pertama secara arbriter tampaknya juga patut dipertanyakan. Mungkin ada alasan strategis untuk keputusan ini tetapi pendekatan yang lebih baik adalah mengumpulkan semua penyedia terlebih dahulu dan kemudian menggunakan beberapa logika terprogram untuk menyaring hasil.
  • Menulis pointer ke _ETW_REG_ENTRY seharusnya berfungsi tetapi teknik ini agak jelas. Akan lebih baik untuk mengganti properti _ETW_ REG_ENTRY atau _ETW_GUID_ENTRY atau _TRACE_ENABLE_INFO.

Saya menerapkan kembali teknik ini untuk sains; namun, saya membuat beberapa penyesuaian pada tekniknya.

  • Algoritma pencarian yang dioptimalkan kecepatan digunakan untuk menemukan semua 0xe8 byte di ntoskrnl.
  • Setelah itu, beberapa pasca-pemrosesan dilakukan untuk menentukan mana yang merupakan instruksi CALL yang valid dan tujuan masing-masing.
  • Tidak semua panggilan ke nt!EtwRegister berguna karena terkadang fungsi dipanggil dengan argumen dinamis untuk handle registrasi. Karena itu, beberapa logika tambahan diperlukan untuk menyaring panggilan yang tersisa.
  • Akhirnya, semua GUID diselesaikan ke bentuk yang dapat dibaca manusia dan handle registrasi dienumerasi.

Secara keseluruhan, setelah penyesuaian, teknik di atas jelas merupakan cara terbaik untuk melakukan jenis enumerasi ini. Karena waktu pencarian dapat diabaikan dengan algoritma yang dioptimalkan, masuk akal untuk memindai seluruh modul pada disk dan kemudian menggunakan beberapa logika pasca-pemindaian tambahan untuk menyaring hasil.

Dampak ETW DKOM

Penting untuk mengevaluasi secara singkat seberapa berdampak serangan semacam itu. Ketika data penyedia dikurangi atau dihilangkan seluruhnya ada kehilangan informasi, tetapi pada saat yang sama tidak semua penyedia menandakan peristiwa sensitif keamanan.

Beberapa subset dari penyedia ini, bagaimanapun, sensitif terhadap keamanan. Contoh paling jelas dari ini adalah Microsoft Windows-Threat-Intelligence (EtwTi) yang merupakan sumber data inti untuk Microsoft Defender Advanced Threat Protection (MDATP) yang sekarang disebut Defender for Endpoint (semuanya sangat membingungkan). Perlu dicatat bahwa akses ke penyedia ini sangat dibatasi, hanya driver Early Launch Anti Malware (ELAM) yang dapat mendaftar ke penyedia ini. Sama halnya, proses di sisi pengguna yang menerima peristiwa ini harus memiliki status terlindungi (ProtectedLight / Antimalware) dan ditandatangani dengan sertifikat yang sama dengan driver ELAM.

Dengan menggunakan EtwExplorer, Anda dapat memperoleh gambaran yang lebih baik mengenai jenis informasi yang dapat disinyalkan oleh penyedia layanan ini.

Tangkapan layar halaman file ETW Explorer
Gambar 18 – Penjelajah ETW

Manifes XML terlalu besar untuk disertakan di sini secara keseluruhan, tetapi satu peristiwa ditunjukkan di bawah ini untuk memberikan gambaran tentang jenis data yang dapat ditekan menggunakan DKOM.

Tangkapan layar kode untuk manifes XML parsial EtwTi
Gambar 19 – Manifest XML parsial EtwTi

Kesimpulan

Kernel telah dan terus menjadi area penting yang diperebutkan di mana Microsoft dan penyedia pihak ketiga perlu melakukan upaya untuk menjaga integritas sistem operasi. Korupsi data di Kernel tidak hanya fitur pasca-eksploitasi tetapi juga komponen sentral dalam pengembangan eksploitasi Kernel. Microsoft telah membuat banyak kemajuan di bidang ini dengan memperkenalkan Keamanan Berbasis Virtualisasi (VBS) dan salah satu komponennya seperti Perlindungan Data Kernel (KDP).

Konsumen sistem operasi Windows, pada gilirannya, perlu memastikan bahwa mereka manfaatkan kemajuan ini untuk mengenakan biaya sebanyak mungkin pada calon penyerang. KontrolAplikasi Windows Defender (WDAC) dapat digunakan untuk memastikan perlindungan VBS ada dan ada kebijakan yang melarang pemuatan driver yang berpotensi berbahaya.

Upaya ini semakin penting karena kita semakin melihat TA komoditas memanfaatkan serangan BYOVD untuk melakukan DKOM di ruang Kernel.

 

Mixture of Experts | 12 Desember, episode 85

Decoding AI: Rangkuman Berita Mingguan

Bergabunglah dengan panel insinyur, peneliti, pemimpin produk, dan sosok kelas dunia lainnya selagi mereka mengupas tuntas tentang AI untuk menghadirkan berita dan insight terbaru seputar AI.

Referensi tambahan

  • Veni, No Vidi, No Vici: Attacks on ETW Blind EDR Sensors (Slide BHEU 2021) - di sini
  • Veni, No Vidi, No Vici: Attacks on ETW Blind EDR Sensors (Video BHEU 2021) - di sini
  • Advancing Windows Security (BlueHat Shanghai 2019) - di sini
  • Exploiting a “Simple” Vulnerability – In 35 Easy Steps or Less! - di sini
  • Exploiting a “Simple” Vulnerability – Part 1.5 – The Info Leak di sini
  • Pengantar Intelijen Ancaman ETW - di sini
  • TelemetrySourcerer – di sini
  • Panduan Kebijakan WDAC - di sini

Pelajari lebih lanjut tentang X-Force Red di sini. Jadwalkan konsultasi gratis dengan X-Force di sini.

Solusi terkait
Solusi keamanan perusahaan

Transformasikan program keamanan Anda dengan solusi dari penyedia keamanan perusahaan terbesar

Jelajahi solusi keamanan siber
Layanan keamanan siber

Transformasikan bisnis Anda dan kelola risiko dengan konsultasi keamanan siber, cloud, dan layanan keamanan terkelola.

    Jelajahi layanan keamanan siber
    Keamanan siber dengan kecerdasan buatan (AI)

    Tingkatkan kecepatan, akurasi, dan produktivitas tim keamanan dengan solusi keamanan siber yang didukung AI.

    Jelajahi keamanan siber AI
    Ambil langkah selanjutnya

    Baik Anda memerlukan solusi keamanan data, manajemen titik akhir, maupun solusi manajemen identitas dan akses (IAM), pakar kami siap untuk bekerja bersama Anda demi mencapai postur keamanan yang kuat. Mentransformasi bisnis Anda dan mengelola risiko bersama pemimpin industri global dalam konsultasi keamanan siber, cloud, dan layanan keamanan terkelola.

    Jelajahi solusi keamanan siber Temukan layanan keamanan siber