
Obfusquer des API Windows spécifiques avec différentes API
Obfusquer (cacher) les importations PE des outils d'analyse statique/dynamique.
C'est assez simple, disons que j'ai utilisé VirtualProtect et que je veux l'obfusquer avec Sleep, l'outil manipulera l'IAT de sorte que le thunk qui pointe vers VirtualProtect pointe plutôt vers Sleep. Lors de l'exécution du fichier, le chargeur Windows chargera Sleep au lieu de VirtualProtect, et déplacera l'exécution vers le point d'entrée. À partir de là, l'exécution sera redirigée vers le shellcode, que l'outil a placé auparavant, pour trouver l'adresse de VirtualProtect et l'utiliser pour remplacer l'adresse de Sleep qui a été assignée précédemment par le chargeur.
#include <cobf.hpp>
int main() {
cobf obf_file = cobf("sample.exe");
obf_file.load_pe();
obf_file.obf_sym("kernel32.dll", "SetLastError", "Beep");
obf_file.obf_sym("kernel32.dll", "GetLastError", "GetACP");
obf_file.generate("sample_obfuscated.exe");
obf_file.unload_pe();
return 0;
};
config.ini).cobf.exe <input file> <out file> [config file]; Template for the config file:
; * Sections can be written as:
; [dll_name]
; old_sym=new_sym
; * The dll name is case insensitive, but
; the old and the new symbols are not.
; * You can use the wildcard on both the
; dll name and the old symbol.
; * You can use '#' at the start of
; the old or the new symbol to flag
; an ordinal.
; * The new symbol should be exported
; by the dll so the windows loader can resolve it.
; For example:
; * Obfuscating all of the symbols
; imported from user32.dll with ordinal 1600.
[user32.dll]
*=#1600
; * Obfuscating symbols imported from both
; kernel32.dll and kernelbase.dll with Sleep.
[kernel*.dll]
*=Sleep
; * Obfuscating fprintf with exit.
[*]
fprintf=exit
Compilez cet exemple de code
#include <windows.h>
#include <stdio.h>
int main() {
SetLastError(5);
printf("Last error is %d\n", GetLastError());
return 0;
};
Après l'avoir compilé, voici à quoi ressemblent les importations kernel32

Maintenant, obfusquons à la fois SetLastError et GetLastError avec Beep et GetACP (en fait, n'importe quelle API de kernel32 fera l'affaire, même si elle n'est pas importée du tout).
Les configurations utilisées sont
[kernel32.dll]
SetLastError=Beep
GetLastError=GetACP
Voici le résultat (vous pouvez aussi utiliser la bibliothèque directement comme montré ci-dessus).

Regardons à nouveau les importations kernel32

Il n'y a aucune trace de SetLastError ou GetLastError
Une confirmation que les deux fichiers fonctionneront correctement

IDA HexRays Decompiler

IDA Debugger

Ghidra

ApiMonitor

C'est parce que tous les outils d'analyse statique dépendent du nom de l'API écrit dans l'IAT, qui peut être manipulé comme montré.
Pour ApiMonitor, à cause de l'utilisation du hooking IAT, le même problème existe.
D'un autre côté, pour des outils comme x64dbg, les noms d'API affichés ne dépendront que de ce qui est réellement appelé (pas de ce qui est écrit dans l'IAT).

.cobf pour contenir le shellcode et les autres données nécessaires.git clone https://github.com/d35ha/CallObfuscator.