From cdc3cf37a53c2730e20bb6909234fd352c090b2c Mon Sep 17 00:00:00 2001 From: pinksawtooth Date: Sat, 29 Sep 2018 08:44:20 +0900 Subject: [PATCH] ver 1.1 --- manager.py | 36 ++++++++---------- mouse_emu.py | 7 ---- setup/setup.sh | 6 +-- tools/mouse_emu.pyw | 21 ++++++++++ xmlrpc_client.py | 93 ++++++++++++++++++++++++++++----------------- xmlrpc_server.py | 4 +- 6 files changed, 102 insertions(+), 65 deletions(-) delete mode 100755 mouse_emu.py create mode 100644 tools/mouse_emu.pyw diff --git a/manager.py b/manager.py index 8e719ed..a1362df 100755 --- a/manager.py +++ b/manager.py @@ -41,24 +41,6 @@ def start_analyze(): with open('config.json', 'w') as outfile: json.dump(json_data, outfile) - cmd=[("virsh snapshot-revert " + VM_NAME + " --current")] - - p = (subprocess.Popen(cmd, shell=True, stdin=None, stdout=subprocess.PIPE, stderr=subprocess.PIPE, close_fds=True)) - output = p.stderr.read().decode('utf-8') - print(output) - - if "busy" in output: - state={"state":0} - with open("state.json", 'w') as f: - json.dump(state, f) - return make_response(jsonify(status_code=2, message="failed to initialize KVM: Device or resource busy"), 500) - - elif "Domain" in output: - state={"state":0} - with open("state.json", 'w') as f: - json.dump(state, f) - return make_response(jsonify(status_code=2, message="Domain snapshot not found: the domain does not have a current snapshot"), 500) - cmd = [("./xmlrpc_client.py "+ uid)] subprocess.Popen(cmd, shell=True, stdin=None, stdout=None, stderr=None, close_fds=True) @@ -87,7 +69,6 @@ def file_upload(): @app.route('/results/') def show_result(uuid=None): - print(uuid) result = list(collection.find({u"UUID":uuid}))[0] result.pop('_id') @@ -97,7 +78,22 @@ def show_result(uuid=None): else: return make_response(jsonify(status_code=1, message='Analysing.'), 206) - +@app.route('/yara/') +def get_yara_file(rule_name=None): + + rule_name_check = rule_name.replace("_", "") + if rule_name_check.isalnum() == False: + return make_response(jsonify(status_code=2, message="Invalid rule_name"), 400) + + cmd=[("find yara/ -type f | xargs grep -l -x -E -e " + "\"rule "+ rule_name +" .*{\" -e \"rule "+ rule_name +"{\" -e \"rule " + rule_name + "\"")] + print(cmd) + p = (subprocess.Popen(cmd, shell=True, stdin=None, stdout=subprocess.PIPE, close_fds=True)) + output = p.stdout.read().decode('utf-8') + + with open(output.strip(), 'r') as f: + yara_file=f.read() + + return jsonify(status_code=0, result=yara_file) @app.errorhandler(404) def not_found(error): diff --git a/mouse_emu.py b/mouse_emu.py deleted file mode 100755 index 0696fe8..0000000 --- a/mouse_emu.py +++ /dev/null @@ -1,7 +0,0 @@ -import pyautogui - -while(1): - pyautogui.moveRel(500, 0, 0.2) - pyautogui.moveRel(0, 500, 0.2) - pyautogui.moveRel(-500, 0, 0.2) - pyautogui.moveRel(0, -500, 0.2) diff --git a/setup/setup.sh b/setup/setup.sh index 69d6b6c..1b1ca34 100755 --- a/setup/setup.sh +++ b/setup/setup.sh @@ -1,6 +1,6 @@ #!/bin/bash -mkdir target result tools yara +mkdir target result yara chmod 777 target result -sudo apt install python3 python3-magic kvm virt-manager libvirt-bin bridge-utils mongodb npm nginx -sudo pip3 install -r requirements.txt +sudo apt install python3 python3-pip python3-magic qemu-kvm virt-manager libvirt-bin bridge-utils mongodb npm nginx autoconf +sudo pip3 install -r setup/requirements.txt diff --git a/tools/mouse_emu.pyw b/tools/mouse_emu.pyw new file mode 100644 index 0000000..d86bf15 --- /dev/null +++ b/tools/mouse_emu.pyw @@ -0,0 +1,21 @@ +import ctypes.wintypes +import random, time + +User32 = ctypes.WinDLL('User32.dll') +GetSystemMetrics = User32.GetSystemMetrics + +RESOLUTION = { + "x": User32.GetSystemMetrics(0), + "y": User32.GetSystemMetrics(1) +} + +def move_mouse(): + x = random.randint(0, RESOLUTION["x"]) + y = random.randint(0, RESOLUTION["y"]) + + User32.SetCursorPos(x, y) + +while(1): + move_mouse() + time.sleep(0.1) + diff --git a/xmlrpc_client.py b/xmlrpc_client.py index dbb3244..c990c54 100755 --- a/xmlrpc_client.py +++ b/xmlrpc_client.py @@ -1,9 +1,9 @@ #!/usr/bin/env python3 import xmlrpc.client -import os, sys, shutil, json, subprocess, time, yara, glob, hashlib, datetime, requests +import os, sys, shutil, json, subprocess, time, yara, hashlib, datetime, requests +from pathlib import Path from pymongo import MongoClient -from pprint import pprint with open("tknk.conf", 'r') as f: tknk_conf = json.load(f) @@ -12,10 +12,7 @@ VM_URL=tknk_conf['vm_url'] def change_state(): - with open("state.json", 'r') as f: - state = json.load(f) - - state['state'] = 0 + state={"state":0} with open("state.json", 'w') as f: json.dump(state, f) @@ -54,18 +51,6 @@ def vm_down(): if __name__ == '__main__': args = sys.argv - c=0 - - while(1): - vm_state = subprocess.check_output(["virsh", "domstate", VM_NAME]) - time.sleep(1) - c+=1 - #print (vm_state.decode('utf-8')) - if "running" in str(vm_state.decode('utf-8')): - break - if c == 60: - change_state() - exit() #db connect client = MongoClient('localhost', 27017) @@ -96,10 +81,42 @@ def vm_down(): result['scans'].append({"sha256":file_sha256, "detect_rule":list(map(str,matches)), "file_name":config['target_file']}) - os.mkdir("result/" + str(now.strftime("%Y-%m-%d_%H:%M:%S"))) + cmd=[("virsh snapshot-revert " + VM_NAME + " --current")] + p = (subprocess.Popen(cmd, shell=True, stdin=None, stdout=subprocess.PIPE, stderr=subprocess.PIPE, close_fds=True)) + output = p.stderr.read().decode('utf-8') + print(output) + + if "busy" in output: + print("failed to initialize KVM: Device or resource busy") + result["result"]["is_success"] = False + result["result"]["detail"] = "failed to initialize KVM: Device or resource busy" + change_state() + collection.update({u'UUID':uid},result) + exit() + + elif "Domain" in output: + print("Domain snapshot not found: the domain does not have a current snapshot") + result["result"]["is_success"] = False + result["result"]["detail"] = "Domain snapshot not found: the domain does not have a current snapshot" + change_state() + collection.update({u'UUID':uid},result) + exit() + + c=0 + + while(1): + vm_state = subprocess.check_output(["virsh", "domstate", VM_NAME]) + time.sleep(1) + c+=1 + #print (vm_state.decode('utf-8')) + if "running" in str(vm_state.decode('utf-8')): + break + if c == 60: + change_state() + exit() upload("config.json") - tools = ["tools/hollows_hunter.exe", "tools/pe-sieve.dll", "tools/procdump.exe", "tools/pssuspend.exe", "tools/mouse_emu.exe"] + tools = ["tools/hollows_hunter.exe", "tools/pe-sieve.dll", "tools/procdump.exe", "tools/pssuspend.exe", "tools/mouse_emu.pyw"] for tool_name in tools: upload(tool_name) @@ -107,24 +124,24 @@ def vm_down(): upload("target/" + config['target_file']) ret = dump() - print("ret===============================") - pprint(ret) if ret == False: print("Connection error\n") - is_success == False + is_success = False result["result"]["detail"] = "Connection error" else: ret = download() if ret == True: - shutil.move("dump.zip", "result/") print("dump finish") is_success = True else: is_success = False - result["result"]["detail"] = "dump file does not exist" + if result["mode"] == "procdump": + result["result"]["detail"] = "Process does not exist" + else: + result["result"]["detail"] = "Dump file does not exist" vm_down() @@ -134,8 +151,8 @@ def vm_down(): result["result"]["is_success"] = True result["result"]["detail"] = "Detected with yara rule!" break - - with open("result/"+ str(now.strftime("%Y-%m-%d_%H:%M:%S")) + "/" +file_sha256+'.json', 'w') as outfile: + os.mkdir("result/" + str(uid)) + with open("result/"+ str(uid) + "/" +file_sha256+'.json', 'w') as outfile: json.dump(result, outfile, indent=4) print (json.dumps(result, indent=4)) @@ -145,15 +162,23 @@ def vm_down(): exit() elif is_success == True: + p = Path("result/dump.zip") + if p.exists(): + p.unlink() + print("remove") + shutil.move("dump.zip", "result/") subprocess.run(['unzip', "dump.zip"], cwd="result") - files = glob.glob("result/dump/**", recursive=True) + p = Path("result/dump/") - for f in files: - if "exe" in f.rsplit(".", 1) or "dll" in f.rsplit(".", 1) or "dmp" in f.rsplit(".", 1): - sha256_hash = str(hashlib.sha256(open(f,'rb').read()).hexdigest()) - matches = rules.match(f) - result['scans'].append({"sha256":sha256_hash, "detect_rule":list(map(str,matches)), "file_name":f.rsplit("/", 1)[1]}) + for f in p.glob("**/*"): + print(f.suffix) + print(f.resolve()) + print(f.name) + if (".exe" == f.suffix) or (".dll" == f.suffix) or (".dmp" == f.suffix): + sha256_hash = str(hashlib.sha256(open(str(f.resolve()),'rb').read()).hexdigest()) + matches = rules.match(str(f.resolve())) + result['scans'].append({"sha256":sha256_hash, "detect_rule":list(map(str,matches)), "file_name":f.name}) for scan in result["scans"]: if scan["detect_rule"] != []: @@ -166,7 +191,7 @@ def vm_down(): with open("result/dump/"+file_sha256+'.json', 'w') as outfile: json.dump(result, outfile, indent=4) - os.rename("result/dump/", "result/"+str(now.strftime("%Y-%m-%d_%H:%M:%S"))) + os.rename("result/dump/", "result/"+str(uid)) os.remove("result/dump.zip") os.remove("config.json") diff --git a/xmlrpc_server.py b/xmlrpc_server.py index e12b4d0..55ea1b2 100755 --- a/xmlrpc_server.py +++ b/xmlrpc_server.py @@ -23,6 +23,8 @@ def dump(): with open('config.json', 'r') as outfile: config = json.load(outfile) + subprocess.call(['cmd.exe', "/c", "start", "pythonw", "mouse_emu.pyw"]) + if config["mode"] == "diff": Psapi = ctypes.WinDLL('Psapi.dll') EnumProcesses = Psapi.EnumProcesses @@ -36,7 +38,7 @@ def dump(): src_set = set(ProcessIds) subprocess.call(['cmd.exe', "/c", "start", config['target_file']]) - subprocess.call(['cmd.exe', "/c", "start", 'mouse_emu.exe']) + print(("wait for unpack %d seconds\n") % config["time"])