Mendefinisikan pemuat reflektif kobalt strike

Pria mengenakan hoodie hitam menggunakan laptop di jalan yang menggambarkan seorang peretas

Sementara AI generasi berikutnya dan komponen machine learning dari solusi keamanan terus meningkatkan kemampuan deteksi berbasis perilaku, pada intinya banyak yang masih mengandalkan deteksi berbasis tanda tangan. Cobalt Strike menjadi kerangka kerja Command and Control (C2) tim merah yang populer digunakan oleh aktor ancaman dan tim merah sejak debutnya, dan terus ditandatangani oleh solusi keamanan.

Untuk melanjutkan penggunaan operasional Cobalt Strike sebelumnya, kami di tim IBM X-Force Red Adversary Simulation menginvestasikan upaya riset dan pengembangan yang signifikan untuk menyesuaikan Cobalt Strike dengan perkakas internal. Beberapa alat internal khusus Cobalt Strike kami memiliki versi publik, seperti "InlineExecute-Assembly", "CredBandit", dan "BokuLoader". Dalam dua tahun terakhir, karena penandatangan Cobalt Strike yang berlebihan, kami membatasi penggunaannya untuk mensimulasikan aktor ancaman yang tidak terlalu canggih, dan sebagai gantinya memanfaatkan pihak ketiga lainnya dan C2 internal ketika melakukan latihan tim merah yang lebih canggih.

Melalui upaya riset dan pengembangan, kami telah menemukan keberhasilan operasional yang lebih baik dalam latihan tim merah tingkat lanjut dengan:

  • Perkakas internal khusus.
  • Pemuat internal khusus.
  • Kerangka kerja C2 internal khusus.
  • Lanjutkan berinvestasi dalam memperluas kemampuan dan siluman kerangka kerja C2 pihak ketiga alternatif.

Namun, masih ada sejumlah besar aktor ancaman yang memanfaatkan salinan bajakan Cobalt Strike, dan tetap penting untuk dapat mensimulasikan aktor ancaman ini. Untuk tim merah yang bersedia melakukan upaya riset dan pengembangan, mereka mungkin masih menemukan kesuksesan operasional dengan Cobalt Strike sambil mensimulasikan musuh-musuh ini. Selain itu, Cobalt Strike adalah alat pembelajaran yang hebat, yang dapat dimanfaatkan oleh pendatang baru untuk mendapatkan pengalaman dengan kerangka kerja C2 melalui kursus pelatihan tim merah.

Ketika kami terus memperluas kemampuan C2 kami, kami membagikan beberapa insight tentang cara kami membangun kerangka kerja Cobalt Strike di masa lalu, khususnya dengan mengembangkan pemuat reflektif khusus. Ini juga dimaksudkan bagi para pembela untuk memahami cara Cobalt Strike bekerja untuk menciptakan deteksi yang lebih kuat.

Membangun kerangka kerja dengan pemuat reflektif

Postingan blog ini adalah yang pertama dari seri yang berfungsi sebagai primer, mencakup dasar-dasar pengembangan pemuat reflektif Cobalt Strike. Seiring berjalannya seri ini, kita akan mengembangkan dasar ini dan merujuk kembali ke posting ini.

Pada akhir seri ini, kami bertujuan untuk membuat pemuat reflektif yang terintegrasi dengan fitur penghindaran Cobalt Strike yang ada dan bahkan meningkatkannya dengan teknik canggih yang saat ini tidak ada di alat. Posting mendatang akan menyelidiki lebih dalam pengembangan fitur penghindaran tertentu dan cara menerapkannya ke pemuat reflektif Cobalt Strike kami.

Untuk memulai, posting ini akan mencakup:

  • Masalah dengan memuat implan C2 dari disk dengan Windows DLL Loader.
  • Konsep dan mekanisme proses pemuatan reflektif Cobalt Strike.
  • Persyaratan desain yang diperlukan untuk membangun pemuat reflektif yang efektif.
  • Fase yang terlibat dalam proses pemuatan reflektif.

Ketika kita menjelajahi pemuatan reflektif Cobalt Strike melalui lensa pengembang alat keamanan ofensif, kita akan menyoroti peluang untuk deteksi dan evasi. Beberapa aspek pengembangan akan dihilangkan atau disederhanakan, dan kami mendorong Anda untuk mengisi kekosongan dengan men-debug proyek pemuat reflektif yang sudah ada, membangunnya kembali dari awal, atau mencari pelatihan.

Memuat DLL beacon

Implan Cobalt Strike C2, yang dikenal sebagai Beacon, adalah Windows Dynamic-Link Library (DLL), dan kemampuan modular menggunakan pemuat DLL kami sendiri di Cobalt Strike dikenal sebagai User-Defined Reflective Loader (UDRL).

Loader DLL Windows bawaan

Biasanya, Windows DLL Loader bawaan bertanggung jawab untuk memuat DLL ke dalam ruang memori virtual proses. Windows DLL Loader ada terutama di dalam ruang pengguna, meskipun ia menyeberang ke ruang kernel saat memetakan DLL dari disk.

Menggunakan Windows DLL Loader menghadirkan beberapa kelemahan saat digunakan selama simulasi musuh:

  • DLL mentah harus ada pada sistem file.
  • DLL mentah harus bebas dari pengaburan.
  • Peristiwa pemuatan gambar kernel dipicu oleh Windows DLL Loader.

Oleh karena itu, menggunakan Windows DLL Loader untuk memuat DLL beacon kami bukanlah solusi yang ideal. Untuk mengatasi tantangan ini, kami memuat DLL beacon dari memori menggunakan pemuat reflektif.

Tiga titik deteksi utama yang dihindari pemuatan reflektif adalah:

  1. Menghindari malware yang ditandatangani pada sistem file.
  2. Menghindari peristiwa pemuatan gambar kernel, yang dapat dipantau oleh solusi keamanan.
  3. Menghindari DLL implan C2 kami yang terdaftar di Blok Lingkungan Proses (PEB).

Loader Reflektif vs Windows DLL Loader

Pemuatan reflektif dapat dianggap sebagai pemuatan DLL mentah secara langsung dari memori, bukan pemuatan dari sistem file.

