Vzhledem k ID okna X11, existuje způsob, jak najít ID procesu, který jej vytvořil?
Samozřejmě to není vždy možné, například pokud okno přišlo přes TCP spojení. V takovém případě bych chtěl IP a port přidružený ke vzdálenému konci.
Tato otázka byla položena dříve na Stack Overflow a navrhovanou metodou bylo použití _NET_WM_PID
vlastnictví. Ale to je nastaveno aplikací. Existuje způsob, jak to udělat, pokud aplikace nehraje dobře?
Přijatá odpověď:
Pokud váš X-server nepodporuje XResQueryClientIds
z rozšíření X-Resource v1.2 neznám žádné snadné způsob spolehlivě ID procesu požadavku. Existují však i jiné způsoby.
Pokud máte před sebou okno a zatím neznáte jeho ID – je snadné ho zjistit. Stačí otevřít terminál vedle příslušného okna a spustit xwininfo
tam a klikněte na toto okno. xwininfo
zobrazí ID okna.
Předpokládejme tedy, že znáte ID okna, např. 0x1600045 a chcete zjistit, jaký proces jej vlastní.
Nejjednodušší způsob, jak zkontrolovat, komu toto okno patří, je spustit pro něj XKillClient, tj.:
xkill -id 0x1600045
a uvidíte, který proces právě zemřel. Ale pouze pokud vám nebude vadit to zabít!
Dalším snadným, ale nespolehlivým způsobem je zkontrolovat jeho _NET_WM_PID
a WM_CLIENT_MACHINE
vlastnosti:
xprop -id 0x1600045
To jsou nástroje jako xlsclients
a xrestop
udělat.
Bohužel tato informace může být nesprávná nejen proto, že proces byl zlý a změnil je, ale také proto, že byl chybný. Například po nějaké havárii/restartu firefoxu jsem viděl osiřelá okna (z flash pluginu, myslím) s _NET_WM_PID
ukazující na proces, který dávno zanikl.
Alternativní způsob je běh
xwininfo -root -tree
a zkontrolujte vlastnosti rodičů daného okna. To vám také může napovědět o původu oken.
Ale! I když možná nenajdete, jaký proces toto okno vytvořil, stále existuje způsob, jak zjistit, odkud se tento proces připojil k X-serveru. A to je cesta pro skutečné hackery. 🙂
ID okna 0x1600045, které znáte s nižšími bity vynulovanými (tj. 0x1600000), je „klientská základna“. A všechna ID prostředků přidělená tomuto klientovi jsou „založena“ na něm (0x1600001, 0x1600002, 0x1600003 atd.). X-server ukládá informace o svých klientech do pole client[] a pro každého klienta je jeho „báze“ uložena v proměnné client[i]->clientAsMask. Chcete-li najít X-socket odpovídající tomuto klientovi, musíte se připojit k X-serveru pomocí gdb
, projděte pole client[], najděte klienta s touto maskou clientAsMask
a vytiskněte jeho deskriptor soketu uložený v ((OsCommPtr)(clients[i]->osPrivate))->fd.
Může být připojeno mnoho X-klientů, takže abychom je všechny nekontrolovali ručně, použijte funkci 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
Když najdete zásuvku, můžete zkontrolovat, kdo je k ní připojen, a nakonec najít proces.
Související:Jak stáhnout aplikaci z obchodu Windows 10 pro sideload?
UPOZORNĚNÍ :NEPŘIPOJUJTE gdb k X-serveru z UVNITŘ X-serveru. gdb pozastaví proces, ke kterému se připojuje, takže pokud se k němu připojíte z X-session, zmrazíte svůj X-server a nebudete moci s gdb interagovat. Musíte buď přepnout na textový terminál (Ctrl+Alt+F2
) nebo se připojte k počítači přes ssh.
Příklad:
-
Najděte PID vašeho X-serveru:
$ ps ax | grep X 1237 tty1 Ssl+ 11:36 /usr/bin/X :0 vt1 -nr -nolisten tcp -auth /var/run/kdm/A:0-h6syCa
-
ID okna je 0x1600045, takže klientská základna je 0x1600000. Připojte se k X-serveru a najděte deskriptor klientského soketu pro tuto klientskou základnu. Budete potřebovat informace o ladění
nainstalované pro X-server (balíček -debuginfo pro rpm-distribuce nebo balíček -dbg pro 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
-
Nyní víte, že klient je připojen k soketu serveru 31. Použijte
lsof
zjistit, co je to soket:$ sudo lsof -n | grep 1237 | grep 31 X 1237 root 31u unix 0xffff810008339340 8512422 socket
(zde „X“ je název procesu, „1237“ je jeho pid, „root“ je uživatel, od kterého běží, „31u“ je deskriptor soketu)
Zde můžete vidět, že klient je připojen přes TCP, pak můžete přejít k počítači, ze kterého je připojen, a zkontrolovat
netstat -nap
tam najít proces. S největší pravděpodobností tam ale uvidíte unixový socket, jak je znázorněno výše, což znamená, že jde o místního klienta. -
Chcete-li najít pár pro tento unixový socket, můžete použít techniku MvG (budete také potřebovat informace o ladění vašeho nainstalovaného jádra):
$ sudo gdb -c /proc/kcore (gdb) print ((struct unix_sock*)0xffff810008339340)->peer $1 = (struct sock *) 0xffff810008339600 (gdb) quit
-
Nyní, když znáte klientský soket, použijte
lsof
najít PID, který jej drží:$ sudo lsof -n | grep 0xffff810008339600 firefox 7725 username 146u unix 0xffff810008339600 8512421 socket
A je to. Proces uchovávající toto okno je „firefox“ s id procesu 7725
Upravit v roce 2017 :Nyní je více možností, jak je vidět na Kdo má druhý konec tohoto unixového socketpair?. S Linuxem 3.3 nebo vyšším as lsof
4.89 nebo vyšší, můžete výše uvedené body 3 až 5 nahradit:
lsof +E -a -p 1237 -d 31
zjistit, kdo je na druhém konci soketu na fd 31 procesu X-server s ID 1237.