mirror of
https://github.com/dobin/SuperMega
synced 2026-06-02 17:27:10 +00:00
refactor: make web work again (split project <-> settings)
This commit is contained in:
+5
-2
@@ -4,16 +4,19 @@ bak/
|
|||||||
tools/
|
tools/
|
||||||
doc/
|
doc/
|
||||||
|
|
||||||
|
projects/*
|
||||||
|
!projects/default/
|
||||||
|
!projects/default/**
|
||||||
|
|
||||||
data/binary/exes_more/
|
data/binary/exes_more/
|
||||||
data/source/payload/
|
data/source/payload/
|
||||||
|
data/binary/exes/*
|
||||||
|
|
||||||
log-*
|
log-*
|
||||||
*.verify.exe
|
*.verify.exe
|
||||||
*.verify.dll
|
*.verify.dll
|
||||||
*.infected.exe
|
*.infected.exe
|
||||||
projects/*
|
|
||||||
*.test.exe
|
*.test.exe
|
||||||
data/binary/exes/*
|
|
||||||
|
|
||||||
main.obj
|
main.obj
|
||||||
mlink$.lnk
|
mlink$.lnk
|
||||||
|
|||||||
+20
-22
@@ -1,52 +1,50 @@
|
|||||||
import pickle
|
import pickle
|
||||||
import os
|
import os
|
||||||
import yaml
|
|
||||||
import pickle
|
import pickle
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
from typing import List, Tuple
|
from typing import List, Tuple
|
||||||
from model.defs import *
|
from model.defs import *
|
||||||
from model.project import WebProject
|
from model.project import Settings
|
||||||
|
|
||||||
|
|
||||||
logger = logging.getLogger("Storage")
|
logger = logging.getLogger("Storage")
|
||||||
|
|
||||||
|
|
||||||
class Storage():
|
class Storage():
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
def get_projects(self) -> List[WebProject]:
|
def get_project_settings(self) -> List[Settings]:
|
||||||
projects: List[WebProject] = []
|
project_settings: List[Settings] = []
|
||||||
for project_name in os.listdir(PATH_WEB_PROJECT):
|
for project_name in os.listdir(PATH_WEB_PROJECT):
|
||||||
project = self.get_project(project_name)
|
project_setting = self.get_project_setting(project_name)
|
||||||
if project is None:
|
if project_setting is None:
|
||||||
continue
|
continue
|
||||||
projects.append(project)
|
project_settings.append(project_setting)
|
||||||
return projects
|
return project_settings
|
||||||
|
|
||||||
|
|
||||||
def get_project(self, project_name: str) -> WebProject:
|
def get_project_setting(self, project_name: str) -> Settings| None:
|
||||||
logger.debug("Load project: {}".format(project_name))
|
|
||||||
path = "{}/{}".format(PATH_WEB_PROJECT, project_name)
|
path = "{}/{}".format(PATH_WEB_PROJECT, project_name)
|
||||||
json_path = "{}/project.pickle".format(path)
|
json_path = "{}/project.pickle".format(path)
|
||||||
if not os.path.exists(json_path):
|
if not os.path.exists(json_path):
|
||||||
return None
|
return None
|
||||||
|
logger.info("Loading project from: {}".format(json_path))
|
||||||
with open(json_path, "rb") as f:
|
with open(json_path, "rb") as f:
|
||||||
project = pickle.load(f)
|
settings = pickle.load(f)
|
||||||
return project
|
return settings
|
||||||
|
|
||||||
|
|
||||||
def add_project(self, project: WebProject):
|
def add_project_setting(self, settings: Settings):
|
||||||
# directories and contents
|
os.makedirs(PATH_WEB_PROJECT + settings.project_name, exist_ok=True)
|
||||||
os.makedirs(PATH_WEB_PROJECT + project.name, exist_ok=True)
|
with open("{}/{}/project.pickle".format(PATH_WEB_PROJECT, settings.project_name), "wb") as f:
|
||||||
with open("{}/{}/project.pickle".format(PATH_WEB_PROJECT, project.name), "wb") as f:
|
pickle.dump(settings, f)
|
||||||
pickle.dump(project, f)
|
|
||||||
|
|
||||||
|
|
||||||
def save_project(self, project: WebProject):
|
def save_project_settings(self, settings: Settings):
|
||||||
with open("{}/{}/project.pickle".format(PATH_WEB_PROJECT, project.name), "wb") as f:
|
with open("{}/{}/project.pickle".format(PATH_WEB_PROJECT, settings.project_name), "wb") as f:
|
||||||
pickle.dump(project, f)
|
pickle.dump(settings, f)
|
||||||
|
|
||||||
|
|
||||||
storage = Storage()
|
storage = Storage()
|
||||||
|
|||||||
@@ -1,31 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
{% include 'header.html' %}
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
{% include 'navigation.html' %}
|
|
||||||
|
|
||||||
<div class="indent">
|
|
||||||
|
|
||||||
<h1> ShcDev: {{name}}</h1>
|
|
||||||
|
|
||||||
<table class="table">
|
|
||||||
{% for file in files %}
|
|
||||||
<tr>
|
|
||||||
<td><a href="/shcdev/{{name}}/file/{file['name']}">{{ file['name']}}</a></td>
|
|
||||||
<td>{{file["date"]}}</td>
|
|
||||||
<td>{{file["info"]}}</td>
|
|
||||||
</tr>
|
|
||||||
{% endfor %}
|
|
||||||
</table>
|
|
||||||
|
|
||||||
<a href="/shcdev/{{name}}/build">Build</a>
|
|
||||||
|
|
||||||
<br><hr>
|
|
||||||
|
|
||||||
<pre>{{log}}</pre>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
{% include 'header.html' %}
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
{% include 'navigation.html' %}
|
|
||||||
|
|
||||||
<div class="indent">
|
|
||||||
|
|
||||||
<h1> ShcDevs: </h1>
|
|
||||||
|
|
||||||
<ul>
|
|
||||||
{% for item in data %}
|
|
||||||
<li><a href="/shcdev/{{item['name']}}">{{ item['name'] }}</a>
|
|
||||||
({{item["date"]}})
|
|
||||||
</li>
|
|
||||||
{% endfor %}
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
@@ -18,24 +18,17 @@
|
|||||||
<a class="nav-link {{ 'active' if request.path == '/' else '' }}"
|
<a class="nav-link {{ 'active' if request.path == '/' else '' }}"
|
||||||
href="/">Home</a>
|
href="/">Home</a>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a class="nav-link {{ 'active' if request.path == '/projects' else '' }}"
|
<a class="nav-link {{ 'active' if request.path == '/projects' else '' }}"
|
||||||
href="/projects">Projects</a>
|
href="/projects">Projects</a>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a class="nav-link {{ 'active' if request.path == '/shellcodes' else '' }}"
|
<a class="nav-link {{ 'active' if request.path == '/exes' else '' }}"
|
||||||
href="/shellcodes">Shellcodes</a>
|
href="/exes">EXEs</a>
|
||||||
</li>
|
</li>
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a class="nav-link {{ 'active' if request.path == '/exes' else '' }}"
|
<a class="nav-link {{ 'active' if request.path == '/exes' else '' }}"
|
||||||
href="/exes">EXE's</a>
|
href="/shellcodes">Shellcodes</a>
|
||||||
</li>
|
|
||||||
|
|
||||||
<li class="nav-item">
|
|
||||||
<a class="nav-link {{ 'active' if request.path == '/shcdev' else '' }}"
|
|
||||||
href="/shcdev">ShcDev</a>
|
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
+19
-19
@@ -45,7 +45,7 @@
|
|||||||
onchange="this.form.submit()" readonly>
|
onchange="this.form.submit()" readonly>
|
||||||
|
|
||||||
<input type="text" name="comment" class="hidden form-control"
|
<input type="text" name="comment" class="hidden form-control"
|
||||||
placeholder="" value="{{project.comment}}"
|
placeholder="" value="{{project_comment}}"
|
||||||
aria-label="PROJECTNAME" aria-describedby="basic-addon1"
|
aria-label="PROJECTNAME" aria-describedby="basic-addon1"
|
||||||
onchange="this.form.submit()">
|
onchange="this.form.submit()">
|
||||||
|
|
||||||
@@ -63,7 +63,7 @@
|
|||||||
aria-label="SHELLCODE" onchange="this.form.submit()">
|
aria-label="SHELLCODE" onchange="this.form.submit()">
|
||||||
{% for shellcode in shellcodes %}
|
{% for shellcode in shellcodes %}
|
||||||
<option value="{{shellcode['filename']}}"
|
<option value="{{shellcode['filename']}}"
|
||||||
{% if shellcode["filename"] in project.settings.payload_path %} selected {% endif %}
|
{% if shellcode["filename"] == settings.payload_base %} selected {% endif %}
|
||||||
>
|
>
|
||||||
{{shellcode['filename']}} ({{shellcode['size']}})
|
{{shellcode['filename']}} ({{shellcode['size']}})
|
||||||
</option>
|
</option>
|
||||||
@@ -71,7 +71,7 @@
|
|||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Input: EXE File -->
|
<!-- Input: EXE File -->
|
||||||
<div class="form-group row">
|
<div class="form-group row">
|
||||||
<label for="exe" class="col-sm-3 col-form-label"
|
<label for="exe" class="col-sm-3 col-form-label"
|
||||||
@@ -85,7 +85,7 @@
|
|||||||
aria-label="EXE" onchange="this.form.submit()">
|
aria-label="EXE" onchange="this.form.submit()">
|
||||||
{% for exe in exes %}
|
{% for exe in exes %}
|
||||||
<option value="{{exe['filename']}}"
|
<option value="{{exe['filename']}}"
|
||||||
{% if exe['filename'] == project.settings.inject_exe_in %} selected {% endif %}
|
{% if exe['filename'] == settings.injectable_base %} selected {% endif %}
|
||||||
>
|
>
|
||||||
{{exe['filename'] | basename}} ({{exe['size']}})</option>
|
{{exe['filename'] | basename}} ({{exe['size']}})</option>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
@@ -98,7 +98,7 @@
|
|||||||
<select class="form-select" name="dllfunc" aria-label="DLLFUNC" onchange="this.form.submit()">
|
<select class="form-select" name="dllfunc" aria-label="DLLFUNC" onchange="this.form.submit()">
|
||||||
{% for export in exports %}
|
{% for export in exports %}
|
||||||
<option value="{{export['name']}}"
|
<option value="{{export['name']}}"
|
||||||
{% if export["name"] == project.settings.dllfunc %} selected {% endif %}
|
{% if export["name"] == settings.dllfunc %} selected {% endif %}
|
||||||
>
|
>
|
||||||
{{export['name']}} ({{export['size']}})</option>
|
{{export['name']}} ({{export['size']}})</option>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
@@ -108,7 +108,7 @@
|
|||||||
|
|
||||||
<!-- Row 3: exe and shellcode info -->
|
<!-- Row 3: exe and shellcode info -->
|
||||||
<div class="col-2">
|
<div class="col-2">
|
||||||
<a href="/exes/{{project.settings.inject_exe_in | basename}}">EXE Info:</a>
|
<a href="/exes/{{settings.get_inject_exe_in() | basename}}">EXE Info:</a>
|
||||||
<ul>
|
<ul>
|
||||||
<li>
|
<li>
|
||||||
{% if is_64 %}
|
{% if is_64 %}
|
||||||
@@ -154,11 +154,11 @@
|
|||||||
<div class="col-3">
|
<div class="col-3">
|
||||||
<div class="form-group row">
|
<div class="form-group row">
|
||||||
<label for="carrier_name" class="col-sm-5 col-form-label
|
<label for="carrier_name" class="col-sm-5 col-form-label
|
||||||
{% if 'rwx' in project.settings.carrier_name %}
|
{% if 'rwx' in settings.carrier_name %}
|
||||||
opsec_bad
|
opsec_bad
|
||||||
{% elif 'peb_walk' in project.settings.carrier_name %}
|
{% elif 'peb_walk' in settings.carrier_name %}
|
||||||
opsec_bad
|
opsec_bad
|
||||||
{% elif 'change' in project.settings.carrier_name %}
|
{% elif 'change' in settings.carrier_name %}
|
||||||
opsec_neutral
|
opsec_neutral
|
||||||
{% else %}
|
{% else %}
|
||||||
opsec_good
|
opsec_good
|
||||||
@@ -172,7 +172,7 @@
|
|||||||
aria-label="CARRIERNAME" onchange="this.form.submit()">
|
aria-label="CARRIERNAME" onchange="this.form.submit()">
|
||||||
{% for name in carrier_names %}
|
{% for name in carrier_names %}
|
||||||
<option value="{{name}}"
|
<option value="{{name}}"
|
||||||
{% if name in project.settings.carrier_name %} selected {% endif %}
|
{% if name in settings.carrier_name %} selected {% endif %}
|
||||||
>{{name}}</option>
|
>{{name}}</option>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</select>
|
</select>
|
||||||
@@ -188,7 +188,7 @@
|
|||||||
aria-label="INJECTSTYLE" onchange="this.form.submit()">
|
aria-label="INJECTSTYLE" onchange="this.form.submit()">
|
||||||
{% for name, value in carrier_invoke_styles %}
|
{% for name, value in carrier_invoke_styles %}
|
||||||
<option value="{{name}}"
|
<option value="{{name}}"
|
||||||
{% if value in project.settings.carrier_invoke_style.value %} selected {% endif %}
|
{% if value in settings.carrier_invoke_style.value %} selected {% endif %}
|
||||||
>{{value}}</option>
|
>{{value}}</option>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</select>
|
</select>
|
||||||
@@ -204,7 +204,7 @@
|
|||||||
aria-label="PAYLOADLOCATION" onchange="this.form.submit()">
|
aria-label="PAYLOADLOCATION" onchange="this.form.submit()">
|
||||||
{% for name, value in payload_locations %}
|
{% for name, value in payload_locations %}
|
||||||
<option value="{{name}}"
|
<option value="{{name}}"
|
||||||
{% if value in project.settings.payload_location.value %} selected {% endif %}
|
{% if value in settings.payload_location.value %} selected {% endif %}
|
||||||
>{{value}}</option>
|
>{{value}}</option>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</select>
|
</select>
|
||||||
@@ -231,7 +231,7 @@
|
|||||||
aria-label="DECODERESTYLE" onchange="this.form.submit()">
|
aria-label="DECODERESTYLE" onchange="this.form.submit()">
|
||||||
{% for name in decoder_styles %}
|
{% for name in decoder_styles %}
|
||||||
<option value="{{name}}"
|
<option value="{{name}}"
|
||||||
{% if name in project.settings.decoder_style %} selected {% endif %}
|
{% if name in settings.decoder_style %} selected {% endif %}
|
||||||
>{{name}}
|
>{{name}}
|
||||||
</option>
|
</option>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
@@ -248,7 +248,7 @@
|
|||||||
aria-label="GUARDRAILSTYLE" onchange="this.form.submit()">
|
aria-label="GUARDRAILSTYLE" onchange="this.form.submit()">
|
||||||
{% for name in guardrailstyles %}
|
{% for name in guardrailstyles %}
|
||||||
<option value="{{name}}"
|
<option value="{{name}}"
|
||||||
{% if name in project.settings.plugin_guardrail %} selected {% endif %}
|
{% if name in settings.plugin_guardrail %} selected {% endif %}
|
||||||
>{{name}}
|
>{{name}}
|
||||||
</option>
|
</option>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
@@ -256,14 +256,14 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{% if project.settings.plugin_guardrail != "none" %}
|
{% if settings.plugin_guardrail != "none" %}
|
||||||
<div class="form-group row">
|
<div class="form-group row">
|
||||||
<label for="guardrail" class="col-sm-5 col-form-label">
|
<label for="guardrail" class="col-sm-5 col-form-label">
|
||||||
Guard Data
|
Guard Data
|
||||||
</label>
|
</label>
|
||||||
<div class="col-sm-7">
|
<div class="col-sm-7">
|
||||||
<input type="text" name="guardrail_data" class="hidden form-control"
|
<input type="text" name="guardrail_data" class="hidden form-control"
|
||||||
placeholder="" value="{{project.settings.plugin_guardrail_data}}"
|
placeholder="" value="{{settings.plugin_guardrail_data}}"
|
||||||
aria-label="guardrail_data" aria-describedby="basic-addon1"
|
aria-label="guardrail_data" aria-describedby="basic-addon1"
|
||||||
onchange="this.form.submit()">
|
onchange="this.form.submit()">
|
||||||
</div>
|
</div>
|
||||||
@@ -279,7 +279,7 @@
|
|||||||
aria-label="antiemulation" onchange="this.form.submit()">
|
aria-label="antiemulation" onchange="this.form.submit()">
|
||||||
{% for name in antiemulationstyles %}
|
{% for name in antiemulationstyles %}
|
||||||
<option value="{{name}}"
|
<option value="{{name}}"
|
||||||
{% if name in project.settings.plugin_antiemulation %} selected {% endif %}
|
{% if name in settings.plugin_antiemulation %} selected {% endif %}
|
||||||
>{{name}}
|
>{{name}}
|
||||||
</option>
|
</option>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
@@ -296,7 +296,7 @@
|
|||||||
aria-label="decoy" onchange="this.form.submit()">
|
aria-label="decoy" onchange="this.form.submit()">
|
||||||
{% for name in decoystyles %}
|
{% for name in decoystyles %}
|
||||||
<option value="{{name}}"
|
<option value="{{name}}"
|
||||||
{% if name in project.settings.plugin_decoy %} selected {% endif %}
|
{% if name in settings.plugin_decoy %} selected {% endif %}
|
||||||
>{{name}}
|
>{{name}}
|
||||||
</option>
|
</option>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
@@ -313,7 +313,7 @@
|
|||||||
aria-label="virtualprotect" onchange="this.form.submit()">
|
aria-label="virtualprotect" onchange="this.form.submit()">
|
||||||
{% for name in virtualprotectstyles %}
|
{% for name in virtualprotectstyles %}
|
||||||
<option value="{{name}}"
|
<option value="{{name}}"
|
||||||
{% if name in project.settings.plugin_virtualprotect %} selected {% endif %}
|
{% if name in settings.plugin_virtualprotect %} selected {% endif %}
|
||||||
>{{name}}
|
>{{name}}
|
||||||
</option>
|
</option>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|||||||
@@ -11,8 +11,8 @@
|
|||||||
<h1> Projects </h1>
|
<h1> Projects </h1>
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
{% for project in projects %}
|
{% for settings in project_settings %}
|
||||||
<li><a href="/project/{{project.name}}">{{ project.name }}</a></li>
|
<li><a href="/project/{{settings.project_name}}">{{ settings.project_name }}</a></li>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ logger = logging.getLogger("Views")
|
|||||||
@views.route("/")
|
@views.route("/")
|
||||||
def index():
|
def index():
|
||||||
return render_template('index.html')
|
return render_template('index.html')
|
||||||
|
return redirect("/project/default", code=302)
|
||||||
|
|
||||||
|
|
||||||
@views.route("/exes/<exe_name>")
|
@views.route("/exes/<exe_name>")
|
||||||
|
|||||||
+66
-53
@@ -15,7 +15,8 @@ from config import config
|
|||||||
from model.settings import Settings
|
from model.settings import Settings
|
||||||
from model.defs import *
|
from model.defs import *
|
||||||
from supermega import start
|
from supermega import start
|
||||||
from app.storage import storage, WebProject
|
from app.storage import storage
|
||||||
|
from model.project import Project
|
||||||
from sender import scannerDetectsBytes
|
from sender import scannerDetectsBytes
|
||||||
from phases.injector import verify_injected_exe
|
from phases.injector import verify_injected_exe
|
||||||
from phases.templater import get_template_names
|
from phases.templater import get_template_names
|
||||||
@@ -36,19 +37,21 @@ thread_running = False
|
|||||||
|
|
||||||
@views_project.route("/projects")
|
@views_project.route("/projects")
|
||||||
def projects_route():
|
def projects_route():
|
||||||
projects = storage.get_projects()
|
projects_settings = storage.get_project_settings()
|
||||||
return render_template('projects.html', projects=projects)
|
return render_template('projects.html', projects_settings=projects_settings)
|
||||||
|
|
||||||
|
|
||||||
@views_project.route("/project/<name>")
|
@views_project.route("/project/<name>")
|
||||||
def project(name):
|
def project(name):
|
||||||
project = storage.get_project(name)
|
project_setting = storage.get_project_setting(name)
|
||||||
if project == None:
|
if project_setting == None:
|
||||||
|
logger.error("Project {} not found".format(name))
|
||||||
return redirect("/projects", code=302)
|
return redirect("/projects", code=302)
|
||||||
|
|
||||||
exe_path = project.settings.inject_exe_out
|
project_setting.print()
|
||||||
|
|
||||||
is_built = False
|
is_built = False
|
||||||
if os.path.exists(exe_path):
|
if os.path.exists(project_setting.project_exe_path):
|
||||||
is_built = True
|
is_built = True
|
||||||
|
|
||||||
exports = []
|
exports = []
|
||||||
@@ -65,16 +68,16 @@ def project(name):
|
|||||||
if config.get("avred_server") != "":
|
if config.get("avred_server") != "":
|
||||||
has_remote = True
|
has_remote = True
|
||||||
|
|
||||||
# when we select a shellcode
|
# payload / shellcode
|
||||||
if project.settings.payload_path != "":
|
if project_setting.get_payload_path() != None:
|
||||||
payload_len = os.path.getsize(project.settings.payload_path)
|
payload_len = os.path.getsize(project_setting.get_payload_path())
|
||||||
|
|
||||||
# when we selected an input file
|
# injectable / exe
|
||||||
if project.settings.inject_exe_in != "" and os.path.exists(project.settings.inject_exe_in):
|
if project_setting.get_inject_exe_in() != None and os.path.exists(project_setting.get_inject_exe_in()):
|
||||||
superpe = SuperPe(project.settings.inject_exe_in)
|
superpe = SuperPe(project_setting.get_inject_exe_in())
|
||||||
#if not superpe.is_64():
|
#if not superpe.is_64():
|
||||||
# # return 500
|
# # return 500
|
||||||
# return "Error: Binary {} is not 64bit".format(project.settings.inject_exe_in), 500
|
# return "Error: Binary {} is not 64bit".format(project.settings.get_inject_exe_in()), 500
|
||||||
|
|
||||||
is_64 = superpe.is_64()
|
is_64 = superpe.is_64()
|
||||||
is_dotnet = superpe.is_dotnet()
|
is_dotnet = superpe.is_dotnet()
|
||||||
@@ -85,17 +88,17 @@ def project(name):
|
|||||||
if rdata_section != None:
|
if rdata_section != None:
|
||||||
data_sect_size = rdata_section.virt_size
|
data_sect_size = rdata_section.virt_size
|
||||||
else:
|
else:
|
||||||
logger.warning("No .rdata section found in {}".format(project.settings.inject_exe_in))
|
logger.warning("No .rdata section found in {}".format(project_setting.get_inject_exe_in()))
|
||||||
|
|
||||||
has_rodata_section = superpe.has_rodata_section()
|
has_rodata_section = superpe.has_rodata_section()
|
||||||
if has_rodata_section:
|
if has_rodata_section:
|
||||||
data_sect_largest_gap_size = superpe.get_rdata_rangemanager().find_largest_gap()
|
data_sect_largest_gap_size = superpe.get_rdata_rangemanager().find_largest_gap()
|
||||||
unresolved_dlls = pe.dllresolver.unresolved_dlls(superpe)
|
unresolved_dlls = pe.dllresolver.unresolved_dlls(superpe)
|
||||||
|
|
||||||
project_dir = os.path.dirname(os.getcwd() + "\\" + project.settings.main_dir)
|
project_dir = os.path.dirname(os.getcwd() + "\\" + project_setting.project_path)
|
||||||
log_files = get_logfiles(project.settings.main_dir)
|
log_files = get_logfiles(project_setting.project_path)
|
||||||
exes = list_files_and_sizes(PATH_EXES, prepend=PATH_EXES)
|
exes = list_files_and_sizes(PATH_EXES)
|
||||||
exes += list_files_and_sizes(PATH_EXES_MORE, prepend=PATH_EXES_MORE)
|
#exes += list_files_and_sizes(PATH_EXES_MORE, prepend=PATH_EXES_MORE)
|
||||||
shellcodes = list_files_and_sizes(PATH_SHELLCODES)
|
shellcodes = list_files_and_sizes(PATH_SHELLCODES)
|
||||||
|
|
||||||
carrier_names = get_template_names()
|
carrier_names = get_template_names()
|
||||||
@@ -110,9 +113,10 @@ def project(name):
|
|||||||
|
|
||||||
return render_template('project.html',
|
return render_template('project.html',
|
||||||
project_name = name,
|
project_name = name,
|
||||||
project=project,
|
project_comment = project_setting.project_comment,
|
||||||
is_built=is_built,
|
is_built=is_built,
|
||||||
project_dir=project_dir,
|
project_dir=project_dir,
|
||||||
|
settings=project_setting,
|
||||||
|
|
||||||
exes=exes,
|
exes=exes,
|
||||||
shellcodes=shellcodes,
|
shellcodes=shellcodes,
|
||||||
@@ -133,7 +137,7 @@ def project(name):
|
|||||||
has_rodata_section=has_rodata_section,
|
has_rodata_section=has_rodata_section,
|
||||||
|
|
||||||
has_remote=has_remote,
|
has_remote=has_remote,
|
||||||
fix_missing_iat=project.settings.fix_missing_iat,
|
fix_missing_iat=project_setting.fix_missing_iat,
|
||||||
|
|
||||||
guardrailstyles = guardrail_styles,
|
guardrailstyles = guardrail_styles,
|
||||||
antiemulationstyles = antiemulation_styles,
|
antiemulationstyles = antiemulation_styles,
|
||||||
@@ -170,18 +174,17 @@ def list_files(directory, prepend="") -> List[str]:
|
|||||||
def add_project():
|
def add_project():
|
||||||
if request.method == 'POST':
|
if request.method == 'POST':
|
||||||
project_name = request.form['project_name']
|
project_name = request.form['project_name']
|
||||||
|
|
||||||
settings = Settings(project_name)
|
|
||||||
comment = request.form['comment']
|
comment = request.form['comment']
|
||||||
|
|
||||||
|
# Empty settings, except name
|
||||||
|
settings = Settings(project_name)
|
||||||
|
|
||||||
# new project?
|
# new project?
|
||||||
if storage.get_project(project_name) == None:
|
if storage.get_project_setting(project_name) == None:
|
||||||
# Default values for web create
|
# Sane defaults for web
|
||||||
settings.init_payload_injectable(
|
settings.injectable_base = "7z.exe"
|
||||||
FilePath("messagebox.bin"),
|
settings.payload_base = "calc64.bin"
|
||||||
FilePath("data/binary/exes/procexp64.exe"),
|
|
||||||
""
|
|
||||||
)
|
|
||||||
settings.decoder_style = "xor_2"
|
settings.decoder_style = "xor_2"
|
||||||
settings.carrier_name = "alloc_rw_rx"
|
settings.carrier_name = "alloc_rw_rx"
|
||||||
settings.carrier_invoke_style = CarrierInvokeStyle.BackdoorCallInstr
|
settings.carrier_invoke_style = CarrierInvokeStyle.BackdoorCallInstr
|
||||||
@@ -189,17 +192,20 @@ def add_project():
|
|||||||
settings.fix_missing_iat = True
|
settings.fix_missing_iat = True
|
||||||
|
|
||||||
# add new project
|
# add new project
|
||||||
project = WebProject(project_name, settings)
|
settings.project_comment = comment
|
||||||
project.comment = comment
|
storage.add_project_setting(settings)
|
||||||
storage.add_project(project)
|
|
||||||
|
|
||||||
# update project
|
# update project
|
||||||
else:
|
else:
|
||||||
settings.init_payload_injectable(
|
logger.info("Update project: {}".format(project_name))
|
||||||
FilePath(request.form['shellcode']),
|
|
||||||
FilePath(request.form['exe']),
|
shellcode_file = request.form['shellcode']
|
||||||
request.form.get('dllfunc', "")
|
injectable_file = request.form['exe']
|
||||||
)
|
dll_func = request.form.get('dllfunc', "")
|
||||||
|
|
||||||
|
settings.injectable_base = injectable_file
|
||||||
|
settings.payload_base = shellcode_file
|
||||||
|
settings.dllfunc = dll_func
|
||||||
|
|
||||||
settings.fix_missing_iat = True if request.form.get('fix_missing_iat') != None else False
|
settings.fix_missing_iat = True if request.form.get('fix_missing_iat') != None else False
|
||||||
settings.carrier_name = request.form['carrier_name']
|
settings.carrier_name = request.form['carrier_name']
|
||||||
@@ -216,10 +222,8 @@ def add_project():
|
|||||||
settings.plugin_virtualprotect = request.form.get('virtualprotect', "standard")
|
settings.plugin_virtualprotect = request.form.get('virtualprotect', "standard")
|
||||||
|
|
||||||
# overwrite project
|
# overwrite project
|
||||||
project = storage.get_project(project_name)
|
#settings = storage.get_project(project_name)
|
||||||
project.settings = settings
|
storage.save_project_settings(settings)
|
||||||
project.comment = comment
|
|
||||||
storage.save_project(project)
|
|
||||||
|
|
||||||
return redirect("/project/{}".format(project_name), code=302)
|
return redirect("/project/{}".format(project_name), code=302)
|
||||||
|
|
||||||
@@ -237,14 +241,18 @@ def supermega_thread(settings: Settings):
|
|||||||
def build_project(project_name):
|
def build_project(project_name):
|
||||||
global thread_running
|
global thread_running
|
||||||
|
|
||||||
project = storage.get_project(project_name)
|
project_settings = storage.get_project_setting(project_name)
|
||||||
|
if project_settings == None:
|
||||||
|
logger.error("Project {} not found".format(project_name))
|
||||||
|
return redirect("/projects", code=302)
|
||||||
|
|
||||||
#if project.settings.inject_exe_in.endswith(".dll"):
|
#if project.settings.get_inject_exe_in().endswith(".dll"):
|
||||||
# if project.settings.dllfunc == "":
|
# if project.settings.dllfunc == "":
|
||||||
# logger.error("DLL injection requires a DLL function name")
|
# logger.error("DLL injection requires a DLL function name")
|
||||||
# return redirect("/project/{}".format(project_name), code=302)
|
# return redirect("/project/{}".format(project_name), code=302)
|
||||||
|
|
||||||
project.settings.try_start_final_infected_exe = False
|
project_settings.try_start_final_infected_exe = False
|
||||||
|
project = Project(project_settings)
|
||||||
prepare_project(project_name, project.settings)
|
prepare_project(project_name, project.settings)
|
||||||
thread = Thread(target=supermega_thread, args=(project.settings, ))
|
thread = Thread(target=supermega_thread, args=(project.settings, ))
|
||||||
thread.start()
|
thread.start()
|
||||||
@@ -266,9 +274,14 @@ def status_project(project_name):
|
|||||||
|
|
||||||
@views_project.route("/project/<project_name>/exec", methods=['POST', 'GET'])
|
@views_project.route("/project/<project_name>/exec", methods=['POST', 'GET'])
|
||||||
def start_project(project_name):
|
def start_project(project_name):
|
||||||
project = storage.get_project(project_name)
|
project_settings = storage.get_project_setting(project_name)
|
||||||
if project == None:
|
if project_settings == None:
|
||||||
return redirect("/", code=302)
|
return redirect("/", code=302)
|
||||||
|
|
||||||
|
project = Project(project_settings)
|
||||||
|
if not project.init():
|
||||||
|
logger.error("Project {} could not be initialized".format(project_name))
|
||||||
|
return redirect("/project/{}".format(project_name), code=302)
|
||||||
|
|
||||||
remote = False
|
remote = False
|
||||||
remote_arg = request.args.get('remote')
|
remote_arg = request.args.get('remote')
|
||||||
@@ -283,10 +296,10 @@ def start_project(project_name):
|
|||||||
logger.info(" Exec project: {} remote: {} no_exec: {}".format(project_name, remote, no_exec))
|
logger.info(" Exec project: {} remote: {} no_exec: {}".format(project_name, remote, no_exec))
|
||||||
|
|
||||||
if remote:
|
if remote:
|
||||||
logger.info(" Exec {} on server {}".format(project.settings.inject_exe_out, config.get("avred_server")))
|
logger.info(" Exec {} on server {}".format(project.settings.get_inject_exe_out(), config.get("avred_server")))
|
||||||
with open(project.settings.inject_exe_out, "rb") as f:
|
with open(project.settings.get_inject_exe_out(), "rb") as f:
|
||||||
data = f.read()
|
data = f.read()
|
||||||
filename = os.path.basename(project.settings.inject_exe_out)
|
filename = os.path.basename(project.settings.get_inject_exe_out())
|
||||||
try:
|
try:
|
||||||
scannerDetectsBytes(data,
|
scannerDetectsBytes(data,
|
||||||
filename,
|
filename,
|
||||||
@@ -302,11 +315,11 @@ def start_project(project_name):
|
|||||||
# Start/verify it at the end
|
# Start/verify it at the end
|
||||||
if project.settings.verify:
|
if project.settings.verify:
|
||||||
logger.info(" Verify infected exe")
|
logger.info(" Verify infected exe")
|
||||||
exit_code = verify_injected_exe(project.settings.inject_exe_out)
|
exit_code = verify_injected_exe(project.settings.get_inject_exe_out())
|
||||||
elif no_exec == False:
|
elif no_exec == False:
|
||||||
run_exe(project.settings.inject_exe_out, dllfunc=project.settings.dllfunc, check=False)
|
run_exe(project.settings.get_inject_exe_out(), dllfunc=project.settings.dllfunc, check=False)
|
||||||
elif no_exec == True:
|
elif no_exec == True:
|
||||||
dirname = os.path.dirname(os.path.abspath(project.settings.inject_exe_out))
|
dirname = os.path.dirname(os.path.abspath(project.settings.get_inject_exe_out()))
|
||||||
logger.info(" Open folder: {}".format(dirname))
|
logger.info(" Open folder: {}".format(dirname))
|
||||||
subprocess.run(['explorer', dirname])
|
subprocess.run(['explorer', dirname])
|
||||||
|
|
||||||
|
|||||||
@@ -1,83 +0,0 @@
|
|||||||
from flask import Flask, Blueprint, current_app, request, redirect, url_for, render_template, send_file, make_response, session, jsonify
|
|
||||||
from threading import Thread
|
|
||||||
import os
|
|
||||||
import logging
|
|
||||||
from typing import List, Tuple
|
|
||||||
from datetime import datetime
|
|
||||||
|
|
||||||
from observer import observer
|
|
||||||
from model.defs import *
|
|
||||||
from supermega import start
|
|
||||||
from phases.compiler import compile_dev
|
|
||||||
from phases.assembler import asm_to_shellcode
|
|
||||||
from helper import clean_tmp_files
|
|
||||||
|
|
||||||
views_shcdev = Blueprint('views_shcdev', __name__)
|
|
||||||
logger = logging.getLogger("ViewsShcdev")
|
|
||||||
|
|
||||||
@views_shcdev.route("/shcdev")
|
|
||||||
def devs_route():
|
|
||||||
data = []
|
|
||||||
for filename in os.listdir(PATH_PAYLOAD):
|
|
||||||
file_path = PATH_PAYLOAD + filename
|
|
||||||
creation_time = os.path.getctime(file_path)
|
|
||||||
readable_time = datetime.fromtimestamp(creation_time).strftime('%Y-%m-%d %H:%M:%S')
|
|
||||||
data.append({
|
|
||||||
"name": filename,
|
|
||||||
"date": readable_time,
|
|
||||||
})
|
|
||||||
return render_template('devs.html', data=data)
|
|
||||||
|
|
||||||
|
|
||||||
@views_shcdev.route("/shcdev/<name>")
|
|
||||||
def dev_route(name):
|
|
||||||
data = []
|
|
||||||
log = ""
|
|
||||||
path = PATH_PAYLOAD + name
|
|
||||||
for filename in os.listdir(path):
|
|
||||||
filepath = path + "/" + filename
|
|
||||||
|
|
||||||
creation_time = os.path.getmtime(filepath)
|
|
||||||
readable_time = datetime.fromtimestamp(creation_time).strftime('%Y-%m-%d %H:%M:%S')
|
|
||||||
|
|
||||||
info = ""
|
|
||||||
if filename.endswith(".asm"):
|
|
||||||
info = "text assembly (cleaned, from compiled .c)"
|
|
||||||
elif filename.endswith(".bin"):
|
|
||||||
info = "generated shellcode (from .exe)"
|
|
||||||
elif filename.endswith(".c"):
|
|
||||||
info = "input C code"
|
|
||||||
elif filename.endswith(".exe"):
|
|
||||||
info = "temporary shellcode holder (from .c)"
|
|
||||||
elif filename.endswith("cmdoutput.log"):
|
|
||||||
info = "command output"
|
|
||||||
with open(path + "/" + filename, "r") as f:
|
|
||||||
log += f.read() + "\n-----------------------------------\n"
|
|
||||||
elif filename.endswith("supermega.log"):
|
|
||||||
info = "supermega logging output"
|
|
||||||
with open(path + "/" + filename, "r") as f:
|
|
||||||
log += f.read()
|
|
||||||
|
|
||||||
data.append({
|
|
||||||
"name": filename,
|
|
||||||
"date": readable_time,
|
|
||||||
"info": info,
|
|
||||||
})
|
|
||||||
|
|
||||||
return render_template('dev.html',
|
|
||||||
name=name, files=data, log=log)
|
|
||||||
|
|
||||||
|
|
||||||
@views_shcdev.route("/shcdev/<name>/build")
|
|
||||||
def dev_build_route(name):
|
|
||||||
|
|
||||||
c_in = PATH_PAYLOAD + "{}/main.c".format(name)
|
|
||||||
asm_out = PATH_PAYLOAD + "{}/main.asm".format(name)
|
|
||||||
build_exe = PATH_PAYLOAD + "{}/main.exe".format(name)
|
|
||||||
shellcode_out = PATH_PAYLOAD + "{}/main.bin".format(name)
|
|
||||||
|
|
||||||
compile_dev(c_in, asm_out)
|
|
||||||
asm_to_shellcode(asm_out, build_exe, shellcode_out)
|
|
||||||
observer.write_logs(PATH_PAYLOAD + "{}/".format(name))
|
|
||||||
clean_tmp_files()
|
|
||||||
return redirect("/shcdev/{}".format(name), code=302)
|
|
||||||
@@ -6,7 +6,7 @@ import logging
|
|||||||
import pickle
|
import pickle
|
||||||
import math
|
import math
|
||||||
|
|
||||||
from model.project import WebProject
|
from model.project import Project
|
||||||
from config import config
|
from config import config
|
||||||
from model.defs import *
|
from model.defs import *
|
||||||
from observer import observer
|
from observer import observer
|
||||||
@@ -16,15 +16,6 @@ logger = logging.getLogger("Helper")
|
|||||||
SHC_VERIFY_SLEEP = 0.2
|
SHC_VERIFY_SLEEP = 0.2
|
||||||
|
|
||||||
|
|
||||||
def write_webproject(project_name, settings):
|
|
||||||
filepath = "{}project.pickle".format(settings.main_dir)
|
|
||||||
logger.info("Write project to: {}".format(filepath))
|
|
||||||
webProject = WebProject(project_name, settings)
|
|
||||||
webProject.comment = "Created by command line interface"
|
|
||||||
with open(filepath, "wb") as f:
|
|
||||||
pickle.dump(webProject, f)
|
|
||||||
|
|
||||||
|
|
||||||
def clean_tmp_files():
|
def clean_tmp_files():
|
||||||
files_to_clean = [
|
files_to_clean = [
|
||||||
# compile artefacts in current working dir
|
# compile artefacts in current working dir
|
||||||
@@ -39,10 +30,10 @@ def clean_tmp_files():
|
|||||||
def clean_files(settings):
|
def clean_files(settings):
|
||||||
files_to_clean = [
|
files_to_clean = [
|
||||||
# temporary files
|
# temporary files
|
||||||
settings.main_c_path,
|
settings.project_c_path,
|
||||||
settings.main_asm_path,
|
settings.project_asm_path,
|
||||||
settings.main_shc_path,
|
settings.project_shc_path,
|
||||||
settings.main_exe_path,
|
settings.project_exe_path,
|
||||||
]
|
]
|
||||||
for file in files_to_clean:
|
for file in files_to_clean:
|
||||||
pathlib.Path(file).unlink(missing_ok=True)
|
pathlib.Path(file).unlink(missing_ok=True)
|
||||||
|
|||||||
+1
-2
@@ -13,14 +13,13 @@ PATH_EXES_MORE = "data/binary/exes_more/"
|
|||||||
PATH_DLLS = "data/binary/dlls/"
|
PATH_DLLS = "data/binary/dlls/"
|
||||||
PATH_SHELLCODES = "data/binary/shellcodes/"
|
PATH_SHELLCODES = "data/binary/shellcodes/"
|
||||||
PATH_CARRIER = "data/source/carrier/"
|
PATH_CARRIER = "data/source/carrier/"
|
||||||
PATH_PAYLOAD = "data/source/payload/"
|
|
||||||
|
|
||||||
PATH_DECODER = "data/source/decoder/"
|
PATH_DECODER = "data/source/decoder/"
|
||||||
PATH_ANTIEMULATION = "data/source/antiemulation/"
|
PATH_ANTIEMULATION = "data/source/antiemulation/"
|
||||||
PATH_DECOY = "data/source/decoy/"
|
PATH_DECOY = "data/source/decoy/"
|
||||||
PATH_GUARDRAILS = "data/source/guardrails/"
|
PATH_GUARDRAILS = "data/source/guardrails/"
|
||||||
PATH_VIRTUALPROTECT = "data/source/virtualprotect/"
|
PATH_VIRTUALPROTECT = "data/source/virtualprotect/"
|
||||||
|
|
||||||
|
PATH_PAYLOAD = "data/source/payload/"
|
||||||
PATH_WEB_PROJECT = "projects/"
|
PATH_WEB_PROJECT = "projects/"
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+14
-14
@@ -1,5 +1,4 @@
|
|||||||
import logging
|
import logging
|
||||||
import shutil
|
|
||||||
|
|
||||||
from model.defs import *
|
from model.defs import *
|
||||||
from model.payload import Payload
|
from model.payload import Payload
|
||||||
@@ -9,31 +8,32 @@ from model.injectable import Injectable
|
|||||||
logger = logging.getLogger("Project")
|
logger = logging.getLogger("Project")
|
||||||
|
|
||||||
|
|
||||||
class WebProject():
|
|
||||||
def __init__(self, name: str, settings: Settings):
|
|
||||||
self.name = name
|
|
||||||
self.settings: Settings = settings
|
|
||||||
self.comment: str = ""
|
|
||||||
|
|
||||||
|
|
||||||
class Project():
|
class Project():
|
||||||
def __init__(self, settings: Settings):
|
def __init__(self, settings: Settings):
|
||||||
self.name: str = ""
|
|
||||||
self.comment: str = ""
|
|
||||||
self.settings: Settings = settings
|
self.settings: Settings = settings
|
||||||
self.payload: Payload = Payload(self.settings.payload_path)
|
|
||||||
self.injectable: Injectable = Injectable(self.settings.inject_exe_in)
|
|
||||||
|
|
||||||
self.project_dir: str = ""
|
# Set by init()
|
||||||
self.project_exe: str = ""
|
self.payload: Payload
|
||||||
|
self.injectable: Injectable
|
||||||
|
|
||||||
|
|
||||||
def init(self) -> bool:
|
def init(self) -> bool:
|
||||||
|
self.payload: Payload = Payload(self.settings.get_payload_path())
|
||||||
|
self.injectable: Injectable = Injectable(self.settings.get_inject_exe_in())
|
||||||
|
|
||||||
if not self.payload.init():
|
if not self.payload.init():
|
||||||
return False
|
return False
|
||||||
if not self.injectable.init():
|
if not self.injectable.init():
|
||||||
return False
|
return False
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
def print(self):
|
||||||
|
logger.info("Project Name: {}".format(self.settings.project_name))
|
||||||
|
logger.info("Comment: {}".format(self.settings.project_comment))
|
||||||
|
logger.info("Settings: {}".format(self.settings.__dict__))
|
||||||
|
logger.info("Payload Path: {}".format(self.payload.payload_path))
|
||||||
|
logger.info("Injectable Path: {}".format(self.injectable.exe_filepath))
|
||||||
|
|
||||||
|
|
||||||
def prepare_project(project_name, settings):
|
def prepare_project(project_name, settings):
|
||||||
|
|||||||
+48
-42
@@ -7,33 +7,46 @@ logger = logging.getLogger("Views")
|
|||||||
class Settings():
|
class Settings():
|
||||||
def __init__(self, project_name: str = "default"):
|
def __init__(self, project_name: str = "default"):
|
||||||
self.project_name: str = project_name
|
self.project_name: str = project_name
|
||||||
self.payload_path: FilePath = FilePath("")
|
self.project_comment: str = ""
|
||||||
|
self.project_path: FilePath = FilePath("{}{}/".format(PATH_WEB_PROJECT, self.project_name))
|
||||||
|
|
||||||
# Settings
|
# OUT: Project directories and files (based on project_path)
|
||||||
|
self.project_c_path: FilePath = FilePath(self.project_path + "main.c")
|
||||||
|
self.project_asm_path: FilePath = FilePath(self.project_path + "main.asm")
|
||||||
|
self.project_exe_path: FilePath = FilePath(self.project_path + "main.exe")
|
||||||
|
self.project_shc_path: FilePath = FilePath(self.project_path + "main.bin")
|
||||||
|
|
||||||
|
# IN: Injectable (like "7z.exe", in data/input/exes/)
|
||||||
|
self.injectable_base: str = ""
|
||||||
|
# IN: Payload / Shellcode (like "createfile.bin", in data/input/shellcodes/)
|
||||||
|
self.payload_base: str = ""
|
||||||
|
|
||||||
|
# Config
|
||||||
self.carrier_name: str = ""
|
self.carrier_name: str = ""
|
||||||
|
self.carrier_invoke_style: CarrierInvokeStyle = CarrierInvokeStyle.BackdoorCallInstr
|
||||||
self.decoder_style: str = "xor_2"
|
self.decoder_style: str = "xor_2"
|
||||||
|
self.payload_location: PayloadLocation = PayloadLocation.DATA
|
||||||
self.short_call_patching: bool = False
|
self.short_call_patching: bool = False
|
||||||
|
self.fix_missing_iat = True
|
||||||
|
self.patch_show_window = True
|
||||||
|
self.dllfunc: str = "" # For DLL injection
|
||||||
|
|
||||||
self.plugin_antiemulation: str = "none"
|
# PLUGIN: Guardrail
|
||||||
self.plugin_decoy: str = "none"
|
|
||||||
self.plugin_guardrail: str = "none"
|
self.plugin_guardrail: str = "none"
|
||||||
self.plugin_guardrail_data_key: str = ""
|
self.plugin_guardrail_data_key: str = ""
|
||||||
self.plugin_guardrail_data_value: str = ""
|
self.plugin_guardrail_data_value: str = ""
|
||||||
self.plugin_virtualprotect: str = "standard"
|
|
||||||
self.plugin_virtualprotect_data: str = ""
|
|
||||||
|
|
||||||
self.dllfunc: str = "" # For DLL injection
|
# PLUGIN: Anti-Emulation / EDR deconditioner
|
||||||
|
self.plugin_antiemulation: str = "none"
|
||||||
# Anti-debugging
|
|
||||||
self.sir_iteration_count: int = 5
|
self.sir_iteration_count: int = 5
|
||||||
self.sir_alloc_count: int = 100
|
self.sir_alloc_count: int = 100
|
||||||
|
|
||||||
# Injectable
|
# PLUGIN: Other (not widely used or important)
|
||||||
self.carrier_invoke_style: CarrierInvokeStyle = CarrierInvokeStyle.BackdoorCallInstr
|
self.plugin_virtualprotect: str = "standard"
|
||||||
self.inject_exe_in: FilePath = FilePath("")
|
self.plugin_virtualprotect_data: str = ""
|
||||||
self.inject_exe_out: FilePath = FilePath("")
|
self.plugin_decoy: str = "none"
|
||||||
|
|
||||||
# Debug
|
# DEBUG: Debug stuff (for development)
|
||||||
self.show_command_output: bool = False
|
self.show_command_output: bool = False
|
||||||
self.verify: bool = False
|
self.verify: bool = False
|
||||||
self.try_start_final_infected_exe: bool = False
|
self.try_start_final_infected_exe: bool = False
|
||||||
@@ -41,33 +54,26 @@ class Settings():
|
|||||||
self.cleanup_files_on_exit: bool = True
|
self.cleanup_files_on_exit: bool = True
|
||||||
self.generate_asm_from_c: bool = True
|
self.generate_asm_from_c: bool = True
|
||||||
|
|
||||||
# More
|
def get_payload_path(self) -> FilePath:
|
||||||
self.fix_missing_iat = True
|
if self.payload_base == "":
|
||||||
self.patch_show_window = True
|
return None
|
||||||
self.payload_location: PayloadLocation = PayloadLocation.DATA
|
return FilePath(PATH_SHELLCODES + self.payload_base)
|
||||||
|
|
||||||
# directories and filenames
|
def get_inject_exe_in(self) -> FilePath:
|
||||||
self.main_dir: FilePath = FilePath("{}{}/".format(PATH_WEB_PROJECT, self.project_name))
|
if self.injectable_base == "":
|
||||||
self.main_c_path: FilePath = FilePath(self.main_dir + "main.c")
|
return None
|
||||||
self.main_asm_path: FilePath = FilePath(self.main_dir + "main.asm")
|
return FilePath(PATH_EXES + self.injectable_base)
|
||||||
self.main_exe_path: FilePath = FilePath(self.main_dir + "main.exe")
|
|
||||||
self.main_shc_path: FilePath = FilePath(self.main_dir + "main.bin")
|
def get_inject_exe_out(self) -> FilePath:
|
||||||
self.inject_exe_out: FilePath = FilePath("{}{}".format(
|
return FilePath("{}{}".format(
|
||||||
self.main_dir, os.path.basename(self.inject_exe_in).replace(".exe", ".infected.exe")))
|
self.project_path,
|
||||||
|
self.injectable_base.replace(".exe", ".infected.exe")
|
||||||
|
|
||||||
def init_payload_injectable(self, shellcode: FilePath, injectable: FilePath, dll_func: str ):
|
|
||||||
self.payload_path = FilePath(PATH_SHELLCODES + shellcode)
|
|
||||||
if shellcode == "createfile.bin":
|
|
||||||
self.verify = True
|
|
||||||
self.try_start_final_infected_exe = False
|
|
||||||
else:
|
|
||||||
self.cleanup_files_on_exit = False
|
|
||||||
|
|
||||||
self.inject_exe_in = FilePath(PATH_EXES + injectable)
|
|
||||||
self.inject_exe_out = FilePath("{}{}".format(
|
|
||||||
self.main_dir,
|
|
||||||
os.path.basename(self.inject_exe_in).replace(".exe", ".infected.exe")
|
|
||||||
))
|
))
|
||||||
|
|
||||||
self.dllfunc = dll_func
|
def print(self):
|
||||||
|
logger.info("Settings for project: {}".format(self.project_name))
|
||||||
|
for attr, value in self.__dict__.items():
|
||||||
|
if isinstance(value, FilePath):
|
||||||
|
value = str(value)
|
||||||
|
logger.info(" {}: {}".format(attr, value))
|
||||||
|
logger.info("-" * 40)
|
||||||
+3
-3
@@ -33,7 +33,7 @@ class Injector():
|
|||||||
|
|
||||||
# superpe is a representation of the exe file. We gonna modify it, and save it at the end.
|
# superpe is a representation of the exe file. We gonna modify it, and save it at the end.
|
||||||
# reuse from injectable
|
# reuse from injectable
|
||||||
#self.superpe = SuperPe(settings.inject_exe_in)
|
#self.superpe = SuperPe(settings.get_inject_exe_in())
|
||||||
self.superpe = injectable.superpe
|
self.superpe = injectable.superpe
|
||||||
self.function_backdoorer = FunctionBackdoorer(self.superpe)
|
self.function_backdoorer = FunctionBackdoorer(self.superpe)
|
||||||
|
|
||||||
@@ -110,8 +110,8 @@ class Injector():
|
|||||||
## Inject
|
## Inject
|
||||||
|
|
||||||
def inject_exe(self):
|
def inject_exe(self):
|
||||||
exe_in = self.settings.inject_exe_in
|
exe_in = self.settings.get_inject_exe_in()
|
||||||
exe_out = self.settings.inject_exe_out
|
exe_out = self.settings.get_inject_exe_out()
|
||||||
carrier_invoke_style: CarrierInvokeStyle = self.settings.carrier_invoke_style
|
carrier_invoke_style: CarrierInvokeStyle = self.settings.carrier_invoke_style
|
||||||
|
|
||||||
logger.info("-[ Injecting Carrier".format())
|
logger.info("-[ Injecting Carrier".format())
|
||||||
|
|||||||
+2
-2
@@ -29,7 +29,7 @@ def create_c_from_template(settings: Settings, payload_len: int):
|
|||||||
dst = "{}{}/".format(PATH_WEB_PROJECT, settings.project_name)
|
dst = "{}{}/".format(PATH_WEB_PROJECT, settings.project_name)
|
||||||
|
|
||||||
logger.info("-[ Carrier create Template: {}".format(
|
logger.info("-[ Carrier create Template: {}".format(
|
||||||
settings.main_c_path))
|
settings.project_c_path))
|
||||||
|
|
||||||
# check that source directory exists
|
# check that source directory exists
|
||||||
if not os.path.exists(src):
|
if not os.path.exists(src):
|
||||||
@@ -139,6 +139,6 @@ def create_c_from_template(settings: Settings, payload_len: int):
|
|||||||
'PAYLOAD_LEN': payload_len,
|
'PAYLOAD_LEN': payload_len,
|
||||||
'plugin_virtualprotect': plugin_virtualprotect,
|
'plugin_virtualprotect': plugin_virtualprotect,
|
||||||
})
|
})
|
||||||
with open(settings.main_c_path, "w", encoding='utf-8') as file:
|
with open(settings.project_c_path, "w", encoding='utf-8') as file:
|
||||||
file.write(rendered_template)
|
file.write(rendered_template)
|
||||||
observer.add_text_file("main_c_rendered", rendered_template)
|
observer.add_text_file("main_c_rendered", rendered_template)
|
||||||
|
|||||||
Binary file not shown.
+25
-25
@@ -54,10 +54,18 @@ def main():
|
|||||||
else:
|
else:
|
||||||
setup_logging(logging.INFO)
|
setup_logging(logging.INFO)
|
||||||
|
|
||||||
|
# IN:
|
||||||
|
# Shellcode: filename
|
||||||
|
# Inject: filename
|
||||||
|
settings.injectable_base = args.inject
|
||||||
|
settings.payload_base = args.shellcode
|
||||||
|
|
||||||
|
# Cleanup
|
||||||
settings.try_start_final_infected_exe = args.start
|
settings.try_start_final_infected_exe = args.start
|
||||||
settings.cleanup_files_on_start = not args.no_clean_at_start
|
settings.cleanup_files_on_start = not args.no_clean_at_start
|
||||||
settings.cleanup_files_on_exit =not args.no_clean_at_exit
|
settings.cleanup_files_on_exit =not args.no_clean_at_exit
|
||||||
|
|
||||||
|
# Settings
|
||||||
settings.fix_missing_iat = not args.no_fix_iat
|
settings.fix_missing_iat = not args.no_fix_iat
|
||||||
if args.guardrail:
|
if args.guardrail:
|
||||||
settings.plugin_guardrail = args.guardrail
|
settings.plugin_guardrail = args.guardrail
|
||||||
@@ -71,13 +79,6 @@ def main():
|
|||||||
settings.plugin_guardrail_data_key,
|
settings.plugin_guardrail_data_key,
|
||||||
settings.plugin_guardrail_data_value))
|
settings.plugin_guardrail_data_value))
|
||||||
|
|
||||||
# Shellcode: filename
|
|
||||||
# Inject: filename
|
|
||||||
settings.init_payload_injectable(
|
|
||||||
shellcode=FilePath(args.shellcode),
|
|
||||||
injectable=FilePath(args.inject),
|
|
||||||
dll_func="")
|
|
||||||
|
|
||||||
settings.decoder_style = args.decoder
|
settings.decoder_style = args.decoder
|
||||||
settings.carrier_name = args.carrier
|
settings.carrier_name = args.carrier
|
||||||
settings.payload_location = PayloadLocation.CODE # makes sense
|
settings.payload_location = PayloadLocation.CODE # makes sense
|
||||||
@@ -89,11 +90,10 @@ def main():
|
|||||||
settings.carrier_invoke_style = CarrierInvokeStyle.BackdoorCallInstr
|
settings.carrier_invoke_style = CarrierInvokeStyle.BackdoorCallInstr
|
||||||
settings.plugin_antiemulation = args.antiemulation
|
settings.plugin_antiemulation = args.antiemulation
|
||||||
|
|
||||||
if not os.path.exists(settings.main_dir):
|
if not os.path.exists(settings.project_path):
|
||||||
logger.info("Creating project directory: {}".format(settings.main_dir))
|
logger.info("Creating project directory: {}".format(settings.project_path))
|
||||||
os.makedirs(settings.main_dir)
|
os.makedirs(settings.project_path)
|
||||||
|
|
||||||
write_webproject("default", settings)
|
|
||||||
exit_code = start(settings)
|
exit_code = start(settings)
|
||||||
exit(exit_code)
|
exit(exit_code)
|
||||||
|
|
||||||
@@ -124,7 +124,7 @@ def start(settings: Settings) -> int:
|
|||||||
ret = start_real(settings)
|
ret = start_real(settings)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f'Error compiling: {e}')
|
logger.error(f'Error compiling: {e}')
|
||||||
observer.write_logs(settings.main_dir)
|
observer.write_logs(settings.project_path)
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
# Cleanup files
|
# Cleanup files
|
||||||
@@ -133,16 +133,16 @@ def start(settings: Settings) -> int:
|
|||||||
clean_files(settings)
|
clean_files(settings)
|
||||||
|
|
||||||
# Write logs (on success)
|
# Write logs (on success)
|
||||||
observer.write_logs(settings.main_dir)
|
observer.write_logs(settings.project_path)
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
|
|
||||||
def sanity_checks(settings):
|
def sanity_checks(settings):
|
||||||
if 'dll_loader' in settings.carrier_name:
|
if 'dll_loader' in settings.carrier_name:
|
||||||
if not settings.payload_path.endswith(".dll"):
|
if not settings.get_payload_path().endswith(".dll"):
|
||||||
raise Exception("dll loader requires a dll as payload, not shellcode")
|
raise Exception("dll loader requires a dll as payload, not shellcode")
|
||||||
else:
|
else:
|
||||||
if not settings.payload_path.endswith(".bin"):
|
if not settings.get_payload_path().endswith(".bin"):
|
||||||
raise Exception("loader requires shellcode as payload, not DLL")
|
raise Exception("loader requires shellcode as payload, not DLL")
|
||||||
|
|
||||||
|
|
||||||
@@ -158,7 +158,7 @@ def start_real(settings: Settings) -> bool:
|
|||||||
|
|
||||||
# CHECK if 64 bit
|
# CHECK if 64 bit
|
||||||
if not project.injectable.superpe.is_64():
|
if not project.injectable.superpe.is_64():
|
||||||
raise Exception("Binary is not 64bit: {}".format(project.settings.inject_exe_in))
|
raise Exception("Binary is not 64bit: {}".format(project.settings.get_inject_exe_in()))
|
||||||
|
|
||||||
# Tell user if they attempt to do something stupid
|
# Tell user if they attempt to do something stupid
|
||||||
sanity_checks(project.settings)
|
sanity_checks(project.settings)
|
||||||
@@ -192,8 +192,8 @@ def start_real(settings: Settings) -> bool:
|
|||||||
if settings.generate_asm_from_c:
|
if settings.generate_asm_from_c:
|
||||||
try:
|
try:
|
||||||
phases.compiler.compile(
|
phases.compiler.compile(
|
||||||
c_in = settings.main_c_path,
|
c_in = settings.project_c_path,
|
||||||
asm_out = settings.main_asm_path,
|
asm_out = settings.project_asm_path,
|
||||||
injectable = project.injectable,
|
injectable = project.injectable,
|
||||||
settings = project.settings)
|
settings = project.settings)
|
||||||
except ChildProcessError as e:
|
except ChildProcessError as e:
|
||||||
@@ -212,8 +212,8 @@ def start_real(settings: Settings) -> bool:
|
|||||||
|
|
||||||
# ASSEMBLE: Assemble .asm to .shc (ASM -> SHC)
|
# ASSEMBLE: Assemble .asm to .shc (ASM -> SHC)
|
||||||
carrier_shellcode: bytes = phases.assembler.asm_to_shellcode(
|
carrier_shellcode: bytes = phases.assembler.asm_to_shellcode(
|
||||||
asm_in = settings.main_asm_path,
|
asm_in = settings.project_asm_path,
|
||||||
build_exe = settings.main_exe_path)
|
build_exe = settings.project_exe_path)
|
||||||
observer.add_code_file("carrier_shc", carrier_shellcode)
|
observer.add_code_file("carrier_shc", carrier_shellcode)
|
||||||
|
|
||||||
# INJECT loader into an exe and do IAT & data references. Big task.
|
# INJECT loader into an exe and do IAT & data references. Big task.
|
||||||
@@ -227,13 +227,13 @@ def start_real(settings: Settings) -> bool:
|
|||||||
injector.inject_exe()
|
injector.inject_exe()
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
return False
|
return False
|
||||||
#observer.add_code_file("exe_final", extract_code_from_exe_file_ep(settings.inject_exe_out, 300))
|
#observer.add_code_file("exe_final", extract_code_from_exe_file_ep(settings.get_inject_exe_out(), 300))
|
||||||
|
|
||||||
# Check binary with avred
|
# Check binary with avred
|
||||||
if config.get("avred_server") != "":
|
if config.get("avred_server") != "":
|
||||||
if settings.verify or settings.try_start_final_infected_exe:
|
if settings.verify or settings.try_start_final_infected_exe:
|
||||||
filename = os.path.basename(settings.inject_exe_in)
|
filename = os.path.basename(settings.get_inject_exe_in())
|
||||||
with open(settings.inject_exe_out, "rb") as f:
|
with open(settings.get_inject_exe_out(), "rb") as f:
|
||||||
data = f.read()
|
data = f.read()
|
||||||
scannerDetectsBytes(data, filename, useBrotli=True, verify=settings.verify)
|
scannerDetectsBytes(data, filename, useBrotli=True, verify=settings.verify)
|
||||||
else:
|
else:
|
||||||
@@ -241,12 +241,12 @@ def start_real(settings: Settings) -> bool:
|
|||||||
if settings.verify:
|
if settings.verify:
|
||||||
logger.info(" Verify infected exe")
|
logger.info(" Verify infected exe")
|
||||||
payload_exit_code = phases.injector.verify_injected_exe(
|
payload_exit_code = phases.injector.verify_injected_exe(
|
||||||
settings.inject_exe_out,
|
settings.get_inject_exe_out(),
|
||||||
dllfunc=settings.dllfunc)
|
dllfunc=settings.dllfunc)
|
||||||
if payload_exit_code != 0:
|
if payload_exit_code != 0:
|
||||||
logger.warning("Payload exit code: {}".format(payload_exit_code))
|
logger.warning("Payload exit code: {}".format(payload_exit_code))
|
||||||
elif settings.try_start_final_infected_exe:
|
elif settings.try_start_final_infected_exe:
|
||||||
run_exe(settings.inject_exe_out, dllfunc=settings.dllfunc, check=False)
|
run_exe(settings.get_inject_exe_out(), dllfunc=settings.dllfunc, check=False)
|
||||||
|
|
||||||
if settings.plugin_guardrail != "none":
|
if settings.plugin_guardrail != "none":
|
||||||
logger.warning("! Remember your guardrails settings when testing")
|
logger.warning("! Remember your guardrails settings when testing")
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ import logging
|
|||||||
|
|
||||||
from app.views import views
|
from app.views import views
|
||||||
from app.views_project import views_project
|
from app.views_project import views_project
|
||||||
from app.views_shcdev import views_shcdev
|
|
||||||
from log import setup_logging
|
from log import setup_logging
|
||||||
from utils import check_deps
|
from utils import check_deps
|
||||||
|
|
||||||
@@ -42,5 +41,4 @@ if __name__ == "__main__":
|
|||||||
|
|
||||||
app.register_blueprint(views)
|
app.register_blueprint(views)
|
||||||
app.register_blueprint(views_project)
|
app.register_blueprint(views_project)
|
||||||
app.register_blueprint(views_shcdev)
|
|
||||||
app.run(host=args.listenip, port=args.listenport, debug=args.debug)
|
app.run(host=args.listenip, port=args.listenport, debug=args.debug)
|
||||||
|
|||||||
Reference in New Issue
Block a user