Pemuatan reflektif dan Windows DLL Loader bawaan keduanya melayani tujuan yang sama untuk memuat DLL dari format file mentah ke dalam ruang memori virtual suatu proses. Namun, pemuatan reflektif memiliki keunggulan utama dibandingkan Windows DLL Loader karena tidak memerlukan file DLL untuk ada di sistem file. Pemuatan dalam memori ini memungkinkan jumlah fase pemuatan berantai yang tidak terbatas, karena DLL implant C2 dapat disembunyikan di dalam lapisan enkripsi dan pengkodean di dalam memori proses.

Format file mentah vs format alamat virtual

Konsep kunci untuk dipahami saat memuat DLL, adalah mengetahui bahwa DLL akan diformat secara berbeda pada disk versus dalam memori. Perbedaan utama antara DLL dalam format file mentah versus format alamat virtual adalah:

Format File Mentah:

  • Format untuk DLL seperti yang ada pada sistem file.
  • Bagian-bagian DLL dikemas rapat bersama.
  • Offset didasarkan pada awal file DLL mentah seperti yang akan ada di disk.
  • Format ini membutuhkan lebih sedikit ruang memori.

Format Alamat Virtual:

  • Format untuk DLL seperti yang ada di ruang memori virtual suatu proses.
  • Bagian-bagiannya diberi jarak.
  • Offset adalah Relative Virtual Address (RVA).
  • Saat berjalan dalam suatu proses, DLL dan modul lainnya menentukan lokasi melalui VIA.
  • Format ini membutuhkan lebih banyak ruang memori.

Beacon mentah vs beacon virtual

Dengan memeriksa DLL beacon HTTP di alat PE-Bear karya Aleksandra Doniec, kita dapat melihat perbedaan antara alamat mentah dan alamat virtual untuk setiap bagian dari DLL tersebut:

Tabel yang mencantumkan alamat mentah dan virtual dari setiap bagian DLL beacon.

Tabel yang mencantumkan alamat mentah dan virtual dari setiap bagian DLL beacon.

DLL beacon HTTP/S ini adalah 0x52000  byte (327KB ) dalam ukuran saat dimuat ke dalam ruang memori virtual suatu proses, dibandingkan dengan 0x44000  byte (272KB ) dalam ukuran seperti yang ada pada sistem file. Perbedaan ukuran ini disebabkan oleh bagian-bagian yang diberi jarak dalam format alamat virtual, bukan dikemas rapat bersama dalam format file mentah.

PE-Bear menyediakan representasi visual dari DLL beacon kami seperti yang ada dalam format file mentah versus format ruang alamat virtual:

Representasi visual dari DLL beacon dalam format mentah versus format virtual

Representasi visual dari DLL beacon dalam format mentah (kiri) versus format virtual (kanan)

Memuat Beacon dengan Windows DLL Loader

Meskipun bukan langkah paling bijaksana untuk dilakukan selama simulasi musuh, menjatuhkan DLL beacon mentah tanpa pengaburan ke disk dan memuatnya dengan Windows DLL Loader adalah cara yang bagus untuk menghilangkan muatan beacon dan DLL. Pada dasarnya, beacon hanyalah sebuah DLL. Windows DLL Loader dan pemuat reflektif hanya memuat DLL ke dalam suatu proses.

Untuk memuat DLL beacon dengan Windows DLL Loader, kami melakukan langkah-langkah berikut:

  1. Menghasilkan DLL beacon mentah tanpa pengaburan.
  2. Buat program yang:
    1. Menggunakan LoadLibrary API untuk memuat DLL beacon kami dari disk.
    2. Menjalankan beacon kita dengan memanggil titik masuk DLL beacon virtual.
  3. Menempatkan program yang dapat dieksekusi dan DLL beacon kami di folder yang sama.
  4. Menjalankan program kami.

Menghasilkan DLL beacon mentah yang bebas dari pengaburan

Pertama, kami menonaktifkan semua opsi Malleable PE yang membuat DLL beacon kami tidak dapat dimuat oleh Windows DLL Loader. Untuk melakukan ini, kami memodifikasi profil Malleable C2 kami dan menonaktifkan opsi penghindaran Malleable PE yang terletak di blok panggung:

Blok tahap profil C2 yang dapat ditempa dimodifikasi untuk menonaktifkan fitur penghindaran Cobalt Strike.

Blok tahap profil C2 yang dapat ditempa dimodifikasi untuk menonaktifkan fitur penghindaran Cobalt Strike.

Setelah memodifikasi profil, kami memulai ulang Cobalt Strike Team Server, memasok no_evasion.profile  profil sebagai argumen.

Tangkapan layar dibuat untuk postingan blog

Kami terhubung ke Server Tim dengan klien Cobalt Strike. Kemudian kita membuatWindows Stageless Payload  dengan opsi output diatur ke Raw dan pendengar disetel ke https . Kami menyimpan muatan sebagai beacon.dll .

Tangkapan layar membuat DLL beacon “mentah tanpa tahap” dari Cobalt Strike Client

Tangkapan layar membuat DLL beacon “mentah tanpa tahap” dari Cobalt Strike Client

Membuat program DLL beacon Loader kami

Menggunakan kode di bawah ini, kami membuat program C bernama loadBeaconDLL.c  dan mengkompilasinya:

Kode Windows C untuk memuat DLL beacon dari disk menggunakan Windows DLL Loader.

Kode Windows C untuk memuat DLL beacon dari disk menggunakan Windows DLL Loader.

Kami menggunakan Kernel32.LoadLibraryA  API untuk memuat DLL beacon mentah kami dari disk. API ini akan memanggil Windows DLL Loader bawaan yang akan memuat DLL beacon kami dari disk ke ruang memori virtual proses host kami.

Sebagai bagian dari proses pemuatan, Windows DLL Loader akan menginisialisasi DLL beacon kami dengan memanggil titik masuknya dengan DLL_PROCESS_ATTACH (1)  sebagai argumen.

Setelah Windows DLL Loader memuat dan menginisialisasi DLL beacon kami ke ruang memori virtual proses kami, kami perlu lagi memanggil titik masuk virtual DLL beacon dengan argumen 0x4.

Program kami harus mengetahui titik masuk DLL beacon virtual kami untuk menjalankan DLL beacon virtual kami. Ini dapat dilakukan secara dinamis dalam program dengan mengurai header DLL beacon virtual untuk titik masuk Relative Virtual alamat (RVA), atau kita dapat dengan cepat melihat apa itu dan hardcode nilainya.

Untuk pembuktian konsep kami, kami akan secara manual menemukan dan membuat hardcode titik masuk DLL beacon kami RVA ke dalam program kami. Menggunakan PE-bear kami menemukan bahwa titik masuk RVA ke beacon adalah 0x1D840 :

