Skip to content

Commit

Permalink
Add file uploader to payloads & auto refresher for files/downloads
Browse files Browse the repository at this point in the history
  • Loading branch information
DotoPototo authored and benpturner committed Sep 2, 2024
1 parent f8a93e4 commit 4db90ca
Show file tree
Hide file tree
Showing 7 changed files with 129 additions and 27 deletions.
92 changes: 79 additions & 13 deletions resources/html-templates/files.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,27 +3,42 @@
<div class="text-center bg-body-secondary">
<div class="pt-2 pb-3 fs-1 fw-bold" style="letter-spacing: 2px;">Files</div>
</div>
<div id="autoruns" class="implants">
<div class="box_border m-2 d-flex align-items-center justify-content-end gap-2">
<strong>Refresh Interval: </strong>
<input type="number" name="refresh-interval" value="30" min="5" style="width: 42px;" />
<span>seconds</span>
</div>
<div id=" autoruns" class="implants">
<table class="table align-middle mb-0 table-hover table-striped">
<thead>
<tr>
<th>#</th>
<th>VIEW</th>
<th>FILENAME</th>
<th style="text-align:center">ACTION</th>
</tr>
</thead>
{% for image in images %}
<tr>
<td>{{loop.index}}</td>
<td style="width:300px;">
<a href="javascript:showImage('{{ url_for('serve_file', filename=image) }}')">
<img src="{{ url_for('serve_file', filename=image) }}" class="img-thumbnail"
onerror="this.style.display = 'none'">
</a>
</td>
<td>{{image}}</td>
</tr>
{% endfor %}
<tbody id="file-table-body">
{% for image in images %}
<tr>
<td>{{(images|length + 1) - loop.index}}</td>
<td style="width:300px;">
<a href="{{ url_for('serve_file', filename=image) }}" target="_blank">
<img src="{{ url_for('serve_file', filename=image) }}" class="img-thumbnail"
onerror="this.style.display = 'none'">
</a>
</td>
<td>{{image}}</td>
<td style="text-align:center">
<a href="{{ url_for('serve_file', filename=image) }}" target="_blank" download="{{image}}">
<button type=" button" class="btn btn-outline-info">
<i class="bi bi-download"></i>
</button>
</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
<div id="subdomainimage" style="background:#000;border:1px solid #dfdfdf;display:none"></div>
Expand All @@ -36,4 +51,55 @@
$("#subdomainimage").css("background-repeat", " no-repeat")
$("#subdomainimage").show()
}

function updateFileTable() {
$.ajax({
url: '/files-list',
method: 'GET',
success: function (response) {
let currentFiles = [];
$('#file-table-body tr').each(function () {
currentFiles.push($(this).find('td:nth-child(3)').text().trim());
});
let baseUrl = response.base_url;
response.files.forEach(function (file, index) {
if (!currentFiles.includes(file)) {
let fileUrl = baseUrl + encodeURIComponent(file);
$('#file-table-body').prepend(
'<tr>' +
'<td>' + (currentFiles.length + 1) + '</td>' +
'<td style="width:300px;">' +
'<a href="' + fileUrl + '" target="_blank">' +
'<img src="' + baseUrl + encodeURIComponent(file) + '" class="img-thumbnail" onerror="this.style.display = \'none\'">' +
'</a>' +
'</td>' +
'<td>' + file + '</td>' +
'<td style="text-align:center">' +
'<a href="' + fileUrl + '" target="_blank" download="' + file + '">' +
'<button type="button" class="btn btn-outline-info">' +
'<i class="bi bi-download"></i>' +
'</button>' +
'</a>' +
'</td>' +
'</tr>'
);
}
});
},
error: function () {
console.log('Error fetching files.');
}
});
}

let interval = setInterval(updateFileTable, 30000);
$('input[name="refresh-interval"]').on('change', function () {
const value = $(this).val();
if (value < 5) {
$(this).val(30);
return;
}
clearInterval(interval);
interval = setInterval(updateFileTable, value * 1000);
});
</script>
29 changes: 15 additions & 14 deletions resources/html-templates/header.html
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,7 @@
const icon = document.getElementById('themeIcon');

