Guide du débutant des Hackers Russes // traduit en français !

Read Time:62 Minute, 30 Second

Le 27 février 2022, une personne ayant un lien avec le célèbre groupe de cyber-extorsion ‘Conti’, a divulgué une mine d’information.
En effet, il a mis en ligne les conversations internes de Conti après que le  groupe de Ransomware  a annoncé qu’il se rangerait définitivement du côté de la Russie dans sa guerre contre l’Ukraine


Ici, je vais vous présenter le fameux guide du débutant, traduit en français, qui est distribué aux nouvelles recrues.
Les APT Chinois utilisent aussi beaucoup RouterScan et tous utilisent cette CVE contre Linux


Bonne lecture à tous.

DÉMARRAGE RAPIDE SUR LES TECHNIQUES CACHÉES, D'INTRODUCTION ET DE PROTECTION DANS WINDOWS


               INTRODUCTION


Il convient de rappeler qu'aucune des techniques de défense ou d'attaque envisagées n'est absolue.
Il existe des contre-mesures pour chacunes.
Certaines techniques sont utilisées malgré leur obsolescence car :
- garanti de fonctionner sur les anciens systèmes d'exploitation, il y en aura toujours beaucoup;
- rien n'a été inventé à la place.

En parallèle de ce manuel, il est recommandé de lire la série d'articles "Malware development" sur le blog https://0xpat.github.io

               I. TECHNIQUES DE CACHÉ ET D'INTRODUCTION

Windows vous permet de manipuler des processus dans une très large gamme,
en raison de la présence d'un ensemble d'appels système CreateRemoteThread(), ReadProcessMemory(), WriteProcessMemory().
Le but de ces appels est d'assurer le travail des débogueurs (il s'ensuit logiquement que de tels mécanismes sont disponibles dans tous les systèmes d'exploitation, vous permettant de déboguer un processus tiers.

Linux en a aussi : voir ptrace,
https://habr.com/post/430302/
https://github.com/gaffe23/linux-inject
https://www.evilsocket.net/2015/05/01/dynamically-inject-a-shared-library-into-a-running-process-on-androidarm/).

Technique d'injection intéressante sans ptrace : https://github.com/DavidBuchanan314/dlinject

Un injecteur simple pour Linux : https://stackoverflow.com/questions/24355344/inject-shared-library-into-a-process


Par conséquent, l'introduction dans d'autres processus et leur manipulation (dans la limite des droits d'accès) est une question de technique.

1. INJECTION DANS LE PROCESSUS

L'injection de processus est nécessaire pour exécuter du code dans un processus étranger du même utilisateur, dans une situation où vous avez déjà accès au système.
Les cibles classiques sont les navigateurs (intercepter et remplacer le trafic pour mettre en œuvre une attaque MITM), les messageries instantanées, les clients de messagerie, etc.
La séquence d'appel ressemble à ceci :

OpenProcess - ouvre le processus de quelqu'un d'autre
VirtualAlloc - allouer de la mémoire dedans
VirtualProtect - autorise l'exécution de cette mémoire
WriteProcessMemory - écrivez votre shellcode dans cette mémoire
CreateRemoteThread - exécute le shellcode en tant que nouveau thread

Si le shellcode est court et écrit avec un adressage relatif, c'est généralement suffisant.
Mais c'est un cas rare, un tel code est généralement écrit en assembleur.
Le plus souvent, vous devez exécuter de gros morceaux de logique, conçus comme des dll.
Pour exécuter une dll dans un processus étranger, cette dll doit être copiée dans la mémoire de quelqu'un d'autre,
et configurez-le - enregistrez toutes les importations, configurez les adresses f-th, etc.
Dans la vie normale, cela est fait par la fonction LoadLibrary.
Mais c'est une fonction très visible qui accède également au disque.
L'injection de mémoire entièrement sans disque est implémentée par deux bibliothèques :

https://github.com/stephenfewer/ReflectiveDLLInjection
https://github.com/dismantl/ImprovedReflectiveDLLInjection

La deuxième bibliothèque n'est qu'une amélioration par rapport à la première :
- travaux d'injection cross-bit (32->64, 64->32, 32->32, 64->64)

Il est important que l'implémentation ait un chargeur injectable qui n'utilise que l'adressage relatif.
L'injection se passe ainsi :
- le chargeur de démarrage est écrit sur un morceau de mémoire
- la dll est écrit dans un autre morceau de la mémoire
- le contrôle est transféré au chargeur
- le chargeur recherche dans la table d'import les fonctions LoadLibrary et GetProcAddress par hachage de leurs noms
- le chargeur recherche la dll en mémoire et la configure
- après configuration, le loader transfère le contrôle à DllMain

Cette technique peut être améliorée en changeant le bootloader injectable en externe:
- il sera exécuté à partir du processus d'attaque, pas de l'intérieur de celui attaqué
- il faut remplacer toutes les fonctions de travail avec mémoire par WriteProcessMemory/ReadProcessMemory.
Le code source de l'implémentation finale n'a pas encore été trouvé sur le réseau, mais il existe une telle implémentation dans la nature.

DLL de chargement réfléchissant dans son propre processus : https://github.com/fancycode/MemoryModule

Téléchargement réfléchissant de niveau 80 : https://github.com/bats3c/DarkLoadLibrary/blob/master/DarkLoadLibrary/src/ldrutils.c
https://www.mdsec.co.uk/2021/06/bypassing-image-load-kernel-callbacks/
Un contournement des déclencheurs nucléaires pour le chargement d'une image en mémoire est annoncé, bien que la différence avec le chargement réfléchissant ne soit pas très claire
(UPD : ils signalent que l'entrée du module ne rentre pas dans PEB)

De plus, l'exécution d'un shellcode arbitraire dans le contexte du processus en cours :
https://github.com/DimopoulosElias/SimpleShellcodeInjector/blob/master/SimpleShellcodeInjector.c


2. INTERCEPTION DES FONCTIONS (HOOKIES)

Technique connue depuis des décennies :
- dans le prologue de la plupart des fonctions du système, il y a plusieurs nop (jusqu'à 5) fournis spécifiquement à cet effet
- la fonction prologue est remplacée par jmp avec notre handler
- le gestionnaire appelle la fonction d'origine par décalage de prologue après nop (ou n'appelle pas - dépend de la logique)

Pour que tout fonctionne sans erreur, la signature de notre fonction de gestionnaire doit correspondre parfaitement aux types de données, convention de retour et d'appel.

S'il n'y a pas de prologue spécial, le crochet peut toujours être mis - pas toujours. Vous devez regarder le contenu du prologue.
Les instructions jmp simplement écrasées doivent être copiées et transférées dans le corps d'un nouveau gestionnaire - mais il existe une approche créative,
Et il n'y a pas de recettes universelles.

Le compilateur Microsoft a un commutateur : Propriétés du projet -> C/C++ -> Génération de code -> Créer une image avec mise à jour
(image patchable) spécifiquement dans le but de générer des prologues de fonction vides.

Ce crochet est aussi appelé tremplin, détour ou crochet en ligne.

Dans l'article "Trampolines In x64" https://www.ragestorm.net/blogs/?p=107 vous pouvez voir les variations de trampoline.

Dans cet article https://www.malwaretech.com/2013/10/ring3-ring0-rootkit-hook-detection-22.html
plusieurs types de crochets sont écrits (y compris dans ring0) - crochets IAT, crochets en ligne, crochets SSDT, crochets SYSENTER_EIP, crochet de fonction majeure IRP


3. PROCESSUS DE CREUSEMENT

Process Hollowing (alias RunPE) est l'implémentation Windows de la paire d'appels système Unix fork()/exec(). 
C'est-à-dire lancer le processus et remplacer son texte par un autre module exécutable, le configurer dans la mémoire de processus et le lancer à partir du point d'entrée.
Sous Windows, au lieu de fork()/exec(), CreateProcess() est utilisé, qui fait à la fois fork() et exec() en même temps.
Il y a un remplacement du texte du processus, que nous ne pouvons pas contrôler.
Par conséquent, la mise en œuvre du remplacement de texte, des paramètres d'importation et des déplacements doit être effectuée par vous-même, ce qui est assez difficile et duplique essentiellement le chargeur système des processus du système d'exploitation Windows.

Les avantages de cette astuce sont :
- notre code ressemble à un autre processus
- un autre processus peut être un processus de système d'exploitation de confiance (explorer, svchost),
ajouté aux exceptions UAC, pare-feu et antivirus.

Une implémentation détaillée est disponible sur
https://github.com/m0n0ph1/Process Hollowing

Les antivirus reconnaissent le creux de processus en comparant le texte du processus en mémoire et sur disque.

Implémentation en VBScript, à utiliser dans les macros dropper :
https://github.com/itm4n/VBA-RunPE

4. PROCESSUS DOPPELGING

Le but de la technique est le même - masquer le nom du véritable processus en cours d'exécution.
L'essence de la performance est différente.

- une transaction NTFS est ouverte pour écrire dans un fichier exécutable. Comme d'habitude, ça va
l'un des processus de confiance - svchost, explorer, etc.
- Le corps .exe est remplacé par notre texte
- le processus est lancé
- la transaction est annulée. Il n'y a pas d'écriture physique dans le corps du fichier.

Pour tous les autres processus, il semble que le fichier d'origine est en cours d'exécution.
Mais le thread qui a ouvert la transaction voit le nouveau texte dans le fichier en cours de lancement.

La technique est devenue obsolète, car à partir de certaines versions de Windows 10, les transactions NTFS semblent avoir été complètement annulées.

La mise en œuvre est disponible sur
https://github.com/hasherezade/process_doppelganging/blob/master/main.cpp

Descriptif en anglais :
https://hshrzd.wordpress.com/2017/12/18/process-doppelganging-a-new-way-to-impersonate-a-process/

Il existe un combo de deux techniques :
Process Doppelgänging combo Process Hollowing
https://blog.malwarebytes.com/threat-analysis/2018/08/process-doppelganging-meets-process-hollowing_osiris/
Evidement transactionnel
https://github.com/hasherezade/transacted_hollowing

4.1. PROCESSUS HERPADERPING

https://jxy-s.github.io/herpaderping/
https://github.com/jxy-s/herpaderping.git

La technique est similaire à Process doppelganging :
- le texte réel du programme est écrit dans un fichier et CreateProcess est lancé
- avant le début du flux réel, le texte est écrasé par du bruit (par exemple, le texte du programme hôte)
- utilisé la condition de concurrence dans Windows Defender pour y glisser le texte de gauche du programme


5. REMPLACEMENT DU PEB

Une technique légère pour cacher le processus après coup.
PEB est un Process Environment Block, une structure avec des informations de base sur le processus, présentes dans chaque processus.
Il contient notamment le nom du processus et sa ligne de commande. Ils peuvent être remplacés à la fois de l'intérieur du processus et de l'extérieur
(en suspendant les threads du processus avec SuspendThread(), en remplaçant les données par WriteProcessMemory() et en reprenant les threads
en utilisant ResumeThread()). Après cela, le nom du processus modifié et la ligne de commande sont visibles dans la liste des processus.

Une autre astuce intéressante consiste à écraser la table d'exportation .dll après le chargement en mémoire.
Après avoir obtenu les adresses de toutes les adresses de fonction nécessaires, il est possible d'écraser l'ensemble de l'exportation et ainsi
compliquer l'identification des processus par des noms de fonction connus/uniques.

De plus, il est possible d'écraser une section avec des ressources si elles ne sont pas utilisées (ou après qu'elles ont été chargées).
En un mot, les variations avec la substitution et l'écrasement des tables / zones de service ne sont limitées que par la fantaisie.

6. CODE COQUE

Le nom vient des temps anciens, lorsque le code injecté était conçu pour obtenir un shell distant sur la machine attaquée.
Par conséquent, le code devait satisfaire aux exigences :
- être le plus concis possible (pour écraser le moins possible dans le processus attaqué)
- être indépendant de la position (seulement adressage relatif)

Par code shell, on entend aujourd'hui toute insertion de code machine, quel que soit le contexte d'utilisation.
Cependant, le contexte typique est toujours une injection dans le processus, par exemple grossièrement dans un morceau d'un thread exécutable (pour contourner DEP).
Les exigences ci-dessus sont donc valides.

Un code shell typique pour les processus Windows effectue un démarrage (y compris pour contourner l'ASLR) :
- définit les jalons importants en mémoire - pointeurs vers TEB et PEB
- de PEB récupère l'adresse de la table d'import
- obtient l'adresse de kernel32.dll à partir de la table d'importation
- de kernel32.dll reçoit les adresses LoadLibrary, GetProcAddress (généralement par le hachage du nom, pas par le nom lui-même)
- lorsqu'il y a LoadLibrary et GetProcAddress, vous pouvez tout faire.
https://habr.com/ru/post/522966/
http://www.hick.org/code/skape/papers/win32-shellcode.pdf
(Ce mec http://www.hick.org/~mmiller/ a d'ailleurs beaucoup de choses intéressantes, quoique obsolètes)
https://www.corelan.be/index.php/2010/02/25/exploit-writing-tutorial-part-9-introduction-to-win32-shellcoding/

Le même code peut être écrit en C sans utiliser d'assembleur.
Exemple - Fonction ReflectiveLoader() https://github.com/dismantl/ImprovedReflectiveDLLInjection/blob/master/dll/src/ReflectiveLoader.c

Hell's Gate : analyse des recherches d'appels système dans le code C indépendant de la position
https://vxug.fakedoma.in/papers/VXUG/Exclusive/HellsGate.pdf

PE->convertisseur coque
https://github.com/hasherezade/pe_to_shellcode

7. INJECTER PE / INFECTER PE

Injecter une charge dans un fichier PE existant :
https://github.com/secrary/InfectPE/
https://github.com/JonDoNym/peinjector

Le code de décompression (bootloader) et load sont ajoutés au fichier, le point d'entrée d'origine est transmis au bootloader.
Vous pouvez ainsi connecter vos charges à des logiciels juridiques.
Les signatures numériques s'envolent bien sûr.


               II. TECHNIQUES DE PROTECTION


COMMENT FONCTIONNE L'ANTI-VIRUS

Les VA reçoivent des informations sur ce qui se passe dans le système de l'une des deux manières suivantes :
- abonnement aux événements du noyau à l'aide d'Event Trace for Windows (ETW) https://docs.microsoft.com/en-us/windows-hardware/drivers/devtest/event-tracing-for-windows--etw-
- connecter votre pilote de minifiltre en mode noyau (ring0), et ainsi vous abonner à l'activité du système de fichiers et aux événements similaires (Windows Defender, Eset, WebRoot, McAfee)
- mettre vos hooks en mode utilisateur (ring3) directement dans les processus exécutables (Avast, BitDefender, Symantec, TrendMicro) sur les fonctions de ntdll.dll, user32.dll, kernel32.dll, etc.
Dans le premier cas, rien ne peut être fait, dans le second cas, les crochets peuvent être retirés.

APPAREIL WINDOWS DEFENDER

Windows Defender utilise un pilote de type minifiltre appelé WdFilter pour s'abonner aux événements système.
Intercepté :
- créer et exécuter un processus
- télécharger l'image de processus
- démarrer les discussions
- manipulations avec un processus non natif - écriture en mémoire et démarrage d'un thread distant
- les pilotes téléchargés sont vérifiés
- les opérations avec le registre sont interceptées.

Parmi toutes les choses utiles que nous avons réussi à trouver dans l'analyse - une liste de conditions dans lesquelles une telle attention peut être évitée :
- liste blanche des processus (elle inclut svchost, werfault et les processus de WinDefender lui-même)
- liste des clés de registre renforcées

https://n4r1b.com/posts/2020/01/dissecting-the-windows-defender-driver-wdfilter-part-1/
https://n4r1b.com/posts/2020/02/dissecting-the-windows-defender-driver-wdfilter-part-2/
https://n4r1b.com/posts/2020/03/dissecting-the-windows-defender-driver-wdfilter-part-3/
https://n4r1b.com/posts/2020/04/dissecting-the-windows-defender-driver-wdfilter-part-4/

DISPOSITIF EMULATEUR

L'émulateur AV est conçu pour une analyse supplémentaire du comportement possible du programme lors de l'analyse statique du binaire :
https://findpatent.ru/patent/251/2514141.html
1) l'émulateur n'exécute pas tous les appels système en faisant un appel à "stubs". Particulièrement nécessaire au fonctionnement du programme peut s'exécuter (comme l'allocation de mémoire),
mais dans le cas général - non;
2) l'émulateur s'intéresse plus à la séquence des appels système qu'à leur résultat ;
3) dans certains AV, l'émulateur exécute toutes les branches du code, que les conditions soient remplies ou non (selon certaines preuves VBA32).
Afin d'examiner toutes les branches du code.
4) l'émulateur est limité en temps d'exécution (de l'ordre de la dizaine de secondes, ou par le nombre d'appels système effectués).