Tangkapan layar saat menemukan titik masuk DLL beacon RVA menggunakan PE-bear

Tangkapan layar saat menemukan titik masuk DLL beacon RVA menggunakan PE-bear

 LoadLibraryA  API mengembalikan alamat dasar dari DLL beacon virtual kami. Kami cukup menambahkan ini ke titik masuk RVA untuk menentukan titik masuk.

Dengan kode kami siap digunakan, kami mengkompilasi program C kami menjadi Windows yang dapat dieksekusi:

Perintah yang digunakan untuk mengkompilasi program kami.

Perintah yang digunakan untuk mengkompilasi program kami.

Memposisikan program kami dan DLL beacon pada sistem file

Dengan menempatkan DLL beacon dan program executable beacon pemuat kita di direktori yang sama, Windows DLL Loader akan dapat menemukan DLL kita saat menjalankan rutinitas pemuatannya.

Kami menempatkan keduanya beacon.dll  dan loadBeaconDLL.exe  pada sistem file dalam direktori yang sama:

DLL beacon dan program pemuat ditempatkan di direktori yang sama.

DLL beacon dan program pemuat ditempatkan di direktori yang sama.

Melaksanakan program kami

Dari desktop Windows, kita klik dua kali program loadBeaconDLL.exe dan buat koneksi beacon aktif ke Server Tim kami.

Berhasil terhubung ke C2 Team Server dari DLL beacon yang dimuat menggunakan Windows DLL Loader.

Berhasil terhubung ke C2 Team Server dari DLL beacon yang dimuat menggunakan Windows DLL Loader.

Beban reflektif serangan kobalt

Cobalt Strike menggunakan versi modifikasi dari proyek Reflective Loader oleh Stephen Fewer. Pemuat DLL dalam memori yang legendaris ini sudah berumur lebih dari satu dekade dan telah digunakan di Metasploit dan alat keamanan ofensif terkenal lainnya.

Pertimbangan penggunaan UDRL

Selama bertahun-tahun, pemuat reflektif Cobalt Strike telah ditingkatkan untuk menangani semua fitur penghindaran Malleable PE yang ditawarkan Cobalt Strike. Kerugian utama untuk menggunakan User-Defined Reflective Loader (UDRL) khusus adalah bahwa fitur penghindaran PE Maleable mungkin atau mungkin tidak didukung di luar kotak.

Beberapa fitur penghindaran diimplementasikan sepenuhnya saat menggunakan UDRL, yang diintegrasikan ke dalam DLL beacon oleh mesin Malleable PE Cobalt Strikes pada saat pembuatan payload beacon. Namun, saat ini fitur-fitur seperti obfuscate harus ditangani oleh UDRL, sementara yang lain seperti sleepmask dan cleanup dapat ditangani oleh beacon dengan integrasi UDRL yang tepat.

Metode pemuatan reflektif

Metode pemuat reflektif asli

Proyek Reflektif Loader asli membutuhkan kompilasi ReflectiveLoader  ke dalam proyek DLL kami dan mengekspornya dalam DLL implan C2 kami.

Kemudian proyek lain bertanggung jawab untuk:

  1. Menemukan alamat virtual dari ReflectiveLoader  ekspor.
  2. Melaksanakan ReflectiveLoader  ekspor, yang mengembalikan titik masuk ke DLL yang dimuat.
  3. Memanggil titik masuk DLL yang dimuat secara reflektif.
Diagram pemuat reflektif asli, memuat DLL ke memori virtual.

Diagram pemuat reflektif asli, memuat DLL ke memori virtual.

Metode pemuat reflektif prepend

Metode alternatif mendahului pemuat reflektif ke DLL. Hal ini memungkinkan setiap DLL yang tidak dikelola untuk dimuat dan tidak memerlukan kompilasi DLL dari kode sumber. Ini adalah metode pemuatan reflektif yang kuat yang dapat memuat file PE apa pun (EXE atau DLL).

Diagram pemuat reflektif ditambahkan ke DLL, memuat DLL ke memori virtual.

Diagram pemuat reflektif ditambahkan ke DLL, memuat DLL ke memori virtual.

Metode pemuat reflektif Cobalt Strike

Implementasi pemuatan reflektif Cobalt Strike menggunakan hybrid dari dua metode di atas. Metode pemuatan reflektif ini mungkin akrab bagi mereka yang memiliki pengetahuan tentang cara Meterpreter Metasploit melakukan pemuatan reflektif.

Seperti metode pemuat reflektif asli, ReflectiveLoader  Fungsi tersebut dikompilasi dan diekspor di dalam DLL beacon asli. Ketika operator menghasilkan muatan beacon dari klien Cobalt Strike, mesin Malleable PE Cobalt Strike menambal DLL beacon mentah untuk menginformasikan pemuat reflektif tentang opsi Malleable PE untuk digunakan. Header DOS Beacon ditambal untuk memanggil ReflectiveLoader ekspor pada offset yang telah ditentukan. Byte patch awal dari header DOS beacon, yang memanggil ReflectiveLoader  ekspor, akan disebut di blog ini sebagai “call reflective loader stub”.

Ketika UDRL dimuat ke Cobalt Strike, dan operator menghasilkan muatan beacon dari klien Cobalt Strike, mesin PE Maleable Cobalt Strike menambal dalam shellcode pemuat reflektif pada offset file mentah dari ReflectiveLoader  export.

Ketika mesin Malleable PE menyelesaikan patch DLL beacon mentah, DLL beacon mentah diberikan kepada operator dalam format seperti shellcode yang dapat dieksekusi.

Diagram pemuat reflektif Cobalt Strike, memuat DLL beacon ke memori virtual.

Diagram pemuat reflektif Cobalt Strike, memuat DLL beacon ke memori virtual.

Call reflective loader stub Beacon

Melihat byte awal di pembongkaran PE-Bear kita dapat melihat bahwa DLL beacon itu sendiri dapat dieksekusi:

Call reflective loader stub ditampilkan sebagai kode operasi perakitan yang dapat dieksekusi.

Call reflective loader stub ditampilkan sebagai kode operasi perakitan yang dapat dieksekusi.

Byte awal MZAR  dapat disesuaikan melalui opsi PE Maleable di profil Cobalt Strikes C2. Byte ini harus dapat dieksekusi dan menghasilkan hasil no-operation (nop ).

