1
2
3
4
5
6 import glob
7 import os
8
9 from _winreg import CreateKey, SetValueEx, CloseKey, REG_DWORD, REG_SZ
10
11 from lib.api.process import Process
12 from lib.common.exceptions import CuckooPackageError
13
15 """Base abstract analysis package."""
16 PATHS = []
17 REGKEYS = []
18
19 - def __init__(self, options={}, analyzer=None):
20 """@param options: options dict."""
21 self.options = options
22 self.analyzer = analyzer
23 self.pids = []
24
25
26 if "curdir" in options:
27 self.curdir = os.path.expandvars(options["curdir"])
28 else:
29 self.curdir = os.getenv("TEMP")
30
32 """Update list of monitored PIDs in the package context.
33 @param pids: list of pids.
34 """
35 self.pids = pids
36
38 """Run analysis package.
39 @raise NotImplementedError: this method is abstract.
40 """
41 raise NotImplementedError
42
44 """Check."""
45 return True
46
48 """Enumerate available paths."""
49 basepaths = {
50 "System32": [
51 os.path.join(os.getenv("SystemRoot"), "System32"),
52 os.path.join(os.getenv("SystemRoot"), "SysWOW64"),
53 ],
54 "ProgramFiles": [
55 os.getenv("ProgramFiles").replace(" (x86)", ""),
56 os.getenv("ProgramFiles(x86)"),
57 ],
58 "HomeDrive": [
59
60
61 os.getenv("HomeDrive") + "\\",
62 ],
63 }
64
65 for path in self.PATHS:
66 basedir = path[0]
67 for basepath in basepaths.get(basedir, [basedir]):
68 if not basepath or not os.path.isdir(basepath):
69 continue
70
71 yield os.path.join(basepath, *path[1:])
72
74 """Search for the application in all available paths.
75 @param applicaiton: application executable name
76 @return: executable path
77 """
78 for path in self.enum_paths():
79 if os.path.isfile(path):
80 return path
81
82 raise CuckooPackageError("Unable to find any %s executable." %
83 application)
84
86 """Search for the application in all available paths with glob support.
87 @param applicaiton: application executable name
88 @return: executable path
89 """
90 for path in self.enum_paths():
91 for path in glob.iglob(path):
92 if os.path.isfile(path):
93 return path
94
95 raise CuckooPackageError("Unable to find any %s executable." %
96 application)
97
99 """Move a file to the current working directory so it can be executed
100 from there.
101 @param filepath: the file to be moved
102 @return: the new filepath
103 """
104 outpath = os.path.join(self.curdir, os.path.basename(filepath))
105 os.rename(filepath, outpath)
106 return outpath
107
109 """Initializes the registry to avoid annoying popups, configure
110 settings, etc.
111 @param regkeys: the root keys, subkeys, and key/value pairs.
112 """
113 for rootkey, subkey, values in regkeys:
114 key_handle = CreateKey(rootkey, subkey)
115
116 for key, value in values.items():
117 if isinstance(value, str):
118 SetValueEx(key_handle, key, 0, REG_SZ, value)
119 elif isinstance(value, int):
120 SetValueEx(key_handle, key, 0, REG_DWORD, value)
121 elif isinstance(value, dict):
122 self.init_regkeys([
123 [rootkey, "%s\\%s" % (subkey, key), value],
124 ])
125 else:
126 raise CuckooPackageError("Invalid value type: %r" % value)
127
128 CloseKey(key_handle)
129
130 - def execute(self, path, args, mode=None, maximize=False, env=None,
131 source=None, trigger=None):
132 """Starts an executable for analysis.
133 @param path: executable path
134 @param args: executable arguments
135 @param mode: monitor mode - which functions to instrument
136 @param maximize: whether the GUI should start maximized
137 @param env: additional environment variables
138 @param source: parent process of our process
139 @param trigger: trigger to indicate analysis start
140 @return: process pid
141 """
142 dll = self.options.get("dll")
143 free = self.options.get("free")
144
145 source = source or self.options.get("from")
146 mode = mode or self.options.get("mode")
147
148 if not trigger and self.options.get("trigger"):
149 if self.options["trigger"] == "exefile":
150 trigger = "file:%s" % path
151
152
153 self.init_regkeys(self.REGKEYS)
154
155 p = Process()
156 if not p.execute(path=path, args=args, dll=dll, free=free,
157 curdir=self.curdir, source=source, mode=mode,
158 maximize=maximize, env=env, trigger=trigger):
159 raise CuckooPackageError(
160 "Unable to execute the initial process, analysis aborted."
161 )
162
163 return p.pid
164
166 """A list of files to upload to host.
167 The list should be a list of tuples (<path on guest>, <name of file in package_files folder>).
168 (package_files is a folder that will be created in analysis folder).
169 """
170 return None
171
173 """Finish run.
174 If specified to do so, this method dumps the memory of
175 all running processes.
176 """
177 if self.options.get("procmemdump"):
178 for pid in self.pids:
179 p = Process(pid=pid)
180 p.dump_memory()
181
182 return True
183
185 - def __init__(self, options={}, analyzer=None):
186 self.options = options
187 self.analyzer = analyzer
188