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 """Gathers information about password entries for keepassx.
30 The retrieved content of those entries comprises the username, title, URL
31 and Comment.
32 """
33
34 import struct
35 from rekall.plugins.linux import heap_analysis
36
37
38 -class Keepassx(heap_analysis.HeapAnalysis):
39 """Gathers password entries for keepassx.
40 The retrieved content of those entries comprises the username, title, URL
41 and Comment."""
42
43 __name = "keepassx"
44
45 table_header = [
46 dict(name="divider", type="Divider"),
47 dict(name="task", hidden=True),
48 dict(name="entry", width=6),
49 dict(name="title", width=26),
50 dict(name="url", width=28),
51 dict(name="username", width=28),
52 dict(name="comment", width=44)
53 ]
54
55
57 for task in self.filter_processes():
58 if self.init_for_task(task):
59
60 yield dict(divider="Task: %s (%s)" % (task.name,
61 task.pid))
62
63 chunks_dict = dict()
64
65 data_offset = self.profile.get_obj_offset("malloc_chunk", "fd")
66
67 for chunk in self.get_all_allocated_chunks():
68 chunks_dict[chunk.v() + data_offset] = chunk
69
70 if self.session.profile.metadata("arch") == 'AMD64':
71 string_offset = 26
72 relevant_chunk_size = 192
73 pointer_offsets = [16, 24, 32, 64]
74
75 else:
76 string_offset = 18
77 relevant_chunk_size = 96
78 pointer_offsets = [12, 16, 20, 36]
79
80 entry_number = 1
81
82 for chunk in chunks_dict.values():
83
84 try:
85
86
87 if not chunk.chunksize() == relevant_chunk_size:
88 continue
89
90 p_entry_data = chunk.to_string()
91
92 field_strings = []
93
94
95
96 for i in pointer_offsets:
97 if self.session.profile.metadata("arch") == 'I386':
98 pointer = struct.unpack('I',
99 p_entry_data[i:i+4])[0]
100 else:
101 pointer = struct.unpack('Q',
102 p_entry_data[i:i+8])[0]
103
104
105
106
107
108 curr_chunk_data = chunks_dict[pointer].to_string()
109
110 string_size = struct.unpack(
111 'I', curr_chunk_data[8:12])[0]
112
113 string_size *= 2
114
115 curr_string = curr_chunk_data[
116 string_offset:string_offset+string_size]
117
118 curr_string = curr_string.decode('utf-16-le')
119
120 field_strings.append(repr(curr_string))
121
122
123 yield dict(task=task, entry=entry_number,
124 title=field_strings[0],
125 url=field_strings[1],
126 username=field_strings[2],
127 comment=field_strings[3])
128
129 entry_number += 1
130
131 except (KeyError, UnicodeDecodeError):
132
133
134 pass
135