Compte tenu d'un ID de fenêtre X11, est-il un moyen de trouver l'identifiant du processus qui l'a créé?
Bien sûr, ce n'est pas toujours possible, par exemple si la fenêtre est venue sur un TCP Connection. Pour ce cas, j'aimerais que l'IP et le port associés à l'extrémité distante.
La question a été posée avant le débordement de la pile et une méthode proposée devait utiliser le _NET_WM_PID
biens. Mais c'est défini par l'application. Y a-t-il un moyen de le faire si l'application ne joue pas bien?
Sauf si votre X-Server prend en charge XResQueryClientIds
de x-ressource V1.2 Extension Je sais non facile Way to Reliblement Demander un identifiant de processus. Il y a d'autres moyens 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
là et cliquez sur cette fenêtre. xwininfo
_ vous montrera l'identifiant de la fenêtre.
Alors supposons que vous connaissez une fenêtre de fenêtre, par exemple. 0x1600045, et veulent trouver, quel est le processus qui en possède.
Le moyen le plus simple de vérifier qui appartient à cette fenêtre est de courir xkillclient pour cela .:
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!
Une autre manière facile 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 les outils comme xlsclients
et xrestop
DO.
Malheureusement, ces informations peuvent être incorrectes non seulement parce que le processus était diabolique et changé ceux-ci, mais aussi parce que c'était une buggie. Par exemple, après un crash/redémarrage de Firefox, j'ai vu des fenêtres orphelinées (du plugin flash, je suppose) avec _NET_WM_PID
pointant vers un processus, qui est mort il y a longtemps.
Voie alternative 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 indications sur les origines de la fenêtre.
Mais! Bien que vous ne trouviez peut-être pas quel processus a créé cette fenêtre, il existe toujours un moyen de trouver où ce processus est connecté à X-Server de. Et de cette façon, c'est pour de vrais pirates informatiques. :)
L'ID de fenêtre 0x1600045 que vous connaissez avec des bits inférieurs à zéro (c'est-à-dire 0x1600000) est une "clientèle". Et tous les ID de ressources, alloués à ce client sont "basés sur" sur celui-ci (0x1600001, 0x1600002, 0x1600003, etc.). X-Server stocke des informations sur ses clients dans les clients [] Array, et pour chaque client, sa "base" est stockée dans les clients [I] -> la variable clientasmask. Pour trouver X-Socket, correspondant à ce client, vous devez vous attacher à X-Server avec gdb
, walk sur les clients [], trouver le client avec ce type clientAsMask
et imprimer son descripteur de socket, stocké dans ((OSCOMMPTR) (clients [I] -> Osprivate)) -> FD.
Il peut y avoir de nombreux clients X-Clients connectés, afin de ne pas les vérifier tous manuellement, utilisons une fonction de 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 est connecté à celui-ci et trouver enfin le processus.
[~ # ~] AVERTISSEMENT [~ # ~ ~]: N'attachez pas GDB sur X-Server de l'intérieur du serveur X. GDB suspend le processus qu'il attache à, de sorte que si vous y attachez à partir de la session X à l'intérieur, vous verrez votre serveur X et ne pourrez pas interagir avec GDB. Vous devez soit basculer sur le terminal de texte (Ctrl+Alt+F2
) ou connectez-vous à votre machine sur ssh.
Trouvez le PID de votre X-Server:
$ 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'ID de la fenêtre est 0x1600045, la base client est donc 0x1600000. Attachez sur X-Server et recherchez le descripteur de prise client pour cette base de clientèle. Vous aurez besoin d'informations de débogage installées pour X-Server (-Debuginfo package pour les distributions RPM ou -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é à une prise de serveur 31. Utilisez lsof
pour trouver ce que cette prise est:
$ 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 de "31u" est un descripteur de socket)
Là, vous pouvez voir que le client est connecté sur TCP, vous pouvez ensuite accéder à la machine qu'elle est connectée et check netstat -nap
là pour trouver le processus. Mais surtout, vous verrez une prise UNIX là-bas, comme indiqué ci-dessus, ce qui signifie que c'est un client local.
Pour trouver une paire pour cette prise UNIX, vous pouvez utiliser le MVG's Technique (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 PID le maintenant:
$ Sudo lsof -n | grep 0xffff810008339600
firefox 7725 username 146u unix 0xffff810008339600 8512421 socket
C'est ça. Le processus qui garde cette fenêtre est "Firefox" avec le processus de processus 7725
EDIT 2017: Il y a plus d'options maintenant comme indiqué sur qui a obtenu l'autre extrémité de ce Socket SocketPair UNIX? . Avec Linux 3.3 ou plus et avec lsof
4.89 ou plus, vous pouvez remplacer les points 3 à 5 ci-dessus avec:
lsof +E -a -p 1237 -d 31
pour découvrir qui est à l'autre extrémité de la prise de la FD 31 du processus X-Server avec ID 1237.
xdotool n'a pas fonctionné pour moi. Cela a fait:
Courir
xprop _NET_WM_PID
et cliquez sur la fenêtre.
Ceci est basé sur la réponse à http://www.linuxquesttions.org/questions/linux-software-/advancef-Question-fining-pid-of-an-x-window-328983/
Si vous avez xdotool installé, puis
xdotool selectwindow getwindowpid
suivi en cliquant sur la fenêtre en question retournera le PID.
(Il existe d'autres moyens de sélectionner la fenêtre en question, par exemple, si vous avez son identifiant de fenêtre, vous pouvez simplement faire xdotool getwindowpid <number>
. Vous pouvez également sélectionner par nom ou classe, etc.)
Je pense que cela nécessite des questions qui jouent bien au nom du WM. Je n'ai pas beaucoup expérimenté ou nécessaire.
Les _NET_WM_PID
n'est pas défini par le gestionnaire de fenêtres (comme un autre client X11, comment savoir?).
Au lieu de cela, des clients compatibles X11 (applications) sont censés définir _NET_WM_PID
et WM_CLIENT_MACHINE
sur leurs propres fenêtres. En supposant une application bien élevée, cela sera vrai si un gestionnaire de fenêtres est en cours d'exécution ou non.
Si WM_CLIENT_MACHINE
est votre propre nom d'hôte, puis le PID devrait être significatif.
[ Par exemple, si vous avez une session SSH ouverte avec X Transfert activé, Windows OND OUVERTÉ par les applications transférées sera marquée avec une télécommande PID et un nom d'hôte, mais vous n'avez pas nécessairement aucun moyen de vous connecter à cet hôte distant.
J'ai pu utiliser le xdotool
sous Ubuntu 11.04 bêta, mais selectwindow
n'était pas une commande valide, je devais pirater un script avec:
$ while true; do sleep 1; xdotool getactivewindow; done
ensuite, regardez l'identifiant de la fenêtre passer pendant que j'ai sélectionné la fenêtre que je voulais, puis décodé le PID responsable avec:
$ xdotool getwindowpid <the-window-id>