Skip to content
KitploitKITPLOIT
StrumentiBlog
Invia
StrumentiBlog
Invia

Strumenti di Hacking, PenTest e Cybersecurity per il tuo Arsenale di Sicurezza!

Kitploit è una directory di strumenti di hacking, cybersecurity e pentesting. Scopri gli ultimi aggiornamenti dei progetti per trovare vulnerabilità, analizzare sistemi, automatizzare i test e rafforzare la tua sicurezza.

··Feed·Contatto·Privacy·© 2026 Kitploit

Directory degli strumenti

Categorie

Vedi tutte le categorie
Loading categories
BlackLotus-Z2A-Challenge — BlackLotus-Z2A-Challenge, Niente da vedere qui per ora , per favore passa oltre | Kitploit
Strumenti/GitHubGitHub/spiralbl0ck/blacklotus-z2a-challenge
Analisi StaticaReverse EngineeringAnalisi MalwareCTFApprendimento e Formazione
GitHubspiralbl0ck/blacklotus-z2a-challenge

BlackLotus-Z2A-Challenge

BlackLotus-Z2A-Challenge, Niente da vedere qui per ora , per favore passa oltre

Vedi Repository

Più Popolari

Vedi tutti →

Scopri gli strumenti più utilizzati dalla nostra community.

Esplora tutti gli strumenti

Sfoglia la nostra collezione di strumenti

Vedi tutti gli strumenti →
Condividi
323 anni faNon ancora revisionato

BlackLotus-Z2A-Challenge

BlackLotus-Z2A-Challenge, non c'è niente da vedere per ora, per favore proseguite

Prima di tutto Capture23

Per scopi puramente estetici, prenderò in prestito (ruberò) :)) senza vergogna le regole di rilevamento yara dalla soluzione di @darthmaulware(Ryan “DM” Smith) solo per farlo sembrare professionale. Vai a dare un'occhiata al suo Twitter, è una persona fighissima! P.S. Ryan, per favore non ti arrabbiare perché l'ho rubato :))) e grazie per il supporto su Discord :)

Date un'occhiata anche al suo lavoro :)

https://gitlab.com/malre-rcs/zero2automated/-/blob/main/solutions/bi_weekly_challenge/BlackLotus_20230321/BlackLotus_HTTP_Downloader.ipynb``` rule Blacklotus_HTTP_Downloader { meta: description = "Rule to detect Blacklotus HTTP Downloader" author = "Darth Maulware" sha256 = "d68f668b4240f9518e4f80499d93d8c5a1eddece0771658c33ae916cc54f5a66"

root@kitploit:~
    strings:
        $opcode1 = {48 89 4C 24 08 48 89 54 24 10 4C}
        $opcode2 = {89 44 24 18 4C 89 4C 24 20 48 83}
        $opcode3 = {EC 28 B9 31 62 D7 2E 90 90 E8 ??}
        $opcode4 = {?? ?? ?? 48 83 C4 28 48 8B 4C 24}
        $opcode5 = {08 48 8B 54 24 10 4C 8B 44 24 18}
        $opcode6 = {4C 8B 4C 24 20 4C 8B D1 90 90}

    condition:
        (uint16(0) == 0x5a4d and filesize < 500KB and all of them)

}

