Étant donné un ID de fenêtre X11, existe-t-il un moyen de trouver l'ID du processus qui l'a créé ?
Bien sûr, ce n'est pas toujours possible, par exemple si la fenêtre est arrivée via une connexion TCP. Dans ce cas, j'aimerais connaître l'adresse IP et le port associés à l'extrémité distante.
La question a déjà été posée sur Stack Overflow, et une méthode proposée consistait à utiliser le _NET_WM_PID
biens. Mais c'est défini par l'application. Existe-t-il un moyen de le faire si l'application ne fonctionne pas correctement ?
Réponse acceptée :
Sauf si votre serveur X prend en charge XResQueryClientIds
de l'extension X-Resource v1.2 je ne connais pas facile moyen de fiable ID de processus de demande. Il existe cependant d'autres moyens.
Si vous avez juste une fenêtre devant vous et que vous ne connaissez pas encore son identifiant, il est facile de le découvrir. Ouvrez simplement un terminal à côté de la fenêtre en question, exécutez xwininfo
là et cliquez sur cette fenêtre. xwininfo
vous montrera le window-id.
Supposons donc que vous connaissiez un identifiant de fenêtre, par ex. 0x1600045, et que vous voulez trouver, quel est le processus qui le possède.
Le moyen le plus simple de vérifier à qui appartient cette fenêtre est d'exécuter XKillClient pour elle, c'est-à-dire :
xkill -id 0x1600045
et voir quel processus vient de mourir. Mais seulement si cela ne vous dérange pas de le tuer bien sûr !
Un autre moyen simple mais peu fiable est de vérifier son _NET_WM_PID
et WM_CLIENT_MACHINE
propriétés :
xprop -id 0x1600045
C'est ce que des outils comme xlsclients
et xrestop
faire.
Malheureusement, ces informations peuvent être incorrectes non seulement parce que le processus était mauvais et les a modifiés, mais aussi parce qu'il était bogué. Par exemple, après un crash/redémarrage de firefox, j'ai vu des fenêtres orphelines (du plugin flash, je suppose) avec _NET_WM_PID
pointant vers un processus, qui est mort il y a longtemps.
Une autre façon est de courir
xwininfo -root -tree
et vérifiez les propriétés des parents de la fenêtre en question. Cela peut également vous donner des indices sur les origines des fenêtres.
Mais! Bien que vous ne trouviez peut-être pas quel processus a créé cette fenêtre, il existe toujours un moyen de savoir d'où ce processus s'est connecté au serveur X. Et cette façon est pour les vrais pirates. 🙂
L'identifiant de fenêtre 0x1600045 que vous connaissez avec les bits inférieurs mis à zéro (c'est-à-dire 0x1600000) est une "base client". Et tous les ID de ressource, alloués pour ce client sont "basés" dessus (0x1600001, 0x1600002, 0x1600003, etc.). Le serveur X stocke des informations sur ses clients dans le tableau clients[] et, pour chaque client, sa "base" est stockée dans la variable clients[i]->clientAsMask. Pour trouver X-socket, correspondant à ce client, vous devez vous connecter au serveur X avec gdb
, parcourez le tableau clients[], trouvez le client avec ce clientAsMask
et affiche son descripteur de socket, stocké dans ((OsCommPtr)(clients[i]->osPrivate))->fd.
Il peut y avoir de nombreux clients X connectés, donc pour ne pas tous les vérifier manuellement, utilisons une fonction gdb :
define findclient
set $ii = 0
while ($ii < currentMaxClients)
if (clients[$ii] != 0 && clients[$ii]->clientAsMask == $arg0 && clients[$ii]->osPrivate != 0)
print ((OsCommPtr)(clients[$ii]->osPrivate))->fd
end
set $ii = $ii + 1
end
end
Lorsque vous trouvez la prise, vous pouvez vérifier qui y est connecté et enfin trouver le processus.
Connexe :Comment télécharger une application à partir de la boutique Windows 10 pour la télécharger ?
AVERTISSEMENT :N'attachez PAS gdb au serveur X depuis l'INTÉRIEUR du serveur X. gdb suspend le processus auquel il s'attache, donc si vous vous y attachez depuis l'intérieur de la session X, vous gèlerez votre serveur X et ne pourrez pas interagir avec gdb. Vous devez soit passer en terminal texte (Ctrl+Alt+F2
) ou connectez-vous à votre machine via ssh.
Exemple :
-
Trouvez le PID de votre serveur X :
$ ps ax | grep X 1237 tty1 Ssl+ 11:36 /usr/bin/X :0 vt1 -nr -nolisten tcp -auth /var/run/kdm/A:0-h6syCa
-
L'identifiant de la fenêtre est 0x1600045, donc la base client est 0x1600000. Connectez-vous au serveur X et recherchez le descripteur de socket client pour cette base de clients. Vous aurez besoin des informations de débogage
installées pour le serveur X (paquet -debuginfo pour les distributions rpm ou paquet -dbg pour deb).$ sudo gdb (gdb) define findclient Type commands for definition of "findclient". End with a line saying just "end". > set $ii = 0 > while ($ii < currentMaxClients) > if (clients[$ii] != 0 && clients[$ii]->clientAsMask == $arg0 && clients[$ii]->osPrivate != 0) > print ((OsCommPtr)(clients[$ii]->osPrivate))->fd > end > set $ii = $ii + 1 > end > end (gdb) attach 1237 (gdb) findclient 0x1600000 $1 = 31 (gdb) detach (gdb) quit
-
Vous savez maintenant que le client est connecté à un serveur socket 31. Utilisez
lsof
pour trouver ce qu'est cette prise :$ sudo lsof -n | grep 1237 | grep 31 X 1237 root 31u unix 0xffff810008339340 8512422 socket
(ici "X" est le nom du processus, "1237" est son pid, "root" est l'utilisateur à partir duquel il s'exécute, "31u" est un descripteur de socket)
Là, vous pouvez voir que le client est connecté via TCP, vous pouvez alors accéder à la machine à partir de laquelle il est connecté et vérifier
netstat -nap
là pour trouver le processus. Mais vous y verrez très probablement un socket Unix, comme indiqué ci-dessus, ce qui signifie qu'il s'agit d'un client local. -
Pour trouver une paire pour ce socket unix, vous pouvez utiliser la technique de MvG (vous aurez également besoin d'informations de débogage pour votre noyau installé) :
$ sudo gdb -c /proc/kcore (gdb) print ((struct unix_sock*)0xffff810008339340)->peer $1 = (struct sock *) 0xffff810008339600 (gdb) quit
-
Maintenant que vous connaissez le socket client, utilisez
lsof
pour trouver le PID qui le contient :$ sudo lsof -n | grep 0xffff810008339600 firefox 7725 username 146u unix 0xffff810008339600 8512421 socket
C'est ça. Le processus qui conserve cette fenêtre est "firefox" avec l'ID de processus 7725
Modification 2017 :Il y a plus d'options maintenant comme on le voit sur Qui a l'autre bout de cette paire de sockets unix ?. Avec Linux 3.3 ou supérieur et avec lsof
4.89 ou supérieur, vous pouvez remplacer les points 3 à 5 ci-dessus par :
lsof +E -a -p 1237 -d 31
pour savoir qui est à l'autre bout du socket sur fd 31 du processus X-server avec l'ID 1237.