123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127 |
- \nocite{keetch2009practicalsandboxing}
- \nocite{ISCWindowsACL}
- \nocite{GoogleProjectZero}
- % TODO: remplacer confiant
- Après la présentation des objectifs liés aux communications inter-processus et à
- l'implémentation Linux, nous pouvons essayer de reprendre le même modèle pour
- l'implémentation Windows. Malheureusement celle-ci vient nous rappeler qu'un
- changement de système implique parfois un changement de paradigme. La
- documentation quelque peu hasardeuse va néanmoins nous permettre de mettre en
- place une architecture similaire.
- \section{Communication inter-processus}
- Windows dispose de beaucoup de moyens de communication inter-processus. Parmi
- ceux là, aucun ne va avoir les mêmes propriétés que les sockets Unix. Nous
- allons même de base éliminer tous les moyens «haut niveau» comme les ports COM
- résolvant plutôt des problèmes d'interopérabilité et se concentrer sur les
- moyens plus bas niveau.
- \subsection{Les sockets Windows}
- Les sockets Windows réimplémentent la même interface que les sockets Berkeley
- mais ne fournissent pas de sockets locaux ou anonymes. Ceux-ci passent par la
- pile réseau pour l'envoi de message. On notera cependant l'implémentation de
- «TCP Loopback Fast Path» depuis Windows Server 2012. Cette fonctionnalité
- conserve la sémantique du protocole TCP tout en désactivant des fonctionnalités
- comme l'algorithme de Nagle. \cite{WindowsFastTCPLoopback}
- C'est donc ce qui ressemble le plus aux sockets Unix, excepté l'accès au réseau
- et le passage de descripteur de fichiers.
- \subsection{Les canaux anonymes}
- Les canaux anonymes donnent un moyen de communication unidirectionnel avec un
- écrivain et un lecteur. Il faut donc utiliser une paire de canaux anonymes pour
- pouvoir discuter en full-duplex, mais également utiliser un mécanisme pour
- transmettre le \inltype{HANDLE} d'un processus à l'autre. À noter que la plupart
- des fonctions sur les canaux nommés fonctionnent avec les canaux anonymes, ces
- derniers étant implémentés comme des canaux nommés avec un nom particulier.
- \subsection{Les canaux nommés}
- Les canaux nommés sont capables de fonctionner en full-duplex et disposent
- pleinement du système d'ACL global de Windows.
- Ici, on va plutôt s'intéresser aux canaux nommés et voir comment on peut les
- utiliser pour transmettre des messages et des ressources. La création d'un canal
- nommé se fait avec avec la famille de fonction \inltype{CreateNamedPipe}. Dans
- notre cas, on sera fortement tenté d'utiliser des \inltype{lpSecurityAttributes}
- définis avec de bonnes valeurs, mais ce point sera exploré dans la suite du
- document.
- \begin{code}{c}{Prototype de \inltype{CreateNamedPipe}}
- HANDLE CreateNamedPipeA(
- LPCSTR lpName,
- DWORD dwOpenMode,
- DWORD dwPipeMode,
- DWORD nMaxInstances,
- DWORD nOutBufferSize,
- DWORD nInBufferSize,
- DWORD nDefaultTimeOut,
- LPSECURITY_ATTRIBUTES lpSecurityAttributes
- );
- \end{code}
- \section{Transfert de ressources entre processus}
- Windows dispose de trois mécanismes pour partager des ressources entre
- processus. Les ressources sont représentées par des objets \inltype{HANDLE}.
- La première méthode est l'héritage, qui a lieu lors de la création d'un nouveau
- processus. Les descripteurs de fichiers marqués comme héritables, ou bien aucun
- si \inltype{bInheritHandles} est précisé à \inltype{FALSE} lors de l'appel de
- \inltype{CreateProcess}, seront récupérés dans le nouveau processus avec la même
- valeur. Lorsqu'un \inltype{HANDLE} est hérité, il garde la même valeur dans le
- nouveau processus et il faut donc le transmettre soit par IPC, soit par
- paramètre de la ligne de commande, soit par injection de code dans le nouveau
- processus.
- La seconde méthode utilise la fonction \inltype{DuplicateHandle} pour injecter
- le descripteur de fichier dans le nouveau processus. Dans ce cas-là, si l'appel
- est fait depuis le processus parent, une nouvelle valeur est générée pour ce
- \inltype{HANDLE} et il faut le transmettre au processus enfant par l'une des
- méthodes mentionnées dans le cas de l'héritage.
- \begin{code}{c}{Prototype de la fonction \inltype{DuplicateHandle}}
- BOOL WINAPI DuplicateHandle(
- _In_ HANDLE hSourceProcessHandle,
- _In_ HANDLE hSourceHandle,
- _In_ HANDLE hTargetProcessHandle,
- _Out_ LPHANDLE lpTargetHandle,
- _In_ DWORD dwDesiredAccess,
- _In_ BOOL bInheritHandle,
- _In_ DWORD dwOptions
- );
- \end{code}
- L'exploitation de \inltype{DuplicateHandle} demande à ce que chacun des deux
- processus rentrant en jeu dans la fonction, à savoir
- \inltype{hSourceProcessHandle} et \inltype{hTargetProcessHandle} disposent du
- droit \inltype{PROCESS_DUP_HANDLE}. Étant donné que la fonction peut être
- utilisée de la source vers la destination ou depuis la destination récupérant un
- \inltype{HANDLE} appartenant à la source, le processus ayant accès à l'autre
- processus est capable de copier tout accès existant et dispose donc des mêmes
- droits que ce dernier.
- Cette remarque est importante pour se rendre compte que l'utilisation de cette
- méthode implique nécessairement un broker, qui sera suffisamment privilégié pour
- accéder aux deux processus souhaitant partager une ressource. Tenter d'appliquer
- cette fonction directement dans les workers impliquerait que chacun des workers
- auraient les mêmes droits que ses voisin et, de façon transitive, aurait accès à
- toutes les zones de privilèges connexes dans le graphe d'IPC.
- Enfin, la troisième méthode consiste à utiliser les objets nommés qui sont
- créés d'un côté par le processus parent, puis ouverts par les processus enfants
- en les référençant par leur nom.
- Dans le prototype, j'ai utilisé des canaux nommés pour faciliter la mise en place
- mais j'ai également essayé d'utiliser des paires de canaux anonymes dans d'autres
- codes simulant le fonctionnement des IPC. J'ai également prévu de mettre en
- place la méthode utilisant \inltype{DuplicateHandle} et donc un broker central
- pour pouvoir transférer des ressources de la même façon que sous Linux.
- J'essayerai cependant de m'approcher d'un modèle orchestrateur avec d'autres
- techniques mais nous allons voir qu'il n'y a pas vraiment d'alternative pour
- l'instant.
|