root@kitploit:~
Anche per ragioni estetiche rubo anche questo perché è figo :) di nuovo scusa Ryan, per favore non arrabbiarti con me :)```
        C:\\Users\\REM\\Desktop>capa.exe -f pe -r capa-rules-5.0.0 d68f668b4240f9518e4f80499d93d8c5a1eddece0771658c33ae916cc54f5a66.exe
        matching: 100%|████████| 124/124 [00:02<00:00, 46.96 functions/s, skipped 1 library functions (0%)]

        +------------------------+------------------------------------------------------------------------------------+
        | ATT&CK Tactic          | ATT&CK Technique                                                                   |
        |------------------------+------------------------------------------------------------------------------------|
        | DEFENSE EVASION        | Obfuscated Files or Information T1027                                              |
        | DISCOVERY              | Process Discovery T1057                                                            |
        | EXECUTION              | Shared Modules T1129                                                               |
        +------------------------+------------------------------------------------------------------------------------+

        +-----------------------------+-------------------------------------------------------------------------------+
        | MBC Objective               | MBC Behavior                                                                  |
        |-----------------------------+-------------------------------------------------------------------------------|
        | ANTI-BEHAVIORAL ANALYSIS    | Debugger Detection::Process Environment Block BeingDebugged [B0001.035]       |
        |                             | Debugger Detection::Process Environment Block NtGlobalFlag [B0001.036]        |
        | CRYPTOGRAPHY                | Encrypt Data::RC4 [C0027.009]                                                 |
        |                             | Generate Pseudo-random Sequence::RC4 PRGA [C0021.004]                         |
        | DATA                        | Encode Data::XOR [C0026.002]                                                  |
        | DEFENSE EVASION             | Obfuscated Files or Information::Encoding-Standard Algorithm [E1027.m02]      |
        +-----------------------------+-------------------------------------------------------------------------------+

        +------------------------------------------------------+------------------------------------------------------+
        | CAPABILITY                                           | NAMESPACE                                            |
        |------------------------------------------------------+------------------------------------------------------|
        | execute syscall instruction (35 matches)             | anti-analysis                                        |
        | check for PEB BeingDebugged flag (2 matches)         | anti-analysis/anti-debugging/debugger-detection      |
        | check for PEB NtGlobalFlag flag                      | anti-analysis/anti-debugging/debugger-detection      |
        | encode data using XOR (2 matches)                    | data-manipulation/encoding/xor                       |
        | encrypt data using RC4 PRGA (2 matches)              | data-manipulation/encryption/rc4                     |
        | get process heap flags                               | host-interaction/process                             |
        | get ntdll base address (3 matches)                   | linking/runtime-linking                              |
        | parse PE header (2 matches)                          | load-code/pe                                         |
        | resolve function by parsing PE exports (2 matches)   | load-code/pe                                         |
        +------------------------------------------------------+------------------------------------------------------+

tbh se fossi in te non mi fiderei al 100% di capa (almeno in questo caso specifico) perché qui dice che il campione usa rc4 mentre in realtà usa aes, ma vabbè, come già detto questo è strettamente per estetica :)

Prima di iniziare, incontrerai durante questo report un sacco di

1

Per favore ignora questo perché ida non riesce a disassemblare correttamente in assembly; questo è

1

E questo crasha il debugger? Perché?

perché cerca di scrivere all'indirizzo 0, cosa che nel folklore hacker è nota come scrittura a un puntatore nullo, che era qualcosa di ampiamente sfruttato per ottenere CE (esecuzione di codice), ed è stato ovviamente mitigato.

E quindi con la mitigazione attuale, se provi a scrivere a 0, il processo crasha - nel nostro caso il malware - e di conseguenza anche il debugger.

Ora, se apriamo questo in ida

1

Ho rinominato ogni funzione per indicare una certa logica che svolge; iniziamo con la prima funzione, do_syscall() Capture23

Notiamo subito l'uso delle syscall, che è un metodo noto per rendere la vita più dura a un analista nell'analisi dinamica.

Per chi non ha familiarità con le syscall in Windows, ecco un bel video fatto da oalabs(https://www.youtube.com/watch?v=Uba3SQH2jNE). Per favore guardatelo perché l'ho fatto anch'io e mi ha aiutato molto a capire cosa succede in questa funzione.

Se ispezioniamo il "pseudo-codice" generato da ida, vediamo che appare così.

Capture4

Se ispezioniamo staticamente solve_hash, appare così.

1

2

Da una prospettiva pseudo, appare così.

4

Per favore fate riferimento a solve_hash.py per vedere la mia "emulazione" di questo, nel caso vogliate vedere un pezzo di automazione e scoprire come le syscall vengono risolte tramite l'algoritmo di lookup basato su hash. Ma comunque, questo fa parte di un progetto chiamato SysWhispers2, o almeno è ciò che presumo gli autori del malware abbiano usato come ispirazione. Ad ogni modo, fate riferimento al video di oalabs qui sopra per una migliore comprensione.

Comunque, la funzione anti_debug è facilmente bypassabile e ben nota(https://anti-debug.checkpoint.com/techniques/debug-flags.html#manual-checks-ntglobalflag). Il modo per bypassarla è avere scyllahide installato e l'opzione NtGlobalFlag spuntata(che dovresti avere attiva di default se usi x86dbg). Ad ogni modo, ecco cosa dovresti controllare:

4

E così appare la "pseudo-funzione" anti-debug:

4

Abbastanza semplice, se me lo chiedi.

Poi abbiamo la funzione check_inmemory_ldr, che appare così:

1

2

Ora, ai fini dell'analisi della funzione, se chiediamo gentilmente a x86dbg, possiamo vedere che se eseguiamo fino all'istruzione syscall, x86dbg sarà così gentile da restituirci la syscall che sta per eseguire. Nel nostro caso:

2

Ora, in base al contesto attuale, possiamo presumere che Ntsetinformationthread venga usata come una sorta di trucco anti-analisi. Sicuramente, se facciamo una rapida ricerca su Google, troviamo questo: https://ntquery.wordpress.com/tag/ntqueryinformationthread/

Fortunatamente è facilmente bypassabile, basta patcharlo con nop+ret :)

=============================================================================

Seguendo l'ordine di esecuzione, dopo questa prossima funzione c'è

4

Ancora una volta, se ispezioniamo per vedere cosa fa

Capture4

Controlla semplicemente un flag nel TEB per vedere se il processo corrente (l'exe nel nostro caso) è sotto debug. Anche questo è facilmente bypassabile, essendo un metodo noto(https://anti-debug.checkpoint.com/techniques/debug-flags.html#manual-checks-peb-beingdebugged-flag), nello stesso modo in cui abbiamo usato scyllahide; questa volta devi avere spuntata
Capturez

che dovrebbe essere attiva di default

=============================================================================

Ora, custom_hash2_and_aplib_possible, che appare così:

2

E da una prospettiva a grafo:

3

Per favore fate riferimento a decompress_aplib.py per vedere l'"emulazione" di questa funzione.

Esplorando get_ntdll_and_unhook2, appare così:

1

2

Da una vista a grafo appare così:

1

Non male :))

Facendo un passo indietro, abbiamo aplib_decompress, che ora appare così:

1

Da un'analisi statica del codice appare così:

1

2

3

4

Mhmm, un po' grande, ma niente di cui preoccuparsi, ragazzi, è fattibile :)

Se usi lo script di emulazione aplib_decompress.py, dovresti ottenere qualcosa del genere:

1

Una cosa figa che non ho notato in altri blog/analisi era questa: se diamo un'altra occhiata al pseudo-codice di ida per ntdll_and_unhook2

1

vedrai un memcpy interessante.

A un certo punto, mentre facevo l'analisi dinamica, ho notato un'altra dll caricata, che era un'altra versione di ntdll:

1

se guardiamo nel debugger, appare così:

1

Non sono riuscito a rilevare cosa fosse stato hookato/patchato, ma se qualcuno lo sa, per favore faccia una pull request e modifichi questo documento. Inoltre, nei miei tentativi di scoprire cosa viene hookato, ho provato a fare un bindiff tra le due ntdll e sfortunatamente non ho trovato nulla, ma potrebbe essere perché stavo già facendo il diff sulla dll di sistema che era infetta, quindi non era un'esecuzione pulita, quindi forse è per questo ¯_(ツ)_/¯

1

=============================================================================

Proseguendo con il processo di analisi, tra le funzioni non spiegate abbiamo some_hasing e ntquertyinformationprocess_anti_debug, che non sono state ancora spiegate. check_if_being_debug_through_teb e anti_debug sono già state spiegate, fortunatamente, perché sono state usate nella/e funzione/funzioni precedente/i, quindi per favore rileggete le sezioni precedenti se volete rivedere le conoscenze su di esse. Vorrei iniziare prima con ntquertyinformationprocess_anti_debug e poi finire con some_hasing.

Ispezionandola, vediamo la stessa funzione chiamata 3 volte.

1234

E da un punto di vista assembly:

1

2

Per comodità l'ho già nominata, cioè ntquertyinformationprocess_ProcessDebugPort. Da dove ho saputo che le funzioni chiamate erano ntquertyinformationprocess_ProcessDebugPort? Ispezionandole, si rivelano una chiamata di funzione già vista / algoritmi a noi noti:

1

E i commenti fatti in ida? Beh, se cerchi ntqueryinformationprocess su Google, troviamo una buona risorsa sull'anti-debug(https://anti-debug.checkpoint.com/techniques/debug-flags.html). Se la seguiamo, possiamo vedere che ci spiega che, in base a certi valori passati come parametri a questa funzione, può essere usata come metodo anti-debug.

Per esempio, per la prima chiamata possiamo vedere i seguenti argomenti di stack nel debugger:

1

Se ora andiamo a controllare la pagina MSDN per ntqueryinformationprocess:

1

Lo stesso processo si ripete per le due syscall successive:

2

dove 0x1e è specifico per il metodo anti-debug ProcessDebugObjectHandle(https://www.apriorit.com/dev-blog/367-anti-reverse-engineering-protection-techniques-to-use-before-releasing-software)

e infine ProcessDebugFlags

2

Quindi come li bypassiamo?! Calmati, fam, perché ScyllaHide ha le spalle coperte

obama-pew

Come puoi vedere

1

Quindi siamo al sicuro! Non proprio: mentre ScyllaHide ci copre le spalle per le prime 2 syscall, per l'ultima syscall dobbiamo farlo manualmente! E che diavolo faccio??? Beh, soluzione semplice! Ritorniamo da questa funzione, cioè dall'intera ntquertyinformationprocess_anti_debug, e impostiamo eax a 0. Quindi in circostanze normali appare così:

1

E con il nostro "aiuto" appare così e lasciamo proseguire l'esecuzione in sicurezza :)

1

=============================================================================

Ora, some_hasing: ormai conoscete la procedura.

1

E ora il pseudo-codice:

2

Notiamo una cosa strana qui. Il pseudo-codice di ida fallisce qui... perché se seguiamo il grafo dopo call_syscall ci sono altre istruzioni da disassemblare. Quindi cosa facciamo qui? Beh, faremo affidamento sul debugger per analizzare dinamicamente questo codice...

Quindi vediamo che la syscall che esegue è:

1

Ora, se cerchiamo ntquerydefaultlocale, Google mostra che è un'API non documentata che accetta 2 argomenti(http://undocumented.ntinternals.net/index.html?page=UserMode%2FUndocumented%20Functions%2FLocale%2FNtQueryDefaultLocale.html). Figo, quindi cosa fa? Restituisce l'identificatore di locale corrente. Figo, e allora che diavolo è un identificatore di locale? Da MSDN (https://learn.microsoft.com/en-us/windows/win32/intl/locale-identifiers): un valore a 32 bit composto da un identificatore di lingua e un identificatore di ordinamento. In sintesi, che lingua parli su quel PC :)

Successivamente controlla se l'API non ha fallito e, se non è fallita, prende il valore restituito da ntquerydefaultlocale, sottrae 0x419 e lo confronta con 0x26 (probabilmente una costante), come puoi vedere nell'immagine qui sotto.

1

Se non è minore o uguale a 0x26, lo confronta con 0x818, altrimenti fa lo stesso confronto con 0x819, come puoi vedere chiaramente.

2

Quindi che diavolo sta succedendo qui? E perché queste costanti specifiche? Beh, vado dritto al punto. Mentre cercavo diverse costanti, mi sono imbattuto in questo articolo(https://www.cnblogs.com/DirWang/p/17281690.html#autoid-8-0-0), di un ricercatore che ha già analizzato blacklotus meglio di quanto potrei fare io. E come disse qualcuno una volta: "Non puoi imbrogliare nell'analisi di malware, puoi solo rendere il tuo lavoro più facile". Quindi quello che ha detto il ricercatore è che fondamentalmente questa funzione controlla costanti specifiche che identificano quale lingua è parlata sul computer. Nel suo articolo fornisce un link a questo(https://winprotocoldoc.blob.core.windows.net/productionwindowsarchives/MS-LCID/[MS-LCID].pdf) che è come un documento standard Microsoft con tutti gli identificatori di lingua.

Ora, usando la nostra logica hax00r l33t, possiamo dedurre che probabilmente 0x26 è una specie di offset usato, quindi tipo qualsiasi identificatore di lingua successivo a 0x419 entro 0x26, che sono:

2

Se ispezioniamo anche quel documento, possiamo vedere che 0x818 corrisponde a:

2

e 0x819 a:

2

E sappiamo da precedenti "indagini"/report online che questo malware non girava su certi PC di certe regioni del mondo, quindi possiamo concludere che questa funzione controlla su quale regione si trova la macchina infetta.

=============================================================================

Che hamburger pazzesco finora, fam, e adesso? Serviamo la funzione some_more_syscall. Va bene! Allora cosa hai lì, ack! Eccola:

1

Ne vogliamo ancora! Certo, dawg!

2

3jgukd

1

Hmmmm

1

Quindi controlla se kerneldebugger è presente(https://www.geoffchappell.com/studies/windows/km/ntoskrnl/inc/api/ntexapi/system_information_class.htm)(0x23), controlliamo, controlliamo!

E quindi, ack! Abbiamo pcr (festa di pile e combinazioni)

2

=============================================================================

Ora, se ispezioniamo la funzione iterate_over_modules(), appare così:

1

Da una prospettiva "pseudo-codice" appare così:

2

Dal punto di vista autonomo, sembra che l'assembly e il pseudo-codice di ida corrispondano; quindi qual è la logica di questa funzione? Beh, abbastanza semplice: itera sui moduli in memoria (dll) e verifica una lista di hash :) v4[0] = 0x1E7EACEF; v4[1] = 0x4468A620; v4[2] = 0x68536B95; v4[3] = 0x73EBBB53; v4[4] = 0xDA165168; v4[5] = 0xB24D33A7; v4[6] = 0xB1E2CEC6; v4[7] = 0x5136992; v4[8] = 0x98C500D9; v4[9] = 0x3E0169B6;

E se nessuna dll in memoria risulta avere lo stesso hash, restituiamo 0, altrimenti 1 e facciamo crashare il debugger. Quindi, con questa conclusione, possiamo dire che è un altro metodo anti-analisi. Corretto, ma riguardo a ciascuno dei valori di hash? Beh, imbroglierò di nuovo (come disse qualcuno una volta, non puoi imbrogliare nell'analisi di malware, solo rendere la tua vita più facile :) ). Il ricercatore asiatico summenzionato è stato così gentile da fornirci una lista di valori da cui sono stati derivati i valori:

sbiedll.dll dbghelp.dll api_log.dll dir_watch.dll pstorec.dll vmcheck.dll wpespy.dll cmdvrt64.dll avghookx.dll snxhk.dll

Ora, per vedere dinamicamente se alcuni valori corrispondono a una delle dll menzionate:

2

E certo che corrispondono :)

Ma come sono arrivato alla conclusione che l'algoritmo verifica questi valori? Beh, quando ho emulato un pezzo di questo malware, ho dovuto reimplementare iterate_over_module_name_and_hash (nel file solve_hash_syscalls.py) e in questa funzione abbiamo:

1

dove x (argomento passato) in questo caso è v2, che è un array (un puntatore) di valori che viene incrementato (dove punta nell'array) finché non corrisponde a nessuno dei valori già menzionati sopra. Accidenti, è un bel boccone :P

Figo! Prossimo

=============================================================================

iterate_over_modules2, più o meno stessa storia qui:

1

E pseudo-codice:

2

Più o meno stessa storia, solo hash diversi :)

v5[0] = 0x7D73878E; v5[1] = 0xEF36424B; v5[2] = 0xAF64BC2B; v5[3] = 0x1DBBC879; v5[4] = 0xAE6D1D56; v5[5] = 0x7B3242F2; v5[6] = 0x14D922B9; v5[7] = 0x4C92DF53;

che corrispondono a:

sample.exe bot.exe sandbox.exe malware.exe test.exe klavme.exe myapp.exe testapp.exe

=============================================================================

iterate_over_modules3, stessa storia qui:

1

E pseudo-codice:

2

stessa storia, hash diversi :)

=============================================================================v4[0] = 0x42D12D59; v4[1] = 0xEC5D7AA; v4[2] = 0x861E460F; v4[3] = 0x84BCC8DB; v4[4] = 0x6474D72B; v4[5] = 0xB8B9C504; v4[6] = 0x69A0620E; v4[7] = 0x6017EE43; v4[8] = 0xE93BE2E0; v4[9] = 0x149EFC55; v4[10] = 0xE3FA84A4; v4[11] = 0x7CFDD7AF; v4[12] = 0x5B098C67; v4[13] = 0x2F1FB18E; v4[14] = 0xFE8F2B18;

che corrispondono a

prl_cc.exe prl_tools.exe qemu-ga.exe vmtoolsd.exe vmwaretray.exe vmwareuser.exe VGAuthService.exe vmacthlp.exe vboxservice.exe vboxtray.exe VMSrvc.exe VMUSrvc.exe xenservice.exe

=============================================================================

Anti_debug_measure_1: ho finito per rinominarlo in anti_debug_measure2_RtlAddVectoredExceptionHandler_int3. Perché? Lo vedrete tra un minuto. Quindi appare così

1

E da una prospettiva di pseudo-codice appare così

1

Allora che diavolo è questo? Beh, fondamentalmente crea un gestore di eccezioni per __debugbreak(int 3) che eseguirà codice ogni volta che viene sollevata una int3. Ho finito per cercare altro e mi sono imbattuto in questo

(https://blog.lexfo.fr/dridex-malware.html) che è una bella risorsa che ci fa capire che questo è semplicemente un meccanismo anti-debug, e nel nostro caso ci basta eseguire questa funzione e ignorare sub_13F2820D0 che

viene attivato ogni volta che eseguiamo int3 e patchiamo eax a 0 :) quindi in memoria l'esecuzione appare così :)

Prima della patch

1

Dopo la patch

1

Dopodiché esci dalla funzione e modifichi anche rax/eax a 0 in modo da saltare il jne che farebbe crashare il debugger

1

=============================================================================

Anti_debug_measure_2 che in seguito ho cambiato in anti_debug_measure2_RtlAddVectoredExceptionHandler_int2

1

2

Di nuovo, niente di nuovo sotto il sole: stessa cosa, solo che aggancia un altro int/syscall, questa volta int2. Stesso trucco per bypassarlo: usare il patching dinamico del valore di ritorno per superarlo :)

Se cerchi su Google "anti analysis 2dh" apparirà un sacco di roba, quindi sì, puoi usarla come riferimento per saperne di più. Non ci ho passato molto tempo :)

Per questo, anche se provi a fare step over, finirai comunque alla ret come qui

1

e per bypassarlo basta eseguire fino al return e sei a posto :)

=============================================================================

Quindi ora arriva anti_debug measure heap, che in seguito ho rinominato in iterate_over_current_process_and_check_again_hases

1

E una caratteristica interessante di questa funzione è che usa ntquerysysteminformation all'interno di iterate_over_current_process_and_hash_check per elencare tutti i processi in esecuzione. Ecco come appare iterate_over_current_process_and_hash_check

1

2

Fico, ma come diavolo sono arrivato alla conclusione che iterate_over_current_process_and_hash_check fa ciò che il nome suggerisce? Beh, prima di tutto c'è la chiamata a ntquerysysteminformation, che se cerchi su Google vedrai che viene usata per ottenere la lista dei processi in esecuzione, e poi ho semplicemente fatto un'ipotesi basata sul seguente snippet di codice LODWORD(v4) = RtlAllocateHeap(NtCurrentPeb()->ProcessHeap, 8u, v10); v3 = v4; v5 = ntquerysysteminformation(); v6 = v3; .... memcpy(v9, v6[8], *(v6 + 28)); v9[*(v6 + 28) >> 1] = 0; if ( some_hash_0x1003F(v9) == a1 ) e cioè che copiasse la lista dei processi, iterasse su ciascuno e confrontasse ogni hash dell'array precedente con qualunque processo fosse in esecuzione. Di nuovo, complimenti al blog di ricerca dell'asiatico, perché non so come diavolo abbia fatto a ottenere il nome effettivo dei valori dell'array v4. Fare riferimento a iterate_over_modules.py nel caso vogliate vedere come ho emulato tutto questo.

Ps. se esegui il debug dinamico di questa funzione, finirai di nuovo su int 2d, e la soluzione è la stessa menzionata sopra, solo che in pratica esegui fino al return 0xf volte, il che sostanzialmente attraversa l'hev e dopo, se vuoi essere sicuro di arrivare al return da iterate_over_current_process_and_check_again_hases, metti un breakpoint alla fine di questa funzione e sei al sicuro :)

============================================================================= anti_debug_measure_heap

1

2

1

Quindi sì, siamo fortunati che non sia così grande, e inoltre abbiamo già implementato demangle_strings. Ora l'ho reimplementato per array più grandi: andate a vedere anti_debug_measure.py .

questo fondamentalmente confronta con``` \Registry\Machine\SOFTWARE\Microsoft\Virtual Machine\Guest\Parameters \Registry\Machine\SYSTEM\ControlSet001\Services\vioscsi \Registry\Machine\SYSTEM\ControlSet001\Services\VirtIO-FS Service \Registry\Machine\SYSTEM\ControlSet001\Services\VirtioSerial \Registry\Machine\SYSTEM\ControlSet001\Services\BALLOON \Registry\Machine\SYSTEM\ControlSet001\Services\BalloonService \Registry\Machine\SYSTEM\ControlSet001\Services\netkvm \Registry\Machine\SOFTWARE\VMware, Inc.\VMware Tools \Registry\Machine\HARDWARE\ACPI\DSDT\VBOX__ \Registry\Machine\HARDWARE\ACPI\FADT\VBOX__ \Registry\Machine\HARDWARE\ACPI\RSDT\VBOX__ \Registry\Machine\SOFTWARE\Oracle\VirtualBox Guest Additions \Registry\Machine\SYSTEM\ControlSet001\Services\VBoxGuest \Registry\Machine\SYSTEM\ControlSet001\Services\VBoxMouse \Registry\Machine\SYSTEM\ControlSet001\Services\VBoxService \Registry\Machine\SYSTEM\ControlSet001\Services\VBoxSF \Registry\Machine\SYSTEM\ControlSet001\Services\VBoxVideo

