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 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
);
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 ";
71 def process_readinfo (command
): # -> pid
80 last_command
= command
;
81 process
= create_process(command
);
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:
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
);
103 # Methods that return the raw file contents (could be LARGE)
105 process_readinfo (command
);
107 with
open(mapsfile
, 'rb') as file:
109 if type(l
).__name
__ == 'str':
110 l
= bytes(l
, encoding
='utf8');
115 process_readinfo (command
);
117 with
open(exe
, 'rb') as file:
119 if type(l
).__name
__ == 'str':
120 l
= bytes(l
, encoding
='utf8');
122 kill_process(process
);
125 def inode (command
, path
):
126 process_readinfo(command
);
128 # Get file contents on inode number
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');
142 process_readinfo(command
);
144 # Get file contents on inode number
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');
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:
164 if type(l
).__name
__ == 'str':
165 l
= bytes(l
, encoding
='utf8');
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:
174 if type(l
).__name
__ == 'str':
175 l
= bytes(l
, encoding
='utf8');
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');
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');
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
);
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
);