Trừ khi máy chủ X của bạn hỗ trợ XResQueryClientIds
từ tiện ích mở rộng X-Resource v1.2, tôi không biết cách dễ dàng để yêu cầu ID tiến trình đáng tin cậy . Tuy nhiên, có nhiều cách khác.
Nếu bạn chỉ có một cửa sổ trước mặt và chưa biết ID của nó - thật dễ dàng để tìm ra nó. Chỉ cần mở một thiết bị đầu cuối bên cạnh cửa sổ trong câu hỏi, chạy xwininfo
ở đó và bấm vào cửa sổ đó. xwininfo
sẽ hiển thị cho bạn id cửa sổ.
Vì vậy, giả sử bạn biết một id cửa sổ, ví dụ 0x1600045 và muốn tìm, quá trình sở hữu nó là gì.
Cách dễ nhất để kiểm tra cửa sổ đó thuộc về ai là chạy XKillClient cho nó, tức là:
xkill -id 0x1600045
và xem quá trình nào vừa chết. Nhưng chỉ khi bạn không phiền giết nó tất nhiên!
Một cách dễ dàng nhưng không đáng tin cậy khác là kiểm tra thuộc tính _NET_WM_PID
và WM_CLIENT_MACHINE
thuộc tính của nó :
xprop -id 0x1600045
Đó là những gì công cụ thích xlsclients
và xrestop
làm.
Thật không may, thông tin này có thể không chính xác không chỉ bởi vì quá trình này là xấu xa và thay đổi chúng, mà còn bởi vì nó là lỗi. Ví dụ: sau một số sự cố / khởi động lại firefox tôi đã thấy các cửa sổ mồ côi (từ plugin flash, tôi đoán vậy) với việc _NET_WM_PID
chỉ ra một quy trình, đã chết từ lâu.
Cách khác là chạy
xwininfo -root -tree
và kiểm tra thuộc tính của cha mẹ của cửa sổ trong câu hỏi. Điều đó cũng có thể cung cấp cho bạn một số gợi ý về nguồn gốc cửa sổ.
Nhưng! Mặc dù bạn có thể không tìm thấy quy trình nào đã tạo ra cửa sổ đó, nhưng vẫn có cách để tìm quá trình đó đã kết nối với máy chủ X từ đâu. Và cách đó là dành cho tin tặc thực sự. :)
Id cửa sổ 0x1600045 mà bạn biết với các bit thấp hơn bằng 0 (tức là 0x1600000) là "cơ sở khách". Và tất cả các ID tài nguyên, được phân bổ cho máy khách đó đều "dựa" vào nó (0x1600001, 0x1600002, 0x1600003, v.v.). Máy chủ X lưu trữ thông tin về các máy khách của nó trong mảng máy khách [] và đối với mỗi máy khách, "cơ sở" của nó được lưu trữ trong các máy khách [i] -> biến clientAsMask. Để tìm ổ cắm X, tương ứng với máy khách đó, bạn cần phải gắn vào máy chủ X với gdb
, đi qua mảng máy khách [], tìm máy khách với đó clientAsMask
và in mô tả ổ cắm của nó, được lưu trữ trong ((OsCommPtr) (máy khách [i] - > osPrivate)) -> fd.
Có thể có nhiều máy khách X được kết nối, vì vậy để không kiểm tra tất cả chúng theo cách thủ công, hãy sử dụng hàm 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
Khi bạn tìm thấy ổ cắm, bạn có thể kiểm tra xem ai đã kết nối với nó và cuối cùng tìm thấy quy trình.
CẢNH BÁO : KHÔNG đính kèm gdb với máy chủ X từ bên trong máy chủ X. gdb tạm dừng quá trình mà nó gắn vào, vì vậy nếu bạn đính kèm vào đó từ bên trong phiên X, bạn sẽ đóng băng máy chủ X của mình và sẽ không thể tương tác với gdb. Bạn phải chuyển sang thiết bị đầu cuối văn bản ( Ctrl+Alt+F2
) hoặc kết nối với máy của bạn qua ssh.
Thí dụ:
Tìm PID của máy chủ X của bạn:
$ 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 cửa sổ là 0x1600045, vì vậy cơ sở khách hàng là 0x1600000. Đính kèm với máy chủ X và tìm mô tả ổ cắm máy khách cho cơ sở khách đó. Bạn sẽ cần thông tin gỡ lỗi được cài đặt cho máy chủ X (gói -debuginfo cho phân phối vòng / phút hoặc gói -dbg cho 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
Bây giờ bạn biết rằng máy khách được kết nối với ổ cắm máy chủ 31. Sử dụng lsof
để tìm ổ cắm đó là gì:
$ sudo lsof -n | grep 1237 | grep 31
X 1237 root 31u unix 0xffff810008339340 8512422 socket
(ở đây "X" là tên quy trình, "1237" là pid của nó, "root" là người dùng mà nó đang chạy, "31u" là một mô tả ổ cắm)
Ở đó bạn có thể thấy rằng máy khách được kết nối qua TCP, sau đó bạn có thể đi đến máy được kết nối từ đó và kiểm tra netstat -nap
tại đó để tìm quy trình. Nhưng rất có thể bạn sẽ thấy một ổ cắm unix ở đó, như được hiển thị ở trên, có nghĩa là nó là một máy khách cục bộ.
Để tìm một cặp cho ổ cắm unix đó, bạn có thể sử dụng kỹ thuật của MvG
(bạn cũng sẽ cần thông tin gỡ lỗi cho kernel đã cài đặt):
$ sudo gdb -c /proc/kcore
(gdb) print ((struct unix_sock*)0xffff810008339340)->peer
$1 = (struct sock *) 0xffff810008339600
(gdb) quit
Bây giờ bạn đã biết ổ cắm máy khách, hãy sử dụng lsof
để tìm PID giữ nó:
$ sudo lsof -n | grep 0xffff810008339600
firefox 7725 username 146u unix 0xffff810008339600 8512421 socket
Đó là nó. Quá trình giữ cửa sổ đó là "firefox" với process-id 7725
Chỉnh sửa 2017 : Hiện tại có nhiều tùy chọn hơn như đã thấy tại Ai có đầu kia của sự thất bại unix này? . Với Linux 3.3 trở lên và bằng lsof
4.89 trở lên, bạn có thể thay thế các điểm từ 3 đến 5 ở trên bằng:
lsof +E -a -p 1237 -d 31
để tìm ra ai ở đầu kia của ổ cắm trên fd 31 của quy trình máy chủ X có ID 1237.