Certains émulateurs AV commencent par des crochets intégrés dans votre code.
Détection de l'émulateur Avast :
    // Contrer Avast CyberCapture.
    BYTE*A = (BYTE*)GET_API(SendMessageA); // Toute fonction accrochée par Avast
    if (A[0] == 0xe9) // Si la première commande est JMP
    {
        // Dans le bac à sable, Avast place des pièges avec un saut à l'adresse où la séquence d'octets FF25 00000000 est écrite (un autre JMP)
        // c'est à dire. une caractéristique de l'émulateur Avast est deux JMP consécutifs, E9 et FF 25 dans le prologue de votre fonction
        // En mode normal, Avast met également des hooks, mais il y en a moins, et ils mènent aux adresses de aswook.dll qui a été introduite de force dans le processus
        TAILLE_T W = (TAILLE_T)(A + 5) + (TAILLE_T)(*(INT32*)(A + 1));
        si (*(MOT*)W == 0x25FF && *(DWORD*)(W + 2) == 0)
        {
            debug_printfA(ORANGE, "Avast CyberCapture (sandbox) détecté\n");
            GET_API(ExitProcess)(-1);
        }
    }

La PARTIE de l'appareil de l'émulateur BitDefender qui détecte le code shell est décrite ici https://habr.com/ru/company/skillfactory/blog/527512/
Les sources de l'émulateur sont disponibles sur https://github.com/bitdefender/bddisasm
Déclencheurs d'émulateur :
- définition du shellcode en mémoire :
  - accès au registre des pointeurs d'instructions EIP/RIP
  - accès aux structures TEB/PEB
  - rechercher les fonctions système de type GetProcAddress
- auto-modification (décodage sur place)
- déchiffrement des chaînes sur la pile
- exécution de la pile
- utilisation de SYSCALL au lieu des points d'entrée dans la bibliothèque .dlls
- en mode noyau
  - des instructions spécifiques comme SWAPGS
  - accès au registre MSR
  - accès à KPCR (Kernel Processor Control Area)

RESPONSABILITÉ ANTI-VIRUS

Il existe deux types de détections antivirus (ci-après AB) :
- statique (par signature)
- dynamique (par comportement).

Le premier est facile à gérer, le second est difficile.

De plus, les antivirus utilisent le hachage flou (ssdeep, imphash), les réseaux de neurones et les filtres bayésiens pour détecter les logiciels malveillants jusque-là inconnus.
selon le degré de similitude du texte ou du comportement avec des échantillons déjà connus :
https://xakep.ru/2020/09/28/clear-hash/

AB sans faute place les détections sur les chaînes connues et les fonctions d'importation.

