เว้นแต่ X-เซิร์ฟเวอร์ของคุณสนับสนุนXResQueryClientIds
จากการขยาย v1.2 X-ทรัพยากรฉันรู้ว่าไม่ง่ายวิธีที่จะเชื่อถือได้ขอหมายเลขกระบวนการ มีวิธีอื่น ๆ
หากคุณมีหน้าต่างอยู่ข้างหน้าคุณและยังไม่ทราบ ID มันเป็นเรื่องง่ายที่จะค้นหา เพียงเปิดเทอร์มินัลถัดจากหน้าต่างที่มีปัญหาเรียกใช้ที่xwininfo
นั่นและคลิกที่หน้าต่างนั้น xwininfo
จะแสดง window-id ให้คุณ
ดังนั้นสมมติว่าคุณรู้จัก window-id เช่น 0x1600045 และต้องการค้นหาสิ่งที่กระบวนการเป็นเจ้าของ
วิธีที่ง่ายที่สุดในการตรวจสอบว่าใครเป็นเจ้าของหน้าต่างนั้นก็คือเรียกใช้ XKillClient เช่น:
xkill -id 0x1600045
และดูว่ากระบวนการใดเพิ่งเสียชีวิต แต่ถ้าคุณไม่รังเกียจที่จะฆ่ามันแน่นอน!
อีกวิธีที่ง่าย แต่ไม่น่าเชื่อถือคือการตรวจสอบ_NET_WM_PID
และWM_CLIENT_MACHINE
คุณสมบัติ:
xprop -id 0x1600045
นั่นคือสิ่งที่เครื่องมือชอบxlsclients
และxrestop
ทำ
น่าเสียดายที่ข้อมูลนี้อาจไม่ถูกต้องไม่เพียงเพราะกระบวนการนี้เป็นสิ่งที่ชั่วร้ายและเปลี่ยนแปลงสิ่งเหล่านั้น แต่ยังเป็นเพราะมันเป็นรถ เช่นหลังจาก firefox crash / restart ฉันเห็น windows กำพร้า (จาก flash plugin ฉันเดา) ด้วยการ_NET_WM_PID
ชี้ไปที่กระบวนการซึ่งเสียชีวิตไปนานแล้ว
ทางเลือกคือการวิ่ง
xwininfo -root -tree
และตรวจสอบคุณสมบัติของผู้ปกครองของหน้าต่างที่เป็นปัญหา ที่อาจให้คำแนะนำบางอย่างเกี่ยวกับต้นกำเนิดของหน้าต่าง
แต่! แม้ว่าคุณอาจไม่พบว่ากระบวนการใดสร้างหน้าต่างนั้น แต่ก็ยังมีวิธีการค้นหาว่ากระบวนการนั้นเชื่อมต่อกับ X-server จากที่ไหน และนั่นก็คือแฮกเกอร์ตัวจริง :)
window-id 0x1600045 ที่คุณรู้ว่ามีบิตต่ำกว่าเป็นศูนย์ (เช่น 0x1600000) คือ "ฐานลูกค้า" และ ID ทรัพยากรทั้งหมดที่ปันส่วนสำหรับไคลเอนต์นั้น "อิง" (0x1600001, 0x1600002, 0x1600003, ฯลฯ ) X-server เก็บข้อมูลเกี่ยวกับลูกค้าในอาร์เรย์ [] และสำหรับลูกค้าแต่ละรายนั้น "ฐาน" จะถูกเก็บไว้ในไคลเอนต์ [i] -> ตัวแปร clientAsMask ในการค้นหา X-socket ที่สอดคล้องกับไคลเอนต์นั้นคุณต้องแนบไปกับ X-server ด้วยgdb
, เดินไปที่อาร์เรย์ของลูกค้า [], ค้นหาไคลเอ็นต์ด้วยนั้นclientAsMask
และพิมพ์ตัวอธิบายซ็อกเก็ตของมันซึ่งเก็บอยู่ใน ((OsCommPtr) (clients [i] - > osPrivate)) -> FD
อาจมีการเชื่อมต่อไคลเอนต์ X จำนวนมากดังนั้นเพื่อที่จะไม่ตรวจสอบพวกเขาทั้งหมดด้วยตนเองลองใช้ฟังก์ชั่น 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
เมื่อคุณพบซ็อกเก็ตคุณสามารถตรวจสอบผู้ที่เชื่อมต่อกับมันและในที่สุดก็พบกระบวนการ
คำเตือน : อย่าแนบ gdb กับ X-server จากภายใน X-server gdb ระงับกระบวนการที่แนบไว้ดังนั้นหากคุณแนบจากภายใน X-session คุณจะตรึง X-server ของคุณและจะไม่สามารถโต้ตอบกับ gdb ได้ คุณต้องสลับไปที่เทอร์มินัลข้อความ ( Ctrl+Alt+F2
) หรือเชื่อมต่อกับเครื่องของคุณผ่าน ssh
ตัวอย่าง:
ค้นหา PID ของ 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
รหัสหน้าต่างคือ 0x1600045 ดังนั้นฐานลูกค้าคือ 0x16000000 แนบไปกับ X-server และค้นหาตัวบอกซ็อกเก็ตไคลเอ็นต์สำหรับฐานลูกค้านั้น คุณจะต้องติดตั้งข้อมูล debug สำหรับ X-server (-debuginfo แพ็คเกจสำหรับ rpm-distributions หรือ -dbg package สำหรับ deb's)
$ 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
ตอนนี้คุณรู้ว่าไคลเอ็นต์เชื่อมต่อกับเซิร์ฟเวอร์ซ็อกเก็ต 31 ใช้lsof
เพื่อค้นหาว่าซ็อกเก็ตนั้นคืออะไร:
$ sudo lsof -n | grep 1237 | grep 31
X 1237 root 31u unix 0xffff810008339340 8512422 socket
(ที่นี่ "X" เป็นชื่อกระบวนการ "1237" เป็น pid "root" เป็นผู้ใช้ที่ทำงานอยู่ "31u" เป็นตัวบ่งชี้ซ็อกเก็ต)
ที่นั่นคุณอาจเห็นว่าไคลเอนต์เชื่อมต่อผ่าน TCP จากนั้นคุณสามารถไปที่เครื่องที่เชื่อมต่อจากนั้นและตรวจสอบที่netstat -nap
นั่นเพื่อค้นหากระบวนการ แต่ส่วนใหญ่คุณจะเห็นซ็อกเก็ตยูนิกซ์ที่นั่นดังที่แสดงไว้ด้านบนซึ่งหมายความว่าเป็นลูกค้าในพื้นที่
ในการค้นหาคู่สำหรับซ็อกเก็ตยูนิกซ์นั้นคุณสามารถใช้เทคนิคของ MvG
(คุณจะต้องใช้ข้อมูลการดีบักสำหรับเคอร์เนลที่ติดตั้งด้วย):
$ sudo gdb -c /proc/kcore
(gdb) print ((struct unix_sock*)0xffff810008339340)->peer
$1 = (struct sock *) 0xffff810008339600
(gdb) quit
ตอนนี้คุณรู้ซ็อกเก็ตไคลเอ็นต์แล้วใช้lsof
เพื่อค้นหา PID ที่ถือมัน:
$ sudo lsof -n | grep 0xffff810008339600
firefox 7725 username 146u unix 0xffff810008339600 8512421 socket
แค่นั้นแหละ. กระบวนการที่ทำให้หน้าต่างนั้นเป็น "firefox" ด้วย process-id 7725
2017 แก้ไข : มีตัวเลือกเพิ่มเติมตามที่เห็นในตอนนี้ใครบ้างที่มีจุดสิ้นสุดของซ็อกเก็ตยูนิกซ์นี้? . ด้วย Linux 3.3 หรือสูงกว่าและด้วยlsof
4.89 หรือสูงกว่าคุณสามารถแทนที่คะแนน 3 ถึง 5 ด้านบนด้วย:
lsof +E -a -p 1237 -d 31
เพื่อค้นหาว่าใครอยู่ที่ปลายอีกด้านของซ็อกเก็ตบน fd 31 ของกระบวนการ X-server ด้วย ID 1237