Compare commits
44 Commits
userland
...
sebaschi-p
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6d88d1e97d | ||
|
|
522fb0a847 | ||
|
|
72bbf7a575 | ||
|
|
92fc49ac9e | ||
|
|
c8da5e4743 | ||
|
|
0e2250816e | ||
|
|
1ffe505c5d | ||
|
|
0f1b6d4543 | ||
|
|
1a0ae39e87 | ||
|
|
8ce2a8c55c | ||
|
|
037963bccb | ||
|
|
d2ab6c92a8 | ||
|
|
b4005d7876 | ||
|
|
6f13ce5d89 | ||
|
|
626915fd70 | ||
|
|
bb607848dc | ||
|
|
0198c6d0fa | ||
|
|
c67c88b750 | ||
|
|
e210227b31 | ||
|
|
02f6d6eba0 | ||
|
|
1988f0c021 | ||
|
|
da25db0825 | ||
|
|
1635c68ade | ||
|
|
d84a0717bc | ||
|
|
4a9af2f04c | ||
|
|
1ea740dfd3 | ||
|
|
e9d283f94e | ||
|
|
0bc3704846 | ||
|
|
00c2b25a27 | ||
|
|
c0893c31e6 | ||
|
|
94cb159a49 | ||
|
|
2150441d48 | ||
|
|
1d5fc7375c | ||
|
|
63b92c967a | ||
|
|
7c9a6101a0 | ||
|
|
6f56f0bd30 | ||
|
|
0cdb0cd846 | ||
|
|
2b2546b70e | ||
|
|
2c9ba696c8 | ||
|
|
9b3151452d | ||
|
|
538c6368c5 | ||
|
|
316ff1c90e | ||
|
|
a4c5d94006 | ||
|
|
d434029e56 |
21
LICENSE
21
LICENSE
@@ -1,21 +0,0 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2023 Sebastian Lenzlinger
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
@@ -131,7 +131,7 @@ Killing a process still doesn't work:
|
||||
## Wednesday, 7. June 2023, night
|
||||
### Sebastian
|
||||
This is the latest output aftert a test run where actually 3 processes has keyloggers runnig.
|
||||
'''
|
||||
```
|
||||
[kldetect@fedora src]$ sudo ./keylogger_detector.py
|
||||
[sudo] password for kldetect:
|
||||
/usr/sbin/fuser
|
||||
@@ -159,7 +159,7 @@ cat: config.: No such file or directory
|
||||
[Verbose] Suspicious processes not killed: []
|
||||
[Verbose] Suspicious processes killed: []
|
||||
[+] No suspicious processes found
|
||||
'''
|
||||
```
|
||||
This is after extensivly refactoring because I was starting to loose oversight over the code. So I split it up into utils, config and keylogger_detector.
|
||||
#### TODO:
|
||||
1. Ivestigate and bug fix
|
||||
@@ -173,3 +173,10 @@ All in all, the main functionality works as intended. Basically now would be the
|
||||
#### TODO
|
||||
1. Write report
|
||||
2. Add functionality to userspace detector
|
||||
|
||||
## Wednesday, 7, June 2023
|
||||
### Michel
|
||||
|
||||
|
||||
I have written 1 systemtap scripts, that can detect, whenever a module registers at the Keyboard-notifier. The Script can currently detect whenever a module registers. My script cant detect which kernel module registered. Here comes Sebastians idea of writing a python script, that can unload all un-known modules and loads them back in, whilst the stap-script is running. Whenever a module is loaded in, and it triggers the stap-script, we know it is tracking key-strokes. Those modules will be shown to the user and the user then has to decide whether to unload and remove them, or keep them. My script is based on a redhat-script. The redhat-script is called funcall_tracer2.stp . The idea behind both scripts is the same. My script is simplyfied for the use with python.
|
||||
|
||||
|
||||
BIN
doc/qr_code_kldetect_repo.png
Normal file
BIN
doc/qr_code_kldetect_repo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 44 KiB |
17
doc/research/acm_2390317.2390326.bib
Normal file
17
doc/research/acm_2390317.2390326.bib
Normal file
@@ -0,0 +1,17 @@
|
||||
@inproceedings{10.1145/2390317.2390326,
|
||||
author = {Howard, Adam and Hu, Yi},
|
||||
title = {An Approach for Detecting Malicious Keyloggers},
|
||||
year = {2012},
|
||||
isbn = {9781450315388},
|
||||
publisher = {Association for Computing Machinery},
|
||||
address = {New York, NY, USA},
|
||||
url = {https://doi.org/10.1145/2390317.2390326},
|
||||
doi = {10.1145/2390317.2390326},
|
||||
abstract = {Keyloggers are applications that are installed onto computers with the intent of monitoring and storing keystrokes that are input by a user. These keystrokes can either be stored on a physical hard disk or transmitted via a network connection to a remote location. Because of their functions, keyloggers have a potential of being used for malicious purposes. In order to protect privacy, it is important to realize the threat that a keylogger application might pose and identify appropriate methods for detecting it. The method presented in this research provides a standardized approach to detect unknown keylogging software from a computer. We also conducted experiments on a variety of keyloggers to verify the effectiveness of the proposed approach.},
|
||||
booktitle = {Proceedings of the 2012 Information Security Curriculum Development Conference},
|
||||
pages = {53–56},
|
||||
numpages = {4},
|
||||
keywords = {rootkit, privacy, system hook, keylogger, malicious software},
|
||||
location = {Kennesaw, Georgia},
|
||||
series = {InfoSecCD '12}
|
||||
}
|
||||
17
doc/research/acm_financial_losses_due_to_malware.bib
Normal file
17
doc/research/acm_financial_losses_due_to_malware.bib
Normal file
@@ -0,0 +1,17 @@
|
||||
@inproceedings{10.1145/2905055.2905362,
|
||||
author = {Amin, Maitri},
|
||||
title = {A Survey of Financial Losses Due to Malware},
|
||||
year = {2016},
|
||||
isbn = {9781450339629},
|
||||
publisher = {Association for Computing Machinery},
|
||||
address = {New York, NY, USA},
|
||||
url = {https://doi.org/10.1145/2905055.2905362},
|
||||
doi = {10.1145/2905055.2905362},
|
||||
abstract = {General survey stat that the main damage malware can cause is to slow down their PCs and perhaps crash some websites which is quite wrong, The Russian antivirus software developer teamed up with B2B International for a study worldwide recently, shown 36\% of users lose money online as a result of a malware attack. Currently malware can't be detected by traditional way based anti-malware tools due to their polymorphic and/or metamorphic nature. Here we have improvised a current detection technique of malware based on mining Application Programming Interface (API) calls and developed the first public dataset to promote malware research.• In survey of cyber-attacks 6.2\% financial attacks are due to malware which increase to 1.3 \% in 2013 compared to 2012.• Financial data theft causes 27.6\% to reach 28,400,000. Victims abused by this targeting malware countered 3,800,000, which is 18.6\% greater than previous year.• Finance-committed malware, associated with Bitcoin has demonstrated the most dynamic development. Where's, Zeus is still top listed for playing important roles to steal banking credentials.Solutionary study stats that companies are spending a staggering amount of money in the aftermath of damaging attack: DDoS attacks recover $6,500 per hour from malware and more than $3,000 each time for up to 30 days to moderate and improve from malware attacks. [1]},
|
||||
booktitle = {Proceedings of the Second International Conference on Information and Communication Technology for Competitive Strategies},
|
||||
articleno = {145},
|
||||
numpages = {4},
|
||||
keywords = {Malware, API, financial losses, Survey},
|
||||
location = {Udaipur, India},
|
||||
series = {ICTCS '16}
|
||||
}
|
||||
17
doc/research/acm_risk_of_stolen_credentials.bib
Normal file
17
doc/research/acm_risk_of_stolen_credentials.bib
Normal file
@@ -0,0 +1,17 @@
|
||||
@inproceedings{10.1145/3133956.3134067,
|
||||
author = {Thomas, Kurt and Li, Frank and Zand, Ali and Barrett, Jacob and Ranieri, Juri and Invernizzi, Luca and Markov, Yarik and Comanescu, Oxana and Eranti, Vijay and Moscicki, Angelika and Margolis, Daniel and Paxson, Vern and Bursztein, Elie},
|
||||
title = {Data Breaches, Phishing, or Malware? Understanding the Risks of Stolen Credentials},
|
||||
year = {2017},
|
||||
isbn = {9781450349468},
|
||||
publisher = {Association for Computing Machinery},
|
||||
address = {New York, NY, USA},
|
||||
url = {https://doi.org/10.1145/3133956.3134067},
|
||||
doi = {10.1145/3133956.3134067},
|
||||
abstract = {In this paper, we present the first longitudinal measurement study of the underground ecosystem fueling credential theft and assess the risk it poses to millions of users. Over the course of March, 2016--March, 2017, we identify 788,000 potential victims of off-the-shelf keyloggers; 12.4 million potential victims of phishing kits; and 1.9 billion usernames and passwords exposed via data breaches and traded on blackmarket forums. Using this dataset, we explore to what degree the stolen passwords---which originate from thousands of online services---enable an attacker to obtain a victim's valid email credentials---and thus complete control of their online identity due to transitive trust. Drawing upon Google as a case study, we find 7--25\% of exposed passwords match a victim's Google account. For these accounts, we show how hardening authentication mechanisms to include additional risk signals such as a user's historical geolocations and device profiles helps to mitigate the risk of hijacking. Beyond these risk metrics, we delve into the global reach of the miscreants involved in credential theft and the blackhat tools they rely on. We observe a remarkable lack of external pressure on bad actors, with phishing kit playbooks and keylogger capabilities remaining largely unchanged since the mid-2000s.},
|
||||
booktitle = {Proceedings of the 2017 ACM SIGSAC Conference on Computer and Communications Security},
|
||||
pages = {1421–1434},
|
||||
numpages = {14},
|
||||
keywords = {keylogger, phishing, risk analysis, data breach, password reuse, authentication, phishing kit, password},
|
||||
location = {Dallas, Texas, USA},
|
||||
series = {CCS '17}
|
||||
}
|
||||
10
doc/research/citation-strange-world-keyloggers.bib
Normal file
10
doc/research/citation-strange-world-keyloggers.bib
Normal file
@@ -0,0 +1,10 @@
|
||||
@article{article,
|
||||
author = {Creutzburg, Reiner},
|
||||
year = {2017},
|
||||
month = {01},
|
||||
pages = {139-148},
|
||||
title = {The strange world of keyloggers - an overview, Part I},
|
||||
volume = {2017},
|
||||
journal = {Electronic Imaging},
|
||||
doi = {10.2352/ISSN.2470-1173.2017.6.MOBMU-313}
|
||||
}
|
||||
@@ -1,2 +1,5 @@
|
||||
clean:
|
||||
rm *.o *.txt *.out *.exe
|
||||
rm *.o *.txt *.out
|
||||
|
||||
sclean:
|
||||
sudo rm -rf *.o *.txt *.out __pycache__
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
{
|
||||
"white_listed_programs": [
|
||||
"systemd_logind",
|
||||
"gnome-shell",
|
||||
"systemd"
|
||||
"systemd",
|
||||
"gnome-shell"
|
||||
],
|
||||
"auto_kill_programs": [],
|
||||
"kbd_names": [
|
||||
|
||||
7
src/funcall_trace.stp
Normal file
7
src/funcall_trace.stp
Normal file
@@ -0,0 +1,7 @@
|
||||
|
||||
probe kernel.function("register_keyboard_notifier").call
|
||||
{
|
||||
print("[-]")
|
||||
exit()
|
||||
}
|
||||
|
||||
184
src/kernel_detector.py
Executable file
184
src/kernel_detector.py
Executable file
@@ -0,0 +1,184 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import subprocess
|
||||
import time
|
||||
import multiprocessing
|
||||
|
||||
import threading
|
||||
|
||||
import os
|
||||
import sys
|
||||
from io import TextIOWrapper, BytesIO
|
||||
|
||||
pipe1, pipe2 = multiprocessing.Pipe()
|
||||
|
||||
#==============================================================================================================
|
||||
#
|
||||
#Functions
|
||||
#
|
||||
#==============================================================================================================
|
||||
def list_modules(command):
|
||||
result = subprocess.run(command, shell = True, capture_output=True, text=True)
|
||||
|
||||
if result.returncode == 0:
|
||||
return result.stdout.strip().split('\n')
|
||||
else:
|
||||
print(f"Failed with error:{result.stderr}")
|
||||
return[]
|
||||
|
||||
def get_whitelist(file_path):
|
||||
try:
|
||||
with open(file_path, 'r') as file:
|
||||
lines = file.read().splitlines()
|
||||
return lines
|
||||
except IOError:
|
||||
print(f'Error: Failed to load whitelist{file_path}')
|
||||
|
||||
def compare_mods(A, B):
|
||||
setA = set(A)
|
||||
setB = set(B)
|
||||
|
||||
result = setB - setA
|
||||
|
||||
return list(result)
|
||||
|
||||
def tidy_up(entries):
|
||||
cleaned_entries = []
|
||||
for entry in entries:
|
||||
modules = entry.split()
|
||||
if modules:
|
||||
first_mod = modules[0]
|
||||
cleaned_entries.append(first_mod)
|
||||
return cleaned_entries
|
||||
|
||||
def unload_mod(modules):
|
||||
tmp = []
|
||||
for module in modules:
|
||||
result = subprocess.run(['sudo','rmmod', module],capture_output = True, text = True)
|
||||
if result.returncode == 0:
|
||||
print(f"Unloaded module: {module}")
|
||||
else:
|
||||
print(f"Failed to unloaded module: {module}")
|
||||
tmp.append(module)
|
||||
print(result.stderr)
|
||||
result_out = compare_mods(tmp, modules)
|
||||
print(result_out)
|
||||
return result_out
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
def stap_start():
|
||||
print("starting sniffing")
|
||||
process = subprocess.Popen(['stap','funcall_trace.stp', '-T', '15'], flush = True)
|
||||
process.wait()
|
||||
print("ended sniffing")
|
||||
|
||||
|
||||
def load_mod(module):
|
||||
print(module)
|
||||
for i in range(2):
|
||||
subprocess.Popen(['sudo','insmod', module])
|
||||
time.sleep(1)
|
||||
subprocess.Popen(['sudo','rmmod', module])
|
||||
time.sleep(1)
|
||||
subprocess.Popen(['sudo', 'insmod', module])
|
||||
|
||||
|
||||
def find_file(filename):
|
||||
result = []
|
||||
for root, dirs, files in os.walk("/"):
|
||||
if filename in files:
|
||||
file_path = os.path.join(root, filename)
|
||||
result.append(file_path)
|
||||
result_out = result
|
||||
result_out = ''.join(result_out)
|
||||
return result_out
|
||||
|
||||
def getpath(sus_modules):
|
||||
for i in range(len(sus_modules)):
|
||||
sus_modules[i] = find_file(sus_modules[i] + ".ko")
|
||||
return sus_modules
|
||||
|
||||
def detect_logger(module):
|
||||
|
||||
|
||||
|
||||
print("starting sniffing")
|
||||
process = subprocess.Popen(['stap','funcall_trace.stp', '-T', '10'], stdout=subprocess.PIPE, text=True)
|
||||
|
||||
|
||||
for i in range(2):
|
||||
subprocess.Popen(['sudo','insmod', module])
|
||||
time.sleep(1)
|
||||
print("-")
|
||||
subprocess.Popen(['sudo','rmmod', module])
|
||||
time.sleep(1)
|
||||
subprocess.Popen(['sudo','insmod', module])
|
||||
print("-")
|
||||
out = process.communicate()[0]
|
||||
|
||||
|
||||
|
||||
|
||||
print("ended sniffing")
|
||||
|
||||
print(out)
|
||||
if out == "[-]":
|
||||
return module
|
||||
print("FAILED")
|
||||
return 0
|
||||
|
||||
|
||||
|
||||
#==============================================================================================================
|
||||
#
|
||||
#Work
|
||||
#
|
||||
#==============================================================================================================
|
||||
|
||||
whitelist = get_whitelist("whitelist.txt")
|
||||
|
||||
lsmod_output = list_modules("lsmod");
|
||||
|
||||
sus_modules = compare_mods(whitelist, lsmod_output)
|
||||
|
||||
sus_modules = tidy_up(sus_modules)
|
||||
|
||||
sus_modules = unload_mod(sus_modules)
|
||||
time.sleep(1)
|
||||
|
||||
sus_modules = getpath(sus_modules)
|
||||
print(sus_modules)
|
||||
if len(sus_modules) == 0:
|
||||
print("nothing to do")
|
||||
print("ALL CLEAN")
|
||||
|
||||
|
||||
|
||||
suspects = []
|
||||
for module in sus_modules:
|
||||
suspects.append(detect_logger(module))
|
||||
time.sleep(1)
|
||||
|
||||
|
||||
|
||||
print("Following modules are logging your keystrokes: ")
|
||||
for i in range(len(suspects)):
|
||||
print( f"[{i}] {suspects[i]}")
|
||||
print("Enter the number of the module you want to remove: ")
|
||||
user_input = input().split()
|
||||
for j in user_input:
|
||||
to_remove = suspects[int(j)]
|
||||
subprocess.Popen(['sudo','rmmod', to_remove])
|
||||
print(f"Removed {to_remove}")
|
||||
print("Finished")
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
import sys
|
||||
from config import CONFIG_FILE, load_config, save_config
|
||||
from utils import (
|
||||
check_platform,
|
||||
check_root,
|
||||
check_packages,
|
||||
get_keyboard_device_files,
|
||||
@@ -13,13 +14,16 @@ from utils import (
|
||||
kill_process
|
||||
)
|
||||
|
||||
# Global variables
|
||||
# Global variables/CLI options
|
||||
|
||||
auto_kill_option = False
|
||||
verbose_option = False
|
||||
safe_option = False
|
||||
add_white_list_option = False
|
||||
add_black_list_option = False
|
||||
debug_option = False
|
||||
kernel_detection_option = False
|
||||
|
||||
|
||||
# Functions
|
||||
def debug(option, to_print):
|
||||
@@ -33,8 +37,10 @@ def print_help():
|
||||
print(' -v, --verbose\t\t\tVerbose mode. Informative information will be displayed duting execution')
|
||||
print(' -a, --auto-kill\t\tAutomatically kill blacklisted processes')
|
||||
print(' -s, --safe\t\t\tSafe mode. Asked to confirm before killing a process')
|
||||
print(' -w, --add-white-list\t\t\tActivate prompt to add program names to the whitelist') #For some reason this line gets messed up in display
|
||||
print(' -w, --add-white-list\t\tActivate prompt to add program names to the whitelist') #For some reason this line gets messed up in display
|
||||
print(' -b, --add-black-list\t\tAutomatically add program names chosen to kill to the blacklist')
|
||||
print(' -d, --debug\t\t\tDebug mode. Print debug statements')
|
||||
print(' -k, --kernel-detection\t\tRun the kernel keylogger detector, too. CURRENTLY NOT IMPLEMENTED TO DIRECTLY RUN KERNEL DETECTOR.')
|
||||
|
||||
def set_input_options():
|
||||
"""
|
||||
@@ -47,7 +53,7 @@ def set_input_options():
|
||||
"""
|
||||
|
||||
global auto_kill_option, verbose_option, safe_option, add_white_list_option
|
||||
global debug_option
|
||||
global debug_option, add_black_list_option, kernel_detection_option
|
||||
if len(sys.argv) > 1:
|
||||
for arg in sys.argv[1:]:
|
||||
print(arg)
|
||||
@@ -62,8 +68,12 @@ def set_input_options():
|
||||
safe_option = True
|
||||
elif arg == '-w' or arg == '--add-white-list' :
|
||||
add_white_list_option = True
|
||||
elif arg == '-b' or arg == '--add-black-list':
|
||||
add_black_list_option = True
|
||||
elif arg == '-d' or arg == '--debug':
|
||||
debug_option = True
|
||||
elif arg == '-k' or arg == '--kernel-detection':
|
||||
kernel_detection_option = True
|
||||
|
||||
|
||||
def confirm_kill_procces(process_name, times=0):
|
||||
@@ -109,8 +119,9 @@ def detect_keyloggers():
|
||||
# 1. Setup and initialization
|
||||
############################
|
||||
debug(True, str(sys.argv)) # Set manually to debug if args are being read
|
||||
global auto_kill_option, verbose_option, safe_option
|
||||
global CONFIG_FILE
|
||||
check_platform()
|
||||
|
||||
global auto_kill_option, verbose_option, safe_option, add_white_list_option, kernel_detection_option, debug_option
|
||||
set_input_options()
|
||||
if verbose_option:
|
||||
print('[Verbose] Input options set')
|
||||
@@ -175,16 +186,18 @@ def detect_keyloggers():
|
||||
print('[Verbose] Auto-killable process found:', name)
|
||||
if safe_option:
|
||||
if confirm_kill_procces(name):
|
||||
kill_process(name_pid_dict[name])
|
||||
kill_processes(name_pid_dict[name])
|
||||
else:
|
||||
kill_process(name_pid_dict[name])
|
||||
kill_processes(name_pid_dict[name])
|
||||
if verbose_option:
|
||||
print('[Verbose] Process auto-killed:', name)
|
||||
|
||||
############################
|
||||
# 6. Identify suspicious processes, i.e. those not whitelisted
|
||||
############################
|
||||
suspicious_processes = []
|
||||
for name in process_names:
|
||||
if name not in white_listed_programs:
|
||||
if (name not in white_listed_programs and name not in auto_kill_programs) or (name in auto_kill_programs and not auto_kill_option):
|
||||
suspicious_processes.append(name)
|
||||
if verbose_option:
|
||||
print('[Verbose] Suspicious processes found:', suspicious_processes)
|
||||
@@ -197,7 +210,8 @@ def detect_keyloggers():
|
||||
############################
|
||||
if len(suspicious_processes) == 0:
|
||||
print("[+] No suspicious processes found")
|
||||
sys.exit(0)
|
||||
if not kernel_detection_option:
|
||||
exit(0)
|
||||
|
||||
############################
|
||||
# 7. Prompt user to chose which processes (not covered by auto kill if set) to kill
|
||||
@@ -241,7 +255,7 @@ def detect_keyloggers():
|
||||
|
||||
|
||||
############################
|
||||
# 8. Update whitelist if option set
|
||||
# 8. Update whitelist and/or blacklist if options set
|
||||
############################
|
||||
debug(debug_option, 'Whitelist option:' + str(add_white_list_option))
|
||||
if add_white_list_option:
|
||||
@@ -254,12 +268,17 @@ def detect_keyloggers():
|
||||
if verbose_option:
|
||||
print('[Verbose] Newly whitelisted programs: ', to_whitelist)
|
||||
|
||||
to_kill = list(set(to_kill))
|
||||
|
||||
if add_black_list_option:
|
||||
auto_kill_programs.extend(to_kill)
|
||||
if verbose_option:
|
||||
print('[Verbose] Newly blacklisted programs: ', to_kill)
|
||||
|
||||
###########################
|
||||
# 9. Cleanup
|
||||
###########################
|
||||
to_kill = list(set(to_kill))
|
||||
auto_kill_programs = list(set(auto_kill_programs))
|
||||
auto_kill_programs.extend(to_kill)
|
||||
config['auto_kill_programs'] = auto_kill_programs
|
||||
white_listed_programs = list(set(white_listed_programs))
|
||||
config['white_listed_programs'] = white_listed_programs
|
||||
@@ -271,9 +290,13 @@ def detect_keyloggers():
|
||||
|
||||
print('[+] Program completed. Exiting.')
|
||||
|
||||
|
||||
debug(debug_option, 'Kernel detection option: ' + str(kernel_detection_option))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
detect_keyloggers()
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,67 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# ===============================
|
||||
# Step1: Find keyboard file paths
|
||||
# ===============================
|
||||
|
||||
# Output file path
|
||||
kbd_output_file="kbd_file_paths.txt"
|
||||
|
||||
# Function to follow symbolic links recursively
|
||||
follow_symlinks() {
|
||||
local filepath=$1
|
||||
|
||||
if [[ -L $filepath ]]; then
|
||||
local resolved_path=$(readlink -f "$filepath")
|
||||
echo "$resolved_path" >> "$kbd_output_file"
|
||||
follow_symlinks "$resolved_path"
|
||||
fi
|
||||
}
|
||||
|
||||
# Traverse files in /dev/input/by-path
|
||||
echo -n > "$kbd_output_file"
|
||||
find /dev/input/by-path -type l -name '*kbd*' -print0 | while IFS= read -r -d '' filepath; do
|
||||
#echo "$filepath" >> "$kbd_output_file"
|
||||
follow_symlinks "$filepath"
|
||||
done
|
||||
|
||||
echo "Keyboard file paths written to $kbd_output_file"
|
||||
|
||||
# ===============================
|
||||
# Step2: Find pids using keyboard event files
|
||||
# ===============================
|
||||
|
||||
# Use found kbd file paths to find corresponding pids
|
||||
pids_input_file="$kbd_output_file"
|
||||
pids_output_file="pids.txt"
|
||||
|
||||
echo -n > "$pids_output_file"
|
||||
|
||||
declare -a pids_array
|
||||
|
||||
# Get pids of processes using the keyboard and put in array
|
||||
while IFS= read -r pathname; do
|
||||
pids=$(fuser "$pathname")
|
||||
# add pids to array
|
||||
for pid in $pids; do
|
||||
pids_array+=("$pid")
|
||||
done
|
||||
done < "$pids_input_file"
|
||||
|
||||
# sort and remove duplicates
|
||||
sorted_pids=$(printf '%s\n' "${pids_array[@]}" | sort -nu)
|
||||
|
||||
# write unique and sorted pids to file, separated by newlines
|
||||
printf '%s\n' "${sorted_pids[@]}" > "$pids_output_file"
|
||||
|
||||
echo "Pids written to $pids_output_file"
|
||||
|
||||
# ===============================
|
||||
# Step3: Find processes/program names using pids
|
||||
# ===============================
|
||||
exe_input_file="$pids_output_file"
|
||||
exe_output_file="suspicous_exes.txt"
|
||||
|
||||
# Clear output file
|
||||
echo -n > "$exe_output_file"
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
import os
|
||||
|
||||
# Output file path
|
||||
kbd_output_file = "kbd_file_paths.txt"
|
||||
|
||||
# Function to follow symbolic links recursively
|
||||
def follow_symlinks(filepath):
|
||||
if os.path.islink(filepath):
|
||||
resolved_path = os.path.realpath(filepath)
|
||||
with open(kbd_output_file, "a") as f:
|
||||
f.write(resolved_path + "\n")
|
||||
follow_symlinks(resolved_path)
|
||||
|
||||
# Traverse files in /dev/input/by-path
|
||||
with open(kbd_output_file, "w") as f:
|
||||
f.write("")
|
||||
for root, dirs, files in os.walk("/dev/input/by-path"):
|
||||
for filename in files:
|
||||
if "kbd" in filename:
|
||||
filepath = os.path.join(root, filename)
|
||||
follow_symlinks(filepath)
|
||||
|
||||
print("Keyboard file paths written to", kbd_output_file)
|
||||
|
||||
@@ -1,40 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Output file path
|
||||
output_file="keyboard_info.txt"
|
||||
|
||||
# Step 1: Find keyboard device files
|
||||
keyboard_files=()
|
||||
while IFS= read -r -d '' file; do
|
||||
if [[ $file == *"kbd"* || $file == *"keyboard"* ]]; then
|
||||
keyboard_files+=("$file")
|
||||
fi
|
||||
done < <(find /dev/input/by-path -type l -name 'event*')
|
||||
|
||||
# Step 2: Check processes with open keyboard files
|
||||
echo "Keyboard Information" > "$output_file"
|
||||
echo "=====================" >> "$output_file"
|
||||
|
||||
for keyboard_file in "${keyboard_files[@]}"; do
|
||||
echo "Keyboard device file: $keyboard_file" >> "$output_file"
|
||||
|
||||
event_file=$(readlink -f "$keyboard_file")
|
||||
echo "Event file: $event_file" >> "$output_file"
|
||||
|
||||
pids=$(fuser -v "$event_file" 2>/dev/null | awk -F'[: ]+' 'NR>1{print $2}')
|
||||
echo "PIDs with file open: $pids" >> "$output_file"
|
||||
|
||||
# Step 3: Check corresponding programs
|
||||
echo "Corresponding Programs" >> "$output_file"
|
||||
echo "---------------------" >> "$output_file"
|
||||
|
||||
for pid in $pids; do
|
||||
program=$(readlink -f "/proc/$pid/exe")
|
||||
echo "PID $pid corresponds to program: $program" >> "$output_file"
|
||||
done
|
||||
|
||||
echo >> "$output_file"
|
||||
done
|
||||
|
||||
echo "Keyboard information written to $output_file"
|
||||
|
||||
@@ -1,251 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import os # for going directories
|
||||
import subprocess # for running commands, in particular fuser
|
||||
import sys # for exiting
|
||||
import signal # for killing processes
|
||||
import json # for handling our configurations
|
||||
|
||||
CONFIG_FILE = 'config.json'
|
||||
|
||||
|
||||
auto_kill_option = False
|
||||
verbose_option = False
|
||||
safe_option = False
|
||||
|
||||
# Check if the user is in sudo mode
|
||||
def check_sudo():
|
||||
if os.geteuid() != 0:
|
||||
print("[-] Please rerun as root")
|
||||
sys.exit(1)
|
||||
|
||||
# Check if the user has the required packages installed
|
||||
def check_packages():
|
||||
packages = ['fuser']
|
||||
missing_packages = []
|
||||
for package in packages:
|
||||
try:
|
||||
subprocess.check_call(['which', package])
|
||||
except subprocess.CalledProcessError:
|
||||
missing_packages.append(package)
|
||||
if len(missing_packages) > 0:
|
||||
print("[-] Please install the following packages:", str(missing_packages))
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
|
||||
|
||||
# Follow symlinks to find real path
|
||||
def get_real_path(path):
|
||||
if os.path.islink(path):
|
||||
return os.path.realpath(path)
|
||||
else:
|
||||
return path
|
||||
|
||||
# get keyboard device files
|
||||
def get_keyboard_device_files(kbd_names):
|
||||
keyboard_device_files = []
|
||||
for root, dirs, files in os.walk('/dev/input/by-path'):
|
||||
for file in files:
|
||||
if any(kbd_name in file for kbd_name in kbd_names):
|
||||
keyboard_device_files.append(get_real_path(os.path.join(root, file)))
|
||||
return keyboard_device_files
|
||||
|
||||
# print a list to a file separated by newlines
|
||||
def print_list_to_file(list, file):
|
||||
with open(file, 'w') as f:
|
||||
for item in list:
|
||||
f.write("%s\n" % item)
|
||||
|
||||
# find pids using file using fuser
|
||||
def get_pids(file):
|
||||
try:
|
||||
pids = subprocess.check_output(['fuser', file]).decode('utf-8').split()
|
||||
except subprocess.CalledProcessError:
|
||||
if verbose_option:
|
||||
print("[-] Error: fuser failed to run on", file)
|
||||
return []
|
||||
#pids = [int(pid) for pid in pids]
|
||||
return pids
|
||||
|
||||
# clear a file
|
||||
def clear_file(file):
|
||||
open(file, 'w').close()
|
||||
|
||||
|
||||
# find programm name using pid
|
||||
def get_program_name(pid):
|
||||
status_file = '/proc/' + str(pid) + '/status'
|
||||
with open(status_file, 'r') as f:
|
||||
# See cat /proc/[pid]/status | grep Name
|
||||
for line in f:
|
||||
if line.startswith('Name:'):
|
||||
program_name = line.split(":")[1].strip()
|
||||
return program_name
|
||||
|
||||
# proces input arguments and set options
|
||||
def set_input_arguments():
|
||||
global auto_kill_option
|
||||
global verbose_option
|
||||
global safe_option
|
||||
if len(sys.argv) > 1:
|
||||
if '-a' in sys.argv:
|
||||
auto_kill_option = True
|
||||
if '-v' in sys.argv:
|
||||
verbose_option = True
|
||||
if '-s' in sys.argv:
|
||||
safe_option = True
|
||||
|
||||
|
||||
# ask user to confirm a list of programs to kill
|
||||
def confirm_kill_programs(programs, times=0):
|
||||
print("Confirm to kill the following programs:")
|
||||
for program in programs:
|
||||
print(program)
|
||||
print("y/n?")
|
||||
answer = input()
|
||||
if answer == 'y':
|
||||
return True
|
||||
elif answer == 'n':
|
||||
return False
|
||||
else:
|
||||
if times > 5:
|
||||
print("[-] Too many tries. Exiting")
|
||||
sys.exit(1)
|
||||
print("[-] Please answer y or n")
|
||||
return confirm_kill_programs(programs, times+1)
|
||||
|
||||
# kill list of processes
|
||||
def kill_processes(pids):
|
||||
print(pids) ## DEBUG
|
||||
print("Killing processes with pids:", pids)
|
||||
for pid in pids:
|
||||
os.kill(pid, signal.SIGKILL)
|
||||
if verbose_option:
|
||||
print("[-] Killed process with pid", pid)
|
||||
|
||||
# the main program starts here
|
||||
def detect_keyloggers():
|
||||
###############################
|
||||
# Step 0: Check minimal requirements/ Set up
|
||||
###############################
|
||||
check_sudo()
|
||||
check_packages()
|
||||
config = load_config()
|
||||
# initialize white_listed_programs
|
||||
if 'white_listed_programs' in config:
|
||||
white_listed_programs = config['white_listed_programs']
|
||||
else:
|
||||
config['white_listed_programs'] = []
|
||||
white_listed_programs = []
|
||||
# initialize auto_kill_programs
|
||||
if 'auto_kill_programs' in config:
|
||||
auto_kill_programs = config['auto_kill_programs']
|
||||
else:
|
||||
config['auto_kill_programs'] = []
|
||||
auto_kill_programs = []
|
||||
# initialize kbd_names
|
||||
if 'kbd_names' in config:
|
||||
kbd_names = config['kbd_names']
|
||||
else:
|
||||
config['kbd_names'] = []
|
||||
kbd_names = []
|
||||
# Set options
|
||||
set_input_arguments()
|
||||
|
||||
###############################
|
||||
# Step 1: Get keyboard device files
|
||||
###############################
|
||||
keyboard_device_files = get_keyboard_device_files(kbd_names)
|
||||
###############################
|
||||
# Step 2: Get pids using keyboard device files
|
||||
###############################
|
||||
pids = []
|
||||
for file in keyboard_device_files:
|
||||
pids += get_pids(file)
|
||||
pids = sorted(list(set(pids)))
|
||||
###############################
|
||||
# Step 3: Get program names using pids
|
||||
###############################
|
||||
program_names = []
|
||||
program_pid_dict = {}
|
||||
# Get program names
|
||||
for pid in pids:
|
||||
program_name = get_program_name(pid)
|
||||
program_pid_dict[program_name] = program_pid_dict[program_name].append(int(pid))
|
||||
if auto_kill_option and program_name in auto_kill_programs:
|
||||
os.kill(pid, signal.SIGKILL)
|
||||
if verbose_option:
|
||||
print("[-] Auto-Killed process", program_name, "with pid", pid)
|
||||
else:
|
||||
program_names.append(program_name)
|
||||
program_names = sorted(list(set(program_names)))
|
||||
|
||||
# Identify suspicious programs
|
||||
suspicious_programs = []
|
||||
for program_name in program_names:
|
||||
if program_name not in white_listed_programs:
|
||||
suspicious_programs.append(program_name)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
if verbose_option:
|
||||
###############################=
|
||||
# Intermezzo: Print results
|
||||
###############################
|
||||
print("Keyboard device files:")
|
||||
for file in keyboard_device_files:
|
||||
print(file)
|
||||
print("")
|
||||
print("Pids:")
|
||||
for pid in pids:
|
||||
print(pid)
|
||||
print("")
|
||||
print("Program names:")
|
||||
for program_name in program_names:
|
||||
print(program_name)
|
||||
print("")
|
||||
|
||||
if len(suspicious_programs) == 0:
|
||||
print("[+] No suspicious programs found")
|
||||
sys.exit(0)
|
||||
|
||||
###############################
|
||||
# Step 4: Ask user to kill any suspicious programs
|
||||
###############################
|
||||
print("Suspicious programs:")
|
||||
for program_name in suspicious_programs:
|
||||
print(program_name)
|
||||
user_input = input("Please enter those programs you want to kill. Use the whitespace(spacebar) to separate values.")
|
||||
if user_input == '':
|
||||
print("[-] No programs to kill")
|
||||
sys.exit(0)
|
||||
|
||||
programs_to_kill = user_input.split()
|
||||
programs_to_kill = [program_name for program_name in programs_to_kill if program_name in suspicious_programs] # Filter out programs that are not suspicious
|
||||
pids_to_kill = []
|
||||
for program_name in programs_to_kill:
|
||||
pids_to_kill.append(program_pid_dict[program_name])
|
||||
auto_kill_programs.append(program_name)
|
||||
|
||||
if safe_option:
|
||||
if confirm_kill_programs(programs_to_kill):
|
||||
kill_processes(pids_to_kill)
|
||||
else:
|
||||
kill_processes(pids_to_kill)
|
||||
|
||||
###############################
|
||||
# Step 5: Save config
|
||||
###############################
|
||||
config['auto_kill_programs'] = list(set(auto_kill_programs))
|
||||
config['white_listed_programs'] = list(set(white_listed_programs))
|
||||
config['kbd_names'] = list(set(kbd_names))
|
||||
save_config(config)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
detect_keyloggers()
|
||||
|
||||
|
||||
@@ -1,77 +0,0 @@
|
||||
import os
|
||||
import subprocess
|
||||
|
||||
# ===============================
|
||||
# Step1: Find keyboard file paths
|
||||
# ===============================
|
||||
|
||||
# Output file path
|
||||
kbd_output_file = "kbd_file_paths.txt"
|
||||
|
||||
# Function to follow symbolic links recursively
|
||||
def follow_symlinks(filepath):
|
||||
if os.path.islink(filepath):
|
||||
resolved_path = os.path.realpath(filepath)
|
||||
with open(kbd_output_file, "a") as output_file:
|
||||
output_file.write(resolved_path + "\n")
|
||||
follow_symlinks(resolved_path)
|
||||
|
||||
# Traverse files in /dev/input/by-path
|
||||
with open(kbd_output_file, "w") as output_file:
|
||||
for root, dirs, files in os.walk("/dev/input/by-path"):
|
||||
for file in files:
|
||||
if "kbd" in file:
|
||||
filepath = os.path.join(root, file)
|
||||
output_file.write(filepath + "\n")
|
||||
follow_symlinks(filepath)
|
||||
|
||||
print("Keyboard file paths written to", kbd_output_file)
|
||||
|
||||
# ===============================
|
||||
# Step2: Find pids using keyboard event files
|
||||
# ===============================
|
||||
|
||||
# Use found kbd file paths to find corresponding pids
|
||||
pids_input_file = kbd_output_file
|
||||
pids_output_file = "pids.txt"
|
||||
|
||||
pids_array = []
|
||||
|
||||
# Get pids of processes using the keyboard and put in array
|
||||
with open(pids_input_file, "r") as input_file:
|
||||
for pathname in input_file:
|
||||
pathname = pathname.strip()
|
||||
pids = subprocess.check_output(["fuser", pathname]).decode().split()
|
||||
pids_array.extend(pids)
|
||||
|
||||
# Sort and remove duplicates
|
||||
sorted_pids = sorted(set(pids_array))
|
||||
print()
|
||||
print("The following pids where found:" + str(sorted_pids) + "\n")
|
||||
|
||||
# Write unique and sorted pids to file, separated by newlines
|
||||
with open(pids_output_file, "w") as output_file:
|
||||
output_file.write("\n".join(sorted_pids) + "\n")
|
||||
print("Pids written to", pids_output_file)
|
||||
|
||||
# ===============================
|
||||
# Step3: Find processes/program names using pids
|
||||
# ===============================
|
||||
exe_input_file = pids_output_file
|
||||
exe_output_file = "suspicious_exes.txt"
|
||||
|
||||
# Clear output file
|
||||
with open(exe_output_file, "w") as output_file:
|
||||
output_file.write("")
|
||||
exe_pid_dict = {}
|
||||
|
||||
for pid in sorted_pids:
|
||||
#Get name of executable from PID using process status file
|
||||
status_file_path = "/proc/" + pid + "/status"
|
||||
with open(status_file_path, "r") as status_file:
|
||||
for line in status_file:
|
||||
# See cat /proc/{pid}/status | grep "Name:"
|
||||
if line.startswith("Name:"):
|
||||
exe_name = line.split(":")[1].strip()
|
||||
exe_pid_dict[exe_name] = pid
|
||||
print("The following executables where found:" + str(exe_pid_dict) + "\n")
|
||||
@@ -1,112 +0,0 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <dirent.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#define DEVICE_DIR "/dev/input"
|
||||
#define BY_PATH_DIR "/dev/input/by-path"
|
||||
#define PROC_DIR "/proc"
|
||||
|
||||
void get_program_name(long pid) {
|
||||
char exe_file_path[256];
|
||||
snprintf(exe_file_path, sizeof(exe_file_path), "/proc/%ld/exe", pid);
|
||||
|
||||
if (access(exe_file_path, F_OK) == 0) {
|
||||
char program_path[256];
|
||||
ssize_t path_len = readlink(exe_file_path, program_path, sizeof(program_path) - 1);
|
||||
if (path_len != -1) {
|
||||
program_path[path_len] = '\0';
|
||||
printf("Corresponding program: %s\n\n", program_path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void find_keyboard_files() {
|
||||
DIR *by_path_dir = opendir(BY_PATH_DIR);
|
||||
if (by_path_dir == NULL) {
|
||||
perror("opendir");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
struct dirent *entry;
|
||||
while ((entry = readdir(by_path_dir)) != NULL) {
|
||||
if (strstr(entry->d_name, "kbd") != NULL || strstr(entry->d_name, "keyboard") != NULL) {
|
||||
char device_file_path[256];
|
||||
snprintf(device_file_path, sizeof(device_file_path), "%s/%s", BY_PATH_DIR, entry->d_name);
|
||||
|
||||
char link_dest[256];
|
||||
ssize_t link_size = readlink(device_file_path, link_dest, sizeof(link_dest) - 1);
|
||||
if (link_size == -1) {
|
||||
perror("readlink");
|
||||
continue;
|
||||
}
|
||||
|
||||
link_dest[link_size] = '\0';
|
||||
printf("Keyboard device file: %s\n", link_dest);
|
||||
|
||||
char event_file[256];
|
||||
snprintf(event_file, sizeof(event_file), "%s/%s", DEVICE_DIR, link_dest);
|
||||
|
||||
DIR *proc_dir = opendir(PROC_DIR);
|
||||
if (proc_dir == NULL) {
|
||||
perror("opendir");
|
||||
continue;
|
||||
}
|
||||
|
||||
struct dirent *pid_entry;
|
||||
while ((pid_entry = readdir(proc_dir)) != NULL) {
|
||||
if (pid_entry->d_type != DT_DIR)
|
||||
continue;
|
||||
|
||||
// Check if the entry name is a numeric value (PID)
|
||||
char *endptr;
|
||||
long pid = strtol(pid_entry->d_name, &endptr, 10);
|
||||
if (*endptr != '\0')
|
||||
continue;
|
||||
|
||||
char fd_dir_path[256];
|
||||
snprintf(fd_dir_path, sizeof(fd_dir_path), "%s/%s/fd", PROC_DIR, pid_entry->d_name);
|
||||
|
||||
DIR *fd_dir = opendir(fd_dir_path);
|
||||
if (fd_dir == NULL)
|
||||
continue;
|
||||
|
||||
struct dirent *fd_entry;
|
||||
while ((fd_entry = readdir(fd_dir)) != NULL) {
|
||||
if (fd_entry->d_type != DT_LNK)
|
||||
continue;
|
||||
|
||||
char fd_file_path[256];
|
||||
snprintf(fd_file_path, sizeof(fd_file_path), "%s/%s", fd_dir_path, fd_entry->d_name);
|
||||
|
||||
char link_dest[256];
|
||||
ssize_t link_size = readlink(fd_file_path, link_dest, sizeof(link_dest) - 1);
|
||||
if (link_size == -1)
|
||||
continue;
|
||||
|
||||
link_dest[link_size] = '\0';
|
||||
|
||||
if (strcmp(link_dest, event_file) == 0) {
|
||||
printf("Process with PID %ld is using this file.\n", pid);
|
||||
get_program_name(pid);
|
||||
}
|
||||
}
|
||||
|
||||
closedir(fd_dir);
|
||||
}
|
||||
|
||||
closedir(proc_dir);
|
||||
}
|
||||
}
|
||||
|
||||
closedir(by_path_dir);
|
||||
}
|
||||
|
||||
int main() {
|
||||
printf("Finding keyboard files...\n\n");
|
||||
find_keyboard_files();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1,77 +0,0 @@
|
||||
import os
|
||||
import subprocess
|
||||
|
||||
# ===============================
|
||||
# Step1: Find keyboard file paths
|
||||
# ===============================
|
||||
|
||||
# Output file path
|
||||
kbd_output_file = "kbd_file_paths.txt"
|
||||
|
||||
# Function to follow symbolic links recursively
|
||||
def follow_symlinks(filepath):
|
||||
if os.path.islink(filepath):
|
||||
resolved_path = os.path.realpath(filepath)
|
||||
with open(kbd_output_file, "a") as output_file:
|
||||
output_file.write(resolved_path + "\n")
|
||||
follow_symlinks(resolved_path)
|
||||
|
||||
# Traverse files in /dev/input/by-path
|
||||
with open(kbd_output_file, "w") as output_file:
|
||||
for root, dirs, files in os.walk("/dev/input/by-path"):
|
||||
for file in files:
|
||||
if "kbd" in file:
|
||||
filepath = os.path.join(root, file)
|
||||
output_file.write(filepath + "\n")
|
||||
follow_symlinks(filepath)
|
||||
|
||||
print("Keyboard file paths written to", kbd_output_file)
|
||||
|
||||
# ===============================
|
||||
# Step2: Find pids using keyboard event files
|
||||
# ===============================
|
||||
|
||||
# Use found kbd file paths to find corresponding pids
|
||||
pids_input_file = kbd_output_file
|
||||
pids_output_file = "pids.txt"
|
||||
|
||||
pids_array = []
|
||||
|
||||
# Get pids of processes using the keyboard and put in array
|
||||
with open(pids_input_file, "r") as input_file:
|
||||
for pathname in input_file:
|
||||
pathname = pathname.strip()
|
||||
pids = subprocess.check_output(["fuser", pathname]).decode().split()
|
||||
pids_array.extend(pids)
|
||||
|
||||
# Sort and remove duplicates
|
||||
sorted_pids = sorted(set(pids_array))
|
||||
print()
|
||||
print("The following pids where found:" + str(sorted_pids) + "\n")
|
||||
|
||||
# Write unique and sorted pids to file, separated by newlines
|
||||
with open(pids_output_file, "w") as output_file:
|
||||
output_file.write("\n".join(sorted_pids) + "\n")
|
||||
print("Pids written to", pids_output_file)
|
||||
|
||||
# ===============================
|
||||
# Step3: Find processes/program names using pids
|
||||
# ===============================
|
||||
exe_input_file = pids_output_file
|
||||
exe_output_file = "suspicious_exes.txt"
|
||||
|
||||
# Clear output file
|
||||
with open(exe_output_file, "w") as output_file:
|
||||
output_file.write("")
|
||||
exe_pid_dict = {}
|
||||
|
||||
for pid in sorted_pids:
|
||||
#Get name of executable from PID using process status file
|
||||
status_file_path = "/proc/" + pid + "/status"
|
||||
with open(status_file_path, "r") as status_file:
|
||||
for line in status_file:
|
||||
# See cat /proc/{pid}/status | grep "Name:"
|
||||
if line.startswith("Name:"):
|
||||
exe_name = line.split(":")[1].strip()
|
||||
exe_pid_dict[exe_name] = pid
|
||||
print("The following executables where found:" + str(exe_pid_dict) + "\n")
|
||||
@@ -1,67 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# ===============================
|
||||
# Step1: Find keyboard file paths
|
||||
# ===============================
|
||||
|
||||
# Output file path
|
||||
kbd_output_file="kbd_file_paths.txt"
|
||||
|
||||
# Function to follow symbolic links recursively
|
||||
follow_symlinks() {
|
||||
local filepath=$1
|
||||
|
||||
if [[ -L $filepath ]]; then
|
||||
local resolved_path=$(readlink -f "$filepath")
|
||||
echo "$resolved_path" >> "$kbd_output_file"
|
||||
follow_symlinks "$resolved_path"
|
||||
fi
|
||||
}
|
||||
|
||||
# Traverse files in /dev/input/by-path
|
||||
echo -n > "$kbd_output_file"
|
||||
find /dev/input/by-path -type l -name '*kbd*' -print0 | while IFS= read -r -d '' filepath; do
|
||||
#echo "$filepath" >> "$kbd_output_file"
|
||||
follow_symlinks "$filepath"
|
||||
done
|
||||
|
||||
echo "Keyboard file paths written to $kbd_output_file"
|
||||
|
||||
# ===============================
|
||||
# Step2: Find pids using keyboard event files
|
||||
# ===============================
|
||||
|
||||
# Use found kbd file paths to find corresponding pids
|
||||
pids_input_file="$kbd_output_file"
|
||||
pids_output_file="pids.txt"
|
||||
|
||||
echo -n > "$pids_output_file"
|
||||
|
||||
declare -a pids_array
|
||||
|
||||
# Get pids of processes using the keyboard and put in array
|
||||
while IFS= read -r pathname; do
|
||||
pids=$(fuser "$pathname")
|
||||
# add pids to array
|
||||
for pid in $pids; do
|
||||
pids_array+=("$pid")
|
||||
done
|
||||
done < "$pids_input_file"
|
||||
|
||||
# sort and remove duplicates
|
||||
sorted_pids=$(printf '%s\n' "${pids_array[@]}" | sort -nu)
|
||||
|
||||
# write unique and sorted pids to file, separated by newlines
|
||||
printf '%s\n' "${sorted_pids[@]}" > "$pids_output_file"
|
||||
|
||||
echo "Pids written to $pids_output_file"
|
||||
|
||||
# ===============================
|
||||
# Step3: Find processes/program names using pids
|
||||
# ===============================
|
||||
exe_input_file="$pids_output_file"
|
||||
exe_output_file="suspicous_exes.txt"
|
||||
|
||||
# Clear output file
|
||||
echo -n > "$exe_output_file"
|
||||
|
||||
14
src/utils.py
14
src/utils.py
@@ -3,6 +3,20 @@ import subprocess # for executing shell commands
|
||||
import signal # for sending signals to processes
|
||||
import sys # for exit
|
||||
|
||||
|
||||
|
||||
|
||||
def check_platform():
|
||||
"""
|
||||
Check if platform is Linux.
|
||||
|
||||
Raises:
|
||||
SystemExit: If the platform isn not LInux.
|
||||
"""
|
||||
if sys.platform != 'linux':
|
||||
print("[-] This script only works on Linux.")
|
||||
|
||||
|
||||
def check_root():
|
||||
"""
|
||||
Check if script is run as root(sudo).
|
||||
|
||||
68
src/whitelist.txt
Normal file
68
src/whitelist.txt
Normal file
@@ -0,0 +1,68 @@
|
||||
Module Size Used by
|
||||
uinput 20480 0
|
||||
isofs 65536 1
|
||||
snd_seq_dummy 16384 0
|
||||
snd_hrtimer 16384 1
|
||||
vboxvideo 36864 0
|
||||
drm_vram_helper 24576 1 vboxvideo
|
||||
nf_conntrack_netbios_ns 16384 1
|
||||
nf_conntrack_broadcast 16384 1 nf_conntrack_netbios_ns
|
||||
nft_fib_inet 16384 1
|
||||
nft_fib_ipv4 16384 1 nft_fib_inet
|
||||
nft_fib_ipv6 16384 1 nft_fib_inet
|
||||
nft_fib 16384 3 nft_fib_ipv6,nft_fib_ipv4,nft_fib_inet
|
||||
nft_reject_inet 16384 6
|
||||
nf_reject_ipv4 16384 1 nft_reject_inet
|
||||
nf_reject_ipv6 24576 1 nft_reject_inet
|
||||
nft_reject 16384 1 nft_reject_inet
|
||||
nft_ct 24576 16
|
||||
nft_chain_nat 16384 3
|
||||
nf_nat 65536 1 nft_chain_nat
|
||||
nf_conntrack 192512 4 nf_nat,nft_ct,nf_conntrack_netbios_ns,nf_conntrack_broadcast
|
||||
nf_defrag_ipv6 24576 1 nf_conntrack
|
||||
nf_defrag_ipv4 16384 1 nf_conntrack
|
||||
ip_set 65536 0
|
||||
nf_tables 352256 237 nft_ct,nft_reject_inet,nft_fib_ipv6,nft_fib_ipv4,nft_chain_nat,nft_reject,nft_fib,nft_fib_inet
|
||||
nfnetlink 20480 3 nf_tables,ip_set
|
||||
rfkill 40960 3
|
||||
qrtr 57344 4
|
||||
sunrpc 815104 1
|
||||
snd_intel8x0 57344 2
|
||||
snd_ac97_codec 200704 1 snd_intel8x0
|
||||
binfmt_misc 28672 1
|
||||
intel_rapl_msr 20480 0
|
||||
ac97_bus 16384 1 snd_ac97_codec
|
||||
intel_rapl_common 36864 1 intel_rapl_msr
|
||||
snd_seq 106496 7 snd_seq_dummy
|
||||
snd_seq_device 16384 1 snd_seq
|
||||
snd_pcm 184320 2 snd_intel8x0,snd_ac97_codec
|
||||
rapl 24576 0
|
||||
snd_timer 53248 3 snd_seq,snd_hrtimer,snd_pcm
|
||||
snd 143360 12 snd_seq,snd_seq_device,snd_intel8x0,snd_timer,snd_ac97_codec,snd_pcm
|
||||
joydev 28672 0
|
||||
soundcore 16384 1 snd
|
||||
pcspkr 16453 0
|
||||
i2c_piix4 36864 0
|
||||
vboxguest 53248 6
|
||||
loop 40960 0
|
||||
zram 32768 2
|
||||
crct10dif_pclmul 16384 1
|
||||
crc32_pclmul 16384 0
|
||||
crc32c_intel 24576 3
|
||||
polyval_generic 16384 0
|
||||
vmwgfx 458752 2
|
||||
ghash_clmulni_intel 16384 0
|
||||
drm_ttm_helper 16384 3 vmwgfx,drm_vram_helper,vboxvideo
|
||||
sha512_ssse3 49152 0
|
||||
e1000 188416 0
|
||||
ttm 102400 3 vmwgfx,drm_vram_helper,drm_ttm_helper
|
||||
serio_raw 20480 0
|
||||
video 73728 0
|
||||
wmi 45056 1 video
|
||||
ata_generic 16384 0
|
||||
pata_acpi 16384 0
|
||||
ip6_tables 40960 0
|
||||
ip_tables 40960 0
|
||||
fuse 212992 5
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user