Adapted proc_PID.py to include command arguments
[signduterre.git] / proc_PID.py
blobe601c2a916161c1ad407ff9062ddb6099040dde4
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 return subprocess.Popen(command.split(), stdin = subprocess.PIPE, stdout = devnull, stderr = subprocess.PIPE, shell=False, universal_newlines=False);
33 def kill_process (process):
34 process.stdin.close();
35 errormess = process.stderr.read();
36 if len(errormess) > 0: print(str(errormess), file=sys.stderr);
38 file_system = None;
39 address_list= {};
40 map_list = {};
41 path_list = [];
42 mapsfile = None;
43 exe = None;
44 last_command = '';
46 def get_filesystem(path):
47 command = 'df -h '+path+' |tail -1';
48 process = subprocess.Popen(command, stdin = None, stdout = subprocess.PIPE, stderr = sys.stderr, shell=True, universal_newlines=True);
49 df_output = process.stdout.read();
50 return df_output.split()[0];
52 def get_debugfs_command ():
53 return "/sbin/debugfs -f - "+file_system+" -R ";
55 def reset ():
56 global file_system;
57 global address_list;
58 global map_list;
59 global path_list;
60 global mapsfile;
61 global exe;
62 global last_command;
63 file_system = None;
64 address_list = {};
65 map_list = {};
66 path_list = [];
67 mapsfile = None;
68 exe = None;
69 last_command = '';
71 def process_readinfo (command): # -> pid
72 global file_system;
73 global address_list;
74 global map_list;
75 global path_list;
76 global mapsfile;
77 global exe;
78 global last_command;
79 reset();
80 last_command = command;
81 process = create_process(command);
82 pid = process.pid;
83 dir = '/proc/'+str(pid);
84 exe = os.readlink(dir+'/exe');
86 # Get all mapped memory and files
87 with open(dir+'/maps', 'r') as file:
88 for l in file:
89 if l.find('00000000 00:00 0') < 0:
90 record_list = l.split();
91 if int(record_list[4]) > 0:
92 (addresses, permissions, offset, device, inode, path) = record_list;
93 if path not in path_list:
94 path_list.append(path);
95 map_list[path] = {'permissions':permissions, 'device':device, 'inode':inode};
96 address_list[path] = [];
97 address_list[path].append({'addresses':addresses, 'offset':offset});
98 kill_process(process);
99 mapsfile = path_list[0];
100 file_system = get_filesystem(mapsfile);
101 return pid;
103 # Methods that return the raw file contents (could be LARGE)
104 def file (command):
105 process_readinfo (command);
106 return_value = b'';
107 with open(mapsfile, 'rb') as file:
108 for l in file:
109 if type(l).__name__ == 'str':
110 l = bytes(l, encoding='utf8');
111 return_value += l;
112 return return_value;
114 def exe (command):
115 process_readinfo (command);
116 return_value = b'';
117 with open(exe, 'rb') as file:
118 for l in file:
119 if type(l).__name__ == 'str':
120 l = bytes(l, encoding='utf8');
121 return_value += l;
122 kill_process(process);
123 return return_value;
125 def inode (command, path):
126 process_readinfo(command);
128 # Get file contents on inode number
129 return_value = b'';
130 inode = map_list[path]['inode'];
131 cat = "'cat <"+str(inode)+">'";
132 debugfs = subprocess.Popen(get_debugfs_command()+cat, stdin = None, stdout = subprocess.PIPE, stderr = sys.stderr, shell=True, universal_newlines=False);
133 # read out the file contents
134 for l in debugfs.stdout:
135 if type(l).__name__ == 'str':
136 l = bytes(l, encoding='utf8');
137 return_value += l;
139 return return_value;
141 def maps (command):
142 process_readinfo(command);
144 # Get file contents on inode number
145 return_value = b'';
146 for file in path_list:
147 inode = map_list[file]['inode'];
148 cat = "'cat <"+str(inode)+">'";
149 debugfs = subprocess.Popen(get_debugfs_command()+cat, stdin = None, stdout = subprocess.PIPE, stderr = sys.stderr, shell=True, universal_newlines=False);
150 # read out the file contents
151 for l in debugfs.stdout:
152 if type(l).__name__ == 'str':
153 l = bytes(l, encoding='utf8');
154 return_value += l;
156 return return_value;
158 # Methods that return the SHA512
159 def fileSHA (command):
160 process_readinfo (command);
161 filehash = hashlib.sha512(prefix);
162 with open(mapsfile, 'rb') as file:
163 for l in file:
164 if type(l).__name__ == 'str':
165 l = bytes(l, encoding='utf8');
166 filehash.update(l);
167 return str(filehash.hexdigest());
169 def exeSHA (command):
170 process_readinfo(command);
171 exehash = hashlib.sha512(prefix);
172 with open(exe, 'rb') as file:
173 for l in file:
174 if type(l).__name__ == 'str':
175 l = bytes(l, encoding='utf8');
176 exehash.update(l);
177 return str(exehash.hexdigest());
179 def inodeSHA (command, path):
180 process_readinfo(command);
182 # Get file contents on inode number
183 mapshash = hashlib.sha512(prefix);
184 inode = map_list[path]['inode'];
185 cat = "'cat <"+str(inode)+">'";
186 debugfs = subprocess.Popen(get_debugfs_command()+cat, stdin = None, stdout = subprocess.PIPE, stderr = sys.stderr, shell=True, universal_newlines=False);
187 # read out the file contents
188 for l in debugfs.stdout:
189 if type(l).__name__ == 'str':
190 l = bytes(l, encoding='utf8');
191 mapshash.update(l);
193 return str(mapshash.hexdigest());
195 def mapsSHA (command):
196 process_readinfo(command);
198 # Get file contents on inode number
199 mapshash = hashlib.sha512(prefix);
200 for path in path_list:
201 inode = map_list[path]['inode'];
202 cat = "'cat <"+str(inode)+">'";
203 debugfs = subprocess.Popen(get_debugfs_command()+cat, stdin = None, stdout = subprocess.PIPE, stderr = sys.stderr, shell=True, universal_newlines=False);
204 # read out the file contents
205 for l in debugfs.stdout:
206 if type(l).__name__ == 'str':
207 l = bytes(l, encoding='utf8');
208 mapshash.update(l);
210 return str(mapshash.hexdigest());
212 if __name__ == "__main__":
213 for command in sys.argv[1:]:
214 result = fileSHA(command);
215 print(mapsfile+(len("/proc/<pid>/inode") - len(command))*' ', result);
216 result = exeSHA(command);
217 print("/proc/<pid>/exe"+(len("/proc/<pid>/inode") - len("/proc/<pid>/exe"))*' ', result);
218 if os.getuid() == 0:
219 result = inodeSHA(command, command.split()[0]);
220 print("/proc/<pid>/inode"+(len(command) - len("/proc/<pid>/inode"))*' ', result);
221 result = mapsSHA(command);
222 print("/proc/<pid>/maps"+(len("/proc/<pid>/inode") - len("/proc/<pid>/all"))*' ', result);
224 print("");