root@kitploit:~
Ora get_oem_key

![1](https://assets.kitploit.com/production/public/readmes/44337/2a188d30cf6be94954d1432a2928bc11c0546da19b9092e5dfc7d2c195e47d54.png)

![2](https://assets.kitploit.com/production/public/readmes/44337/aa44c5cb77b983c38dfa6be61b9ed0482df4082a81ebe73c7f295dd43844669f.png)

![3](https://assets.kitploit.com/production/public/readmes/44337/6227b500e17378e4f4682e86ce1928898be52b0781b496156ce8a975f4ae1226.png)

![4](https://assets.kitploit.com/production/public/readmes/44337/67227ce4e2999496337e5894b1990937f519ebf72574d20532e6ea9a2170f864.png)

![5](https://assets.kitploit.com/production/public/readmes/44337/82fa372a01bbc8dba4d2dec1b0a0ca46836c9c9cd514aecb8637ebcfd6059435.png)

![1](https://assets.kitploit.com/production/public/readmes/44337/24973f6832bf4752014bfe5f77dbc75b2a5254e5ed809b980f98803d35464824.png)

![2](https://assets.kitploit.com/production/public/readmes/44337/b976c0dad1e2b872649a6df1b61d19b220863b0cb770feb5caa92c93ffa9bad7.png)

Prima esegue il demangling della stringa in```
 \Registry\Machine\HARDWARE\DEVICEMAP\Scsi\Scsi Port 0\Scsi Bus 0\Target Id 0\Logical Unit Id 0
 \Registry\Machine\SYSTEM\ControlSet001\Control\SystemInformation
 \Registry\Machine\HARDWARE\Description\System
 Identifier
 SystemManufacturer
 SystemBiosVersion
 VMWARE
 QEMU
 VBOX

E poi interroga
\Registry\Machine\HARDWARE\DEVICEMAP\Scsi\Scsi Port 0\Scsi Bus 0\Target Id 0\Logical Unit Id 0 \Registry\Machine\SYSTEM\ControlSet001\Control\SystemInformation \Registry\Machine\HARDWARE\Description\System

e confronta i loro valori con qemu, vbox, VMWARE, come si può vedere nello snippet di IDA e nella finestra x86 :)

1

2

Come si può vedere nel primo snippet, controlla vmware rispetto ai valori memorizzati nella mia VM al momento dell'analisi :)

Niente di che: basta eseguire questa funzione fino a ret e cambiare eax quando ritorna a 0 :) per bypassare questo metodo anti-analisi :)

=============================================================================

ora get_oem_from_firmware

1

2

3

4

5

Ora qualcosa di interessante: vediamo che questa funzione inizia con sub_13F267288() a cui viene passato 0x52534D42 come parametro. Se cerchi questo valore su Google, troverai molte domande interessanti su vari forum, ad esempio (https://ru.stackoverflow.com/questions/778618/c-%D0%9A%D0%B0%D0%BA-%D0%B4%D0%BE%D1%81%D1%82%D0%B0%D1%82%D1%8C-%D0%B8%D0%BD%D1%84%D0%BE%D1%80%D0%BC%D0%B0%D1%86%D0%B8%D1%8E-%D0%BE%D0%B1-%D1%83%D1%81%D1%82%D1%80%D0%BE%D0%B9%D1%81%D1%82%D0%B2%D0%B0%D1%85-%D0%BA%D0%BE%D0%BC%D0%BF%D1%8C%D1%8E%D1%82%D0%B5%D1%80%D0%B0-%D0%BD%D0%B5-%D0%B8%D1%81%D0%BF%D0%BE%D0%BB%D1%8C%D0%B7%D1%83%D1%8F-wmi) (https://msdn-whiteknight.github.io/answers/html/tools/html/ru.stackoverflow.com/posts/780170.html) (https://www.maldun.com/analysis/YXNkZmRzZmFkc2Y2NDEwNjlkc2Zhc2RmYXNkZg==/) oppure questo (https://github.com/digitalocean/go-smbios/blob/master/smbios/stream_windows.go), ma la cosa più interessante è che dopo aver letto questo e aver cercato RSMB potresti imbatterti in questo https://evasions.checkpoint.com/techniques/firmware-tables.html che ci spiega che questo è un metodo anti-analisi :) Figo, quindi che cazzo fa?

Prima effettua il dump della tabella firmware SMBIOS, poi demangla una stringa, la prima stringa è qemu, e quindi chiama sub_13F2655E0 con come parametri la stringa demanglata e la tabella firmware. Dall'analisi statica

1

2

precisamente, per via di if ( v4 != v5), sono giunto alla conclusione che questa è una specie di implementazione di strcmp: controlla ciò che c'è nella tabella firmware con la stringa demanglata. Come si può vedere nel debugger

1 r8 è un puntatore alla tabella firmware e, cosa più interessante, possiamo vedere che blah blah qualcosa... virtualbox è il nome trovato nella tabella firmware, mentre rcx è qemu, quindi possiamo tranquillamente dire che è una specie di implementazione di strcmp. E sicuramente, come si può vedere, siamo al sicuro :) per questo controllo

1

Ora questo processo si ripete per le stringhe VirtualBox, vbox, VBOX, VMware :) In generale, la soluzione per bypassare il controllo di questa funzione è eseguirla fino a ret, applicare una patch a eax e continuare l'analisi :)

============================================================================

Bene, ora check_oem_key()

1

2

3

1

2

3

Quindi che cazzo fa? Beh, stesso trucco spiegato in precedenza, ma questa volta con la tabella ACPI. Cosa intendo? Beh, meglio leggere queste 14 slide (https://dc4420.org/slides/2015-11-24/acpi_vm_detect.pdf), la spiegano meglio, ma è lo stesso trucco economico :)) questa volta contro BOCHS, BXPC, VMWARE

1

2

============================================================================

Voglio iniziare con la funzione anti_debug_processor_Timing() e poi finire con check_for_flags(). Quindi

1

Ecco come appare. Quindi che cazzo fa? Legge il valore corrente del time-stamp del processore, poi prende il nome del processore (nel nostro caso GenuineIntel), poi sottrae il time-stamp ottenuto dal nome del processore e infine controlla semplicemente se il risultato è maggiore di 19999.

Dopo rdtsc

1

dopo cpuid

1

Come si può vedere, la stringa è divisa su 3 registri

1

E nel nostro caso vediamo che "falliamo" questo controllo e impostiamo eax a 1

1

La soluzione a questo anti-controllo è semplicemente tornare dalla funzione e applicare una patch a eax impostandolo a 0 :)

============================================================================

Ora entry_to_peb()

1

2

3

4

5

6

7

Da una prospettiva di pseudo-codice

1

2

3

Quindi, fino al controllo if non c'è niente di nuovo: abbiamo già visto questo tipo di algoritmo, quindi che succede? Beh, se vai al write-up già citato della ricerca asiatica, vedrai che dice che controlla se la versione di Windows è più recente di Win7/Server 2008 R2. Ma come gli è venuta quest'idea? Beh, se leggiamo http://waleedassar.blogspot.com/2012/08/major-minorsubsystemversion.html dice

1

inoltre, se leggete anche questo :)

https://reverseengineering.stackexchange.com/questions/26157/how-to-show-kuser-shared-data-members-in-decompiled-c-code

e applicate ciò che dice qui, cioè che viene automaticamente castato alla struttura KUSER_SHARED_DATA, ma qui la mia IDA era buggata durante l'analisi, quindi è quel che è :)

Per non annoiarvi con la stessa ripetizione di più o meno lo stesso algoritmo, ecco le stringhe finali recuperate e demanglate delle funzioni :) È stato un processo estenuante, visto che è stato fatto con un debugger :) ero troppo pigro per emularlo.``` user32.dll advapi32.dll Rpcrt4.dll bcrypt.dll ole32.dll Cabinet.dll

CreateWindowExW
ShutdownBlockReasonCreate
ShutdownBlockReasonDestroy
DestroyWindow CloseHandle
CreateProcessW InitializeProcThreadAttributeList
UpdateProcThreadAttribute LoadAppInitDlls Sleep
GetExitCodeProcess
MoveFileExW
OpenSCManagerW OpenServiceW
QueryServiceStatus
StartServiceW
CloseServiceHandle
GetUserNameW
ConvertSidToStringSidW
LookupAccountNameW
CreateWellKnownSid
LookupPrivilegeValueW
ConvertStringSecurityDescriptorToSecurityDescriptorW
RpcStringBindingComposeW
RpcBindingFromStringBindingW
RpcStringFreeW RpcBindingSetOption
RpcBindingSetAuthInfoExW
RpcBindingFree
NdrClientCall2
NdrClientCall3
BCryptOpenAlgorithmProvider
BCryptSetProperty
BCryptGenerateSymmetricKey
BCryptDecrypt
BCryptDestroyKey
BCryptCloseAlgorithmProvider
BCryptGetProperty BCryptGenRandom
CoCreateInstance
CoInitializeEx
CoUninitialize CoInitializeSecurity
CoSetProxyBlanket
if >win7/server 2008 r2 { CreateDecompressor
CloseDecompressor Decompress
}

root@kitploit:~
E con questo si segna la fine della prima metà della sfida di analisi blacklotus. 

============================================================================

Per la seconda metà

Prospettiva assembly

![1](https://assets.kitploit.com/production/public/readmes/44337/f509798bf72f72025531efc98bbd0a850e571d003e3a39b7ac2e6438d1da93c8.png)

Prospettiva pseudo-codice

![1](https://assets.kitploit.com/production/public/readmes/44337/23fafc5104114ff3d2086230e1be3d9b2dbe1660120b55ad100af0c8a12baec5.png)

Inizieremo la dissezione con la funzione some_hash()

============================================================================

Prospettiva grafico

![1](https://assets.kitploit.com/production/public/readmes/44337/2c8d738be9b2f025155521050ba0ea68aaeebd7cf3bd9a5c4fcd122c24722712.png)

Prospettiva assembly

![1](https://assets.kitploit.com/production/public/readmes/44337/04fb6139172c8f4fab8898395d505ad40b8ba52051ca387a2ec93ffe56ff8674.png)

![2](https://assets.kitploit.com/production/public/readmes/44337/7133eb6348241a56009a6a0d1ce87c26a840bbbc2da99bd459b40c8f5654d366.png)

![3](https://assets.kitploit.com/production/public/readmes/44337/1f60aef395eccf029138d3ca7bcbccafd5328b5056bcae635deabadb8005e2c0.png)

Prospettiva pseudo-codice

![1](https://assets.kitploit.com/production/public/readmes/44337/3ae95f232939daab4e4b2b68fa31d94150b4e9b69abd0cd324e5ecc4f8ffe14b.png)
Scarica lo strumento