Skip to content
KitploitKITPLOIT
OutilsExploitsBlog
Log in
Soumettre
OutilsExploitsBlog
Soumettre

Outils de Hacking, PenTest et Cybersécurité pour votre Arsenal de Sécurité !

Kitploit est un répertoire d'outils de hacking, de cybersécurité et de pentesting. Découvrez les dernières mises à jour des projets pour trouver des vulnérabilités, analyser des systèmes, automatiser les tests et renforcer votre sécurité.

FluxContactConfidentialité© 2026 Kitploit

Répertoire d'outils

Catégories

Voir toutes les catégories
Loading categories
NullGate — Bibliothèque qui facilite l'utilisation des syscalls indirects. Contournement AV/EDR assez intéressant en tant que PoC. | Kitploit
Outils/GitHubGitHub/0xsch1zo/nullgate
Outils de Chiffrement/DéchiffrementShellcodePost-ExploitationRed TeamingDéveloppement de Charges UtilesAttaque Adversariale
GitHub0xsch1zo/nullgate

NullGate

Bibliothèque qui facilite l'utilisation des syscalls indirects. Contournement AV/EDR assez intéressant en tant que PoC.

Voir le dépôt
1681932il y a 1 anVérifié par Kitploit

Populaires

Voir tout →

Découvrez les outils les plus utilisés par notre communauté.

Explorer tous les outils

Parcourez notre collection d'outils

Voir tous les outils →
Partager

NullGate

Ce projet implémente une manière confortable et moderne d'utiliser les fonctions NTAPI via des appels système indirects, couplée à la méthode FreshyCalls avec une petite variante pour la récupération dynamique des numéros d'appels système. Il utilise également une technique que je n'ai pas vu être mentionnée pour contourner l'analyse mémoire de Windows Defender. Le projet implémente un injecteur de processus PoC classique utilisant la bibliothèque. Des fonctions pratiques pour le chiffrement sont également disponibles.

Démo

Démonstration de l'exemple

Compilation

Pour compiler l'exemple, utilisez -DNULLGATE_BUILD_SAMPLE=ON. Si vous avez compilé nullgate directement, il sera accessible à <build_dir>/sample.exe, si vous l'avez compilé en tant que dépendance à <build_dir>/_deps/nullgate-build/sample.exe. Sous Windows, comme les destinations de compilation sont étranges, il sera probablement dans les mêmes répertoires de base que les emplacements des exemples, mais probablement avec beaucoup plus de niveaux d'imbrication. Il prend en argument un PID dans lequel vous souhaitez injecter du shellcode.

[!WARNING] Si vous utilisez Linux, vous devez avoir le compilateur croisé mingw installé. Sur Arch par exemple, vous pouvez faire pacman -S mingw-w64-gcc. Utilisez ensuite l'option -DNULLGATE_CROSSCOMPILE=ON pour définir mingw comme compilateur par défaut.

[!TIP] Il est également recommandé de stripper le binaire résultant afin de réduire les possibilités de détection

git clone https://github.com/0xsch1zo/NullGate
cd NullGate
cmake . -B build -DNULLGATE_BUILD_SAMPLE=ON
cmake --build build/

hashser obsolète (versions 1.1.3 et inférieures)

Il peut être compilé à l'aide de l'option -DNULLGATE_DEPRECATED_HASHER.

Utilisation

Ajouter nullgate à votre projet

Le CMake FetchContent est pris en charge. Voici un exemple de CMakeLists.txt simple :

cmake_minimum_required(VERSION 3.25)

include(FetchContent)

FetchContent_Declare(nullgate
    GIT_REPOSITORY https://github.com/0xsch1zo/NullGate
    GIT_TAG 1.2.0 
)

FetchContent_MakeAvailable(nullgate)

project(test)

add_executable(test
    main.cpp
)

target_link_libraries(test
    PRIVATE nullgate
)

La liaison est effectuée statiquement, vous n'avez donc pas à vous soucier de la visibilité des symboles.

[!NOTE] Les exemples suivants utiliseront namespace ng = nullgate

Appels système

L'utilisation est assez simple, voici un extrait illustrant la fonctionnalité principale :

ng::syscalls syscalls;
typedef NTSTATUS NTAPI NtAllocateVirtualMemory(
    _In_ HANDLE ProcessHandle,
    _Inout_ _At_(*BaseAddress,
                 _Readable_bytes_(*RegionSize) _Writable_bytes_(*RegionSize)
                     _Post_readable_byte_size_(*RegionSize)) PVOID *BaseAddress,
    _In_ ULONG_PTR ZeroBits, _Inout_ PSIZE_T RegionSize,
    _In_ ULONG AllocationType, _In_ ULONG PageProtection);

