-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathsandfly-file-decloak.py
96 lines (82 loc) · 3.42 KB
/
sandfly-file-decloak.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
# Copyright © 2018-2022 Sandfly Security - Agentless Security for Linux (www.sandflysecurity.com)
#
# A utility to test if a file is hiding cloaked data due to a Loadable Kernel Module (LKM) or
# LD_PRELOAD stealth rootkit on Linux. Simply call the command as follows against a suspect file:
#
# python3 ./sandfly-file-decloak.py -f /etc/modules
#
# Any cloaked data will be reported and decloaked so you can see the contents and investigate if
# it is malicious.
#
# Sandfly produces an agentless Linux endpoint detection and incident response platform (EDR) that can detect
# thousands of compromise tactics against Linux, including stealth rootkits. Sandfly hunts for threats
# against your Linux systems without loading any agents on your endpoints and works against most distributions
# and architectures.
#
# Please see our website for more information or a free trial.
#
# MIT Licensed
# https://www.sandflysecurity.com
# @SandflySecurity
#
# Please see our blog for more detailed information on this tool and other Linux forensics articles and
# techniques.
import getopt
import mmap
import sys
import binascii
VERSION="1.0"
def main():
filename = None
try:
opts, args = getopt.getopt(sys.argv[1:], "f:")
except getopt.GetoptError:
print("Illegal option. Valid option is -f")
sys.exit(-1)
if len(opts) > 0:
for opt, arg in opts:
if opt == '-f':
filename = arg
if not filename:
print("Need to supply filename with -f")
sys.exit(-1)
print("\nSandfly File Decloaking Utility - Version {0}".format(VERSION))
print("Copyright (c) 2018-2022 Sandfly Security")
print("Agentless Security for Linux - https://www.sandflysecurity.com")
print("\n\n**************************************")
print("File contents with standard I/O")
print("**************************************\n\n")
with open(filename, "r+b") as f:
file_size_standard_io = 0
for line in f:
output = line
try:
print(output.decode('utf-8').rstrip())
except UnicodeDecodeError:
print("hex: ", binascii.hexlify(output))
file_size_standard_io += len(output)
print("\n\n**************************************")
print("File contents with memory mapped I/O")
print("**************************************\n\n")
with open(filename, "r+b") as f:
map = mmap.mmap(f.fileno(), 0, access=mmap.PROT_READ)
file_size_mmap = map.size()
file_seek = 0
while file_seek < file_size_mmap:
output = map.readline()
try:
print(output.decode('utf-8').rstrip())
except UnicodeDecodeError:
print("hex: ", binascii.hexlify(output))
file_seek += len(output)
print("\n\n")
print("Standard IO file size bytes: ", file_size_standard_io)
print("MMAP IO file size bytes: ", file_size_mmap)
if file_size_standard_io != file_size_mmap:
print("\n********************************************************************************************")
print("ALERT: File sizes do not match. File has cloaked data. Check contents above for hidden data.")
print("********************************************************************************************\n\n")
else:
print("\nOK: File sizes are same so they are not cloaked.\n\n")
if __name__ == '__main__':
main()