Setelah mengeksekusi secara opsional ditambahkan di depan nops  dan byte ajaib, call reflective loader stub:

  • Membuat bingkai tumpukan.
  • Menggunakan pengalamatan relatif RIP untuk menentukan alamat dasar dari DLL beacon mentah.
  • Memanggil ReflectiveLoader  ekspor di tempat yang diketahui 0x16E3C  offset file mentah.
  • Memanggil titik masuk dari DLL beacon yang dimuat.

Kami mengonfirmasi bahwa offset file mentah untuk ReflectiveLoader  ekspor adalah 0x16E3C  dengan melihat direktori ekspor DLL beacon:

Tangkapan layar saat menggunakan PE-Bear untuk menentukan offset file mentah dari ekspor ReflectiveLoader.

Tangkapan layar saat menggunakan PE-Bear untuk menentukan offset file mentah dari ekspor ReflectiveLoader.

Karena ada di dalam direktori ekspor, alamat untuk ReflectiveLoader ekspor dalam format RVA, mengacu pada DLL beacon dalam keadaan virtualnya. Karena ReflectiveLoader  ekspor dapat dieksekusi, kita tahu bahwa itu ada di dalam.text bagian dari DLL beacon.

Untuk menemukan offset file mentah dari ReflectiveLoader  ekspor, pertama-tama kita perlu mengetahui perbedaan antara .text  bagian alamat virtual dan mentah. Dengan perbedaan yang diketahui, kita cukup menguranginya dari ReflectiveLoader  RVA, untuk menemukan ReflectiveLoader  offset file mentah ekspor.

Alamat virtual dan mentah untuk .text  bagian tercantum dalam header bagian DLL beacon:

Alamat mentah dan virtual dari .text bagian dari DLL beacon.

Alamat mentah dan virtual dari .text bagian dari DLL beacon.

Perbedaan antara keduanya adalah 0xC00  byte. Dengan mengurangi ReflectiveLoader  RVA ekspor dari 0x17A3C  dengan perbedaannya, kami menemukan bahwa offset file mentah adalah 0x16E3C .

Kami dapat mengonfirmasi ini di PE-bear dengan mengklik kanan ReflectiveLoader  Fungsi ekspor RVA dan klik Follow RVA:17A3C . Penampil hex di widget di atas akan melompat untuk melihat ReflectiveLoader  ekspor pada offset file mentah.

Singkatnya, aliran proses pemuatan reflektif Cobalt Strike adalah:

  • Utas mengeksekusi DLL beacon mentah.
  • Call reflective loader stub memanggil ReflectiveLoader  ekspor pada offset file mentah yang diketahui.
  • Loader reflektif memuat DLL beacon mentah ke memori virtual proses host.
  • Setelah proses pemuatan, pemuat reflektif mengembalikan titik masuk DLL virtual beacon ke call reflective loader stub.
  • Call reflective loader stub memanggil titik masuk dari DLL virtual beacon.
Diagram yang menunjukkan fase utama cara Cobalt Strike melakukan pemuatan reflektif dari DLL beacon.

Diagram yang menunjukkan fase utama cara Cobalt Strike melakukan pemuatan reflektif dari DLL beacon.

Persyaratan desain pemuat reflektif

Kode independen posisi

Karena pemuat reflektif kita dieksekusi sebelum DLL beacon dimuat, kode pemuat reflektif harus berupa shellcode murni.

Cara termudah untuk membuat shellcode kompleks adalah dengan menulisnya dalam C tanpa dependensi eksternal. Kemudian file C dikompilasi ke file objek. Semuanya harus dimasukkan dalam bagian text dari berkas objek. Akhirnya, kami merobek.text bagian untuk mendapatkan shellcode pemuat reflektif.

Cara Cobalt Strike memasukkan UDRL kami

Mesin PE Maleable Cobalt Strike akan menangani pekerjaan mendapatkan shellcode dari file objek pemuat reflektif kami dan menambalnya ke DLL beacon mentah pada offset file mentah ReflectiveLoader  ekspor. Ini dilakukan dalam skrip UDRL Aggressor seperti yang terlihat di bawah ini:

Skrip agresor untuk menulis shellcode pemuat reflektif ke dalam DLL beacon mentah yang memanfaatkan Cobalt Strike.

Skrip agresor untuk menulis shellcode pemuat reflektif ke dalam DLL beacon mentah yang memanfaatkan Cobalt Strike.

Skrip UDRL Aggressor kami memiliki Cobalt Strike menulis di shellcode pemuat reflektif kami dengan melakukan langkah-langkah ini:

  • Kami membuka$handle ke file objek UDRL kami denganopenf fungsi bisnis.
  • Dengan file$handle kami membaca aliran byte dan menyimpannya ke$data variabel array byte.
  • Kemudian kami tutup file tersebut$handle denganclosef fungsi bisnis.
  • Built-in
    <a href="https://hstechdocs.helpsystems.com/manuals/cobaltstrike/current/userguide/content/topics_aggressor-scripts/as-resources_functions.htm#extract_reflective_pemuat">extract_reflective_pemuat</a>
    
    Fungsi Cobalt Strike Aggressor akan mengurai file objek UDRL kita dari$data array byte, mencari.text bagian dari file objek UDRL kami, mengekstrak .text dan menyimpannya ke dalam$loader variabel array byte.
  • Built-in
    <a href="https://hstechdocs.helpsystems.com/manuals/cobaltstrike/current/userguide/content/topics_aggressor-scripts/as-resources_functions.htm#setup_reflective_loader">setup_reflective_pemuat</a>
    
    Fungsi Cobalt Strike Aggressor akan menggunakan mesin Malleable PE untuk menemukan offset file mentah dari kamiReflectiveLoader ekspor, dan menambal kode shell UDRL kami dari$loader variabel array byte.
  • Akhirnya, kami mengembalikan DLL beacon yang dimodifikasi ke Cobalt Strike dan menyimpan file kami dari klien.

Fase pemuatan reflektif

Cobalt Strike telah melakukan pekerjaan untuk kami mengenai mengekstraksi bagian .text dari file objek pemuat reflektif kami, menambal kode shell pemuat reflektif kami, dan memanggil pemuat reflektif kami dengan call reflective loader stub yang terletak di header DLL beacon.