NTSTATUS status = syscalls.SCall<NtAllocateVirtualMemory>(
      ng::obfuscation::fnv1Const("NtAllocateVirtualMemory"), processHandle,
      &buf, 0, &regionSize, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);

La sécurité de types est intégrée. Vous avez simplement besoin de fournir la définition de la fonction NT que vous souhaitez appeler ! Vous pouvez facilement l'obtenir depuis ntdoc. C'est la manière recommandée d'utiliser la bibliothèque.

L'interface précédente non obsolète

Pour ceux qui n'aiment pas la magie noire du templating C++ ou quelque chose du genre, l'interface précédente est toujours disponible :

NTSTATUS status = syscalls.Call(ng::obfuscation::fnv1Const("NtAllocateVirtualMemory"),
                         processHandle, (PVOID)&buf, (ULONG_PTR)0, &regionSize,
                         (ULONG)(MEM_RESERVE | MEM_COMMIT), (ULONG)PAGE_EXECUTE_READWRITE);

Avec cette interface, vous devez caster les arguments vers le bon type ; ne pas le faire peut causer des problèmes.

Chiffrement/hachage

Hachage des appels NTAPI

constexpr uint64_t hash = ng::obfuscation::fnv1Const("NtAllocateVirtualMemory");

La méthode fnv1Const démontrée précédemment apporte les joies du C++ moderne au monde du maldev. C'est une fonction consteval, donc il est garanti qu'elle sera évaluée au moment de la compilation, remplaçant le nom de fonction lisible par un hash fnv1.

Il existe également un équivalent à l'exécution appelé fnv1Runtime, mais bien sûr il n'apporte pas l'avantage d'obfusquer nos noms de fonctions. Il est utilisé par l'implémentation pour vérifier quelle fonction dans ntdll doit être utilisée pour obtenir le numéro d'appel système.

Chiffrement xor général

Il existe trois routines pour le « chiffrement » xor :

xorConst
constexpr ng::obfuscation::ConstData xored = ng::obfuscation::xorConst("some string");
std::cout << xored.string();

Sortie possible :

<Y:-E&X0

Cette routine, comme la fonction fnv1Const, est évaluée au moment de la compilation, donc "some string" n'apparaîtra jamais dans le binaire, car la chaîne sera stockée sous sa forme chiffrée. Mais bon, nous devons réellement utiliser ces données ! ConstData est une fine enveloppe autour d'octets bruts, de taille constante. Elle a deux méthodes : raw() et string(). raw() retourne un std::vector<unsigned char> et string, comme son nom l'indique, retourne un std::string.

[!NOTE] Si vous devez construire ConstData directement avec une chaîne littérale, utilisez std::to_array pour construire un tableau intermédiaire passé à ConstData. Veuillez toutefois noter qu'avec cette approche, ConstData stockera le caractère nul supplémentaire de la chaîne littérale.

Bien sûr, nous avons besoin d'un moyen de déchiffrer ces données et de les utiliser, c'est ce que couvre la fonction suivante.

xorRuntime

xorRuntime est la deuxième routine disponible. Comme son nom l'indique, c'est l'équivalent à l'exécution de xorConst. Veuillez noter qu'elle ne doit pas être utilisée uniquement pour le déchiffrement : elle fonctionne dans les deux sens, bien que l'utiliser pour le chiffrement n'apporte pas les avantages d'obfusquer la chaîne au moment de la compilation.

ng::obfuscation::ConstData xored = ng::obfuscation::xorConst("some string");
ng::obfuscation::ConstData data = ng::obfuscation::xorRuntime(xored);
assert(data.string() == "some string");

std::string dynamicString = "some data of dynamic size";
auto dynamicData = ng::obfuscation::DynamicData(dynamicString);
auto xoredDynamic = ng::obfuscation::xorRuntime(dynamicData);
auto unxoredDynamic = ng::obfuscation::xorRuntime(xoredDynamic);
assert(unxoredDynamic.string() == dynamicString);

DynamicData possède les mêmes méthodes que ConstData, avec quelques constructeurs supplémentaires pour l'interopérabilité, et comme son nom l'indique, elle peut avoir une taille non connue au moment de la compilation. xorRuntime accepte à la fois DynamicData et ConstData.

Télécharger l’outil