Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
Davide Arcuri committed Oct 23, 2024
1 parent b90df40 commit fb6d942
Show file tree
Hide file tree
Showing 18 changed files with 453 additions and 168 deletions.
2 changes: 1 addition & 1 deletion compose/local/dask/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ RUN freshclam
# Workers should have similar reqs as django
WORKDIR /
COPY ./requirements /requirements
RUN pip install uv==0.4.21 -e git+https://github.com/dadokkio/volatility3.git@7b0cb4facd1e1714a36793a27c0570461a3f02a1#egg=volatility3 \
RUN pip install uv==0.4.25 -e git+https://github.com/dadokkio/volatility3.git@7b0cb4facd1e1714a36793a27c0570461a3f02a1#egg=volatility3 \
&& uv pip install --no-cache --system -r /requirements/base.txt

COPY ./compose/local/dask/prepare.sh /usr/bin/prepare.sh
Expand Down
2 changes: 1 addition & 1 deletion compose/local/django/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ RUN /usr/local/go/bin/go build
FROM common-base
WORKDIR /
COPY ./requirements /requirements
RUN pip install uv==0.4.21 -e git+https://github.com/dadokkio/volatility3.git@7b0cb4facd1e1714a36793a27c0570461a3f02a1#egg=volatility3 \
RUN pip install uv==0.4.25 -e git+https://github.com/dadokkio/volatility3.git@7b0cb4facd1e1714a36793a27c0570461a3f02a1#egg=volatility3 \
&& uv pip install --no-cache --system -r /requirements/base.txt