Berikut adalah tahapan yang harus kita kembangkan untuk memuat beacon secara reflektif:

  1. Temukan DLL Raw Beacon
  2. Uraikan Header DLL Beacon
  3. Alokasikan Memori untuk DLL Virtual Beacon
  4. Muat Bagian ke Ruang Memori Virtual
  5. Muat Ketergantungan DLL
  6. Selesaikan Tabel Alamat Impor
  7. Selesaikan Relokasi
  8. Jalankan Beacon

Tahap 1: Menemukan alamat dasar DLL beacon mentah

Ada beberapa metode berbeda yang dapat kita gunakan untuk menemukan alamat DLL beacon mentah di memori. Beberapa metode tersebut adalah:

  • Cari mundur untuk Header MZ & PE
  • Berburu mundur untuk Egg
  • Dapatkan alamat dasar DLL beacon mentah dari stub penelepon pemuat reflektif

Menemukan posisi kita dalam ingatan

Saat menggunakan metode yang berburu mundur, pertama-tama kita harus mendapatkan alamat saat ini dari Instruction Pointer utas kita (RIP ). Kita bisa menggunakan trik sederhana ini untuk getRip :

  1. Dalam UDRL kami, kami membuat fungsi yang disebut getRip .
  2. Kami memanggil getRip  yang akan mendorong alamat yang mengikuti”call getRip " ke bagian atas tumpukan. Ini adalah alamat pengembalian.
  3. Kemudian dalam fungsi getRip  kita, kita cukup menyalin alamat pengembalian pemanggil dari bagian atas tumpukan.
  4. Dalam pengkodean Windows C, fungsi dapat mengembalikan nilai. Nilai yang dikembalikan ini dikembalikan ke pemanggil melalui RAX  daftar. Dengan memindahkan alamat penelepon kembali ke RAX  daftar, kami mengembalikan alamat penelepon kembali ke penelepon.
Kode perakitan Intel x64 untuk mendapatkan alamat dasar DLL beacon mentah dari register RDI.

Kode perakitan Intel x64 untuk mendapatkan alamat dasar DLL beacon mentah dari register RDI.

Berburu ke belakang untuk header MZ & PE

Proyek pemuat reflektif asli berburu mundur untuk header MZ dan PE. Header ini telah menjadi titik deteksi. Untuk mengatasi Cobalt Strike ini menambahkan magic_mz  dan magic_pe  Fitur penghindaran PE yang mudah dibentuk.

Dokumentasi Cobalt Strike menyatakan bahwa magic_mz  pilihan:

  • “Ganti byte pertama (termasuk header MZ) dari DLL Reflektif Beacon. Instruksi yang valid diperlukan. Ikuti instruksi yang mengubah status CPU dengan instruksi yang membatalkan perubahan.”

Saat dikonfigurasi MZ--  Byte pada offset file mentah 0x00  dan PE00  Byte pada offset file mentah 0x80  dikenal oleh pemuat reflektif. Mereka disisipkan ke dalam DLL beacon oleh mesin Malleable PE.

Byte ini harus agak unik, atau pemuat reflektif tidak akan dapat menemukannya. Selain itu, byte untuk header MZ harus tanpa operasi dan dapat dieksekusi. Nilai-nilai tersebut tidak bisa seperti itu 0x00  atau beacon tersebut mungkin mengalami kerusakan. Ini mungkin titik deteksi potensial.

Mencari egg dengan cara mundur

Setelah menemukan titik deteksi potensial ini, saya mengembangkan metode yang berbeda, tetapi serupa untuk menemukan alamat dasar beacon mentah DLL. Metode ini menggunakan pemburu telur yang mampu mencari mundur dari RIP , yang berburu dua contoh berulang dari egg 64-bit unik di tempat yang diketahui beacon.dll+0x50  offset file mentah.

Alamat beacon.dll+0x50  dipilih karena ini adalah lokasi spanduk “Program ini tidak dapat dijalankan dalam mode DOS”, yang tidak diperlukan saat memuat beacon secara reflektif.

Karena kami tidak memiliki akses mudah ke mesin Java Malleable PE, BokuLoader.cna  Skrip UDRL Aggressor dapat digunakan untuk menulis 0xB0C0ACDC  egg menjadi beacon. Kode di bawah ini menunjukkan cara DLL beacon mentah dapat dimodifikasi untuk memuat egg:

Skrip agresor untuk menulis egg ke dalam DLL beacon mentah dan menampilkan perubahan di konsol skrip Cobalt Strike.

Skrip agresor untuk menulis egg ke dalam DLL beacon mentah dan menampilkan perubahan di konsol skrip Cobalt Strike.

Kode UDRL harus mengetahui nilai telur yang ditulis ke DLL beacon mentah oleh skrip UDRL. Setelah mengetahui letak telurnya, pemburu telur mencari mundur dua kemunculan telur tersebut, seperti yang terlihat pada kode di bawah ini:

Kode perakitan Intel x64 untuk pemburu egg yang mencari mundur untuk dua contoh egg 64-bit.

Kode perakitan Intel x64 untuk pemburu egg yang mencari mundur untuk dua contoh egg 64-bit.

  • Baik skrip penyerang UDRL dan kode UDRL C dapat dimodifikasi untuk menggunakan egg yang berbeda.

Sekarang header MZ dan PE tidak lagi digunakan, kita dapat menuliskannya di skrip UDRL Aggressor:

Skrip agresor untuk menutupi MZ, PE, dan byte yang tidak digunakan dari spanduk DOS yang terletak di header DLL beacon mentah.

Skrip agresor untuk menutupi MZ, PE, dan byte yang tidak digunakan dari spanduk DOS yang terletak di header DLL beacon mentah.

Mendapatkan alamat dasar DLL beacon mentah dari call reflective loader stub

Ada juga cara lain, khusus Cobalt Strike, untuk menemukan alamat dasar beacon mentah DLL. Seperti yang kita lihat di atas, byte awal dalam call reflective loader stub menyimpan alamat dasar DLL beacon mentah di RDI  Daftar sebelum memanggil pemuat reflektif. Daripada berburu mundur dari RIP untuk beberapa egg, kita bisa mendapatkan nilai dari RDI  daftar di awal kode pemuat reflektif kami.

Untuk memeriksa ini lebih lanjut di debugger, kami menghasilkan beacon, mendahului breakpoint (0xCC ), dan buka beacon di x64dbg. Karena breakpoint ditambahkan di depan, alamat dasar dari beacon mentah berada di +1  dari memori yang dialokasikan. Seperti yang kita lihat di atas, call reflective loader stub menggunakanRIP relative addressing untuk mendapatkan alamat dasar DLL beacon mentah:

