Adapted proc_PID.py to include command arguments
[signduterre.git] / proc_PID.py
blob69d8182b1edec82a9fde96ca914e5f94d52719eb
1 # proc_PID
2 #
3 # Signature-du-Terroir module to handle /proc/<pid>
5 # Help text
6 help_text = """
8 The following methods return the SHA512
9 Files are read using the inode numbers in debugfs (sudo only)
10 inodeSHA (command) : The command file based on the inode number in /proc/<pid>/maps
11 mapsSHA (command) : All files in /proc/<pid>/maps, based on inode number
13 For debugging purposes:
14 fileSHA (command) : Simple file read from disk
15 exeSHA (command) : File read using the /proc/<pid>/exe link
16 """
18 import sys;
19 import os;
20 import subprocess;
21 import hashlib;
23 # Define prefix
24 if __name__ == "__main__":
25 prefix = b'';
26 else:
27 prefix = bytes(mainprefix, encoding='ascii');
29 def create_process (command):
30 devnull = open('/dev/null', 'w');
31 print(command.split());
32 return subprocess.Popen(command.split(), stdin = subprocess.PIPE, stdout = devnull, stderr = subprocess.PIPE, shell=False, universal_newlines=False);
34 def kill_process (process):
35 process.stdin.close();
36 errormess = process.stderr.read();
37 if len(errormess) > 0: print(str(errormess), file=sys.stderr);
39 file_system = None;
40 address_list= {};
41 map_list = {};
42 path_list = [];
43 mapsfile = None;
44 exe = None;
45 last_command = '';
47 def get_filesystem(path):
48 command = 'df -h '+path+' |tail -1';
49 process = subprocess.Popen(command, stdin = None, stdout = subprocess.PIPE, stderr = sys.stderr, shell=True, universal_newlines=True);
50 df_output = process.stdout.read();
51 return df_output.split()[0];
53 def get_debugfs_command ():
54 return "/sbin/debugfs -f - "+file_system+" -R ";
56 def reset ():
57 global file_system;
58 global address_list;
59 global map_list;
60 global path_list;
61 global mapsfile;
62 global exe;
63 global last_command;
64 file_system = None;
65 address_list = {};
66 map_list = {};
67 path_list = [];
68 mapsfile = None;
69 exe = None;
70 last_command = '';
72 def process_readinfo (command): # -> pid
73 global file_system;
74 global address_list;
75 global map_list;
76 global path_list;
77 global mapsfile;
78 global exe;
79 global last_command;
80 reset();
81 last_command = command;
82 process = create_process(command);
83 pid = process.pid;
84 dir = '/proc/'+str(pid);
85 exe = os.readlink(dir+'/exe');
87 # Get all mapped memory and files
88 with open(dir+'/maps', 'r') as file:
89 for l in file:
90 if l.find('00000000 00:00 0') < 0:
91 record_list = l.split();
92 if int(record_list[4]) > 0:
93 (addresses, permissions, offset, device, inode, path) = record_list;
94 if path not in path_list:
95 path_list.append(path);
96 map_list[path] = {'permissions':permissions, 'device':device, 'inode':inode};
97 address_list[path] = [];
98 address_list[path].append({'addresses':addresses, 'offset':offset});
99 kill_process(process);
100 mapsfile = path_list[0];
101 file_system = get_filesystem(mapsfile);
102 return pid;
104 # Methods that return the raw file contents (could be LARGE)
105 def file (command):
106 process_readinfo (command);
107 return_value = b'';
108 with open(mapsfile, 'rb') as file:
109 for l in file:
110 if type(l).__name__ == 'str':
111 l = bytes(l, encoding='utf8');
112 return_value += l;
113 return return_value;
115 def exe (command):
116 process_readinfo (command);
117 return_value = b'';
118 with open(exe, 'rb') as file:
119 for l in file:
120 if type(l).__name__ == 'str':
121 l = bytes(l, encoding='utf8');
122 return_value += l;
123 kill_process(process);
124 return return_value;
126 def inode (command, path):
127 process_readinfo(command);
129 # Get file contents on inode number
130 return_value = b'';
131 inode = map_list[path]['inode'];
132 cat = "'cat <"+str(inode)+">'";
133 debugfs = subprocess.Popen(get_debugfs_command()+cat, stdin = None, stdout = subprocess.PIPE, stderr = sys.stderr, shell=True, universal_newlines=False);
134 # read out the file contents
135 for l in debugfs.stdout:
136 if type(l).__name__ == 'str':
137 l = bytes(l, encoding='utf8');
138 return_value += l;
140 return return_value;
142 def maps (command):
143 process_readinfo(command);
145 # Get file contents on inode number
146 return_value = b'';
147 for file in path_list:
148 inode = map_list[file]['inode'];
149 cat = "'cat <"+str(inode)+">'";
150 debugfs = subprocess.Popen(get_debugfs_command()+cat, stdin = None, stdout = subprocess.PIPE, stderr = sys.stderr, shell=True, universal_newlines=False);
151 # read out the file contents
152 for l in debugfs.stdout:
153 if type(l).__name__ == 'str':
154 l = bytes(l, encoding='utf8');
155 return_value += l;
157 return return_value;
159 # Methods that return the SHA512
160 def fileSHA (command):
161 process_readinfo (command);
162 filehash = hashlib.sha512(prefix);
163 with open(mapsfile, 'rb') as file:
164 for l in file:
165 if type(l).__name__ == 'str':
166 l = bytes(l, encoding='utf8');
167 filehash.update(l);
168 return str(filehash.hexdigest());
170 def exeSHA (command):
171 process_readinfo(command);
172 exehash = hashlib.sha512(prefix);
173 with open(exe, 'rb') as file:
174 for l in file:
175 if type(l).__name__ == 'str':
176 l = bytes(l, encoding='utf8');
177 exehash.update(l);
178 return str(exehash.hexdigest());
180 def inodeSHA (command, path):
181 process_readinfo(command);
183 # Get file contents on inode number
184 mapshash = hashlib.sha512(prefix);
185 inode = map_list[path]['inode'];
186 cat = "'cat <"+str(inode)+">'";
187 debugfs = subprocess.Popen(get_debugfs_command()+cat, stdin = None, stdout = subprocess.PIPE, stderr = sys.stderr, shell=True, universal_newlines=False);
188 # read out the file contents
189 for l in debugfs.stdout:
190 if type(l).__name__ == 'str':
191 l = bytes(l, encoding='utf8');
192 mapshash.update(l);
194 return str(mapshash.hexdigest());
196 def mapsSHA (command):
197 process_readinfo(command);
199 # Get file contents on inode number
200 mapshash = hashlib.sha512(prefix);
201 for path in path_list:
202 inode = map_list[path]['inode'];
203 cat = "'cat <"+str(inode)+">'";
204 debugfs = subprocess.Popen(get_debugfs_command()+cat, stdin = None, stdout = subprocess.PIPE, stderr = sys.stderr, shell=True, universal_newlines=False);
205 # read out the file contents
206 for l in debugfs.stdout:
207 if type(l).__name__ == 'str':
208 l = bytes(l, encoding='utf8');
209 mapshash.update(l);
211 return str(mapshash.hexdigest());
213 if __name__ == "__main__":
214 for command in sys.argv[1:]:
215 result = fileSHA(command);
216 print(mapsfile+(len("/proc/<pid>/inode") - len(command))*' ', result);
217 result = exeSHA(command);
218 print("/proc/<pid>/exe"+(len("/proc/<pid>/inode") - len("/proc/<pid>/exe"))*' ', result);
219 if os.getuid() == 0:
220 result = inodeSHA(command, command.split()[0]);
221 print("/proc/<pid>/inode"+(len(command) - len("/proc/<pid>/inode"))*' ', result);
222 result = mapsSHA(command);
223 print("/proc/<pid>/maps"+(len("/proc/<pid>/inode") - len("/proc/<pid>/all"))*' ', result);
225 print("");