Mesures nécessaires (mais insuffisantes) pour se protéger des AB :
- obscurcissement des chaînes
- obfuscation des importations (c'est-à-dire importées à partir de fonctions .dll tierces)
- introduction de bruit dans le code
- chiffrement du code avec déchiffrement avant exécution.

Mesures supplémentaires pour contrer AB :
- désactiver AV (avec les droits suffisants)
- suppression des crochets (uniquement pour les AB travaillant en userland)

Technique connue KHOBE (Kernel HOoks Bypassing Engine). Il n'y a pas de code dans le public, seules les informations générales sont connues.
Il est nécessaire d'utiliser la condition de course (dont ?), de présenter un code sûr pour l'analyse pour le moment et de changer rapidement de contexte immédiatement après l'analyse de l'AB.

Voir la section "Nettoyage des détections antivirus" pour plus de détails.


RECHERCHE DE SIGNATURES DANS LA BD CONNUE

Décodeur de règles Windows Defender :
https://github.com/hfiref0x/WDExtract

Le moyen le plus simple consiste à rechercher des signatures déjà connues dans la base de données de signatures YARA.
Yara est un outil d'analyse de signature gratuit pour les logiciels malveillants.
https://virustotal.github.io/yara/
Mais les règles elles-mêmes qui en découlent ne sont pas définies de manière centralisée.
Il existe des collections commerciales de règles, par exemple
https://www.nextron-systems.com/2018/12/21/yara-rule-sets-and-rule-feed/
Il y en a des gratuits de mauvaise qualité https://github.com/Neo23x0/signature-base/
Une grande collection de bases de données, parmi lesquelles il y a à la fois des scories et des pertinentes: https://github.com/InQuest/awesome-yara
Syntaxe et fonctionnalités des règles : https://habr.com/ru/company/varonis/blog/584618/


Vous pouvez convertir la base de données ClamAV dans un format Yara lisible par l'homme, puis rechercher les détections nécessaires :
https://resources.infosecinstitute.com/topic/yara-simple-effective-way-dissecting-malware/
> YARA avec les règles ClamAV
>
> YARA peut être intégré à la base de données de règles ClamAv. Effectuez les étapes ci-dessous pour intégrer les règles ClamAv à YARA :
>
> Téléchargez le script Python ClamAV vers YARA ici : https://code.google.com/p/malwarecookbook/source/browse/trunk/3/3/clamav_to_yara.py
> Téléchargez et décompressez la base de données ClamAV : http://database.clamav.net/main.cvd
> Exécutez le script Python ClamAV vers YARA :
> python clamav_to_yara.py –f main.cvd –o testing_clamav.yara
> Testez maintenant les règles converties avec YARA comme ci-dessous :
> yara –r testing_clamav.yara /directory/to/check"


DÉSACTIVER WINDOWS DEFENDER

Parfois, AV peut être simplement désactivé, en particulier, vous pouvez vous ajouter aux exceptions Windows Defender (pas toujours) ici
HKLM|HKCU\MACHINE\SOFTWARE\Microsoft\Windows Defender\Exclusions\Paths
HKLM|HKCU\MACHINE\SOFTWARE\Policies\Microsoft\Windows Defender\Exclusions\Paths
Et à peu près au même endroit, éteignez complètement AB.
Notez que cela se fait par le biais de politiques !


OBFUSCATION DES APPELS SYS

La technique la plus simple consiste à obtenir l'adresse d'une fonction en utilisant GetProcAddress(LoadLibrary(decode("lib.dll"), decode("funcname"))
Cependant, les appels GetProcAddress et LoadLibrary brillent ici.

L'ancienne mais toujours efficace technique GetApi a été utilisée dans le cheval de Troie Carberp :
https://github.com/hzeroo/Carberp/blob/master/source%20-%20absource/pro/all%20source/RemoteCtl/DrClient/GetApi.h

Son essence est de rechercher des fonctions dans la table d'importation par le hachage de leur nom. Cela annule les détections de signature, bien qu'il soit accessible à l'analyse automatisée.
dans les désassembleurs. La méthode de hachage peut être modifiée périodiquement.

Une autre approche est les appels système en ligne - nous mettons l'intégralité du code de préparation des appels système passe-partout dans l'assembleur
https://github.com/JustasMasiulis/inline_syscall

Bibliothèque de substituts pour certains appels WinAPI :
https://github.com/vxunderground/WinAPI-Tricks

En fin de compte, les appels système sont toujours interceptés par les AV fonctionnant en mode noyau via des abonnements d'interception d'appels.

OBFUSCATION DE CODE

Habituellement, le code sous la forme d'un .dll est compressé, chiffré et compressé dans un tableau (voir Cacher des données dans un segment de code ci-dessous),
au moment de l'exécution, ils allouent de la mémoire, extraient et décompressent le code, puis configurent le .dll en mémoire
(délocalisations, importations et tout ça). Voir ci-dessous sur les cryptos et les packers - c'est tout.
Cette astuce est connue d'AB et cela ne sauve pas d'une défense proactive.

La réflexion est donc allée plus loin :

1. Déballer chaque fonction juste avant l'exécution.
Chaque fonction définit un prologue et un épilogue qui décrypte et crypte le corps de la fonction, respectivement.
Les signatures sont utilisées pour trouver la limite d'une fonction.
Un encodeur externe est nécessaire pour chiffrer initialement les fonctions dans le fichier.
Il existe d'autres options de décodage à la volée, mais elles sont toutes difficiles à mettre en œuvre.

2. propres interprètes JIT.
Par exemple, https://github.com/jacob-baines/jit_obfuscation_poc
L'idée est claire d'après le nom - nous traduisons un code en un autre code inconnu des antivirus et inaccessible
retour automatique et analyse.

VMProtect-2 - machine virtuelle obscurcissante
https://back.engineering/tags/vmprotect-2/
	
Il existe un projet de compilateur obscurcissant intéressant basé sur LLVM :
https://github.com/obfuscator-llvm/obfuscator
et explications de ses algorithmes
https://0xpat.github.io/Malware_development_part_6/
Un autre commercial :
http://www.star-force.ru/products/starforce-obfuscator/

Une approche intéressante pour déchiffrer le code consiste à obtenir la clé de déchiffrement du serveur.
Cela a un certain effet contre les émulateurs AV.

OBFUSCATION DE CHAINE

Avant l'apparition de constexpr, l'obscurcissement des chaînes était effectué avec un utilitaire tiers et une construction en deux passes :
- les lignes du code étaient marquées par des marqueurs spéciaux, généralement dans le tableau global des lignes
- les lignes ont été accédées via la fonction de déchiffrement, par son index dans la table
- l'utilitaire est passé par le fichier .exe fini et les a remplacés par un texte chiffré.

Cette approche rendait le débogage très difficile et nécessitait des étapes d'assemblage supplémentaires,
rendant le code illisible.

constexpr vous permet de chiffrer une chaîne au stade de la construction, résolvant tous les problèmes ci-dessus.
Cependant, cela fonctionne dans Visual Studio 2015 ou version ultérieure, nécessitant la norme C++ 14.
Bibliothèque de chiffrement Ready Anddrivet ADVObfuscator :
https://github.com/anddrivet/ADVobfuscator
Avoir aussi
https://github.com/Snowapril/String-Obfuscator-In-Compile-Time (basé sur Anddrivet)
https://github.com/adamyaxley/Obfuscate
https://github.com/fritzone/obfy
https://github.com/revsic/cpp-obfuscator

L'obscurcissement fonctionne avec les paramètres d'optimisation maximum dans Visual Studio :
- C/C++/ Optimisation : Optimisation complète
- C/C++/ Optimisation / Optimisation du programme complet : Activé
- C/C++/ Optimisation/Développer les fonctions en ligne : désactiver
- C/C++/Génération de code/Activer la concaténation de chaînes : Oui
Cependant, ce paramètre doit être essayé, il affecte quand comment, différemment sur x64 / x86
- d'autres paramètres d'optimisation doivent également être essayés, ils peuvent influencer.

Commentaire du développeur sur le fait que l'obfuscateur ne fonctionne pas sur l'optimisation complète pour la compilation x86 :
"... pourquoi l'obfuscateur de chaînes ne fonctionne pas toujours.
Le point est dans la méthode de décryptage, il s'avère que lorsque l'optimisation est activée pour déployer des fonctions en ligne,
le compilateur insère son corps à l'endroit où cette méthode est appelée, et comme ce corps utilise des expressions qu'il peut calculer à la compilation,
puis et déchiffre la chaîne obtenue au moment de la compilation.
Il s'avère qu'il a chiffré et déchiffré la chaîne au moment de la compilation.
Corrigé en désactivant les optimisations en ligne de déballage."

L'un des défauts bien connus des obfuscateurs en ligne est la limitation de la longueur des lignes.
Chaque caractère supplémentaire dans la chaîne est une récursivité supplémentaire du compilateur lors des calculs au moment de la compilation.
La pile MSVC2015 se termine à environ 100 caractères.

Il existe aussi une astuce simple à utiliser en l'absence de C++ (en C pur)
char str[] = { 'H', 'E', 'L', 'L', 'O' } ;
Dans une telle initialisation, la chaîne est entrée dans un tableau sur la pile par mov's au moment de l'exécution, et comment la chaîne ne tombe pas dans le segment .data
(c'est-à-dire qu'il se transformera en un ensemble d'instructions assembleur en .text comme ceci :

       mov edx, 8EB5h
       pousser edx
       mov edx, 6C6CD488h
       pousser edx
etc

Au fait, le décodage de la chaîne en place ressemble à ceci :

       mov edx, 8EB5h
       xor edx, 8EDAh
       pousser edx
       mov edx, 6C6CD488h
       xor edx, 0B1C0h
       pousser edx
       mov esi, esp
       sous esp, 20h
       mov edx, 0F478h
       xor edx, 0F459h
       pousser edx
       mov edx, 74690CD7h
       xor edx, 2CB2h
       pousser edx

Une ligne propre ressemble à ceci dans le désassembleur :

.code:004010A5 aTest001 db 'Test001',0
.code:004010AD aLoremIpsumDolo db 'Lorem ipsum dolor sit amet',0

)

char str[] = "BONJOUR" ; sera rempli au moment de la compilation sous forme de chaîne et se retrouvera dans .data.

OBFUSCATION DU POINT D'ENTRÉE

Cette mesure est utilisée pour contrer les émulateurs AV et l'analyse manuelle.
Le point d'entrée réel diffère de celui déclaré dans les en-têtes PE/ELF.
Par exemple, dans .dll, il existe une fausse exportation inoffensive (certains DllMain, DoTheWork, etc.) qui effectue certaines actions pour éviter les regards.
Pour démarrer un chargement réel, vous devez extraire une fonction non exportée à une adresse connue uniquement du contexte de lancement.
Une autre option consiste à utiliser un stub DOS. Changer la signature MZ en une autre dans le binaire PE entraînera l'exécution du binaire en mode DOS.
En conséquence, AB ignorera le véritable point d'entrée.
En mode 16 bits, les émulateurs ne fonctionnent pas ; via la fonction d'interruption 4B DOS, vous pouvez exécuter un binaire tiers.
Cela peut être utilisé dans la technique de « rupture de chaîne ».

MASQUER LES DONNÉES DANS LE SEGMENT DE CODE

Les AV sont sensibles à une section de données inhabituellement grande (.data, .rdata) - c'est un signe qu'un code de charge utile crypté y est caché.
Les données peuvent être masquées dans la section de texte. Le compilateur Microsoft C++ vous permet de le faire avec cette astuce :

#pragma code_seg(pousser, ".texte")
#pragma code_seg(pop)
caractère non signé __declspec(allocate(".text")) hiddencode[]={ ... } ;

Par un principe similaire, vous pouvez ajouter la charge à d'autres sections, pragmas/declspec data_seg, const_seg.
Certes, l'éditeur de liens peut produire des sections avec les mêmes noms et des droits d'accès différents, il existe donc une autre option :

#pragma comment(linker,"/SECTION:.data,EW")
caractère non signé PayloadName0[]={}
#pragma comment(linker,"/SECTION:.rdata,R")
caractère non signé PayloadName2[]={}

La réaction à cette mesure de la part d'AB est l'analyse de fréquence de la section de code. La section de code a une faible entropie,
car le nombre d'opcodes est limité et la distribution statistique des symboles dans le code a une structure bien définie.
Par conséquent, le masquage des tableaux chiffrés et/ou compressés est suivi assez clairement.
Ceci, à son tour, peut être contré par des techniques de cryptage entropique à faible variation - par exemple,
xor 1 octet (bien sûr, si le code sous la forme de .dll est caché dans un tel tableau. S'il y a d'autres données, cela n'aidera pas).

À propos de l'entropie et à quoi ressemble votre fichier PE pour AB :
https://0xpat.github.io/Malware_development_part_4/
L'entropie peut être mesurée avec DIE (Detect It Easy).

CRYPTEURS ET EMBALLEURS

Des implémentations fiables de packers sont connues depuis au moins le milieu des années 90.
L'idée est simple - un .exe est empaqueté dans un autre .exe, et lorsqu'il est exécuté, il exécute l'astuce du baron Münghausen
pour tirer et lancer la charge de lui-même.
Bien sûr, c'est un excellent outil pour cacher du code.
Le cryptage est également ajouté à l'emballage.
L'emballage peut être multicouche pour rendre l'analyse difficile.
Le pic de popularité des emballeurs est venu dans les 0.

Pour déterminer le type d'emballeur, le programme PEId a été utilisé (abandonné en 2011).

Des cryptos beaucoup plus intelligents sont maintenant utilisés.
Cryptor assume en outre les fonctions de contournement de l'émulation AV, de détection de bac à sable,
parfois même contournement UAC et élévation des privilèges (en raison de la nature du lancement de la charge, ces fonctions
il convient de l'affecter au cryptoteur).
De plus, en plus de l'extraction banale de la charge du tableau crypté à l'intérieur de lui-même,
un bon cryptor génère des tables d'importation plausibles, un code plausible, un AB déroutant,
dilue l'entropie de la charge, pousse la charge au hasard dans différentes sections,
génère de vraies ressources (chaînes en localisation), en un mot il prétend être un vrai programme.
Une approche similaire est décrite dans https://xss.is/threads/39006/

En un mot, c'est une coque de protection qui cache votre code.

Bien sûr, les cryptos ne sont pas omnipotents et ils ne supprimeront pas les détections par comportement.

Une approche intéressante de la crypto-construction : la clé de décryptage de la charge utile est située séparément de la crypte et est transmise via la ligne de commande (ou autre chose) :
https://habr.com/ru/company/solarsecurity/blog/519994/

Utilisation d'un combo à partir de code public dans un packer à partir de zéro
https://iwantmore.pizza/posts/PEzor.html
y compris l'utilisation
Emballeur de beignets https://github.com/TheWover/donut
métamorphoser Shikata Ga Nai https://github.com/EgeBalci/sgn

Chiffrement open source :
https://github.com/oddcod3/Phantom-Evasion
Une autre:
https://github.com/ximerus/Kryptonite

Protecteur avec "nanomites":
https://www.apriorit.com/white-papers/293-nanomite-technology
Débogage du processus de blocage appliqué par son propre débogueur ;
remplacement de TOUTES les instructions de branche par les opcodes INT 3 dans le thread enfant (interruption de débogage) ;
et génération de l'adresse de transition dans le processus de débogage.

RETRAIT DES CROCHETS

Pour supprimer les crochets d'autres personnes, vous pouvez utiliser la comparaison de la fonction prologue dans la mémoire de processus
avec un prologue dans le fichier .dll correspondant. S'ils diffèrent, c'est un signe que le crochet de quelqu'un d'autre a été mis sur la fonction.
La lutte est appropriée : lisez le corps de la fonction à partir du fichier et remplacez le corps de la fonction en mémoire.
Les 10 premiers octets suffisent.
Présentation et comparaison des différentes techniques :
https://www.first.org/resources/papers/telaviv2019/Ensilo-Omri-Misgav-Udi-Yavo-Analyzing-Malware-Evasion-Trend-Bypassing-User-Mode-Hooks.pdf
Démo : https://github.com/apriorit/antirootkit-anti-splicer
Plus : https://github.com/CylanceVulnResearch/ReflectiveDLLRefresher
Détection de crochet : https://github.com/asaurusrex/Probatorum-EDR-Userland-Hook-Checker
Comparaison des hooks userland de différents EDR ; travail direct avec les appels système : https://github.com/Mr-Un1k0d3r/EDRs

Gardez à l'esprit que les hooks de votre processus peuvent être restaurés après les avoir supprimés.


INTERCEPTION DES FLUX ETRANGERS (PROTECTION CONTRE L'INJECTION)

Vous pouvez intercepter l'injection de quelqu'un d'autre dans le processus en définissant votre gestionnaire sur la fonction BaseThreadInitThunk ().
La création d'un nouveau thread commence par lui (y compris un processus initié de l'extérieur).
Dans ce gestionnaire, vous pouvez décider d'autoriser ou de bloquer le lancement du thread, selon certains critères.
L'approche la plus simple consiste à démarrer tous vos threads en même temps, puis à bloquer tout le reste.
Si cela est inacceptable, vous pouvez consulter l'adresse et les propriétés de la page mémoire à partir de laquelle le code est exécuté.
Pour un flux injecté, il s'agit généralement d'un tas. Pour un flux de personne en bonne santé, il s'agit de la section texte (.text).

En particulier, la protection contre les injections du navigateur Mozilla Firefox est implémentée de cette manière.

Cette technique peut être contrecarrée avec succès - de l'extérieur du processus, vous pouvez supprimer le crochet sur BaseThreadInitThunk
selon la méthode de retrait des crochets décrite ci-dessus, après quoi l'injection est possible.

Une autre façon - immédiatement après le début du processus, dévissez toutes les atténuations au maximum (voir ci-dessous), en particulier par DEP
et la signature de code.

Lets Create An EDR… And Bypass It! Part 2
Voici comment sécuriser un processus avec : - développement de code "innocent" - enlever les crochets - travailler directement avec les appels système - atténuations - SharpBlock est une autre technique qui utilise des événements de débogage pour intercepter le début d'un thread enfant et patcher son point d'entrée pour obscurcir l'EDR. PROTÉGER UN PROCESSUS CONTRE LA RÉSILIATION 1. Refuser l'accès via une liste de contrôle d'accès discrétionnaire (DACL). DACL est vide => le processus ne peut être tué que par l'administrateur : https://stackoverflow.com/questions/6185975/prevent-user-process-from-being-killed-with-end-process-from-process-explorer 2. Marquage du processus comme critique (RtlSetProcessIsCritical, NtSetInformationProcess). Toute tentative d'arrêter un tel processus entraînera un BSOD ; si vous essayez de tuer un tel processus via le gestionnaire de tâches, un avertissement s'affichera indiquant que le processus est critique et sa suppression peut conduire à l'effondrement du système. Nécessite des droits d'administrateur et le privilège SeDebugPrivelege : RtlSetProcessIsCritical : https://www.codeproject.com/Articles/43405/Protecting-Your-Process-with-RtlSetProcessIsCriti NtSetInformationProcess avec la valeur de paramètre ProcessInformationClass = BreakOnTermination : http://www.rohitab.com/discuss/topic/40275-set-a-process-as-critical-process-using-ntsetinformationprocess-function/ L'utilisation de ces appels peut entraîner des plantages. Il a été empiriquement établi que NtSetInformationProcess avec le paramètre BreakOnTermination fonctionne de manière stable sur les systèmes d'exploitation 32 bits, et RtlSetProcessIsCritical - sur les 64 bits. 3. S'il existe une clé privée pour signer numériquement le code Microsoft (lol))), puis en commençant par Windows Vista il est possible de rendre n'importe quel processus protégé de tout changement de l'extérieur. De plus, un processus parent protégé peut générer un processus enfant protégé, en utilisant l'appel de fonction CreateProcess avec l'indicateur CREATE_PROTECTED_PROCESS. Ce mécanisme a été amélioré dans Windows 8.1, mais il n'est pas parfait et n'exclut pas la possibilité de sécuriser n'importe quel processus. ou supprimer la protection des processus système qui ont une signature numérique. Un exemple de création d'un processus enfant protégé se trouve dans la description de la fonction UpdateProcThreadAttribute sur MSDN : https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-updateprocthreadattribute Article sur les processus sécurisés par Alex Ionescu : https://www.crowdstrike.com/blog/evolution-protected-processes-part-1-pass-hash-mitigations-windows-81 https://www.crowdstrike.com/blog/evolution-protected-processes-part-2-exploitjailbreak-mitigations-unkillable-processes-and Présentation d'Alex Ionescu : http://www.nosuchcon.org/talks/2014/D3_05_Alex_ionescu_Breaking_protected_processes.pdf Un exemple d'exploit pour une vulnérabilité dans un pilote Capcom qui permet de sécuriser n'importe quel processus : https://www.unknowncheats.me/forum/anti-cheat-bypass/271789-pplib-ppl-processes.html https://github.com/notscimmy/pplib Un article avec des exemples sur la façon de protéger un processus et d'élever ses privilèges en corrigeant la mémoire du processus : https://www.blackhat.com/docs/asia-17/materials/asia-17-Braeken-Hack-Microsoft-Using-Microsoft-Signed-Binaries-wp.pdf Sources de pilotes qui suppriment la protection de la signature numérique : https://github.com/Mattiwatti/PPLKiller https://github.com/katlogic/windows 4. D'autres moyens de protection des processus, qui ne sont pas les plus efficaces, sont décrits ici : https://security.stackexchange.com/questions/30985/create-a-unterminable-process-in-windows PROTÉGER UN PROCESSUS CONTRE L'ARRÊT 1. Vous pouvez définir le gestionnaire d'événements de la console en appelant SetConsoleCtrlHandler, dans lequel retourner 0 pour les événements CTRL_LOGOFF_EVENT et CTRL_SHUTDOWN_EVENT. - Fonctionne pour les programmes de console pour lesquels aucun autre gestionnaire d'événements de console n'est en cours d'exécution. - À partir de Windows 7, la gestion des événements CTRL_LOGOFF_EVENT et CTRL_SHUTDOWN_EVENT ne fonctionne pas pour les programmes qui utilisent les fonctions des bibliothèques user32.dll et gdi32.dll. Exemple sur MSDN : https://docs.microsoft.com/en-us/windows/console/registering-a-control-handler-function 2. Vous pouvez appeler la fonction AbortSystemShutdown dans une boucle infinie. - nécessite des droits d'administrateur et le privilège SeShutdownPrivilege - n'a pas le temps de s'entraîner si vous exécutez la commande shutdown dans la console avec la touche / t avec la valeur 0 (timeout 0 secondes) - ne sauve pas de l'exécution de la commande shutdown dans la console avec la touche /f - ne semble pas fonctionner sur Windows 10. 3. Vous pouvez créer une fenêtre invisible et renvoyer 0 dans le gestionnaire d'événements de fenêtre pour les événements WM_QUERYENDSESSION et WM_ENDSESSION. - A partir de Windows Vista, il est nécessaire d'appeler la fonction ShutdownBlockReasonCreate sur l'événement WM_QUERYENDSESSION, soit masquer la fenêtre en appelant la fonction ShowWindow avec la valeur du deuxième paramètre FALSE (bien que la fenêtre soit déjà créée invisible). - il ne sauve pas d'appuyer sur le bouton d'arrêt forcé. - ne sauve pas de l'exécution de la commande shutdown dans la console avec la touche /f - ne fonctionne pas pour les programmes console, en particulier il est inutile d'utiliser cette technique à l'intérieur d'une dll lancée via rundll32 Plus détaillé sur MSDN : https://docs.microsoft.com/en-us/windows/win32/shutdown/shutdown-changes-for-windows-vista https://docs.microsoft.com/en-us/previous-versions/windows/desktop/ms700677(v=vs.85) ATTÉNUATIONS voir SetProcessMitigationPolicy()/UpdateProcThreadAttribute(PROC_THREAD_ATTRIBUTE_MITIGATION_POLICY) Vous permet d'activer DEP, ASLR pour le processus, de désactiver la génération de code dynamique, vérifications supplémentaires pour la vérification de la signature, la validité du descripteur, les exceptions SEHOP et bien plus encore. Ceci est utilisé par les navigateurs et AV, tordant les atténuations au maximum afin de rendre difficile leur injection ou de gâcher le processus. Sur Windows 10, c'est vraiment efficace. Bon article http://www.sekoia.fr/blog/microsoft-edge-binary-injection-mitigation-overview/ et coder pour cela https://github.com/SekoiaLab/BinaryInjectionMitigation/ démontrer la protection du code par atténuation en vérifiant la signature du code. Cet article https://habr.com/ru/post/494000/ donne un aperçu des politiques d'atténuation, y compris la pile fantôme, cite : "Code Integrity Guard (CIG) a une exigence de signature obligatoire pour les binaires téléchargés. Arbitrary Code Guard (ACG) garantit que les pages signées sont immuables, et le code dynamique ne peut pas être généré, ce qui garantit l'intégrité des binaires téléchargés. Avec l'introduction de CIG et ACG, les attaquants ont de plus en plus recours au piratage en utilisant des appels et des retours indirects, connue sous le nom de programmation orientée appel/saut (COP/JOP) et programmation orientée retour (ROP)." ASYMÉTRIE DU RÉSEAU Les résultats du travail antivirus dépendent du pays. La plupart des fabricants de solutions audiovisuelles sont des pays de l'Occident collectif. L'efficacité de l'AV dépend principalement de la vérification avec les réseaux de neurones dans le "cloud". Avec le début de la cyber-confrontation russo-américaine, ces derniers ont priorisé tout le trafic en provenance de leur pays, au détriment des autres pays (dont l'Europe de l'Ouest), pour améliorer leur propre sécurité. Apparemment, les puissances de test ne sont pas sans dimension. Par conséquent, la situation est devenue normale lorsque la même charge ne fonctionne pas aux États-Unis et fonctionne dans d'autres pays. NETTOYAGE DES DÉTECTIONS ANTI-VIRUS Avant de nettoyer, vous devez d'abord vous assurer que l'antivirus ne draine pas d'échantillons : - virustotal divulgue TOUJOURS des échantillons en direct - dyncheck fusionne les échantillons lors des vérifications comportementales dynamiques. Avec les contrôles statiques - il semble que ce ne soit pas le cas - dans Windows Defender, vous devez désactiver l'option "Soumettre des échantillons" - pour le reste des AV, vous devez trouver l'option d'envoi d'échantillons et de protection cloud et les désactiver. La procédure générale de nettoyage est la suivante : 1. Trouvez les lignes de code spécifiques sur lesquelles le détecteur est réglé ; 2. Nous le remplaçons. Le point 1 est long et fastidieux, fait comme ceci : - désactivez TOUS les codes de programme avec un commentaire ou ifdef, collectez - AB se tait - décommentez la moitié du code - AV est silencieux - un demi-moitié de plus - AV est silencieux - moitié moitié moitié - AB crie -> a trouvé un site ! Plus loin, par la même dichotomie, nous arrivons à des lignes spécifiques : - décommentez la ligne - crie, commentez - est silencieux. Nous prenons en compte le compilateur d'optimisation : l'optimiseur peut générer un énorme bloc de code, s'il ne voit pas l'impact de ce code sur le comportement global. Par exemple, si vous mettez retour au milieu de la fonction testée dans le cadre de la recherche de détection, l'optimiseur peut jeter à la fois la queue du f-ii et son début à partir du binaire final, car considère que dans la partie restante de la fonction, rien d'utile et affectant la performance globale ne se produit. Par le même principe, l'optimiseur rejette des sections de code inattendues, ce qui embrouille les cartes. En règle générale, les détections antivirus sont définies sur : - nom du fichier binaire (une fois le nom surligné donnera des détections) - Microsoft Visual C++ ajoute une chaîne avec le nom du projet au binaire : Propriétés du projet -> Général -> Nom de l'objet cible (la valeur par défaut est $(ProjectName)) vous devez le randomiser, ou simplement l'écraser avec des zéros/espaces dans la construction post-événement directement dans le binaire - appels système séparés (CreateRemoteThread, VirtualProtect, CreateFile, CreateProcess, OpenProcess, travail avec le registre, etc.) - séquences d'appels système (silencieux pour les appels système individuels, hurle pour une séquence) - cordes ouvertes - algorithmes caractéristiques (générateurs de nombres aléatoires, (dé)chiffrement, (dé)compression) - haute entropie d'un fichier binaire (tableaux chiffrés/archivés, y compris dans la section code) De plus, la détection d'un fichier sain peut être définie : - Lors du téléchargement depuis un site de mauvaise réputation (pour lequel il y avait déjà des informations complètes sur la présence de fichiers suspects) - Alternativement, lors du téléchargement d'un fichier depuis un autre pays (affecte à la fois l'adresse du client et l'adresse du site) - En l'absence de hash du fichier dans la base de données AB (il existe un nombre limité de fichiers exécutables dans le monde) Sous Linux, n'oubliez pas de supprimer les caractères et les lignes supplémentaires avec l'utilitaire strip (ou mieux encore, sstrip). Les appels système sont soit obscurcis par GetApi.h (peuvent être extraits directement de carberp/GetApi.h https://github.com/hzeroo/Carberp/blob/master/source%20-%20absource/pro/all%20source/RemoteCtl/DrClient/GetApi.h) ou, si l'appel requis est manquant dans GetApi, par la séquence suivante : HANDLE h = LoadLibrary(_OBFUSCATED("dll.dll")); void* f = GetProcAddress(h, _OBFUSCATED("funcname")); ici les deux lignes sont masquées. Les séquences d'appels système sont masquées de la même manière, ou les appels système sont remplacés de manière créative par des analogues. Voir ci-dessus pour savoir comment masquer les chaînes. On dilue les algorithmes caractéristiques avec du code de bruit : - ajouter/supprimer volatile aux variables locales - changer l'emplacement de la définition d'une variable locale dans le code (c'était dans le prologue de f-ii - on l'a rapproché du lieu d'utilisation, et inversement) - ajouter du code de bruit entre les lignes (incrément de variable volatile indésirable, addition, soustraction, autres opérations) - un tel code de bruit peut être formaté en inline-f-th ou macro : dans l'assemblage de débogage, le corps f-th est désactivé, en combat - avec constexprs des modèles de code aléatoires sont créés. - nous supprimons l'entropie en poussant les morceaux du tableau dans différentes sections et en complétant les tableaux avec des octets constants inutilisés, collecter un tableau avant de l'utiliser à partir de morceaux. Une autre tactique pour supprimer les détections consiste à randomiser les adresses de fonction dans le fichier .exe final. Ceci peut être réalisé en mélangeant simplement la liste des fichiers objets sur la ligne de commande de l'éditeur de liens : link.exe /out:file.exe foo.obj bar.obj --> détecter link.exe /out:file.exe bar.obj foo.obj --> pas de détection Il existe un utilitaire de recherche de signatures dans les fichiers PE : https://github.com/vxlabinfo/SignFinder basé sur des articles https://vxlab.info/%d1%87%d0%b8%d1%81%d1%82%d0%ba%d0%b0-pe32-%d1%87%d0%b0%d1%81%d1% 82%d1%8c-1/ https://vxlab.info/%d1%87%d0%b8%d1%81%d1%82%d0%ba%d0%b0-pe32-%d1%87%d0%b0%d1%81%d1% 82%d1%8c-2/ le site est déjà pourri, mais il reste des copies, par exemple ici https://ru-sfera.org/threads/chistka-ot-signaturnogo-detekta-antivirusov.2870/ et aussi google purge-pe32-part-1 purge-pe32-part-2 RÉPUTATION DU FICHIER Un fichier avec un nouveau hachage inconnu de tous sera bloqué par AB au cas où. C'est ce qu'on appelle "le manque de réputation". De ce fait, le fichier est généralement triché avec une réputation sur les machines contrôlées : il est lancé, et quand AB est bloqué, débloquez-le manuellement, ajoutez-le à l'exception et faites-le fonctionner. L'écran SmartScreen standard et l'écran Chrome AV fonctionnent de la même manière. Description du mécanisme de réputation dans Mozilla Firefox : https://wiki.mozilla.org/Security/Features/Application_Reputation_Design_Doc RUPTURE DE CHAÎNE Lors du contournement de l'AB dans le cas d'un démarrage de charge à plusieurs étages, presque le seul moyen d'éviter la détection est de rompre la chaîne de démarrage. Ainsi, le processus parent des étapes suivantes n'est pas l'étape précédente, mais un fichier de système d'exploitation légitime. Par exemple, nous souhaitons télécharger et exécuter la deuxième étape du chargement à partir du chargeur. Si nous le faisons directement, l'AB détectera la connexion entre le chargeur et la charge. Si nous ajoutons un maillon intermédiaire à la chaîne (par exemple, démarrer le chargement avec la commande AT), alors la chaîne sera rompue. Une bonne âme a créé un répertoire de ces utilitaires système et des critères d'utilisation https://lolbas-project.github.io/ https://github.com/api0cradle/LOLBAS SUBSTITUTION DU PROCESSUS PARENT Une sorte de rupture de chaîne qui rompt la connexion avec le processus généré. CreateProcessA reçoit lpStartupInfo, dont lpAttributesList spécifie le handle du processus parent souhaité. Au fait, de cette manière, vous pouvez élever les privilèges en héritant du contexte de sécurité du processus. Détails sur https://blog.f-secure.com/detecting-parent-pid-spoofing/ RUSH ZERG Nous lançons 100500 hachages différents de la crypte d'une même charge, surchargeant ainsi l'AB. Avec de la chance, AB ne coupera que 10499 : https://habr.com/ru/company/solarsecurity/blog/519994/ CONTOURNEMENT AMSI AMSI est une interface d'analyse antimalware, un module antivirus permettant d'analyser le code des langages de script Windows. Il traite le code en PowerShell, C#, VBScript, JavaScript, Windows Script Host (wscript.exe et cscript.exe), Macros Office VBA et UAC. Brève essence : nous analysons les sources (si nécessaire, décompilons), uniquement en statique, mettons les détections sur les chaînes - noms de variables, chaînes, modèles similaires, en utilisant des ponts pour WinAPI. Nous nettoyons en conséquence. Un mec nommé S3cur3Th1sSh1t a fait un excellent travail d'organisation de toutes les méthodes de contournement AMSI. Deux articles décrivent le fonctionnement d'AMSI et comment le contourner : https://s3cur3th1ssh1t.github.io/Bypass_AMSI_by_manual_modification/ https://s3cur3th1ssh1t.github.io/Bypass-AMSI-by-manual-modification-part-II/ TL;DR : AMSI place les détections sur les lignes, nous renommons donc activement les identifiants dans les scripts, nous collons des lignes à la volée, nous utilisons des encodages à gauche pour stocker les scripts. Scanner de détection (trouve les lignes sur lesquelles la détection est définie) : https://github.com/RythmStick/AMSITrigger Obfuscateur anti-AMSI : https://amsi.fail/ Les techniques de contournement sont rassemblées ici : https://github.com/S3cur3Th1sSh1t/Amsi-Bypass-Powershell Obfuscateur de script PowerShell :
Chimera PowerShell obfuscation script For bypass AMSI And Antivirus
Les documents sont nettoyés comme ceci : - tout d'abord, nous modifions la mise en page (hachage des images, disposition des éléments, textes, etc.) - Masquer le code VBA - définir des délais d'attente avant de déballer le compte-gouttes et avant de lancer le fichier lui-même GRAS BINAIRE Une technique peu développée, mais connue de longue date et prometteuse liée à la nécessité de délivrer une charge universelle 32/64 bits : https://en.wikipedia.org/wiki/Fat_binary https://habr.com/ru/company/macloud/blog/545278/ En jouant avec les en-têtes exécutables, le prologue de démarrage est générique, qui sélectionne ensuite la charge souhaitée avec le point d'entrée souhaité. III. DÉTECTION DE SANDBOX ET DEBUGGER DÉTECTION DU BAC À SABLE La détection des bacs à sable est nécessaire pour ne pas s'y exécuter. Ne pas charger ou allumer la charge principale. Les sandbox sont majoritairement constituées de machines virtuelles, mais ce critère à lui seul est insuffisant, car un serveur terminal légitime peut très bien être en cours d'exécution sur la machine virtuelle. De nombreuses méthodes sont ici systématisées : Al-Khaser : https://github.com/LordNoteworthy/al-khaser PaFish : https://github.com/a0rtega/pafish Bon article sur la détection des émulateurs et sandbox : https://0xpat.github.io/Malware_development_part_2/ Vous trouverez ci-dessous un résumé très bref et incomplet des stratégies : 1. Par nom de machine (https://www.blackhat.com/docs/us-17/thursday/us-17-Kotler-The-Adventures-Of-Av-And-The-Leaky-Sandbox.pdf) : *ESET : REYNAPC, MALVAPC, ELEANOREPC, WRIGHTPC, BRIAPC, JORIPC, GABBIPC, HELSAPC, MAMEPC, SHARAIPC, ARACHONPC, FLORIANPC, EDITHPC * Divers : WIN7-PC, ROGER-PC, DAVID-PC, ADMIN-PC, APIARY7-PC, ANTONY-PC, LUSER-PC, PERRY-PC, KLONE_X64-PC, 0M9P60J5W-PC, MIKI-PC *Avira : C02TT22, C02TT26, C02TT36, C02TT18, C06TT43 *Comodo : spurtif, circumstellaire *Autres : ZGXTIQTG8837952 (Comodo), ABC-WIN7, PC, WIN-U9ELNVPPAD0, PC-4A095E27CB, WIN-LRG949QLD21 2. Par numéros de série et nom d'équipement - adresses MAC de la carte réseau, nom du volume du disque dur (vbox, qemu, vmware, hd virtuel) 3. Par exécution dans une machine virtuelle. 4. Par le temps d'exécution de l'instruction CPUID 4.1. Par la différence GetTickCount() avant et après Sleep(); 5. Par manque d'activité dans la session interactive (souris, clavier) 6. Résoudre un domaine inexistant connu (killswitch NotPetya) Quelques exemples de mise en œuvre de la détection sandbox : - https://habr.com/ru/company/solarsecurity/blog/473086/ - Aperçu des méthodes Deshman de Positive Technologies : https://habr.com/en/company/pt/blog/507912/ - Moissonneuse avec détection de bac à sable en plusieurs étapes : https://blog.talosintelligence.com/2020/05/astaroth-analysis.html lire la section "Mécanismes anti-analyse/anti-sandbox" ÉMULATEURS DE BYPASS L'émulateur fait généralement partie de l'antivirus, et il doit déterminer très rapidement s'il faut autoriser ou non le code donné à fonctionner. Pour cette raison, l'enregistrement de l'émulateur ne prend généralement pas beaucoup de temps. C'est la base de la principale stratégie de contournement des émulateurs - le délai d'exécution. Simple Sleep() n'a pas fonctionné depuis longtemps, car est intercepté par l'émulateur, il n'y a pas de réel délai. Par conséquent, en règle générale, au lieu d'un retard, un cycle de calcul est utilisé (par exemple, calcul de Pi avec une grande précision). De nombreuses techniques intéressantes et simples pour contourner les émulateurs : https://wikileaks.org/ciav7p1/cms/files/BypassAVDynamics.pdf Une approche basée sur l'imperfection de l'émulation WinAPI - analyse des registres ECX EDX après le retour de l'appel :
Fuzzing the Windows API for AV Evasion
https://github.com/jackullrich/Windows-API-Fuzzer Travaux antérieurs https://github.com/SPTHvx/SPTH/blob/master/articles/files/dynamic_anti_emulation.txt Masquage de la véritable séquence d'appel système dans de nombreux appels bruyants : https://habr.com/en/company/pt/blog/551954/ DEBUGGER DETECTION, DEBUG PROTECTION 1. IsDebuggerPresent() - non fiable, la fonction est corrigée et renvoie "nous ne sommes pas débogués" 2. Rechercher des processus par nom (windbg, idapro, etc.) 3. Marques du temps de passage de morceaux de code caractéristiques Méthodes de protection de débogage intéressantes pour le crypteur OnionCrypter : https://decoded.avast.io/jakubkaloc/onion-crypter/ - utiliser des signatures de packers bien connus (UPX) pour boucler l'autoanalyse et confondre des inverseurs plus simples. Bien entendu, la charge n'est pas recouverte par le packer dont il reste des traces. - une exception est levée après la détection du débogueur - trois fonctions différentes pour l'allocation de mémoire - HeapAlloc GlobalAlloc VirtualAlloc. De nombreuses fausses allocations rendent l'analyse manuelle difficile, rend le point d'arrêt et le crochet sur ces fonctions inutiles. - début du chargement par rappel du système f-ii. Ceux. ne "transférez pas le contrôle à telle ou telle adresse", et "appelez EnumWhateverA et transmettez le point d'entrée de chargement à cette fonction en tant que rappel". IV. TECHNIQUES DE FIXATION Sous Windows, les méthodes d'épinglage classiques sont les suivantes : - chargement automatique [HKLM|HKCU]\Software\Microsoft\Windows\CurrentVersion\Run - tâche planifiée CoCreateInstance(CLSID_TaskScheduler, ...) Parmi les avantages - les droits d'administrateur ne sont pas requis, des inconvénients - ils sont si évidents qu'ils donnent une détection comportementale immédiate. - vous installer en tant que service (vous ne pouvez pas vous passer de droits) - BITS - pas si souvent utilisé, mais ne fatigue pas AB - ... (technicien nombreux) Ici https://habr.com/ru/post/425177/ est un bon aperçu des techniques. Ici http://www.hexacorn.com/blog/2017/01/28/beyond-good-ol-run-key-all-parts/ un grand nombre de normes et des points d'extension non standard dans Windows. En particulier, les idées de lancement sur des déclencheurs non standard sont jouées - sur des événements matériels, points d'extension des programmes populaires, etc., etc. Voir aussi "Briser la chaîne" ci-dessus. V. CANAL DE RETOUR ET COMMUNICATIONS Les serveurs C&C sont toujours cachés : soit derrière des pads (proxy inverses), soit derrière un domaine tor. Les joints s'alignent en cascades, ils sont nombreux, de sorte que la défaillance de l'un n'entraîne pas l'effondrement de l'ensemble du réseau. Lors de la mise en œuvre d'un canal de communication avec C&C, n'oubliez pas que le système d'exploitation peut avoir son propre proxy système configuré. Pour la recherche C&C initiale, vous pouvez utiliser l'algorithme de génération de domaine (DGA - Domain Generation Algorithm) http://www.marc-blanchard.com/BotInvaders/index.php Son but est de générer des noms de domaine pseudo-aléatoires - qui ne sont pas trop nombreux (jusqu'à 10k) à trier dans un délai raisonnable ; - il y en a suffisamment pour qu'ils ne puissent pas être squattés ou interdits/usurpés d'une manière ou d'une autre ; - la liste des domaines d'un mois diffère de la liste des domaines d'un autre mois ; - il est difficile de créer une regex pour les découper sur les serveurs DNS. HTTPS est généralement utilisé pour communiquer avec le C&C, mais le port ou le protocole requis n'est pas toujours ouvert. Si le filtre DPI coupe le trafic HTTP(s), d'autres protocoles sont utilisés : - vous pouvez faire des requêtes DNS spécifiques au _nécessaire_ (votre) serveur DNS, et cacher des informations dans les noms de domaine - vous pouvez envoyer des messages ICMP spécifiques *** - Les protocoles de messagerie SMTP/IMAP/POP3 sont utilisés https://habr.com/ru/company/kaspersky/blog/522128/ En un mot, vous pouvez utiliser différentes options pour moduler le signal utile sur la porteuse, qui est garanti de passer à travers le pare-feu. Le trafic est intercepté et analysé par des systèmes comme Suricata https://suricata-ids.org/ détecter les anomalies et rechercher des modèles de trafic. bibliothèque PyWhat pour l'analyse automatique du trafic https://habr.com/ru/company/dcmiran/news/t/563206/ https://github.com/bee-san/pyWhat Il existe des listes noires de domaines, d'adresses, de certificats SSL, de profils de trafic, par exemple : https://sslbl.abuse.ch https://urlhaus.abuse.ch https://feodotracker.abuse.ch Des techniques telles que la prise d'empreinte client JA3/la prise d'empreinte serveur JA3S/JARM (hachage flou) sont utilisées : https://engineering.salesforce.com/tls-fingerprinting-with-ja3-and-ja3s-247362855967 https://habr.com/ru/company/acribia/blog/560168/ Leur essence est que la poignée de main TLS est prévisible pour la connexion client + serveur, car la poignée de main contient un grand nombre de combinaisons de chiffrements, en tenant compte de leur position relative. La poignée de main du même client avec le même serveur est toujours la même. Cette poignée de main est enregistrée en collant la version TLS, les chiffrements acceptés, la liste des extensions, les courbes elliptiques et les formats de courbe elliptique, et en superposant MD5. Suppresseur d'empreintes digitales : https://github.com/salesforce/ja3 https://ja3er.com/form Le remède à cela est la randomisation de la pile TLS (Cipher-Stunting) à la fois sur le client et sur le serveur (randomisation du paramètre SSLCipherSuite et autres) :
JA3/S Signatures and How to Avoid Them
https://www.vectra.ai/blogpost/c2-evasion-techniques TL; DR : l'applet de commande Enable-TlsCipherSuite vous permet de modifier la combinaison de chiffrement du client, mais il s'agit d'un paramètre à l'échelle du système. BCryptAddContextFunctionBCryptAddContextFunction https://docs.microsoft.com/en-us/windows/win32/secauthn/prioritizing-schannel-cipher-suites Il faut prévoir la pertinence constante de l'adresse du serveur C&C dans le corps du programme. Ainsi, au lieu d'utiliser des noms de domaine et une infrastructure DNS classiques, vous pouvez utiliser une infrastructure publique non révocable : - domaines emercoin et DNS (peuvent être effectués sous forme de requêtes spécifiques via le protocole Emercoin, et requêtes DNS régulières aux serveurs OpenNIC) - enregistrements dans les blockchains de crypto-monnaie (modulation des informations en montants, adresses ou enregistrements de service) - Domaines TOR (TOR n'est pas ouvert partout, et un code client spécifique est requis pour fonctionner au-dessus de TOR) - twitters et autres réseaux sociaux publics (moins souvent, car le compte peut être révoqué) par exemple https://safe.cnews.ru/news/top/2020-09-08_hakerynaemniki_shest_let Aperçu des techniques de communication avec l'aimable autorisation de Positive Technologies : https://habr.com/ru/company/pt/blog/497608/ Tunnellisation DNS : https://habr.com/ru/company/varonis/blog/513160/ Les approches de masquage de trafic sont utilisées pour lutter contre les détections de trafic réseau. Pour travailler à l'échelle industrielle, des constructeurs comme le C2 Malleable Profile pour Cobalt Strike sont utilisés. https://www.cobaltstrike.com/help-malleable-c2 https://github.com/threatexpress/random_c2_profile ou C3 Gateway Builder https://github.com/FSecureLABS/C3 Le principe est de sortir d'elle-même la couche transport du logiciel, de la rendre souplement personnalisable et masquable, permettre une expansion rapide et une réponse flexible aux détections grâce à la modularité (la fonctionnalité principale du logiciel est le module principal, fonctionnalité réseau - module d'extension à distance). Si tous les canaux du réseau sont complètement fermés, les informations peuvent toujours être envoyées. Une option est le courrier (SMTP): - Nous recherchons un client de messagerie sur la machine locale et mettons la lettre dans la boîte d'envoi, sans oublier de nettoyer après nous - nous recherchons un serveur SMTP dans la zone locale (bien qu'ils nécessitent désormais toujours une authentification) - De plus, la messagerie Web peut être disponible sur la machine locale (par exemple, OWA = Outlook Web Access) et Internet est fermé en même temps. Une autre option est la soi-disant "fusée": https://www.blackhat.com/docs/us-17/thursday/us-17-Kotler-The-Adventures-Of-Av-And-The-Leaky-Sandbox.pdf consistant, comme son nom l'indique, en deux étapes. La première étape doit être entièrement indétectable. Il collecte des informations du système, forme un message et le flashe dans la deuxième étape. La deuxième étape est un binaire avec les propriétés suivantes : - ça énerve AV (il y a des détections par signature) - il est en mesure de contacter le serveur C&C et de lui envoyer un colis cousu par le transporteur. D'autres événements se développent comme suit : - l'entreprise AB envoie la deuxième étape au "cloud" pour exécution dans le bac à sable - la deuxième étape entre dans le bac à sable et démarre - le bac à sable est situé dans le "cloud", en dehors du périmètre défendu, et à partir de là, il y a une connexion à Internet - la tâche du bac à sable est d'étudier le comportement de l'échantillon, donc son activité n'est pas supprimée, bien qu'elle soit enregistrée - la deuxième étape envoie des données à C&C, puis il ne s'en soucie plus - PROFIT VI. Élévation de privilèges CONTOURNER UAC C'est la première chose à faire : https://github.com/hfiref0x/UACME Les méthodes jusqu'au 20 environ sont obsolètes et ne fonctionnent pas; jusqu'à la 40e par une. En un mot, l'idée de contournement est la suivante : 1. Nous masquons le processus actuel comme un processus légitime, pour lequel Windows ne demande jamais la nécessité d'une élévation (en remplaçant le nom du processus dans PEB) 2. nous extrayons un autre processus qui a défini l'auto-élévation afin qu'il lance le .exe dont nous avons besoin (similaire à suid root sous Unix) Pour le deuxième point, il y a plusieurs façons. En aucun cas ne courez pas sur une machine personnelle ! IL EST POSSIBLE DE METTRE L'OS EN ERREUR ! ÉLÉVATION PRIVILÈGE (LPE) Sur l'escalade des privilèges, un aperçu des stratégies générales est ici : https://habr.com/ru/post/428602/ Les exploits spécifiques deviennent rapidement obsolètes, nous ne les présentons donc pas ici. L'idée générale derrière LPE sur Windows est d'obtenir et d'utiliser le jeton de sécurité de quelqu'un d'autre https://habr.com/ru/company/pt/blog/563436/ Théorie et pratique de LPE : https://habr.com/ru/company/otus/blog/530596/ Techniques générales d'exploitation des vulnérabilités dans le noyau : https://habr.com/ru/company/pt/blog/566698/ (correction HalDispatchTable, vol de jeton) VII. RECHERCHER Comment comprendre ce qui se passe à l'intérieur de la boîte noire, qu'elle soit recouverte d'un packer .exe, ou d'un système inconnu en général ? INTERCEPTION DES APPELS SYSTÈME Windows a l'API Monitor (du bundle rohitab) et Linux a strace. Nous écoutons les appels système du fichier exécutable qui nous intéresse, filtrons selon les critères nécessaires et comprenons l'image de ce qui se passe. INTERCEPTION DU TRAFIC Wireshark, vous pouvez trouver des adresses, des ports, des protocoles. Si vous êtes chanceux, vous pouvez même voir les détails. En raison du SSL omniprésent, c'est devenu difficile, mais vous pouvez glisser votre certificat racine dans le système, créer un proxy en l'utilisant, et attraper le trafic déjà sur le proxy. https://mitmproxy.org/ proxy pour HTTPS, également utile pour détecter les problèmes aux jonctions du sous-système DIFFÉRENCE DE PATCH / DIFFÉRENCE BINAIRE Un moyen de trouver une vulnérabilité pour la corriger. On prend l'ancien fichier exécutable, on prend le nouveau fichier exécutable (avec un patch de vulnérabilité), on regarde la différence, par la différence nous calculons les détails de l'opération. https://habr.com/ru/company/dsec/blog/479972/ https://wumb0.in/extracting-and-diffing-ms-patches-in-2020.html FUZZING Nous alimentons le système en entrées féroces non-sens, générées aléatoirement (mais selon les règles), et regardons quand il se casse (nous attrapons des plantages). De plus, en corrélant les données d'entrée et les plantages, nous trouvons une image stable. Plus loin, il est déjà possible de composer le shellcode pour le fonctionnement. Il existe de nombreux outils pour cela, personne ne le fait manuellement, tout est automatisé. Description du fuzzing en boîte blanche (avec des sources connues). https://habr.com/ru/company/dsec/blog/517596/ C'est plus pour les testeurs automatiques, le contrôle qualité et la génération de tests à la volée que pour la recherche/l'inverse. Néanmoins, l'article donne des notions générales de méthodes et d'outils. Fuzzer AFL (American Fuzzy Lop) populaire basé sur des algorithmes génétiques (morphing de l'échantillon d'entrée correct) https://github.com/google/AFL il est sous Windows https://github.com/googleprojectzero/winafl Justification des approches du fuzzing avec analyse de la théorie : https://habr.com/ru/company/bizone/blog/570312/ https://habr.com/ru/company/bizone/blog/570534/ https://wcventure.github.io/FuzzingPaper/ Fuzzer juste une boîte noire est futile. Besoin - inverser/analyser le code - rechercher les contrôles d'entrée - remplissez le fuzzer avec eux afin qu'il puisse muter correctement l'entrée et franchir les contrôles VIII. TECHNICIENS DES SERVICES AUXILIAIRES EXCEPTIONS ET LA PILE POST-MORT La capture de bogues et le débogage à l'échelle industrielle est une tâche plutôt banale, mais les solutions ne sont pas connues de tous et ne sont pas toujours triviales. Le principal moyen de découvrir ce qui n'a pas fonctionné est de supprimer la pile d'appels post-mortem et de l'envoyer par télémétrie au serveur. Théorie et pratique de la gestion des exceptions dans Windows : https://habr.com/ru/post/536990/ Pour ce faire, vous devez supprimer cette pile posthume. Pour ce faire, vous devez attraper un vol d'urgence du programme (alias crash) et supprimer les informations nécessaires avant de le laisser mourir. Il existe deux manières principales de procéder : * VEH - Gestion vectorielle des exceptions * SEH - Gestion structurée des exceptions Sur Linux/*nix, il y a des signaux (SIGBUS, SIGSTOP, SIGILL, etc.), man signal Encore une fois: - VEH est AddVectoredExceptionHandler() et article https://docs.microsoft.com/en-us/windows/win32/debug/using-a-vectored-exception-handler - SEH est __try ... __except et article https://docs.microsoft.com/en-us/cpp/cpp/try-except-statement?view=vs-2019 Si SEH est utilisé, tous les threads principaux doivent être enveloppés dans try / except. Si VEH est utilisé, il suffit de définir un gestionnaire commun dans le prologue du programme. Parmi les inconvénients de SEH - Erreur C2712 Impossible d'utiliser __try dans les fonctions qui nécessitent le déroulement d'un objet, et la solution est décrite ici https://stackoverflow.com/questions/51701426/cannot-use-try-in-functions-that-require-object-unwinding-fix Propriétés / C/C++ / Génération de code / Activer les exceptions C++ : Non Le principal inconvénient de l'une ou l'autre approche est qu'avec des processus évidés, aucune méthode ne donnera des numéros de ligne et des noms de fonction, car le chargement des symboles ne fonctionnera pas. Il n'y aura que des adresses nues. Dans le gestionnaire d'exceptions, il faut désempiler la pile (code ci-dessous). Si nous voulons des numéros de ligne de code, nous avons besoin de symboles (.pdb), et le projet doit être construit avec des options - C/C++ / Général / Format des informations de débogage : Base de données du programme (/Zi) - Linker / Débogage / Générer des informations de débogage : Optimiser pour le débogage (/DEBUG) - Linker / Debugging / Générer un fichier de base de données complet du programme : Oui et le .pdb doit se trouver à côté du .exe ou .dll mourant. Cela ne convient pas aux versions de combat, mais pour le débogage sur les ressources internes, vous pouvez le faire. Pour les assemblages de combat, la pile n'aura que des adresses, ce qui est également beaucoup. Le code de saut de pile est assez petit, nous le présentons ici : #include <windows.h> #include <Psapi.h> // Certaines versions de imagehlp.dll n'ont pas les directives d'emballage appropriées elles-mêmes // donc nous devons le faire. #pragma pack( push, before_imagehlp, 8 ) #include <imagehlp.h> #pragma pack( pop, before_imagehlp ) #pragma comment(lib, "psapi.lib") #pragma comment(lib, "dbghelp.lib") __declspec(noinline) DWORD DumpStackTrace() { entier non signé i ; vide * pile[100] ; trames courtes non signées ; SYMBOL_INFO*symbole ; traiter le processus ; debug_printf("PROGRAMME CRASHÉ, SUIVI DE LA PILE :\r\n"); processus = GetCurrentProcess(); if (!SymInitialize(process, NULL, TRUE)) renvoie 0 ; DWORD symOptions = SymGetOptions(); symOptions |= SYMOPT_LOAD_LINES | SYMOPT_UNDNAME | SYMOPT_LOAD_ANYTHING | SYMOPT_CASE_INSENSITIVE ; SymSetOptions(symOptions); frames = CaptureStackBackTrace(0, 100, pile, NULL); symbole = (SYMBOL_INFO *)calloc(sizeof(SYMBOL_INFO) + 256 * sizeof(char), 1); symbole->MaxNameLen = 255 ; symbole->SizeOfStruct = sizeof(SYMBOL_INFO); DWORD offset_from_symbol = 0 ; #ifdef _WIN64 IMAGEHLP_LINE64* ligne = (IMAGEHLP_LINE64*)calloc(sizeof(IMAGEHLP_LINE64), 1); ligne->SizeOfStruct = sizeof(IMAGEHLP_LINE64); #autre IMAGEHLP_LINE* line = (IMAGEHLP_LINE*)calloc(sizeof(IMAGEHLP_LINE), 1); ligne->SizeOfStruct = sizeof(IMAGEHLP_LINE); #fin si pour (i = 0; i < images; i++) { SymFromAddr(processus, (DWORD64)(pile[i]), 0, symbole); SymGetLineFromAddr(process, (DWORD64)(stack[i]), &offset_from_symbol, line); debug_printf( "%i : %s (%s :%i) - 0x%0X\n", frames - i - 1, symbole->Nom, ligne-> nom de fichier, ligne-> numéro de ligne, symbole-> adresse ); symbole->Nom[0] = 0 ; symbole->Adresse = 0 ; si(ligne->NomFichier) ligne->NomFichier[0] = 0 ; ligne->NuméroLigne = 0 ; } libre(symbole); ligne gratuite); retour 1 ; } FICHIERS DE CARTE (.MAP) Inclus dans le lien : Visual Studio / Propriétés du projet / Linker / Débogage / Générer un fichier de mappage : OUI Si le programme planté n'a pas de symboles dans .pdb, mais que l'adresse du plantage est connue, alors l'adresse de la fonction peut être trouvée à partir de la carte, comme décrit ici : https://www.codeproject.com/articles/3472/finding-crash-information-using-the-map-file RÉDUCTION DE LA TAILLE DU CODE AVIS DE NON-RESPONSABILITÉ CRT (BIBLIOTHÈQUE D'EXÉCUTION C) Un exemple de programme qui se compile en un .exe 3k : bonjour.cpp : #include <windows.h> const char *str="Message" ; int MaPrincipale() { MessageBoxA(NULL,str,str,MB_OK); ExitProcess(0); renvoie 0 ; } build.bat : définir PATH=c:\LLVM9\bin clang++.exe -DUNICODE -c -D_UNICODE -m32 -std=c++14 -Wall -Os -mno-sse -fms-extensions -fms-compatibility -fno-exceptions -fno-rtti -fomit-frame-pointer -ffunction -sections -fdata-sections -Wno-c++11-narrowing -Wc++11-compat-deprecated-writable-strings *.cpp -I"c:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\ comprendre" lld-link.exe /subsystem:windows /nodefaultlib /entry:MyMain /libpath:"c:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\lib" /libpath:"c:\Program Files (x86)\ Microsoft SDK\Windows\v7.1A\Lib" *.o kernel32.lib user32.lib Le point d'entrée par défaut est WinMainCRTStartup dans le CRT. Lorsque votre point d'entrée, CRT n'est pas nécessaire. De plus, le commutateur /nodefaultlib qui désactive le CRT est répertorié ici. Mais les fonctions strcpy devront être écrites par vous-même et les exceptions ne peuvent pas être utilisées. Mais strcpy est déjà dans shlwapi.lib, donc nous le faisons dans le code #include <Shlwapi.h> #pragma comment(lib,"Shlwapi.lib") CONTRÔLES DE SÉCURITÉ DÉSACTIVÉS Le compilateur Microsoft insère beaucoup de code défensif supplémentaire dans le code final - canaris de pile, vérifications hors tableau, la mise à zéro des variables à l'entrée de la fonction. Tout cela donne des kilo-octets supplémentaires et n'est pas nécessaire dans le code de combat. - Propriétés / C / C ++ / Génération de code / Vérifications d'exécution de base (/RTC) - par défaut (ce n'est pas très clair ce qu'il faut réellement définir ici) - Propriétés / C/C++ / Génération de code / Protection du flux de contrôle - Non - Propriétés / C/C++ / Génération de code / Créer une image avec mise à jour - Non (sauf si vous mettez des crochets sur vos propres fonctions) - Propriétés / С/С++ / Langage / Supprimer le code et les données non référencés - Oui / Zc:inline) - Propriétés / C/C++ / Langage / Inclure les informations de type d'exécution - Non OPTIMISATIONS - Désactiver les cadres de pile (omettre les pointeurs de cadre) - par défaut, lors de l'entrée dans la fonction, le sommet actuel de la pile dans le registre BSP. Ainsi, il est possible de délimiter la pile personnelle de la fonction courante de la pile des fonctions supérieures. Si vous désactivez l'enregistrement des cadres de pile, un registre supplémentaire sera libéré et le nombre d'instructions assembleur diminuera, à la fois en n'y écrivant pas et en permettant à davantage de variables d'être stockées et transmises à travers des registres. EN-TÊTE RICHE MICROSOFT http://ntcore.com/files/richsign.htm http://bytepointer.com/articles/the_microsoft_rich_header.htm Une section non standard dans un en-tête PE insérée par les éditeurs de liens Microsoft depuis 1998 et Microsoft Visual Studio 6.0. Il enregistre des statistiques sur la chaîne d'outils qui a collecté ce binaire, d'une manière ou d'une autre - le nombre de fichiers d'objets C, nombre de fichiers objets C++, nombre de fichiers objets ASM, version de l'éditeur de liens, version du compilateur de ressources, nombre de fonctions dans l'import, et tout ça. Cela a probablement été fait à des fins de débogage (pour déboguer la chaîne d'outils d'assemblage). Cependant, il faut comprendre que ce titre peut être utilisé pour la médecine légale comme une empreinte digitale. CODE CROSS-BIT Il est possible d'exécuter à la fois du code 32 bits en mode 64 bits et vice versa. Le noyau Windows fournit des passerelles telles que Heaven's Gate pour effectuer des appels système depuis le mode 32 bits : https://medium.com/@fsx30/hooking-heavens-gate-a-wow64-hooking-technique-5235e1aeed73 Un autre exemple:
Mixing x86 with x64 code
https://github.com/rwfpl/rewolf-wow64ext GÉNÉRATION DE NOMBRES PSEUDO-ALÉATOIRES Code et analyse d'algorithmes PRNG simples ici https://habr.com/ru/post/499490/ Revue théorique des PRNG non crypto-résistants et crypto-résistants : https://habr.com/en/post/531750/ Il faut rappeler que la qualité du RNG (précisément aléatoire, sans la lettre P dans l'abréviation) est le maillon le plus important en cryptographie. Un bon crypto-algorithme est annulé par l'utilisation d'un mauvais RNG (par exemple, pour générer gamma, vecteur IV, etc.). LITTÉRATURE 1. M. Russinovich, D. Solomon - Éléments internes de Microsoft Windows, 6e édition (Partie 1) [2013, PDF, RUS] - https://rutracker.org/forum/viewtopic.php?t=4469765 2. M. Russinovich, D. Solomon, A. Ionescu - La structure interne de Microsoft Windows. Sous-systèmes de base du système d'exploitation. 6e édition (Partie 2) [2014, PDF, RUS] - https://rutracker.org/forum/viewtopic.php?t=4727796 3. Bibliothèque du développeur - Love R. - Noyau Linux : une description du processus de développement, 3e éd. [2013, PDF, RUS] - https://rutracker.org/forum/viewtopic.php?t=5169029 4. Bibliothèque du programmeur - Alger J. - C++ [2008, PDF, RUS] - https://rutracker.org/forum/viewtopic.php?t=694260 5. Chris Kaspersky. Recueil de 507 articles - 01.03.2017 [PDF, DOC] - https://rutracker.org/forum/viewtopic.php?t=5375505 6. Comprendre Windows Shellcode - mmiller@hick.org - http://www.hick.org/code/skape/papers/win32-shellcode.pdf 7. https://0xpat.github.io/ 0xPat blog Red/purple teamer - série d'articles "Développement de logiciels malveillants"
Happy
Happy
100 %
Sad
Sad
0 %
Excited
Excited
0 %
Sleepy
Sleepy
0 %
Angry
Angry
0 %
Surprise
Surprise
0 %