3 # Signature-du-Terroir module to handle /proc/<pid>
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
24 if __name__
== "__main__":
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
);
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 ";
72 def process_readinfo (command
): # -> pid
81 last_command
= command
;
82 process
= create_process(command
);
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:
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
);
104 # Methods that return the raw file contents (could be LARGE)
106 process_readinfo (command
);
108 with
open(mapsfile
, 'rb') as file:
110 if type(l
).__name
__ == 'str':
111 l
= bytes(l
, encoding
='utf8');
116 process_readinfo (command
);
118 with
open(exe
, 'rb') as file:
120 if type(l
).__name
__ == 'str':
121 l
= bytes(l
, encoding
='utf8');
123 kill_process(process
);
126 def inode (command
, path
):
127 process_readinfo(command
);
129 # Get file contents on inode number
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');
143 process_readinfo(command
);
145 # Get file contents on inode number
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');
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:
165 if type(l
).__name
__ == 'str':
166 l
= bytes(l
, encoding
='utf8');
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:
175 if type(l
).__name
__ == 'str':
176 l
= bytes(l
, encoding
='utf8');
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');
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');
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
);
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
);