Tangkapan layar x64dbg tentang melangkah melalui call reflective loader stub untuk melihat bahwa alamat dasar DLL beacon mentah disimpan dalam register RDI sebelum memanggil pemuat reflektif.

Tangkapan layar x64dbg tentang melangkah melalui call reflective loader stub untuk melihat bahwa alamat dasar DLL beacon mentah disimpan dalam register RDI sebelum memanggil pemuat reflektif.

Di bawah ini adalah contoh kerja tentang cara mendapatkan alamat dasar DLL beacon mentah dari call reflective loader stub:

Kode C perakitan sebaris untuk mendapatkan alamat dasar DLL beacon mentah dari register RDI.

Kode C perakitan sebaris untuk mendapatkan alamat dasar DLL beacon mentah dari register RDI.

Tahap 2: Mengurai header DLL Beacon

Dengan alamat dasar DLL beacon mentah, kita sekarang bisa mendapatkan nilai-nilai yang kita butuhkan untuk memuat beacon ke dalam ruang alamat virtual proses.

Tabel di bawah ini mencantumkan nilai yang kita butuhkan dari header DLL beacon mentah, lokasi tempat kita akan menemukannya, dan tipenya:.

Tabel mencantumkan nilai-nilai dari header DLL beacon mentah yang berguna untuk memuat DLL beacon.

Tabel mencantumkan nilai-nilai dari header DLL beacon mentah yang berguna untuk memuat DLL beacon.

Penghindaran

Tidak semua isi header diperlukan untuk memuat DLL beacon. Nilai yang diperlukan dapat dikemas ulang atau dikaburkan. Nilai yang tidak diperlukan dapat dihapus atau diacak.

Fase 3: Mengalokasikan memori untuk Virtual Beacon

Setelah kita tahuSizeOfImagef rom header DLL beacon mentah, kita perlu mengalokasikan memori ukuran ini. Ruang memori ini akan menampung DLL beacon virtual kami.

Metode yang berbeda dapat digunakan untuk mengalokasikan memori untuk virtual DLL beacon. Metode yang berbeda akan menggunakan berbagai jenis memori. Metode berbeda yang didukung oleh pemuat reflektif default Cobalt Strike adalah:

Tabel yang menunjukkan opsi alokasi memori Cobalt Strike untuk beacon virtual DLL.

Tabel yang menunjukkan opsi alokasi memori Cobalt Strike untuk beacon virtual DLL.

Penghindaran

Hal ini dapat ditingkatkan lebih lanjut dengan UDRL. Versi NTAPI dari fungsi-fungsi ini dapat digunakan sebagai gantinya. Lebih jauh lagi, fungsi NTAPI dapat dipanggil melalui panggilan sistem langsung atau tidak langsung yang mungkin atau mungkin tidak membantu memperkuat kemampuan penghindaran.

Ketika metode alokator diatur ke VirtualAlloc  dalam profil Cobalt Strike Malleable C2, saat ini proyek BokuLoader akan menggunakan panggilan sistem langsung ke NtAllocateVirtualMemory  untuk mengalokasikan memori untuk beacon virtual DLL:

Contoh kode dari proyek BokuLoader yang menunjukkan panggilan sistem langsung digunakan untuk mengalokasikan memori untuk DLL beacon virtual.

Contoh kode dari proyek BokuLoader yang menunjukkan panggilan sistem langsung digunakan untuk mengalokasikan memori untuk DLL beacon virtual.

  • Nomor panggilan sistem ditemukan dengan menggunakan metode HellsGate .
  • Jika hook userland ada pada stub panggilan sistem, metode HalosGate digunakan.

Gambar di bawah ini menunjukkan contoh kode menggunakan metode HellsGate dan HalosGate untuk menentukan nomor panggilan sistem:

Contoh kode dari proyek BokuLoader yang menunjukkan cara panggilan sistem ditemukan dari proses.

Contoh kode dari proyek BokuLoader yang menunjukkan cara panggilan sistem ditemukan dari proses.

Fase 4: Memuat bagian ke ruang memori virtual

Setelah mengalokasikan memori untuk DLL beacon virtual, kita perlu menyalin bagian-bagian beacon dari offset file mentahnya, sebagaimana adanya dalam DLL beacon mentah, ke memori yang dialokasikan pada offset virtual relatifnya.

Jika kita mengalokasikan memori kita denganREADWRITE kita perlu melacak alamat bagian .text dan ukurannya. Sebelum memanggil titik masuk DLL beacon virtual kita perlu mengubah perlindungan memori bagian .text bagian yang dapat dieksekusi.

Mengalokasikan memori kita dengan READWRITE_EXECUTE membuat proses pemuatan reflektif lebih mudah tetapi meningkatkan kemungkinan deteksi oleh solusi keamanan.

Di bawah ini adalah contoh kode yang disederhanakan, dari proyek BokuLoader, yang menunjukkan ini:.

Contoh kode dari proyek BokuLoader yang menunjukkan bagian yang disalin dari DLL beacon mentah ke DLL beacon virtual.

Contoh kode dari proyek BokuLoader yang menunjukkan bagian yang disalin dari DLL beacon mentah ke DLL beacon virtual.

Penghindaran

Beberapa fitur penghindaran terkait bagian pemuatan adalah:

  • Tidak menyalin header beacon ke DLL beacon virtual.
  • Mengalokasikan ruang memori di DLL beacon virtual tempat header akan berada.

Dalam proyek BokuLoader publik, header untuk DLL beacon tidak disalin dari DLL beacon mentah ke DLL beacon virtual. Saat ini yang pertama 0x1000  byte dari DLL beacon virtual adalah nol (0x00‘s ). Dari pengujian saya, beacon tidak bergantung pada header setelah beacon dimuat dengan benar ke dalam memori virtual. Menghindari menyalin header dapat membantu menghindari pemindai dalam memori, tetapi byte nol ini juga bisa menjadi titik deteksi potensial.

Peluang penghindaran lain yang mungkin terjadi adalah memiliki skrip UDRL Aggressor mengenkripsi bagian-bagiannya. Bagian dapat didekripsi dalam memori oleh UDRL, menggunakan kunci yang dibagikan antara UDRL dan skrip UDRL Aggressor.

Fase 5: Memuat dependensi DLL

Beacon x64 HTTP/S bergantung pada empat DLL untuk berfungsi dengan baik. Jika DLL ini saat ini tidak dimuat ke dalam proses, pemuat reflektif kami perlu memuatnya.

