À moins que votre serveur X prend en charge XResQueryClientIds
de l' extension v1.2 X-ressources Je ne connais pas facile moyen de manière fiable demander l' ID de processus. Il y a d'autres façons cependant.
Si vous avez juste une fenêtre devant vous et que vous ne connaissez pas encore son identifiant, il est facile de le trouver. Ouvrez simplement un terminal à côté de la fenêtre en question, exécutez xwininfo
-le et cliquez sur cette fenêtre. xwininfo
va vous montrer l'id de la fenêtre.
Supposons donc que vous connaissez un identifiant de fenêtre, par exemple 0x1600045, et que vous souhaitiez savoir quel est le processus le possédant.
Le moyen le plus simple de vérifier à qui appartient cette fenêtre est d’exécuter XKillClient, c’est-à-dire:
xkill -id 0x1600045
et voir quel processus vient de mourir. Mais seulement si ça ne vous dérange pas de le tuer bien sûr!
Une autre façon facile , mais peu fiable est de vérifier ses _NET_WM_PID
et WM_CLIENT_MACHINE
propriétés:
xprop -id 0x1600045
C'est ce que les outils aiment xlsclients
et xrestop
font.
Malheureusement, ces informations peuvent être incorrectes, non seulement parce que le processus était pervers et les a modifiées, mais également parce qu’il était bogué. Par exemple, après un crash / redémarrage de Firefox, j'ai vu des fenêtres orphelines (provenant du plug-in flash, je suppose) _NET_WM_PID
pointant vers un processus qui s'est éteint depuis 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 aussi vous donner des indices sur l’origine 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 où ce processus s'est connecté au serveur X. Et cette façon est pour les vrais hackers. :)
L'identificateur de fenêtre 0x1600045 que vous connaissez avec les bits inférieurs mis à zéro (c.-à-d. 0x1600000) est une "base client". Et tous les ID de ressources alloués à ce client sont "basés" sur celui-ci (0x1600001, 0x1600002, 0x1600003, etc.). X-server stocke des informations sur ses clients dans le groupe de clients [] et, pour chaque client, sa "base" est stockée dans la variable de clients [i] -> clientAsMask. Pour trouver X-socket correspondant à ce client, vous devez vous connecter au serveur X avec gdb
, parcourir le tableau clients [], trouver le client avec cela clientAsMask
et imprimer son descripteur de socket, stocké dans ((OsCommPtr) (clients [i] - > osPrivate)) -> fd.
Il peut y avoir beaucoup de clients X connectés, donc pour ne pas les vérifier tous 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 le socket, vous pouvez vérifier qui est connecté et enfin trouver le processus.
AVERTISSEMENT : N'attachez PAS gdb au serveur X depuis INSIDE. gdb suspend le processus auquel il est attaché; ainsi, si vous vous y attachez depuis X-session, vous figez votre serveur X et vous ne pourrez plus interagir avec gdb. Vous devez soit basculer sur text terminal ( Ctrl+Alt+F2
), soit vous connecter à 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, la base du client est donc 0x1600000. Attachez 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 (paquetage -debuginfo pour les distributions rpm ou paquetage -dbg pour les 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 socket de serveur 31. Utilisez lsof
pour trouver ce qu'est ce socket:
$ 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 depuis lequel il est en cours d'exécution, "31u" est un descripteur de socket)
Là, vous pouvez voir que le client est connecté via TCP, alors vous pouvez aller sur la machine à partir de laquelle il est connecté et vérifier netstat -nap
le processus. Mais très probablement, vous verrez une prise Unix ici, 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 rechercher le PID le tenant:
$ sudo lsof -n | grep 0xffff810008339600
firefox 7725 username 146u unix 0xffff810008339600 8512421 socket
C'est ça. Le processus maintenant cette fenêtre est "firefox" avec l'identifiant de processus 7725
Édition 2017 : Il y a maintenant plus d'options comme on peut le voir sur Qui a l'autre extrémité de cette socket 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 se trouve à l’autre extrémité du socket sur le disque 31 du processus du serveur X avec l’ID 1237.