COPY ./compose/local/__init__.py /src/volatility3/volatility3/framework/constants/__init__.py
Expand Down
76 changes: 50 additions & 26 deletions examples/local_api.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@
"}\n",
"\n",
"req = session.post(\n",
" f\"{url}/api/auth/\", data=data, cookies=first.cookies, verify=False, headers=headers\n",
" f\"{url}/api/auth/\", data=data, cookies=first.cookies, headers=headers, verify=False\n",
")\n",
"if req.status_code != 200:\n",
" print(req.text)\n",
Expand All @@ -67,9 +67,10 @@
"metadata": {},
"outputs": [],
"source": [
"dumps = session.get(f\"{url}/api/dumps/\").json()\n",
"dumps = session.get(f\"{url}/api/dumps/\", verify=False).json()\n",
"print(f\"{len(dumps)} dumps found\")\n",
"pprint(dumps[0])"
"if dumps: \n",
" pprint(dumps[0])"
]
},
{
Expand All @@ -85,16 +86,17 @@
"metadata": {},
"outputs": [],
"source": [
"\"\"\" TODO\n",
"files = {'upload': open('/home/DATA/AMF_MemorySamples/linux/sorpresa.zip','rb')}\n",
"values = {'operating_system': 'Linux', 'name': 'sorpresa'}\n",
"res = session.post(f\"{url}/api/dumps/\", files=files, data=values)\n",
"\n",
"files = {'upload': ('sorpresa.zip', open('/home/dadokkio/Insync/[email protected]/Google Drive/Lavoro/Agusta/DATA/AMF_MemorySamples/linux/sorpresa.zip','rb'))}\n",
"data = {\n",
" 'payload': '{\"operating_system\": \"Linux\", \"name\": \"sorpresa\", \"folder\": {\"name\": \"linux-samples\"}}'\n",
"}\n",
"res = session.post(f\"{url}/api/dumps/\", files=files, data=data, cookies=first.cookies, headers=headers, verify=False)\n",
"if res.status_code == 200:\n",
" pprint(res.json())\n",
" dump_pk = res.json()[\"pk\"]\n",
" dump_pk = res.json()[\"index\"]\n",
"else:\n",
" print(res.status_code)\n",
"\"\"\""
" print(res.status_code, res.text)"
]
},
{
Expand All @@ -110,20 +112,19 @@
"metadata": {},
"outputs": [],
"source": [
"\"\"\" TODO\n",
"# This code requires a file on the server in the folder specified in the LOCAL_UPLOAD_PATH\n",
"# settings folder\n",
"\n",
"res = session.post(f\"{url}/api/dumps/import_local/\", files=(\n",
" ('operating_system', (None, 'Linux')),\n",
" ('name', (None, 'sasf3sfas33')),\n",
" ('filepath', (None, '/uploads/linux/linux-sample-4.bin')),\n",
" ))\n",
"files = {'upload': None}\n",
"data = {\n",
" 'payload': '{\"operating_system\": \"Linux\", \"name\": \"remote-test\", \"folder\": {\"name\": \"linux-samples\"}, \"local_folder\": \"/uploads/sorpresa.vmem\"}'\n",
"}\n",
"res = session.post(f\"{url}/api/dumps/\", files=files, data=data, cookies=first.cookies, headers=headers, verify=False)\n",
"if res.status_code == 200:\n",
" pprint(res.json())\n",
" dump_pk = res.json()[\"index\"]\n",
"else:\n",
" print(res.status_code)\n",
"\"\"\""
" print(res.status_code, res.text)"
]
},
{
Expand All @@ -139,16 +140,41 @@
"metadata": {},
"outputs": [],
"source": [
"res = session.get(f\"{url}/api/plugins/\")\n",
"res = session.get(f\"{url}/api/plugins/\", verify=False)\n",
"if res.status_code == 200:\n",
" plugins = res.json()\n",
" print(f\"{len(plugins)} plugins found\")\n",
" pprint(plugins[0])\n",
"res = session.get(f\"{url}/api/plugins/?operating_system=Other\")\n",
"else:\n",
" print(res.status_code, res.text) \n",
"res = session.get(f\"{url}/api/plugins/?operating_system=Other\", verify=False)\n",
"if res.status_code == 200:\n",
" plugins = res.json()\n",
" print(f\"{len(plugins)} plugins found\")\n",
" pprint(plugins[0])"
" pprint(plugins[0])\n",
"else:\n",
" print(res.status_code, res.text) "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# GET PLUGINS FOR A SPECIFIC DUMP"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"res = session.get(f\"{url}/api/dumps/{dump_pk}/plugins\", verify=False)\n",
"if res.status_code == 200:\n",
" if example := res.json():\n",
" print(example[0])\n",
"else:\n",
" print(res.status_code, res.text) "
]
},
{
Expand All @@ -164,13 +190,11 @@
"metadata": {},
"outputs": [],
"source": [
"\"\"\" TODO\n",
"res = session.get(f\"{url}/api/dumps/{dump_pk}/results/\")\n",
"res = session.get(f\"{url}/api/dumps/{dump_pk}/plugins/{plugin_pk}/\", verify=False)\n",
"if res.status_code == 200:\n",
" pprint(res.json())\n",
" result_pk = [x['pk'] for x in res.json() if x['plugin'] == 'linux.pslist.PsList'][0]\n",
" print(res.status_code)\n",
"\"\"\""
" print(res.status_code)\n"
]
},
{
Expand Down Expand Up @@ -267,7 +291,7 @@
],
"metadata": {
"kernelspec": {
"display_name": "orochi",
"display_name": "base",
"language": "python",
"name": "python3"
},
Expand Down
24 changes: 21 additions & 3 deletions orochi/api/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
from ninja.orm import create_schema

from orochi.website.defaults import OSEnum
from orochi.website.models import Bookmark, CustomRule, Dump, Folder, Plugin
from orochi.website.models import Bookmark, CustomRule, Dump, Folder, Plugin, Result
from orochi.ya.models import Rule


Expand Down Expand Up @@ -158,18 +158,35 @@ class Meta:
###################################################
# Dump
###################################################
class DumpSchema(ModelSchema):
class DumpIn(ModelSchema):
folder: Optional[FolderSchema] = None
local_folder: Optional[str] = None
password: Optional[str] = None
original_name: Optional[str] = None

class Meta:
model = Dump
fields = [
"operating_system",
"description",
"comment",
"name",
"color",
]


class DumpSchema(ModelSchema):
folder: Optional[FolderSchema] = None
author: UserOutSchema = None

class Meta:
model = Dump
fields = [
"id",
"index",
"name",
"color",
"operating_system",
"author",
"upload",
"status",
"description",
Expand Down Expand Up @@ -211,6 +228,7 @@ class Meta:
class ResultSmallOutSchema(Schema):
name: str = Field(..., alias="plugin__name")
comment: Optional[str] = Field(..., alias="plugin__comment")
id: int = Field(..., alias="plugin__id")


###################################################
Expand Down
102 changes: 96 additions & 6 deletions orochi/api/routers/dumps.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,21 @@
from typing import List
from uuid import UUID
import shutil
from pathlib import Path
from typing import List, Optional
from uuid import UUID, uuid1

from django.conf import settings
from django.db import transaction
from django.http import HttpResponse
from django.shortcuts import get_object_or_404
from guardian.shortcuts import get_objects_for_user
from ninja import Query, Router
from ninja import File, Query, Router, UploadedFile
from ninja.security import django_auth

from orochi.api.filters import DumpFilters, OperatingSytemFilters
from orochi.api.models import DumpInfoSchema, DumpSchema, ResultSmallOutSchema
from orochi.website.models import Dump, Result
from orochi.api.models import DumpIn, DumpInfoSchema, DumpSchema, ResultSmallOutSchema
from orochi.website.defaults import RESULT_STATUS_NOT_STARTED, RESULT_STATUS_RUNNING
from orochi.website.models import Dump, Folder, Result, UserPlugin
from orochi.website.views import index_f_and_f

router = Router()

Expand Down Expand Up @@ -62,6 +68,90 @@ def get_dump_info(request, pk: UUID):
return dump


@router.post("/", url_name="create_index", response=DumpSchema, auth=django_auth)
def create_dump(request, payload: DumpIn, upload: Optional[UploadedFile] = File(None)):
"""
Creates a new dump index and handles the associated file uploads. This function processes the provided payload to create a dump entry in the database and manages file storage based on the input parameters.
Args:
request: The HTTP request object.
payload (DumpIn): The data containing information about the dump to be created.
upload (Optional[UploadedFile]): An optional file to be uploaded.
Returns:
DumpSchema: The created dump object.
Raises:
HttpResponse: Returns a 400 Bad Request response if an error occurs during the process.
"""

try:
if payload.folder:
folder, _ = Folder.objects.get_or_create(
name=payload.folder.name, user=request.user
)
else:
folder = None
dump_index = str(uuid1())
Path(f"{settings.MEDIA_ROOT}/{dump_index}").mkdir()
dump = Dump.objects.create(
name=payload.name,
color=payload.color,
comment=payload.comment,
operating_system=payload.operating_system,
folder=folder,
author=request.user,
index=dump_index,
)
if payload.local_folder:
start = payload.local_folder
start = start.replace("/upload/upload", "/media/uploads")
filename = payload.original_name or Path(start).name
shutil.move(start, f"{settings.MEDIA_ROOT}/{dump_index}/{filename}")
dump.upload.name = f"{settings.MEDIA_URL}{dump_index}/{filename}"
move = False
elif upload:
dump.upload.save(Path(upload.name).name, upload)
move = True
else:
return HttpResponse("Bad Request", status=400)
dump.save()
Result.objects.bulk_create(
[
Result(
plugin=up.plugin,
dump=dump,
result=(
RESULT_STATUS_RUNNING
if up.automatic
else RESULT_STATUS_NOT_STARTED
),
)
for up in UserPlugin.objects.filter(
plugin__operating_system__in=[
dump.operating_system,
"Other",
],
user=request.user,
plugin__disabled=False,
)
]
)

transaction.on_commit(
lambda: index_f_and_f(
dump.pk,
request.user.pk,
password=payload.password,
restart=None,
move=move,
)
)
return dump
except Exception as excp:
return HttpResponse(f"Bad Request ({excp})", status=400)


@router.get(
"/{idxs:pks}/plugins",
url_name="dumps_plugins",
Expand Down Expand Up @@ -93,7 +183,7 @@ def get_dump_plugins(request, pks: List[UUID], filters: Query[DumpFilters] = Non
.filter(dump__index__in=dumps)
.order_by("plugin__name")
.distinct()
.values("plugin__name", "plugin__comment")
.values("plugin__name", "plugin__comment", "plugin__id")
)
if filters and filters.result:
res = res.filter(result=filters.result)
Expand Down
46 changes: 46 additions & 0 deletions orochi/static/js/handlebars/dump.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit fb6d942

Please sign in to comment.