def main(): parser = argparse.ArgumentParser(description='Push sample to the karton') parser.add_argument('sample', help='Path to the sample') parser.add_argument('--start_command', help='e.g. start %f, %f will be replaced by file name', required=False) parser.add_argument('--timeout', default=600, type=int, help='analysis timeout in seconds', required=False) args = parser.parse_args() conf = patch_config(Config(os.path.join(ETC_DIR, 'config.ini'))) producer = Producer(conf) task = Task({"type": "sample", "stage": "recognized", "platform": "win32"}) with open(args.sample, "rb") as f: sample = Resource("sample", f.read()) task.add_resource("sample", sample) # Add filename filename = os.path.basename(args.sample) task.add_payload("file_name", os.path.splitext(filename)[0]) # Extract and add extension extension = os.path.splitext(filename)[1][1:] if extension: task.headers['extension'] = extension if args.start_command is not None: task.add_payload("start_command", args.start_command) if args.timeout is not None: task.add_payload("timeout", args.timeout) producer.send_task(task)
def upload(): producer = Producer(conf) with NamedTemporaryFile() as f: request.files['file'].save(f.name) with open(f.name, "rb") as fr: sample = Resource("sample", fr.read()) task = Task({"type": "sample", "stage": "recognized", "platform": "win32"}) task.add_resource("override_uid", task.uid) # Add analysis timeout to task timeout = request.form.get("timeout") if timeout: task.add_resource("timeout", int(timeout)) # Add filename override to task filename = request.form.get("file_name") if filename: task.add_resource("file_name", filename) # Add startup command to task start_command = request.form.get("start_command") if start_command: task.add_resource("start_command", filename) task.add_resource("sample", sample) producer.send_task(task) return jsonify({"task_uid": task.uid})
def upload(): producer = Producer(conf) with NamedTemporaryFile() as f: request.files['file'].save(f.name) with open(f.name, "rb") as fr: sample = Resource("sample", fr.read()) task = Task({"type": "sample", "stage": "recognized", "platform": "win32"}) task.payload["override_uid"] = task.uid task.add_resource("sample", sample) producer.send_task(task) return jsonify({"task_uid": task.uid})
def main(): parser = argparse.ArgumentParser(description='Push sample to the karton') parser.add_argument('sample', help='Path to the sample') args = parser.parse_args() conf = Config('/etc/drakrun/config.ini') producer = Producer(conf) with open(args.sample, "rb") as f: sample = Resource("sample", f.read()) task = Task({"type": "sample", "stage": "recognized", "platform": "win32"}) task.add_resource("sample", sample) producer.send_task(task)
def upload(): producer = Producer(conf) with NamedTemporaryFile() as f: request.files['file'].save(f.name) with open(f.name, "rb") as fr: sample = Resource("sample", fr.read()) task = Task({"type": "sample", "stage": "recognized", "platform": "win32"}) task.add_payload("override_uid", task.uid) # Add analysis timeout to task timeout = request.form.get("timeout") if timeout: task.add_payload("timeout", int(timeout)) # Add filename override to task if request.form.get("file_name"): filename = request.form.get("file_name") else: filename = request.files['file'].filename if not re.fullmatch( r'^((?![\\/><|:&])[\x20-\xfe])+\.(?:dll|exe|doc|docm|docx|dotm|xls|xlsx|xlsm|xltx|xltm)$', filename, flags=re.IGNORECASE): return jsonify({"error": "invalid file_name"}), 400 task.add_payload("file_name", os.path.splitext(filename)[0]) # Extract and add extension extension = os.path.splitext(filename)[1][1:] if extension: task.headers['extension'] = extension # Add startup command to task start_command = request.form.get("start_command") if start_command: task.add_payload("start_command", start_command) task.add_resource("sample", sample) producer.send_task(task) return jsonify({"task_uid": task.uid})
def upload(): producer = Producer(conf) with NamedTemporaryFile() as f: request.files['file'].save(f.name) with open(f.name, "rb") as fr: sample = Resource("sample", fr.read()) task = Task({"type": "sample", "stage": "recognized", "platform": "win32"}) task.add_payload("override_uid", task.uid) # Add analysis timeout to task timeout = request.form.get("timeout") if timeout: task.add_payload("timeout", int(timeout)) # Add filename override to task if request.form.get("file_name"): filename = request.form.get("file_name") else: filename = request.files['file'].filename task.add_payload("file_name", os.path.splitext(filename)[0]) # Extract and add extension extension = os.path.splitext(filename)[1][1:] if extension: task.headers['extension'] = extension # Add startup command to task start_command = request.form.get("start_command") if start_command: task.add_payload("start_command", start_command) task.add_resource("sample", sample) producer.send_task(task) return jsonify({"task_uid": task.uid})
def process(self): sample = self.current_task.get_resource("sample") local_sample = self.download_resource(sample) self.log.info("hostname: {}".format(socket.gethostname())) sha256sum = hashlib.sha256(local_sample.content).hexdigest() magic_output = magic.from_buffer(local_sample.content) self.log.info("running sample sha256: {}".format(sha256sum)) analysis_uid = self.current_task.uid override_uid = self.current_task.payload.get('override_uid') self.log.info(f"analysis UID: {analysis_uid}") if override_uid: analysis_uid = override_uid self.log.info(f"override UID: {override_uid}") self.log.info("note that artifacts will be stored under this overriden identifier") workdir = '/tmp/drakrun/vm-{}'.format(int(INSTANCE_ID)) extension = self.current_task.headers.get("extension", "exe").lower() start_command = 'start malwar.{}'.format(extension) if extension == 'dll': run_command = self._get_dll_run_command(local_sample.content) if not run_command: self.log.info('Unable to run malware sample, could not generate any suitable command to run it.') return self.log.info('Using command: {}'.format(run_command)) start_command = 'start {}'.format(run_command) try: shutil.rmtree(workdir) except Exception as e: print(e) outdir = os.path.join(workdir, 'output') os.makedirs(workdir, exist_ok=True) os.mkdir(outdir) os.mkdir(os.path.join(outdir, 'dumps')) metadata = { "sample_sha256": sha256sum, "magic_output": magic_output, "time_started": int(time.time()), "start_command": start_command } with open(os.path.join(outdir, 'sample_sha256.txt'), 'w') as f: f.write(hashlib.sha256(local_sample.content).hexdigest()) with open(os.path.join(workdir, 'run.bat'), 'wb') as f: f.write(b'ipconfig /renew\r\nxcopy D:\\malwar.' + extension.encode('ascii') + b' %USERPROFILE%\\Desktop\\\r\nC:\r\ncd %USERPROFILE%\\Desktop\r\n' + start_command.encode('ascii')) with open(os.path.join(workdir, 'malwar.{}'.format(extension)), 'wb') as f: f.write(local_sample.content) try: subprocess.run(["genisoimage", "-o", os.path.join(workdir, 'malwar.iso'), os.path.join(workdir, 'malwar.{}'.format(extension)), os.path.join(workdir, 'run.bat')], cwd=workdir, check=True) except subprocess.CalledProcessError as e: logging.exception("Failed to generate CD ISO image. Please install genisoimage") raise e watcher_tcpdump = None watcher_dnsmasq = None for _ in range(3): try: self.log.info("running vm {}".format(INSTANCE_ID)) watcher_dnsmasq = start_dnsmasq(INSTANCE_ID, self.config.config['drakrun'].get('dns_server', '8.8.8.8')) d_run.ETC_DIR = ETC_DIR d_run.LIB_DIR = LIB_DIR d_run.logging = self.log d_run.run_vm(INSTANCE_ID) watcher_tcpdump = start_tcpdump_collector(INSTANCE_ID, outdir) self.log.info("running monitor {}".format(INSTANCE_ID)) kernel_profile = os.path.join(LIB_DIR, "profiles/kernel.json") runtime_profile = os.path.join(LIB_DIR, "profiles/runtime.json") with open(runtime_profile, 'r') as runtime_f: rp = json.loads(runtime_f.read()) inject_pid = rp['inject_pid'] kpgd = rp['vmi_offsets']['kpgd'] hooks_list = os.path.join(ETC_DIR, "hooks.txt") dump_dir = os.path.join(outdir, "dumps") drakmon_log_fp = os.path.join(outdir, "drakmon.log") drakvuf_cmd = ["drakvuf", "-o", "json", "-x", "poolmon", "-x", "objmon", "-j", "5", "-t", "600", "-i", inject_pid, "-k", kpgd, "-d", "vm-{vm_id}".format(vm_id=INSTANCE_ID), "--dll-hooks-list", hooks_list, "--memdump-dir", dump_dir, "-r", kernel_profile, "-e", "D:\\run.bat"] with open(drakmon_log_fp, "wb") as drakmon_log: drakvuf = subprocess.Popen(drakvuf_cmd, stdout=drakmon_log) try: exit_code = drakvuf.wait(660) except subprocess.TimeoutExpired as e: logging.error("BUG: Monitor command doesn\'t terminate automatically after timeout expires.") logging.error("Trying to terminate DRAKVUF...") drakvuf.terminate() drakvuf.wait(10) logging.error("BUG: Monitor command also doesn\'t terminate after sending SIGTERM.") drakvuf.kill() drakvuf.wait() logging.error("Monitor command was forcefully killed.") raise e if exit_code != 0: raise subprocess.CalledProcessError(exit_code, drakvuf_cmd) break except subprocess.CalledProcessError: self.log.info("Something went wrong with the VM {}".format(INSTANCE_ID), exc_info=True) finally: try: subprocess.run(["xl", "destroy", "vm-{}".format(INSTANCE_ID)], cwd=workdir, check=True) except subprocess.CalledProcessError: self.log.info("Failed to destroy VM {}".format(INSTANCE_ID), exc_info=True) if watcher_dnsmasq: watcher_dnsmasq.terminate() else: self.log.info("Failed to analyze sample after 3 retries, giving up.") return self.log.info("waiting for tcpdump to exit") if watcher_tcpdump: try: watcher_tcpdump.wait(timeout=60) except subprocess.TimeoutExpired: self.log.exception("tcpdump doesn't exit cleanly after 60s") self.crop_dumps(os.path.join(outdir, 'dumps'), os.path.join(outdir, 'dumps.zip')) if os.path.exists("/opt/procdot/procmon2dot"): self.generate_graphs(outdir) self.slice_logs(outdir) self.log.info("uploading artifacts") metadata['time_finished'] = int(time.time()) with open(os.path.join(outdir, 'metadata.json'), 'w') as f: f.write(json.dumps(metadata)) payload = {"analysis_uid": analysis_uid} payload.update(metadata) t = Task( { "type": "analysis", "kind": "drakrun", "quality": self.current_task.headers.get("quality", "high") }, payload=payload ) for resource in self.upload_artifacts(analysis_uid, workdir): t.add_resource(resource.name, resource) t.add_resource('sample', sample) self.send_task(t)