// Function to update the icon based on the current theme
function updateIcon() {
isDark = document.documentElement.getAttribute('data-bs-theme') === 'dark';
function updateIcon(isDark) {
if (isDark) {
icon.className = 'bi bi-sun-fill';
} else {
Expand All @@ -24,9 +23,8 @@
}

// Function to update the logo based on the current theme
function updateLogo() {
function updateLogo(isDark) {
const logo = document.querySelector('#posh-logo');
isDark = document.documentElement.getAttribute('data-bs-theme') === 'dark';
if (isDark) {
logo.src = '/include/img/logo-for-dark.webp';
} else {
Expand All @@ -36,23 +34,25 @@

// Function to load the theme from localStorage
function loadTheme() {
const isDark = document.documentElement.getAttribute('data-bs-theme') === 'dark';
const theme = localStorage.getItem('theme');

if (theme === 'dark') {
document.documentElement.setAttribute('data-bs-theme', 'dark');
} else {
document.documentElement.setAttribute('data-bs-theme', 'light');
}
updateIcon();
updateLogo();
updateIcon(isDark);
updateLogo(isDark);
}

// Function to toggle the theme and save it to localStorage
function toggleTheme() {
isDark = document.documentElement.getAttribute('data-bs-theme') === 'dark';
const isDark = document.documentElement.getAttribute('data-bs-theme') === 'dark';
document.documentElement.setAttribute('data-bs-theme', isDark ? 'light' : 'dark');
localStorage.setItem('theme', isDark ? 'light' : 'dark');
updateIcon();
updateLogo();
updateIcon(isDark);
updateLogo(isDark);
}

// Load the theme on page load
Expand All @@ -70,6 +70,7 @@
links.forEach(link => {
if (link.getAttribute('href') === currentPath) {
link.classList.add('active');
return;
}
});
}
Expand Down Expand Up @@ -97,9 +98,9 @@

<body class="bg-secondary-subtle vh-100 d-flex">
<div class="d-flex flex-column flex-shrink-0 p-3 bg-body-tertiary h-100 me-2 fixed-top border-end border-3"
style="width: 220px;">
style="width: 230px;">
<a href="/" class="d-flex align-items-center mb-3 mb-md-0 me-md-auto text-decoration-none">
<img id="posh-logo" src="/include/img/logo-for-dark.webp" alt="Posh C2" style="max-width: 190px; padding: 2px;">
<img id="posh-logo" src="/include/img/logo-for-dark.webp" alt="Posh C2" style="max-width: 198px; padding: 2px;">
</a>
<hr>
<ul class="nav nav-pills flex-column mb-auto fs-6">
Expand All @@ -124,13 +125,13 @@
<li>
<a href="/payloads" class="nav-link">
<i class="bi bi-virus"></i>
<span class="mx-2">Payloads</span>
<span class="mx-2">Payloads/Uploads</span>
</a>
</li>
<li>
<a href="/files" class="nav-link">
<i class="bi bi-file-earmark-code-fill"></i>
<span class="mx-2">Files</span>
<span class="mx-2">Files/Downloads</span>
</a>
</li>
<li>
Expand All @@ -152,4 +153,4 @@
Toggle Theme
</button>
</div>
<div style="width: 220px; min-width: 220px;"></div>
<div style="width: 230px; min-width: 230px;"></div>
Empty file.
Empty file.
Empty file.
9 changes: 9 additions & 0 deletions resources/html-templates/payloads.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,15 @@
<div class="text-center bg-body-secondary">
<div class="pt-2 pb-3 fs-1 fw-bold" style="letter-spacing: 2px;">Payloads</div>
</div>
<div class="box_border">
<form method="post" action="/file/upload" enctype="multipart/form-data" class="m-2 d-flex align-items-center gap-2">
<strong>Upload new file: </strong>
<div class="flex-grow-1 d-flex align-items-center">
<input type="file" name="file" class="flex-grow-1" />
</div>
<input type="submit" class="btn btn-info btn-sm" value="Upload" />
</form>
</div>
<div id="autoruns" class="implants">
<table class="table align-middle mb-0 table-hover table-striped">
<thead>
Expand Down
26 changes: 26 additions & 0 deletions start_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -295,12 +295,38 @@ def list_files(number_of_files=None):
return render_template('files.html', images=images)


@app.route('/files-list', methods=['GET'])
@app.route('/files-list/<int:number_of_files>', methods=['GET'])
@auth.login_required
def list_files_json(number_of_files=None):
files = os.listdir(DOWNLOADS_DIR)
sorted_files = sorted(files, key=lambda x: os.path.getctime(os.path.join(DOWNLOADS_DIR, x)), reverse=True)
if number_of_files:
images = [f for f in sorted_files[0:number_of_files]]
else:
images = [f for f in sorted_files]
response = {
'files': sorted_files,
'base_url': url_for('serve_file', filename='', _external=True)
}
return jsonify(response)


@app.route('/file/<path:filename>', methods=['GET'])
@auth.login_required
def serve_file(filename):
return send_from_directory(DOWNLOADS_DIR, filename)


@app.route('/file/upload', methods=['POST'])
@auth.login_required
def upload_file():
file = request.files['file']
if file:
file.save(os.path.join(PAYLOADS_DIR, file.filename))
return redirect(url_for('list_payloads'))


@app.route('/taskviewwithnew')
@app.route('/taskviewwithnew/<number_of_rows>')
@app.route('/taskviewwithnew/implant/<implant_id>')
Expand Down

0 comments on commit 4db90ca

Please sign in to comment.