126 lines
3.0 KiB
Python
Executable File
126 lines
3.0 KiB
Python
Executable File
import os # for path operations, getuid, kill
|
|
import subprocess # for executing shell commands
|
|
import signal # for sending signals to processes
|
|
import sys # for exit
|
|
|
|
def check_root():
|
|
"""
|
|
Check if script is run as root(sudo).
|
|
|
|
Raises:
|
|
SystemExit: If not run as root.
|
|
"""
|
|
if os.getuid() != 0:
|
|
print("[-] Please run as root.")
|
|
sys.exit(1)
|
|
|
|
def check_packages():
|
|
"""
|
|
Check if all required packages are installed.
|
|
|
|
Raises:
|
|
SystemExit: If any packges is missing.
|
|
"""
|
|
packages = ['fuser', 'which']
|
|
missing_packages = []
|
|
|
|
for package in packages:
|
|
if subprocess.call(['which', package]) != 0:
|
|
missing_packages.append(package)
|
|
if len(missing_packages) > 0:
|
|
print("[-] Missing packages: {}".format(', '.join(missing_packages)))
|
|
sys.exit(1)
|
|
|
|
def get_keyboard_device_files(names):
|
|
"""
|
|
Get paths corresponding to keyboard device files by searching /dev/input/by-path.
|
|
Uses get_real_path() to resolve symlinks.
|
|
|
|
Args:
|
|
names (list): List of strings to use for searching. e.g.['kbd']
|
|
|
|
Returns:
|
|
str: Path to keyboard device file.
|
|
|
|
"""
|
|
keyboard_device_files = []
|
|
for root, dirs, files in os.walk('/dev/input/by-path'):
|
|
for file in files:
|
|
if any(name in file for name in names):
|
|
keyboard_device_files.append(get_real_path(os.path.join(root, file)))
|
|
return keyboard_device_files
|
|
|
|
def get_real_path(path):
|
|
"""
|
|
Resolve a path of a file.
|
|
Args:
|
|
path (str): Path to a file. Possibly a symlink.
|
|
|
|
Returns:
|
|
str: The resolved (real) path.
|
|
"""
|
|
if os.path.islink(path):
|
|
return os.path.realpath(path)
|
|
else:
|
|
return path
|
|
|
|
def get_pids_using_file(path):
|
|
"""
|
|
Get all process IDs using a file. (Essentially a wrapper for fuser.)
|
|
|
|
Args:
|
|
path (str): Path to a file. Usually /dev/input/eventX.
|
|
|
|
Returns:
|
|
list: List of process IDs.
|
|
|
|
Raises:
|
|
SystemExit: If fuser fails to run.
|
|
"""
|
|
try:
|
|
pids = subprocess.check_output(['fuser', path]).decode('utf-8').split()
|
|
except subprocess.CalledProcessError:
|
|
print("[-] Error: fuser failed to run on", path)
|
|
sys.exit(1)
|
|
return pids
|
|
|
|
def get_process_name(pid):
|
|
"""
|
|
Get the name of a process.
|
|
|
|
Args:
|
|
pid (int): Process ID.
|
|
|
|
Returns:
|
|
str: Name of the process.
|
|
"""
|
|
with open('/proc/{}/comm'.format(pid)) as f:
|
|
return f.read().strip()
|
|
|
|
def kill_processes(pids):
|
|
"""
|
|
Kill processes.
|
|
|
|
Args:
|
|
pids (list): List of process IDs.
|
|
"""
|
|
|
|
for pid in pids:
|
|
try:
|
|
os.kill(int(pid), signal.SIGKILL)
|
|
except ProcessLookupError:
|
|
print("[-] Process {} not found.".format(pid))
|
|
|
|
def kill_process(pid):
|
|
"""
|
|
Kill single process.
|
|
|
|
Args:
|
|
pid (str): Process ID of process to kill
|
|
"""
|
|
try:
|
|
os.kill(int(pid), signal.SIGKILL) # pid apparently arrives as string
|
|
except ProcessLookupError:
|
|
print("[-] Process {} not found.".format(pid))
|
|
|