Skip to content
Obfuscationintermediate

Dynamic Import Resolution

Au lieu d'une table d'imports normale, le programme résout les API à l'exécution via LoadLibrary et GetProcAddress sur des chaînes chiffrées, laissant l'IAT statique quasi vide et l'analyste aveugle.

La résolution dynamique d'imports cache les API qu'un programme utilise en refusant de les déclarer dans l'Import Address Table (IAT). À l'exécution, le code appelle LoadLibraryA pour obtenir un handle de module et GetProcAddress pour rechercher chaque fonction par son nom, en utilisant des chaînes déchiffrées ou reconstruites sur la pile. L'IAT statique ne liste alors que quelques fonctions de chargement, si bien qu'un triage rapide ne révèle presque rien du comportement du malware. Cette technique est distincte du hachage d'API, qui résout les fonctions par un hachage de leur nom plutôt que par le nom en clair.

Fonctionnement

Le programme ne référence jamais l'API cible directement. Il construit le nom de la DLL et de la fonction (souvent déchiffré ou assemblé octet par octet pour déjouer la recherche de chaînes), résout l'adresse et l'appelle. L'IAT ne contient que LoadLibraryA et GetProcAddress.

c
// static IAT shows nothing useful; everything is resolved at runtime
char dll[]  = decrypt("kernel32.dll");
char name[] = decrypt("VirtualAlloc");        // also built on the stack

HMODULE h   = LoadLibraryA(dll);
FARPROC fn  = GetProcAddress(h, name);        // <-- real API recovered here
void *mem   = ((PFN_VirtualAlloc)fn)(0, len, MEM_COMMIT, PAGE_RWX);

Détection & contournement

  • Statique — Dans IDA/Ghidra, la vue des imports est quasi vide à l'exception de LoadLibraryA/GetProcAddress. Les appels passent par des pointeurs en registre (call rax) plutôt que par des thunks nommés, et l'on voit des stubs de déchiffrement ou de construction de chaînes sur la pile alimenter les appels de chargement. Les références croisées depuis GetProcAddress cartographient les sites de résolution.
  • Dynamique — Posez des points d'arrêt de journalisation conditionnels sur LoadLibraryA et GetProcAddress, journalisez le nom demandé (argument) et l'adresse retournée (rax/eax), et vous obtenez immédiatement la liste complète des API résolues et l'emplacement de chaque pointeur. L'Interceptor de Frida ou API Monitor capturent la même correspondance sans scripter de points d'arrêt.
  • Patch / simplification — Annotez chaque pointeur résolu avec le vrai nom d'API dans le désassembleur, puis dumpez le processus et reconstruisez une IAT correcte afin que le listing devienne lisible et ré-exécutable.
  • Outils — Points d'arrêt de journalisation conditionnels de x64dbg, Scylla ou ImpRec pour la reconstruction d'IAT sur un dump, l'Interceptor de Frida pour le hooking à chaud, et API Monitor.
Votes

Commentaires(0)