Keempat DLL tercantum dalam direktori impor HTTP DLL beacon:

Tangkapan layar dari PE-bear yang mencantumkan DLL dari direktori impor DLL beacon.

Tangkapan layar dari PE-bear yang mencantumkan DLL dari direktori impor DLL beacon.

Pemuat reflektif Cobalt Strike bawaan menggunakan API Kernel32.loadLibrarya untuk pemuatan DLL.

Penghindaran

Pemuatan DLL dapat dicapai dengan berbagai cara yang berbeda, dengan pertimbangan keamanan operasional yang berbeda. Beberapa metode tersebut adalah:

Jika DLL sudah ada dalam proses, maka API Windows di atas masih dapat digunakan untuk mendapatkan alamat dasar DLL, meskipun ini dapat memicu peringatan deteksi yang tidak diinginkan.

Atau, PEB memegang penunjuk ke 

<a title="https://learn.microsoft.com/id-id/windows/win32/api/winternl/ns-winternl-peb_ldr_data" href="https://learn.microsoft.com/id-id/windows/win32/api/winternl/ns-winternl-peb_ldr_data">_PEB_LDR_DATA</a>

struktur. Di dalamnya, ada daftar tertaut dari semua DLL yang dimuat dalam proses dan informasi relatifnya (

InMemoryOrderModuleList

). BokuLoader memanfaatkan ini untuk menemukan informasi DLL, menghindari panggilan API yang tidak perlu.

Jika DLL tersebut tidak ada di InMemoryOrderModuleList Saat ini, BokuLoader menggunakan NTDLL.LdrLoadDll  API untuk memuat ketergantungan DLL ke dalam memori, memanfaatkan Windows DLL Loader bawaan.

Pemuatan reflektif bersarang tidak dapat dengan mudah digunakan untuk memuat dependensi DLL karena pemuat reflektif umumnya tidak mendaftarkan DLL ke proses. Kode di luar DLL tidak dapat menggunakan DLL yang dimuat secara reflektif dengan benar. Proyek DarkLoadLibrary mungkin dapat memuat DLL dengan benar ke dalam memori tanpa memicu peristiwa pemuatan gambar kernel.

Contoh kode dari proyek BokuLoader yang menunjukkan cara alamat dasar DLL yang dimuat dapat diselesaikan dengan berjalan di InMemoryOrderModuleList.

Contoh kode dari proyek BokuLoader yang menunjukkan cara alamat dasar DLL yang dimuat dapat diselesaikan dengan berjalan di InMemoryOrderModuleList.

Tahap 6: Menyelesaikan tabel alamat impor

Dengan DLL yang diperlukan dimuat ke dalam proses, API yang tercantum dalam direktori impor harus diselesaikan. Alamat API kemudian perlu ditulis ke Tabel Alamat Impor (IAT) DLL beacon virtual. Dengan cara ini, beacon tahu alamat mana yang harus dituju ketika perlu memanggil API seperti WININET.HttpSendRequest

Entri impor perlu diselesaikan melalui string ordinal atau nama.

Pada gambar di bawah ini, kita melihat bahwa Cobalt Strike DLL beacon menggunakan kombinasi ordinal dan string nama untuk entri impor:

Tangkapan layar dari PE-bear yang menunjukkan beberapa entri impor untuk DLL beacon harus diselesaikan dengan ordinal.

Tangkapan layar dari PE-bear yang menunjukkan beberapa entri impor untuk DLL beacon harus diselesaikan dengan ordinal.

Pemuat reflektif Cobalt Strike bawaan menggunakan Kernel32.GetProcAddress  API untuk menyelesaikan alamat virtual untuk entri impor.

Penghindaran

Beberapa metode penghindaran untuk menyelesaikan alamat API adalah:

  • Implementasi kode kustom dari GetProcAddress
  • NTDLL.LdrGetProcedureAddress

BokuLoader menggunakan implementasi kode khususGetProcAddress untuk menyelesaikan alamat untuk entri impor, menangani string nama dan ordinal.

Alamat NTDLL.LdrGetProcedureAddress mampu menangani string nama dan ordinal juga. Jika alamat yang dikembalikan untuk Entri Impor adalah forwarder ke DLL lain, BokuLoader akan default ke NTDLL.LdrGetProcedureAddress untuk menyelesaikan masalah penerusan.

Saat menulis IAT, hooking dapat diimplementasikan dengan menulis alamat virtual fungsi hook yang telah kami terapkan daripada alamat virtual API yang dimaksud. Selama output yang diharapkan dikembalikan ke beacon ketika alamat di IAT dipanggil, kita dapat mengeksekusi kode tambahan sebelum kembali ke beacon. Postingan mendatang dan rilis BokuLoader publik akan mendemonstrasikan cara kami dapat memanfaatkan pengait IAT untuk fitur penghindaran tingkat lanjut.

Dengan rilis terbaru, proyek publik BokuLoader mendukung fitur obfuscate Malleable PE dari profil Cobalt Strike C2 dengan implementasi khusus. Dengan memodifikasi kunci masking diBokuLoader.cna Skrip UDRL Aggressor, pengaburan dapat ditingkatkan dengan memilih kunci XOR byte tunggal Anda sendiri.

Mengenai keamanan operasional, penting untuk diketahui bahwa mesin pencocokan pola mampu memaksa masker XOR single-byte secara brutal. Posting mendatang akan menunjukkan cara kami dapat membuat mesin Malleable PE kami sendiri menggunakan fungsionalitas skrip Cobalt Strikes Aggressor untuk mengaburkan beacon untuk mengatasi pencocokan pola.

Fase 7: Menyelesaikan relokasi

DLL beacon memiliki banyak relokasi yang harus diselesaikan dan ditulis ke Tabel Relokasi Dasar DLL beacon virtual sebelum dijalankan.

Di PE-bear kita dapat melihat bahwa DLL beacon secara default memiliki alamat dasar gambar 0x180000000 :

Tangkapan layar dari PE-bear menunjukkan alamat dasar gambar dari DLL beacon.

Tangkapan layar dari PE-bear menunjukkan alamat dasar gambar dari DLL beacon.

Sebelum kita mulai menulis relokasi, kita perlu menghitung delta antara alamat dasar DLL beacon virtual kita dan alamat dasar hardcode.

