Analisi bootkit-rootkit della sfida Z2A-BlackLotus stage 2
Analisi del bootkit-rootkit stage 2 di BlackLotus
Prima di addentrarci in questa merda divina(credimi, questa è una merda divina perché nessuno può farlo senza la volontà di DIO(almeno questa è la mia opinione)) ,ecco l'hash del file bootkit
Prima di tutto, ecco come appare un sistema sano
identifier {bootmgr} device partition=\Device\HarddiskVolume9 path \EFI\MICROSOFT\BOOT\BOOTMGFW.EFI description Windows Boot Manager locale en-US inherit {globalsettings} default {current} resumeobject {3f80ecd0-df10-11ed-bafc-80a84b2564bb} displayorder {current} toolsdisplayorder {memdiag} timeout 30
``` So how do we set up a breakpoint in order to debug the bootkit? Well that's we we compiled the ovmf image as debug rather than release. If you specifically start qemu with that command you'll have qemu run and debug messages will be logged in a file called debug.log , which looks like this ```identifier {current} device partition=C: path \Windows\system32\winload.efi description Windows 10 locale en-US inherit {bootloadersettings} recoverysequence {3f80ecd2-df10-11ed-bafc-80a84b2564bb} displaymessageoverride Recovery recoveryenabled Yes isolatedcontext Yes allowedinmemorysettings 0x15000075 osdevice partition=C: systemroot \Windows resumeobject {3f80ecd0-df10-11ed-bafc-80a84b2564bb} nx OptIn bootmenupolicy Standard
Ora nella mia analisi non sono mai riuscito a infettare la mia macchina, quindi userò l'esempio del post del blog del ricercatore asiatico già citato, che è così che dovrebbe apparire una macchina infetta.```
// Windows Boot Manager
// --------------------
// identifier {9dea862c-5cdd-4e70-acc1-f32b344d4795}
// description Windows Boot Manager
// locale en-US
// inherit {7ea2e1ac-2e61-4728-aaa3-896d9d0a9f0e}
// bootdebug Yes
// displayorder {57e1b615-0355-11ec-abb0-005056c00008}
// timeout 30
// Windows Boot Loader
// -------------------
// identifier {57e1b615-0355-11ec-abb0-005056c00008}
// device boot
// path \system32\hvloader.efi
// description Hoy la disco se flota
// locale en-US
// inherit {6efb52bf-1766-41db-a6b3-0ee5eff72bd7}
// truncatememory 0x10000000
// avoidlowmemory 0x1000
// nointegritychecks Yes
// testsigning Yes
// isolatedcontext Yes
// osdevice boot
// systemroot \
// ems Yes
=============================================================================
=============================================================================
Prima di iniziare, come si fa, comunque, a configurare l'ambiente per l'analisi di un modulo efi? Beh, il merito va a @MaverickMusic__, durante una discussione con lui mi ha passato questo( https://zhuanlan-zhihu-com.translate.goog/p/343293521?_x_tr_sl=auto&_x_tr_tl=en&_x_tr_hl=en-GB ). Non ho seguito completamente i passaggi di quel link, quindi ecco esattamente cosa ho fatto per avere l'ambiente operativo:
-Primo ho installato edk2(https://github.com/tianocore/tianocore.github.io/wiki/Windows-systems)
-Secondo ho configurato il mio ovmf come debug e non release(questo ci aiuterà più avanti). Ecco il comando build -a X64 -t VS2019 -b DEBUG -p OvmfPkg/OvmfPkgX64.dsc
-Terzo ho dovuto configurare il mio windbg. Come diavolo ho fatto? Ho scaricato tutto da questo link(git clone https://github.com/microsoft/WinDbg-Samples). Poi ho compilato ExdiGdbSrv.sln. Poi ho seguito tutto da questo link(https://learn.microsoft.com/en-us/windows-hardware/drivers/debugger/setting-up-qemu-kernel-mode-debugging-using-exdi), da dove diceva Use regsvr32 to register the DLL in an Administrator command prompt. fino a PS>.\Start-ExdiDebugger.ps1 -ExdiTarget "QEMU" -GdbPort 1234 -Architecture x64 -ExdiDropPath "C:\path\to\built\exdi\files". Lo so, è confuso, ma abbi pazienza, perché di sicuro farò un video in cui spiego ogni passaggio! Bene, ora che abbiamo un ambiente configurato per il debug, come diavolo facciamo a fare il debug del codice? Quindi avviamo qemu; nel mio caso l'ho fatto eseguendo qemu-system-x86_64.exe -L . -bios OVMF.fd -hdd dos.img -debugcon file:debug.log -global isa-debugcon.iobase=0x402. Una volta eseguito il comando di qemu, sono subito andato a selezionare compat_monitor0 dal menu View di qemu. Dovrebbe apparire così quando lo fai.

inoltre, dopo aver selezionato questo, dovresti digitare gdbserver per avviare un'istanza remota di gdb per il debug, alla quale ci collegheremo con windbg usando questo comando .\Start-ExdiDebugger.ps1 -ExdiTarget "QEMU" -GdbPort 1234 -Architecture x64. Bene, una volta connessi, apparirà così
Quindi, per dare un senso a questo output, nel nostro caso l'unica riga rilevante è EntryPoint=0x000062C9A8C, che è come l'indirizzo di caricamento preferito ogni volta che eseguiamo il bootkit. Nello specifico per il bootkit varia tra 0x62C4A8C or 0x62C9A8C. Ora possiamo ribasare il programma in IDA e svolgere il nostro normale lavoro :) . Godetevi il resto del blog!
=============================================================================
Bindiffing del winload.efi originale con quello rilasciato da blacklotus
Vediamo alcune somiglianze ma anche alcune discrepanze, ma nulla di utile, comunque....
=============================================================================
Bene, allora diamo il via a questa festa.
Bene, iniziamo a dissezionare. Prima di tutto vediamo che c'è una funzione che viene chiamata. Bene, e allora? beh
Bene, un'altra funzione. Non proprio... Notate qualcosa di familiare?

Ancora niente???
Nessun problema, forse ora
Stessa funzione demangle! Ciao vecchio amico :)))
Bene, ma che dire di return (*(a1 + 88))(v2, &unk_62CEABC, 3i64); ?? Beh, onestamente non so cosa dire solo da una prospettiva statica, quindi proviamo a usare il debugger per capirlo :))
Quindi quando demangliamo la stringa otteniamo
Quindi poi quando arriviamo all'istruzione di chiamata
e non otteniamo informazioni.... fantastico, ma perché? Perché non abbiamo un file .pdb, quindi non possiamo ottenere i simboli di debug.... Bene, almeno IDA è utile qui. Quindi sappiamo che la funzione "grande" prende come input SystemTable->RuntimeServices, che è di tipo EFI_SYSTEM_TABLE. Bene, se lo ispezioniamo, questo è Un puntatore alla tabella dei servizi di runtime EFI. . Se cerchiamo su Google troviamo un mucchio di documenti, ma un documento cruciale che troviamo è https://uefi.org/sites/default/files/resources/UEFI\_Spec\_2\_1\_D.pdf . lì dice
Bene, quindi una struct con un mucchio di puntatori, sì, ma ingrandiamo un po'.
Quindi prima demangla VbsPolicyDisable; se cerchiamo su Google troviamo un'analisi di ESET che afferma che questa variabile viene valutata dal loader del sistema operativo Windows durante l'avvio e, se definita, le funzionalità VBS principali, come HVCI e Credential Guard, non verranno inizializzate. , quindi in pratica questa variabile è responsabile dell'attuale "sicurezza" a livello di avvio. Bene, poi abbiamo la funzione che prende quella variabile e
e quindi possiamo concludere che questa deve essere una funzione che in qualche modo cambia lo stato di quella variabile. Bene, quali sono le possibili funzioni che potrebbero farlo? C'è solo una funzione del genere in EFI_SYSTEM_TABLE, cioè EFI_SET_VARIABLE SetVariable;
Quindi concludiamo che questa funzione prende semplicemente VbsPolicyDisable e la imposta a``` db 77h ; w .data:0000000180005034 db 59h ; Y .data:0000000180005035 db 3 .data:0000000180005036 db 32h ; 2 .data:0000000180005037 db 4Dh ; M .data:0000000180005038 db 0BDh ; ½ .data:0000000180005039 db 60h ; ` .data:000000018000503A db 28h ; ( .data:000000018000503B db 0F4h ; ô .data:000000018000503C db 0E7h ; ç .data:000000018000503D db 8Fh .data:000000018000503E db 78h ; x .data:000000018000503F db 4Bh ; K.
Ora, c'è qualcosa di importante in questi byte? Beh sì, se per caso hai letto la prima parte dell'analisi di BlackLotus, saprai che ho fatto riferimento al lavoro di un ricercatore asiatico. Beh, quel ricercatore è stato così gentile da analizzare anche il bootkit rilasciato. Dai un'occhiata (https://www.cnblogs.com/DirWang/p/17294545.html#autoid-3-2-1) , quindi nella sua analisi è stato così gentile da fornirci quell'informazione. Ci indica https://github.com/Mattiwatti/EfiGuard/blob/master/EfiGuardDxe/PatchWinload.c . lì vediamo una riga simile
<div>
<img src="https://assets.kitploit.com/production/public/readmes/44336/33c755aa460f5bdc338c75f3f5e1322c731123299d59c43dcdf2be3b72d1276c.png" alt="1">
<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/144b057568871a60a32e477ed1ae7e8d7090778a67b7fc24222f0f58fe44afc1.png" alt=""><figcaption></figcaption></figure>
</div>
C'è un motivo specifico dietro a questo? Onestamente non lo so, è la prima volta che analizzo un bootkit. Per favore, fammelo sapere o fai una pr/pull request per modificare questo documento se hai più esperienza di me :) in quest'area
\=============================================================================
Bene, dopo, la fortuna ci assiste e lo pseudocodice di IDA è simile all'assembly
<div>
<img src="https://assets.kitploit.com/production/public/readmes/44336/7457c9d8beb807556618728c7aba102109a472ef2f990f35ec344038fafc4cd5.png" alt="1">
<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/e11c4b4e4260f7a91e6dc08bcabb7c3ac420dcee346b1bf9dff02835342f7837.png" alt=""><figcaption></figcaption></figure>
</div>
quindi quello che suppongo accada qui è la normale inizializzazione di EFI\_SYSTEM\_TABLE che fondamentalmente, suppongo, inizializza quale processo deve continuare il processo di avvio. E poi abbiamo la chiamata alla funzione PatchBootManager
\=============================================================================
PatchBootManager
<div>
<img src="https://assets.kitploit.com/production/public/readmes/44336/66c49bf5b64655af7e0edfe384ad715912c02fbeea1ac1313e4f65479ab58f80.png" alt="1">
<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/7a1dc3ac7c01cbd4cfd9b3ec614c357895210e4f03ae5d58000e6b047f84eb96.png" alt=""><figcaption></figcaption></figure>
</div>
<div>
<img src="https://assets.kitploit.com/production/public/readmes/44336/3fc22a51052c24c9e436ace83a1672ce88bf25fb11103b32d0143fa0ab4d7216.png" alt="2">
<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/22c7869b067f26c6469e4baffcd4226535c47e82d4baaf7fa8e27820915b1580.png" alt=""><figcaption></figcaption></figure>
</div>
<div>
<img src="https://assets.kitploit.com/production/public/readmes/44336/38cf7697523141faa68a59b52abd2a1ca14d0d9053f1e6960052a5093e3a94bb.png" alt="3">
<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/505a3fd02b96bcb823bf108ee03a8a1204827852260c1e8ce3902638237259b3.png" alt=""><figcaption></figcaption></figure>
</div>
E dallo pseudocodice
<div>
<img src="https://assets.kitploit.com/production/public/readmes/44336/9c8482f0faa4d4de5f8643acc4276ebbbfc57386e9b00a4057793b5c67b1bf3b.png" alt="1">
<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/c44de61b9f089fd8972bcc8567110bc2d58c21e5465a7b4f14fc7beaefee30a3.png" alt=""><figcaption></figcaption></figure>
</div>
<div>
<img src="https://assets.kitploit.com/production/public/readmes/44336/6809c28e881b3626d73a476cd31631891539f6a7b71cf276619f9cd2244d83e9.png" alt="2">
<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/c8cd4870cd0488e57cde3448ba01fdd44063f266516d8530731f42e6ccc5be78.png" alt=""><figcaption></figcaption></figure>
</div>
Okay, quindi la prima chiamata di funzione che vediamo è HandleProtocol. Allora cosa fa il codice? Fortunatamente ci imbattiamo in questo facendo una rapida ricerca su Google (https://tianocore-docs.github.io/edk2-ModuleWriteGuide/draft/5\_uefi\_drivers/54\_communication\_between\_uefi\_drivers.html) e vediamo che `recupera i protocolli`. Bello, non c'è molto che possa capire. Sì, ti capisco. Quindi fondamentalmente recupera i metodi di informazioni di comunicazione usati da altri driver UEFI. Bene, scavando ancora un po', vediamo che il secondo parametro è
<div>
<img src="https://assets.kitploit.com/production/public/readmes/44336/703c3f52bd8c3d10eaf046fc801cbc60ca7a62e9162d67a6ba63caf4c9e9038d.png" alt="1">
<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/9d41aacaed9c15391beb8b1b62739572bf7f873508938ade770610eec371a17c.png" alt=""><figcaption></figcaption></figure>
</div>
Se cerchiamo quei byte specifici, ci imbattiamo in questo
<div>
<img src="https://assets.kitploit.com/production/public/readmes/44336/f4a8ed3b81486c8481c0f8894175f9d7390ddf62f9974ba025aad9827dea119e.png" alt="1">
<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/882b5116cfd08886c3dac510443fb77c9aa31781eb234208ec81fdf313544c29.png" alt=""><figcaption></figcaption></figure>
</div>
quindi che diavolo fa EFI\_LOADED\_IMAGE\_PROTOCOL\_GUID? citando da (https://uefi.org/specs/UEFI/2.10/09\_Protocols\_EFI\_Loaded\_Image.html) `Può essere usato su qualsiasi image handle per ottenere informazioni sull'immagine caricata.` , che tipo di info? ```This section defines EFI\_LOADED\_IMAGE\_PROTOCOL and the EFI\_LOADED\_IMAGE\_DEVICE\_PATH\_PROTOCOL. Respectively, these protocols describe an Image that has been loaded into memory and specifies the device path used when a PE/COFF image was loaded through the EFI Boot Service LoadImage(). These descriptions include the source from which the image was loaded, the current location of the image in memory, the type of memory allocated for the image, and the parameters passed to the image when it was invoked.```
Quindi nel nostro caso recupera informazioni sul bootkit. Ora c'è un problema: non possiamo davvero ispezionare il risultato della funzione perché non abbiamo simboli di debug :/ ma possiamo presumere. E tendo a presumere che la struttura (risultato della chiamata di funzione precedente) sarà in rbx.
<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/b8f744ecd9fd4be572a1e2d191b06231559eca2b32aeaa981a399eec7f3ee710.png" alt=""><figcaption></figcaption></figure>
Poi chiamiamo demangle string
<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/1fdc75d2dc9221250e6d46692770ad5240f7a0d6cda9cc5634749b327fc8c146.png" alt=""><figcaption></figcaption></figure>
che ci restituisce
<div>
<img src="https://assets.kitploit.com/production/public/readmes/44336/e073b265ff13675b755ec8413554bec74ab4eae57dd002b25694632eb43cbc8e.png" alt="1">
<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/3654bb54071386cd020c43ed4a35fae40aec386897a0ca26a27b58b8e1a91c95.png" alt=""><figcaption></figcaption></figure>
</div>
e poi chiamiamo
<div>
<img src="https://assets.kitploit.com/production/public/readmes/44336/c433aa63cddd2ecfb5ce0fd57a6774ad35b1c1ed4ee71e7cecb566cc861d2b80.png" alt="1">
<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/6834be566cdd81f2410ec7d4ee97936d14a27017a723371eea3046b8590609f4.png" alt=""><figcaption></figcaption></figure>
</div>
\=============================================================================
sub\_180002B14
<div>
<img src="https://assets.kitploit.com/production/public/readmes/44336/483f2b789c0fa6fe9378ba324f8e349bc72cbb45e540bbc2355ef55acaf1b6b4.png" alt="1">
<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/d84d79115facbc0f9ff7afe06d70a18555e7d94bc196f6f9d0ff6b5cfd40408a.png" alt=""><figcaption></figcaption></figure>
</div>
<div>
<img src="https://assets.kitploit.com/production/public/readmes/44336/19e2366fddab99fa3aa4375b8306475ee31d3bf9a3c3737efeeb4d627868404e.png" alt="2">
<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/6c808c76821c756eca776cf6290482f6f9829167f539bf31b2ad82b3de0af829.png" alt=""><figcaption></figcaption></figure>
</div>
<div>
<img src="https://assets.kitploit.com/production/public/readmes/44336/ad0d06238e39e4ba1decb2f1305510a8375822b13ae9148d91e267d14762eb3b.png" alt="3">
<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/0e45e9ae64c3fbd8a61ffdf60ec2e532529d8cab6cfc7786fa2c91824233d347.png" alt=""><figcaption></figcaption></figure>
</div>
e dallo pseudocodice
<div>
<img src="https://assets.kitploit.com/production/public/readmes/44336/c14b1eacbe8eef4155c4148b66fa95f93bbd9e6fc81e5ca80f1ddc5b2b9a7a16.png" alt="1">
<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/b7c452865661d95b79886a48a455eba663c2e3915e0a81ad16dc7ddd8c2c0189.png" alt=""><figcaption></figcaption></figure>
</div>
Bene, fino all'if tutto è autoesplicativo; ora, per quanto riguarda l'if? Vediamo di nuovo che fa una chiamata con unk\_180005010 come parametro, che è di nuovo un array di byte; a un esame più attento, appare così
<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/c3bb66f35a4e559ae793ba590fc0c342bdde1e1c9765e144cb450a809009655d.png" alt=""><figcaption></figcaption></figure>
Ora, se ispezioniamo di nuovo i primi byte e facciamo una rapida ricerca, ci imbattiamo in questo (https://github.com/theopolis/uefi-firmware-parser/blob/master/uefi\_firmware/guids/efiguids\_ami.py) più precisamente questo `'EFI_DEVICE_PATH_PROTOCOL_GUID': [0x09576e91, 0x6d3f, 0x11d2, 0x8e, 0x39, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b]` .
Se torniamo sulla pagina delle specifiche UEFI vediamo che `Può essere usato su qualsiasi device handle per ottenere informazioni generiche su percorso/posizione relative al dispositivo fisico o logico.`. Poi vediamo anche questo `Il device path descrive la posizione del dispositivo a cui l'handle si riferisce`. OK bello, e se scorriamo solo un po' vediamo una funzione chiamata \_EFI\_DEVICE\_PATH\_PROTOCOL. Ok, quindi per concludere sappiamo che questo ha a che fare con EFI\_DEVICE\_PATH\_PROTOCOL\_GUID, ma la nostra funzione è di tipo EFI\_BOOT\_SERVICES. Quindi c'è qualche funzione in EFI\_BOOT\_SERVICES che potrebbe fare qualcosa come gestire un protocollo? Sì, c'è. Se ispezioniamo https://www.intel.com/content/dam/doc/product-specification/efi-v1-10-specification.pdf sezione 4.4 vediamo
<div>
<img src="https://assets.kitploit.com/production/public/readmes/44336/918a0a5184849cbb87454df44c5ffa5e5fa586f223213287f6c7fbe737a0fbc8.png" alt="1">
<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/fab94604327fe596d9eeb68368efcf0afc721ef7bfcdc07a8977392b4309238c.png" alt=""><figcaption></figcaption></figure>
</div>
più precisamente ha una funzione a cui siamo familiari (HandleProtocol). Bello
Poi vediamo un'altra chiamata di funzione, questa volta sconosciuta a noi. Vediamo quali argomenti accetta: ne accetta 2, poi la lunghezza della stringa passata come unicode e un puntatore a una variabile
<div>
<img src="https://assets.kitploit.com/production/public/readmes/44336/39e0d1d9baabff8d95da7109294db94f9fc4409a6ede34d37ece9662fb73651d.png" alt="2">
<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/e116e90f20a09d48f21a981e7d24c49f7474ea9ac6007b6fa41973300af4e83d.png" alt=""><figcaption></figcaption></figure>
</div>
Ora se ispezioniamo questo in un debugger
<div>
<img src="https://assets.kitploit.com/production/public/readmes/44336/f412c3bf83f60da9213f4c29b39350c925a0aa6411c42de52d7fa4530c5bc3fe.png" alt="1">
<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/5285bf4d5e52dbbef857e46e8738c3ba6e7f6cda87f9b67a4965b23cc70aba0e.png" alt=""><figcaption></figcaption></figure>
</div>
vediamo una cosa strana: rcx ha una stringa di debug che dice AllocatePool, che arriva dopo una chiamata di funzione, quindi concludiamo che questa era probabilmente una chiamata a AllocatePool. Ironia della sorte, se ispezioni anche le specifiche, vedrai che boot\_services ha anche un puntatore a AllocatePool, il che rende la nostra ipotesi ancora più solida.
Ok, quindi se riusciamo ad allocare abbastanza spazio (il controllo if >= 0 serve a verificare se l'allocazione è riuscita, perché se EFI\_OUT\_OF\_RESOURCES è implementato come
<div>
<img src="https://assets.kitploit.com/production/public/readmes/44336/bf08cd5dd33ad9ca16ff4e6a44a4cbfd51cd1f8b0300d9b6b44984c4306fcb6e.png" alt="1">
<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/c28af9995294473937be13a6094de90cb57a688c83727617ca9f667c2705d7cd.png" alt=""><figcaption></figcaption></figure>
</div>
è lecito supporre
<div>
<img src="https://assets.kitploit.com/production/public/readmes/44336/3741ef8be2dc989f601d26568907381f1847d29c0bf514add76485b0f0fef4b6.png" alt="1">
<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/cdfc6ccb296659fc8156d4bfba6d777da8b2792e4af56677d0f0d57695932216.png" alt=""><figcaption></figcaption></figure>
</div>
sia usato per l'allocazione riuscita).
Un fatto interessante è che il buffer dopo l'allocazione non è zero, ma contiene questi byte. Se qualcuno ne sa di più, per favore apra una pr request per modificare questo documento
<div>
<img src="https://assets.kitploit.com/production/public/readmes/44336/e4b15da615e07faa4965d864435bf4deec0e01270f9d1ac1134fb5b20ad46892.png" alt="1">
<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/b229a700b321040fc8978f4f0f489a058381795c128d27dbcfbcfff5f9ffd3b2.png" alt=""><figcaption></figcaption></figure>
</div>
Quindi sì, comunque finiamo per chiamare memcpy; dopo la chiamata il nostro buffer appare così
<div>
<img src="https://assets.kitploit.com/production/public/readmes/44336/28e61d8725687245e9a9dae7e467929ac15d5a81e33178262f0ce886a3c4555c.png" alt="1">
<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/f161ab0441b14d71dbade9fc3acebbd12b1453de5d53b77b09af98c0cf0ac6d6.png" alt=""><figcaption></figcaption></figure>
</div>
Poi aggiungiamo alcuni byte per far sì che il buffer appaia così
<div>
<img src="https://assets.kitploit.com/production/public/readmes/44336/80906384a49ef1d6eaea9667cb962459c27feb8e9deac857491a248be5443a4f.png" alt="1">
<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/7c703952c72c154d156603c457a00013305c48519ddee808925c32a62499135f.png" alt=""><figcaption></figcaption></figure>
</div>
E poi chiamiamo una funzione chiamata FileDevicePath\_call che assomiglia più o meno a questo 
<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/66c77ae12715ee6d982ba2cfb769ba6a650f52ce56d7bae54e3bd93686695f02.png" alt=""><figcaption></figcaption></figure>
<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/5f7e06800ec3eecb9559d1592b8a76868038c0cbb64744e5c928b65d189ef183.png" alt=""><figcaption></figcaption></figure>
E si traduce in questo
<div>
<img src="https://assets.kitploit.com/production/public/readmes/44336/2b36492bb7dd46a7139c27de61371b59adac5bfbec989bbb542b58d34ce7982d.png" alt="2">
<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/361e2b338c676b99393f7baa48e970ba886894f579065a4468fe113841c0783b.png" alt=""><figcaption></figcaption></figure>
</div>
Ok, ma questo non ha senso se non viene spiegato, quindi....
prima abbiamo un'implementazione personalizzata di strlen che non analizzeremo perché è inutile :) Ma ecco il risultato
<div>
<img src="https://assets.kitploit.com/production/public/readmes/44336/03a0aabe9f7c87f42b7e64bb284d74738ecdc81134136cfec68c70084644c3ea.png" alt="1">
<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/823c30bd0a6a8c1d750ef1dfb0bce5be67a13a96de12e53b3e46b2226a1c2be1.png" alt=""><figcaption></figcaption></figure>
</div>
<div>
<img src="https://assets.kitploit.com/production/public/readmes/44336/5dd4684c37f3129c8234cd69574bb6371b4bef72ff7e027199b7900134cdd101.png" alt="2">
<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/118ee749874a6b08d40286821735190f67af45ca8d4573fc94aee3a2cea04af2.png" alt=""><figcaption></figcaption></figure>
</div>
32 caratteri da len(of(str)+"\x00" e poi gli ultimi 4 byte aggiunti prima della chiamata di funzione 0x4FF7F
Poi chiamiamo quella che ho usato anche dal blog di ricerca del ricercatore asiatico, PxepDevicePathInstanceCount, che è semplicemente strlen, perché conta ogni lettera e ha un contatore. Come visto qui
<div>
<img src="https://assets.kitploit.com/production/public/readmes/44336/130931a6676f0519da2b50a9762955b7581e7102434e587236137b216cc62ead.png" alt="1">
<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/ce1a6ad93452a8092d2fb71ffd6418df78c32fc8cdf4fb99133924cc9037f12e.png" alt=""><figcaption></figcaption></figure>
</div>
Quindi sì, vediamo pop rbx e dopo la chiamata vediamo rbx=0x48
<div>
<img src="https://assets.kitploit.com/production/public/readmes/44336/4c2eabdd91ec40fc82c100e67579d729def9e74c6bfd000fff287bc9c10b0f38.png" alt="1">
<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/818bb3c8398d4a53c0260d9310d4d192cfa5b65a404348df5516c94fa3d8dcaa.png" alt=""><figcaption></figcaption></figure>
</div>
poi chiamiamo di nuovo strlen sulla stessa stringa, suppongo sia solo perché nella riga successiva, precisamente, `v6 + v4 * v5;` facciamo v4\*v5 che è, suppongo, un modo per avere stringhe unicode, suppongo
Comunque, poi allochiamo di nuovo memoria usando gEfiBootServices + 64, che abbiamo già incontrato in precedenza e che si risolveva in AllocatePool.
Quindi qui vediamo anche una cosa carina, cioè
<div>
<img src="https://assets.kitploit.com/production/public/readmes/44336/26d19e06bd335f1267946a5da2542cf3eb9f2965fab788d0bcf720d7e3c08d37.png" alt="1">
<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/225c92cbe9a5e72214cb279e61ad5fcbaef0a243db835b67fce5ff7ef74e7c86.png" alt=""><figcaption></figcaption></figure>
</div>
il fatto che qui il blocco di memoria contiene il pattern afafafaf.
Quindi ciò che accade dopo è che otteniamo due buffer che appaiono così dopo l'esecuzione del loop principale
<div>
<img src="https://assets.kitploit.com/production/public/readmes/44336/35f257d96c752ac436e81778da5f37c28bfcb79fc5614f3ea8e099888cc011c3.png" alt="1">
<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/b9c706cc28161a6e7274c5cabc895bedc1279728b3ed7c11084cb6cb38dbf9e3.png" alt=""><figcaption></figcaption></figure>
</div>
<div>
<img src="https://assets.kitploit.com/production/public/readmes/44336/52477a3825650e47112a5e619a098c74e7e0de778ebfeda5682e5b49d48f3923.png" alt="2">
<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/762a6dd3897f3b630ce1d0faa371e58ed9b2bce755bb8edd54f958aab7c3b69b.png" alt=""><figcaption></figcaption></figure>
</div>
E a dire il vero siamo interessati solo al primo perché è quello che viene restituito, quindi possiamo concludere che, semplicemente, suppongo, copia il device path e ripulisce un po' di spazzatura dal buffer. :))
Ora, dopo aver finito con questo, controlliamo se il device path nel nostro caso è già, suppongo, inizializzato e liberiamo il pool; se non lo è, restituiamo il buffer più pulito dalla funzione menzionata in precedenza.
Prima di finire con questa funzione vorrei sottolineare un altro fatto interessante: ecco come appare in memoria la bootservice table :) secondo le specifiche, con l'intestazione iniziale. Ho pensato che potesse essere interessante lasciarlo qui per chiunque voglia fare lavoro futuro e si ritrovi a trovare questa stringa BOOTSERVF in un dump: questa è di sicuro la bootservice table.
\=============================================================================
Ok, quindi cosa succede dopo? Beh, controlliamo se siamo riusciti a individuare il file winload.efi e lo carichiamo in memoria. Questo è lo pseudocodice :)
<div>
<img src="https://assets.kitploit.com/production/public/readmes/44336/b59f211cb997e5ad783cbb6421833c23bea4ef4f7f21743577cd8aba4656ad2f.png" alt="1">
<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/a96f7410f6bd6f7e207b76dff36a411f3c17a3f40dcb1a9433d5292b46f775e2.png" alt=""><figcaption></figcaption></figure>
</div>
E questo è come appare in memoria
<div>
<img src="https://assets.kitploit.com/production/public/readmes/44336/e3ee7b08fdc84433a08e60c7065c74692fb3a4e26eb81def063b662aa5229558.png" alt="1">
<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/445d40332ba97516eebf129d17c56a38e28688858515d787ebf90a99580daa51.png" alt=""><figcaption></figcaption></figure>
</div>
cos'è rax? rax è un handle all'immagine :) non essere scemo come me quando pensavo che fosse una zona di memoria :)
Bene, prima di andare avanti con altro, lascia che ti spieghi rapidamente cosa diavolo è winload.efi. Quindi, `con lo sviluppo dei computer, il boot BIOS tradizionale è obsoleto e lo scontro di sicurezza sul boot UEFI è iniziato. Dal diagramma di flusso qui sotto, possiamo vedere che MBR e VBR non esistono più in UEFI, ma è l'UEFI stesso a essere responsabile del caricamento di bootmgr, il che significa anche più sicuro e veloce`
<div>
<img src="https://assets.kitploit.com/production/public/readmes/44336/d2443977ce3d56790e424fd6236d1d0594db283caa9357ed4e6abb9b8b30b8ed.png" alt="1">
<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/1259e1f45b2d2bb8edcb12609e057d089f7c1dcf907677973d799049c58bee4a.png" alt=""><figcaption></figcaption></figure>
</div>
Quindi come si avvia un normale PC Windows? Dopo il BDS, il codice del firmware UEFI memorizzato nello SPI ha completato il lavoro, quindi il boot manager del firmware UEFI interroga prima la variabile NVRAM UEFI per trovare l'ESP, e trova il boot manager specifico del sistema operativo bootmgfw.efi per chiamare la sua funzione di ingresso (driver DXE).
Questa funzione chiamerà prima la funzione EfiInitCreateInputParametersEx, che serve principalmente a convertire il parametro EfiEntry nel formato di parametri atteso da bootmgfw.efi.
Viene poi chiamata la funzione BmMain, punto di ingresso del Windows Boot Manager.
In questa funzione, viene chiamata BmFwInitializeBootDirectoryPath per inizializzare il percorso dell'applicazione di avvio (BootDirectory) (\EFI\Microsoft\Boot).
Poi BootMgr leggerà la lettera di configurazione di avvio del sistema (BCD); se ci sono più opzioni di avvio, chiamerà BmDisplayGetBootMenuStatus per visualizzare il menu di avvio.
Poi chiamerà la funzione BmpLaunchBootEntry per avviare l'applicazione (winload.efi).
Ovviamente, bootmgfw.efi fa molto di più, tra cui la verifica dell'integrità del codice della policy di avvio e l'inizializzazione dei componenti Secure Boot, quindi non entrerò nei dettagli.
Nella fase finale del Windows Boot Manager (BootMgr), la funzione BmpLaunchBootEntry selezionerà la voce di avvio corretta in base al precedente valore BCD. Se è abilitata la crittografia completa del volume (BitLocker), la partizione di sistema verrà decriptata per prima, e poi il controllo potrà essere trasferito a winload.efi.
Successivamente, viene chiamata la funzione BmTransferExecution, vengono controllate le opzioni di avvio e il flusso di esecuzione viene passato alla funzione BlImgStartBootApplication.
Poi la funzione BlImgStartBootApplication chiamerà la funzione ImgFwStartBootApplication e infine chiamerà la funzione ImgArchStartBootApplication. In essa, verrà inizializzata la modalità di protezione della memoria di winload.efi. Poi chiama la funzione BlpArchTransferTo64BitApplication; BlpArchTransferTo64BitApplication chiama la funzione Archpx64TransferTo64BitApplicationAsm e infine consegna il controllo a winload.efi.
Questa funzione abiliterà il nuovo GDT e IDT, e poi consegnerà completamente il controllo a winload.efi. A questo punto, BootMgr completa la sua missione e Winload inizia a funzionare. -Fine delle citazioni rubate da un sito cinese che parla di questo (per favore consultalo per ulteriori contenuti https://bbs.kanxue.com/thread-268267.htm )E da lì winload.efi fa il suo lavoro, ovvero caricare Windows e fare altro lavoro hardware prima di passare il controllo al kernel.
Ora, dopo questo breve riepilogo, come dicevamo
<div>
<img src="https://assets.kitploit.com/production/public/readmes/44336/65537ae888c278e8e487029f93d909fb1e4699069699cf1b7d5ad8fa1f9e0d69.png" alt="1">
<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/3b00c68a215f4568fca5d672ea6f892fecf9809e671c68795c067d2660fa3f1f.png" alt=""><figcaption></figcaption></figure>
</div>
controlliamo ulteriormente se il caricamento in memoria è riuscito e poi eseguiamo una funzione chiamata ati\_analysis\_rdtsc\_aia\_cu\_4e1f, che dovresti conoscere se hai già letto la prima parte di questa analisi.
Ora, per divertimento, supponiamo di non riuscire ad analizzare quella funzione e di venire rilevati. Vediamo com'è fatta sub\_180002A08.
<div>
<img src="https://assets.kitploit.com/production/public/readmes/44336/4eb3ae379ab937e19e6a699339d992b2a5fd1fcb33202ca67355f62a5b1203b4.png" alt="1">
<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/a4b252df16a31b5bf165d2a500ebe3c54ad5dad3c58cf9fe88a8a1da11ed6b63.png" alt=""><figcaption></figcaption></figure>
</div>
<div>
<img src="https://assets.kitploit.com/production/public/readmes/44336/dd594955a663274e25603804c348b516ca22755886b2732ef81dc8e1e0177544.png" alt="2">
<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/6fba01328584e8abb254912b81b048e8dcf80bda6d3eadc11573a52a5e84dd15.png" alt=""><figcaption></figcaption></figure>
</div>
vediamo di nuovo gEfiSystemTable + 64, che questa volta in realtà non conosciamo perché è di tipo diverso: non è di tipo bootservices, ma questa volta è di tipo efisystemtable; poi c'è memcpy e altre 3 chiamate di funzione che non conosciamo. Ora, se eseguiamo fino all'inizio del ciclo
<div>
<img src="https://assets.kitploit.com/production/public/readmes/44336/20e0db7308860023b613310ea14e0880529a588540d9dabac2218b52dc93cefb.png" alt="2">
<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/b8f498165a4016c19d8d5797517680fc32dea241d343b38fcc613620270d58dd.png" alt=""><figcaption></figcaption></figure>
</div>
e se ispezioniamo i parametri precedenti di memcpy
<div>
<img src="https://assets.kitploit.com/production/public/readmes/44336/21f546fbfb10a39e0e603186c8c505a3ae0679e8c7bad40f31643022f9ebfbcd.png" alt="2">
<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/2ef8c97938b8f961abf92c03937ca15d5a48cd03eb58a0169891559fad27dde5.png" alt=""><figcaption></figcaption></figure>
</div>
e ispezioniamo l'immagine di output di qemu, otteniamo
<div>
<img src="https://assets.kitploit.com/production/public/readmes/44336/e4325617bfda31fb45f7920d0d1d977103fd6b85260e590fc7cfdca1efacb787.png" alt="1">
<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/04e29142b4cf543a6e5b8f55de2c27d1f3f0034707a6d19e2b1ea45b8251e899.png" alt=""><figcaption></figcaption></figure>
</div>
Bene, allora cerchiamo di dare un senso a tutto questo; farò di nuovo riferimento al post di ricerca degli asiatici perché, onestamente, qui mi sono perso.
Quindi, nel suo blog, dice che le due funzioni in realtà erano```
ConOut->ClearScreen(ConOut);
ConOut->OutputString(ConOut, String);
Ok ma che cavolo è conOut? beh, dice anche che conout è di tipo EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL e che conout si ottiene con ConOut = gEfiSystemTable->ConOut; . ok, quindi cosa significa questo nel codice??
Ok, quindi scaviamo
la definizione
e il guid
Ora il mio bellissimo cervello si è dimenticato di catturare tutto questo in un debugger perché all'inizio, quando ho analizzato la cosa, ho confuso i tipi di dati tra efisystemtable e bootservices e pensavo fosse in realtà allocatepool.
Ora cosa fanno quelle funzioni?
Beh, ClearScreen dovrebbe essere abbastanza autoesplicativo, e anche OutputString. Come ha fatto il ricercatore a concludere che quella variabile è di tipo EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL? beh, probabilmente ha visto i byte del guid nel debugger.
Ora, per quanto riguarda l'ultima funzione?
Beh, nel suo post dice che l'ultima funzione è gEfiBootServices->Stall? quindi che cavolo fa? Dalle specifiche UEFI La funzione Stall() blocca l'esecuzione sul processore per almeno il numero di microsecondi richiesto. L'esecuzione del processore non viene ceduta per la durata dello stall.
Quindi in pratica congela la nostra cpu. figo, per quanto tempo 0x1C9C380 secondi. un bel po' di tempo, se me lo chiedi. che è di nuovo messo in un loop infinito, quindi sì, siamo fregati :)))
Ed ecco come appare in un debugger
Ora continuiamo con la nostra funzione principale
se riusciamo a caricare bootmgfrw.efi (cioè winload.efi, che qui è il vero bootloader di Windows) chiamiamo sub_180002538
============================================================================= sub_180002538
Dal punto di vista del grafo
Dal punto di vista dell'assembly
Vi suona un campanello? nah, beh, dategli un minuto e vi entrerà in testa, nel frattempo date un'occhiata dal punto di vista del pseudo-codice
vediamo un po' di parsing di un exe :) ora non so quanto sarà simile a quello della parte precedente (parte 1), ma vediamo :)
quindi confrontiamo la nostra versione in memoria del binario (bootmgfrw.efi) con il classico header MZ (0x5A4D), come potete vedere
ok, poi facciamo un altro classico controllo, cioè se riusciamo a trovare l'header PE
Figo, poi chiamiamo sub_1800024C4(), che assomiglia a questo
Figo, quindi quello che succede qui è che individuiamo alcuni valori in memoria e se li troviamo li restituiamo. Fare riferimento a sub_180002538.py.py per l'emulazione.
Comunque, ecco sub_180002464
Se eseguiamo con successo sub_1800024C4, torniamo nella funzione più grande e seguiamo altri controlli. Fico, diamo un senso a tutto questo.
Figo, quindi confrontiamo ulteriormente ciò che si trova in rax+0xe con 0x64, hmm figo interessante, ispezionando rax+0xe
C'è qualche motivo speciale dietro questo controllo specifico? onestamente non so? potrebbe essere; se lo sapete, per favore fate una pull request e modificate questo documento
facciamo qualche altra addizione e poi un confronto
Voglio fermarmi qui un attimo e fare di nuovo riferimento alla precedente fonte di ispirazione di questo articolo ogni volta che mi perdevo. Nel suo blog ha rinominato la funzione che confrontava i valori in RtlpImageDirectoryEntryToDataEx; se cerchiamo, non otteniamo risultati, ma c'è qualcosa di abbastanza vicino al suo nome, cioè RtlImageDirectoryEntryToData, che fondamentalmente fa questo: Data l'indirizzo di base di un modulo del kernel e l'indice di una voce nella directory dei dati, RtlImageDirectoryEntryToData() restituisce l'indirizzo virtuale e la dimensione della voce di directory(https://codemachine.com/articles/top\_ten\_kernel\_apis.html). Nel nostro caso, siccome siamo in un'app efi/uefi, possiamo considerare che il 50 che vediamo è la dimensione in byte/mb, non so, della nostra partizione root in questo caso, e che quell'indirizzo in rax è una voce nella nostra directory.
Prima di proseguire, c'è un altro dettaglio interessante da spiegare. Nella sua ricerca converte l'output di RtlImageDirectoryEntryToData in questa struttura``` typedef struct _IMAGE_RESOURCE_DIRECTORY_ENTRY { union { struct { DWORD NameOffset : 31; DWORD NameIsString : 1; }; DWORD Name; WORD Id; }; union { DWORD OffsetToData; struct { DWORD OffsetToDirectory : 31; DWORD DataIsDirectory : 1; }; }; } IMAGE_RESOURCE_DIRECTORY_ENTRY, *PIMAGE_RESOURCE_DIRECTORY_ENTRY;
Ora, che cazzo è questa struttura ?
beh, facendo una rapida ricerca su quella struttura arriviamo qui(http://www.brokenthorn.com/Resources/OSDevPE.html) che ci dice che `Parsare le risorse è un po' più complesso rispetto agli altri tipi di directory, comunque. Come per le altre sezioni, esiste una struttura di base IMAGE_RESOURCE_DIRECTORY che può essere ottenuta dal membro DataDirectory dell'optional header: blah blah` e anche che \`\`\`Questa struttura non ha molti campi interessanti, tranne gli ultimi tre.
Se hai lavorato con le risorse Win32, potresti sapere che le risorse possono essere identificate tramite ID o nome. Due dei membri di questa struttura ci permettono di conoscere il numero di queste voci, e il totale delle voci (NumberOfNamedEntries + NumberOfIdEntries), utile per iterare su tutte le voci. Come puoi probabilmente immaginare, le voci si trovano nell'array DirectoryEntries. DirectoryEntries consiste in un array di strutture IMAGE\_RESOURCE\_DIRECTORY\_ENTRY, che seguono il formato:\`\`\`
quindi fondamentalmente questa merda è usata internamente per parsare roba internamente e per noi ha senso nel contesto del fatto che lavoriamo con una directory che contiene risorse, figo.
Ancora, per favore!
Quindi, il prossimo
<div>
<img src="https://assets.kitploit.com/production/public/readmes/44336/137d3d2aebf0db9501f550b09baddf01c3e50bf703ca8d13386a7185a567f19a.png" alt="1">
<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/045c3a8a2bab306f516cdc7e9a59954e3c1ff16efe4189273c50f54b9e84f3e6.png" alt=""><figcaption></figcaption></figure>
</div>
quello che fa è fondamentalmente iterare su ogni risorsa della directory e controllare se è di tipo string
a dire il vero non so perché lo farebbe, quindi se sbaglio scusa, se non sbaglio, saluti!
prossimo
<div>
<img src="https://assets.kitploit.com/production/public/readmes/44336/a57c5815ee8b5498fed6d8dde92f48b9fc2bdfd2d4f4e231796ba96e5e28bea9.png" alt="1">
<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/bd4513fdf1f8f165fc404b8462d6bc36644de4937e42d560d54f1a5f1c0e8799.png" alt=""><figcaption></figcaption></figure>
</div>
quindi quello che succede qui è che aggiungiamo alcuni offset e finiamo in quella che il ricercatore cinese dice essere la seconda tabella delle risorse, come puoi vedere
<div>
<img src="https://assets.kitploit.com/production/public/readmes/44336/8f6655fb8117abf8a4d38b5173d51e4bc3ce67b86803c57cce36d47b73cd1e76.png" alt="1">
<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/ebdf5a9a749f2cb1b7a656be5f2d99419edfc9cd2a737e15c6845f2c008e3f11.png" alt=""><figcaption></figcaption></figure>
</div>
e poi ripetiamo lo stesso processo per ottenere alcuni offset
<div>
<img src="https://assets.kitploit.com/production/public/readmes/44336/faa12c96d0b22e6128ef1cdf14110c31cc9ebca89325f28a07fc6a0a064daeba.png" alt="2">
<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/216539eaf48a407a7f691d10cca06679a545471c3e54f25fedb31c38f0c61a66.png" alt=""><figcaption></figcaption></figure>
</div>
e ripetiamo lo stesso processo, questa volta controlliamo il tipo VS\_VERSION\_INFO
<div>
<img src="https://assets.kitploit.com/production/public/readmes/44336/ac2d2e82085f4ddbc3f5ae1ce35528dd8420924b0298c65db056d0837c3e4b6d.png" alt="1">
<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/23788c642b82988c14654e9dac2afd2504cd22846be0487efce96cae4d6fe094.png" alt=""><figcaption></figcaption></figure>
</div>
quindi che cazzo è VS\_VERSION\_INFO? beh, Microsoft(https://learn.microsoft.com/en-us/windows/win32/menurc/versioninfo-resource) dice che `Definisce una risorsa con informazioni di versione`, cioè credo che semplicemente indichi la versione di bootmgfrw.ef
e infine, se troviamo VS\_VERSION\_INFO, ripetiamo lo stesso algoritmo
<div>
<img src="https://assets.kitploit.com/production/public/readmes/44336/4f00ecf2c2c9b32b2d25fcbf3c62e9bb45679df1390a085371f5166a70d67933.png" alt="1">
<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/facd25069491b5d7826500e4f2c04cafe213191075012ddb4c1fa9a8bc97c4c5.png" alt=""><figcaption></figcaption></figure>
</div>
questa volta con una svolta, la svolta è che restituiamo il build id :) come possiamo vedere
Quindi, in conclusione, che cazzo è successo qui? Beh, in base al nome usato dal ricercatore cinese (GetPeFileVersionInfo\_BuildNumber\_) possiamo concludere che in realtà otteniamo il numero di build del bootloader, come si può vedere dalla prima immagine
<div>
<img src="https://assets.kitploit.com/production/public/readmes/44336/b28007dda110fc31d53233931ff077ac42fc81146d803b91999069e204020a4d.png" alt="1">
<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/d19f1311c2ee242ced63da8334db384929ada3acae147009becc0dbf34d2b7fb.png" alt=""><figcaption></figcaption></figure>
</div>
dove qui vediamo il bootloader caricato in memoria
nella seconda immagine vediamo
<div>
<img src="https://assets.kitploit.com/production/public/readmes/44336/2000f17c51ccc65267b46ac2c1d191bd033b3bc6e6b655973423dbbd8a1fc77e.png" alt="2">
<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/7c47fe45fe4b422618a400f2c26c28cd33fea9416f2b24086a2c852d08f1614b.png" alt=""><figcaption></figcaption></figure>
</div>
un intero in rcx che potrebbe essere il numero di build o la versione del file PE
e nella terza immagine
<div>
<img src="https://assets.kitploit.com/production/public/readmes/44336/41729b1d4a4701480d64f058f421cd2ad8a8b9b871bf17675fd7b537cec3dd85.png" alt="3">
<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/d2b17725eeb9af2336d725be9c556565fba221fd2a3517912c942f411f9ed33b.png" alt=""><figcaption></figcaption></figure>
</div>
che possiamo ipotizzare essere il numero di build, dato che ebx verrà spostato in rax :)
Come ultima nota su questa funzione: wow, ingegneria incredibile
\=============================================================================
Ora passiamo alla prossima sfida :) in base all'output dello stage precedente impostiamo v10 a sub\_180001D80 oppure a sub\_180001D48, come visto
<div>
<img src="https://assets.kitploit.com/production/public/readmes/44336/33581031e03f29b5997d46b708c467bfd49ce58625e99381dd28c109cadae7d3.png" alt="1">
<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/6647119081cffb664dcca365392271398b2572ee04c24a0456141f33cbaaeecf.png" alt=""><figcaption></figcaption></figure>
</div>
e nel nostro caso v10=sub\_180001D80
<div>
<img src="https://assets.kitploit.com/production/public/readmes/44336/2af043a1449f6bf10e2925f06697438716976d24a1539a61ab42c4301c4a8435.png" alt="1">
<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/0769d4dff6e1da51acaf9c5bac3a9a9b4b446aae9d7c593e7e54d865ec13c2ea.png" alt=""><figcaption></figcaption></figure>
</div>
\=============================================================================
Poi facciamo una strcmp tra il nostro bootloader manager e quell'array di byte
<div>
<img src="https://assets.kitploit.com/production/public/readmes/44336/59164794afc69304133f0a4c008b9e4755671e8d57bd8dc4ea5a2b2e6ae54164.png" alt="1">
<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/03b00f7c18ff7db73dfd5253f02d6966955e38732fa7d1cfb4840366c17355a1.png" alt=""><figcaption></figcaption></figure>
</div>
Voglio fermarmi qui per un breve periodo, perché come avrete capito ho visto qualcosa di interessante nel post del blog del ricercatore cinese. Ha chiamato l'array di byte SigImgArchStartBootApplication. Quindi che cazzo è SigImgArchStartBootApplication, a chi appartiene e perché diavolo quell'array si chiama così (migos). Quindi se cerchiamo su google (gulugulu) SigImgArchStartBootApplication non otteniamo nulla. Dato che nel contesto attuale usiamo il bootloader manager di Windows, apriamolo in IDA. Andiamo su C:\Windows\Boot\EFI, apriamo il binario in IDA e cerchiamo SigImgArchStartBootApplication: nulla. Cerchiamo ImgArchStartBootApplication e ci troviamo davanti a
<div>
<img src="https://assets.kitploit.com/production/public/readmes/44336/1ad42d5236e8ca4da08688fe3d4c72e6b3de01fdce633a1bdaa870de421cdc40.png" alt="1">
<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/d6e211aa12b37dfba0244d48516a08703248484c070f8d7ffcf0a28f08e8a833.png" alt=""><figcaption></figcaption></figure>
</div>
Quindi ImgArchStartBootApplication .... che sta facendo il cane...!? Beh, amm...hh la ruberò da `@_xeroxz` (seguilo, che cazzo stai facendo se non segui il suo lavoro....) quindi fondamentalmente in un articolo dice che `bootmgfw.ImgArchStartBootApplication tra le versioni di Windows 2004-1709 viene invocato per avviare winload.efi` come possiamo vedere anche dalla sua immagine(https://guidedhacking.com/threads/hyper-v-hacking-framework-works-on-every-version-of-windows-10-2004-1511-amd-intel.16251/)
<div>
<img src="https://assets.kitploit.com/production/public/readmes/44336/4967559cb05e49785841a2dc216e13fc0b94fe8be8f17d9bceaf1914722156ff.jpg" alt="1603213912596">
<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/4967559cb05e49785841a2dc216e13fc0b94fe8be8f17d9bceaf1914722156ff.jpg" alt=""><figcaption></figcaption></figure>
</div>
Se non fosse abbastanza chiaro, in un articolo() vediamo che `ImgArchStartBootApplication per catturare il momento in cui il loader del sistema operativo Windows (winload.efi) viene caricato in memoria ma non è ancora stato eseguito`(https://rustrepo.com/repo/rusty-bootkit--uefi-bootkit-in-rust)
Figo, quindi che cazzo c'entra strcmp con ImgArchStartBootApplication? Beh, diamo un'occhiata più da vicino a IDA e presto ci verrà rivelata la risposta: se cerchiamo nel codice del bootloader i byte 41 b8 09, presto incontriamo il colpevole.
<div>
<img src="https://assets.kitploit.com/production/public/readmes/44336/91050c01f95eb88488cbc575c21af7f453228eeb13c665b94d415eecf5682a55.png" alt="1">
<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/7239d85f2dc9e220a2eab80f79b5db9705285a17c074f85958c041d122bfaf8e.png" alt=""><figcaption></figcaption></figure>
</div>
E nel caso in cui i byte dell'immagine in memoria del bootloader corrispondano alla firma dei byte, eseguiamo sub\_180002398
E sicuramente, come si può vedere, abbiamo individuato il pattern: ci viene restituito in eax la zona di memoria in cui si trovano i byte e procediamo tranquillamente a eseguire sub\_180002398
\=============================================================================
sub\_180002398
"Prospettiva assembly"
<div>
<img src="https://assets.kitploit.com/production/public/readmes/44336/5aa624d92161499019e7ce6597bf46853c59ba89d37fec483a8ac7ee168ddbeb.png" alt="1">
<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/afbf940a1eb535d73dce744606cc63c568c2b447c9cf85034c422a8e900859f4.png" alt=""><figcaption></figcaption></figure>
</div>
<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/6468513a220946bbccfab53328c056a620755e1fe94ad3e36d8c8958ed777794.png" alt=""><figcaption></figcaption></figure>
<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/c5c36e7c29f1cdea6f42d55d7605ad3c2044d66397c867c221da6c0bf74f8d6a.png" alt=""><figcaption></figcaption></figure>
"Prospettiva pseudo-codice"
<div>
<img src="https://assets.kitploit.com/production/public/readmes/44336/5b1d8a264dad55f34a0cc958a2f4a26014a31987af5b66754e754589ea085097.png" alt="3">
<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/1d3db7165e0f71a3fa76862ba8afb3869f821f59db6fc5a5c5e99d5002ecfba1.png" alt=""><figcaption></figcaption></figure>
</div>
<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/ae65504884fa2881cb50af2f88e846a0ad029c9431ee6296b28993de8f2e4a0d.png" alt=""><figcaption></figcaption></figure>
Quindi che sta facendo il cane? Onestamente fa qualche calcolo, qualche addizione e sottrazione e niente di davvero importante? Sì, perché non è così interessante. Quello che ci interessa è cosa succede dopo che la funzione restituisce il controllo. Vediamo rax
<div>
<img src="https://assets.kitploit.com/production/public/readmes/44336/4eae862955421b2b1629c120bb09970714cf085e9255590d6cfa36a77bbc69e9.png" alt="1">
<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/43917bf46096449ad92172baa282fd3e70ec0bec67fec2bbf2a276285d878b52.png" alt=""><figcaption></figcaption></figure>
</div>
ok figo, ma non capisco ancora. Beh, rax = 0x5eec108 che punta a 0x48c48b48, ok e quindi? Beh, ero confuso quanto te, quindi sono tornato di nuovo al blog cinese. Quello che il ricercatore descrive che succede qui è questo: si torna all'inizio della funzione ImgArchStartBootApplication. Ma come cazzo è arrivato a questa conclusione? Beh, come detto prima, rax =\
0x48c48b48 e se ispezioniamo il booloadermnfr.efi vediamo
<div>
<img src="https://assets.kitploit.com/production/public/readmes/44336/2dbe283fa0b0dd9cf837e79f1f42eaeb6dcd61252e76979c0a4af3cf2f68e8d8.png" alt="1">
<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/624e1927cac5a0011d6fabea0f2ce4740b8dfd14102509656d6e5c0395a9c08d.png" alt=""><figcaption></figcaption></figure>
</div>
che è esattamente la stessa sequenza di byte in 0x5eec108. ok, questo è figo :)
Per favore fai riferimento a sub\_180002398.py per vedere il mio tentativo fallito di emulare questo comportamento :)
\=============================================================================
Figo, il prossimo?
<div>
<img src="https://assets.kitploit.com/production/public/readmes/44336/432ad1832fa35743bc5676f7f8362ad9e2043e17387121136a1f6dfe1bdf16f1.png" alt="1">
<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/aab798c5c80621b1c367ea6eecfff0d7caf9ecc368ae2fe2e947538e4f0e2b0c.png" alt=""><figcaption></figcaption></figure>
</div>
<div>
<img src="https://assets.kitploit.com/production/public/readmes/44336/f04ebd9c650ddadb5553e4f2c43c72af8a5ccbef372a4dbdc811600e9583b0c9.png" alt="1">
<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/3411e1620450739ea98f6db634346748487377106547324591b148cefe358df2.png" alt=""><figcaption></figcaption></figure>
</div>
Quindi quello che succede dopo è RaiseTPL. Ok, e cosa fa? Aumenta la priorità dell'attività attualmente in esecuzione e restituisce il suo livello di priorità precedente. Nel nostro caso verrà eseguita con i privilegi di esecuzione più alti.
Poi chiamiamo quella che ho chiamato patch\_something, che assomiglia a questo
<div>
<img src="https://assets.kitploit.com/production/public/readmes/44336/0a31b0c154406b340e9bb044c4211afd6494bcac6ec197c99a10a6d0effb6a31.png" alt="1">
<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/3fcff1b34a5d9af3cdd70e4dac1188abd3edd13e74d11e4f0bba5d667d4f53a1.png" alt=""><figcaption></figcaption></figure>
</div>
<div>
<img src="https://assets.kitploit.com/production/public/readmes/44336/c2f9bb8ca36961def04d4a3111a7d4213bb219949d13094b525a1a906ab788f7.png" alt="2">
<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/accdd93e3428b9b03132eafceda3ec5e1cfda742a978f1cd7f2c6bcf1904ceaa.png" alt=""><figcaption></figcaption></figure>
</div>
<div>
<img src="https://assets.kitploit.com/production/public/readmes/44336/e0f6c806d296e47269b9908ceab7b90954bbd219d3d9c13462ebee8344f854f3.png" alt="1">
<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/1ed164077989d04273ae3b40ec6daf7cf9b93ec42d917533b1e9758525231b7b.png" alt=""><figcaption></figcaption></figure>
</div>
Quindi dall'analisi statica possiamo vedere che questo è ciò che è noto come hooking. :) quindi fondamentalmente patcha i byte di ImgArchStartBootApplication per far puntare a sub\_180001D80 e salva la funzione originale di ImgArchStartBootApplication in byte\_180015C78
<div>
<img src="https://assets.kitploit.com/production/public/readmes/44336/6c48bf4c9126a9a1466493aed943113cc27b4bbf9f7d68cdd251d0e14303ad8a.png" alt="1">
<figure><img src="https://assets.kitploit.com/production/public/readmes/44336/633d84a62c16dba91229fe6bb73ed0318719fc06f63f7f2a9d19adba0d0e8cfe.png" alt=""><figcaption></figcaption></figure>
</div>
e come possiamo vedere, cambia esattamente in sub\_180001D80
poi resettiamo i privilegi e da lì passiamo il controllo a boomgrfw.efi :)
Quindi questo segna ufficialmente la fine della prima metà dell'analisi :) nella prossima parte impareremo come fare ulteriormente il debug di sub\_180001D80 e boomgrfw.efi (nel nostro caso winload.efi). Quindi per favore resta sintonizzato finché non imparo a preparare l'ambiente per la seconda parte dell'analisi
\=============================================================================
Ora per la seconda metà dell'analisi.... Come facciamo a fare il debug di boomgrfw.efi?