Misalnya, mari kita pura-pura alamat dasar untuk DLL beacon virtual kita adalah 0x7FFC44FE0000 . Kami mengurangi alamat dasar hardcode dari alamat dasar DLL beacon virtual kami untuk mendapatkan alamat dasar delta:

Tangkapan layar saat mendapatkan alamat dasar delta

Selanjutnya, untuk menentukan alamat virtual untuk setiap entri relokasi di Tabel Relokasi Dasar, kami menambahkan alamat dasar delta ke alamat entri relokasi kode keras untuk menentukan relokasi dalam DLL beacon virtual kami.

Pada gambar di bawah ini kita dapat melihat bahwa entri relokasi beacon ditulis mundur dalam format little-endian:

Tangkapan layar dari PE-bear menunjukkan beberapa entri relokasi ada dalam format little-endian.

Tangkapan layar dari PE-bear menunjukkan beberapa entri relokasi ada dalam format little-endian.

Alamat hardcode untuk entri relokasi ini adalah 0x1800341C8 .

Kami menambahkan alamat ini ke alamat dasar delta, untuk mendapatkan alamat virtual untuk relokasi seperti yang ada di DLL beacon virtual:

Tangkapan layar menambahkan alamat ke alamat dasar delta, untuk mendapatkan alamat virtual untuk relokasi seperti yang ada di DLL beacon virtual:

Untuk setiap entri relokasi, kita perlu memeriksa apakah jenisnya

<a title="https://learn.microsoft.com/id-id/windows/win32/debug/pe-format" href="https://learn.microsoft.com/id-id/windows/win32/debug/pe-format">IMAGE_REL_BASED_DIR64 (0xA)</a>

. Jika ini salah, kami akan melewatkan penulisan relokasi.

Setelah kita menentukan alamat virtual dari relokasi yang ada di dalam DLL beacon virtual, kita menuliskannya ke ruang memori yang menyimpan alamat entri relokasi yang dikodekan.

Jika Anda tertarik untuk mempelajari lebih lanjut tentang cara melakukan relokasi PE, lihat kode fungsi doRelocations di proyek publik BokuLoader. Sebelum merilis postingan blog ini, saya mengubah kode relokasi dari assembly ke kode C, untuk membantu orang lain yang ingin mengetahui detail teknis tentang cara hal ini dilakukan.

Tahap 8: Menjalankan Beacon

Eksekusi beacon dapat dipecah menjadi tiga langkah:

  • Memastikan bagian DLL beacon virtual memiliki izin memori yang benar.
  • Menginisialisasi DLL beacon virtual.
  • Memanggil titik masuk DLL beacon virtual.

Membuat Virtual Beacon dapat dieksekusi

Jika memori yang kita alokasikan untuk DLL beacon virtual kita adalah READWRITE_EXECUTE kita tidak perlu mengubah proteksi memori agar beacon berfungsi dengan baik tanpa mengalami crash.

Jika kita mengalokasikan memori beacon virtual kita sebagai non-eksekusi (READWRITE ), kita perlu mengubah .text  bagian dari DLL beacon virtual kita untuk dapat dieksekusi. Lokasi dan ukuran virtual .text  bagian seharusnya sebelumnya disimpan dalam fungsi utama UDRL kita sebagai variabel.

Dalam proyek BokuLoader publik, perubahan perlindungan memori dilakukan dengan panggilan sistem langsung ke NTProtectVirtualMemory , seperti yang terlihat pada contoh kode di bawah ini:

Contoh kode dari proyek BokuLoader yang menunjukkan perubahan .text bagian dari DLL beacon virtual menjadi file yang dapat dieksekusi.

Contoh kode dari proyek BokuLoader yang menunjukkan perubahan .text bagian dari DLL beacon virtual menjadi file yang dapat dieksekusi.

Kemampuan .data  bagian dari DLL beacon virtual kita harus memiliki izin READWRITE Jika bagian tersebut tidak dapat ditulis, DLL beacon kita mungkin akan mengalami crash saat dieksekusi.

Menginisialisasi DLL Virtual Beacon

Agar DLL beacon virtual dapat berjalan dengan benar, DLL tersebut harus diinisialisasi terlebih dahulu dengan memanggil titik masuk DLL beacon virtual. Argumen pertama adalah alamat dasar dari DLL beacon virtual. Argumen kedua adalah fwdReason  dan itu harus diatur ke DLL_PROCESS_ATTACH (1) .

Contoh kode dari proyek BokuLoader yang menginisialisasi DLL beacon virtual.

Contoh kode dari proyek BokuLoader yang menginisialisasi DLL beacon virtual.

Menjalankan DLL Virtual Beacon kami

Setelah menginisialisasi DLL beacon virtual, kita dapat mengembalikan titik masuk beacon virtual ke call reflective loader stub, atau kita dapat memanggil titik masuk virtual DLL beacon di UDRL kita dengan fwdReason  diatur ke 0x4 .

Tidak seperti DLL tipikal di mana argumen pertama hinstDLL  ke 

<a href="https://learn.microsoft.com/id-id/windows/win32/dlls/dllmain">DLLMAIN</a>

akan menjadi alamat dasar DLL virtual, beacon mengharapkan alamat dasar dari DLL beacon mentah. Jika ini tidak disediakan, beberapa fitur penghindaran Malleable PE mungkin gagal.

Contoh kode dari proyek BokuLoader menunjukkan dua cara berbeda untuk mengeksekusi virtual DLL beacon.

Contoh kode dari proyek BokuLoader menunjukkan dua cara berbeda untuk mengeksekusi virtual DLL beacon.

Kesimpulan

Semoga postingan blog ini membantu tim merah dan tim biru lebih memahami Cobalt Strike dan proses pemuatan reflektif. Masih ada banyak sekali peluang penghindaran yang dapat diimplementasikan melalui pembebanan reflektif. Dengan pemahaman yang lebih dalam tentang konsep-konsep ini, organisasi dapat mempersiapkan diri dengan lebih baik untuk pertahanan yang sukses terhadap ancaman siber.

Posting mendatang dalam seri ini akan berfokus pada mengintegrasikan UDRL dengan fitur penghindaran Cobalt Strike saat ini, menyelami fitur penghindaran tanpa dokumen yang sudah ada di BokuLoader publik, serta fitur-fitur canggih yang belum dirilis ke publik. Nantikan informasi dan teknik yang lebih mendalam untuk mempelajari cara membawa game Cobalt Strike Anda ke tingkat berikutnya dengan pengembangan UDRL!

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.