Activity

grm

Shipped this project!

Hours: 81.16
Cookies: 🍪 2095
Multiplier: 25.81 cookies/hr

It’s alive!! The demo is now available The ship is officially… shipped :3


Login is passwordless, because passwords are booooriiing x3 The app uses magic links instead: enter one of the demo emails, request a link, then use the generated magic link to sign in.


Demo accounts:


Once you’re in, the best event to start with is the big launch summit. It has the most complete demo data: collaborators, branding, planner timeline, assigned work, unassigned work, socials, lifecycle state and enough timeline chaos to actually show why the app exists x3


The main things to try:

  • open an event and check the overview/lifecycle panel
  • look at the planner timeline and move/edit some scheduled work
  • check the staff page to see workload and unassigned tasks
  • open collaborators to see roles and event access
  • try the socials tab and update post statuses
  • play with branding if you want to make the event look cursed or cute
  • export an event if you want to see the current event data bundle

The demo database resets automatically, so don’t worry too much about breaking things. In fact, please break things a little. That is kind of the point x3

This is still an early version, but it’s finally public-demo-shaped now. The app is real enough to click around, test the concept, and see where the event-ops idea is going.

grm

This one’s just README adjustments and making sure the demo environment is healthy and working as intended :3 Coming very soon -w-

Attachment
0
grm

Most of this update was demo polish. I replaced the tiny dev seed with actual demo data. There are proper test users now, multiple events across different lifecycle states, real-looking memberships, branding, planner items, timeline work, assignments, unassigned queues, social drafts, posted posts, blocked tasks, the whole thing. The demo finally has enough stuff inside it to show what the app is supposed to be, instead of me clicking around an empty shell x3


The staff/planner side especially needed this. A workload dashboard is not very convincing if everyone has one fake task and nothing is blocked. So now the seeded events have enough scheduled work to make the timeline scroll, enough assignments to make staff cards useful, and enough unassigned items to show the flow. I may have slightly overfed the demo data creature, but honestly it needed food x3


There were also a few last frontend fixes. The sidebar now shows the real event ID even when the URL uses the slug, because the slug URL work made that little corner weird. The planner timeline got another pass so the grid behaves better when there is more data, milestones sit in their own row more cleanly, and the controls do not feel like they are floating off into… I don’t even know where they were going QwQ Also, owner is now a dropdown instead of a free-text field, because free-text owner names were useful for scaffolding and kind of silly for the actual demo.


Tests got fixed again too. I wish they would stop needing emotional support, but here we are. At least I didn’t have to correct them manually. The important part is that the suite is back in line with the current codebase.

Root deploy state was updated as well, so this is basically the demo deploy build. Not the fully public release yet, but the version that should be shown is assembled now.


So yeah, this one is not about adding a new tab or a new module (what a shame!!). It is about making the demo stop feeling like a dev environment and start feeling like a thing I can actually hand to people :3

Which is scary…

But also. Finally @w@

Attachment
0
grm

Shipped this project!

Hours: 12.18
Cookies: 🍪 147
Multiplier: 12.08 cookies/hr

Dawnline is out!

This is the first (somewhat) official release of Dawnline! This ambitious piece of software was made with one goal in mind: making focus feel natural, in a world that constantly fights for your attention.

It’s still early, still rough and very much not a finished productivity system. But the core loop is here.

Let me know how I did.

Run

From the release binary:

chmod +x dawnline
./dawnline

Or from source:

git clone https://github.com/ENIX1701/Dawnline
cd Dawnline

cargo run

What’s inside

  • Plan/Execute/Review flow
  • blocks, tasks and notes
  • command palette with :
  • keyboard-only navigation
  • focus timer/logging
  • carry-forward review
  • local event log storage
  • config + starter themes

The goal is small: make the focus come to you.

grm

Small update before the ship.


This was mostly cleanup and release prep. Most panes finally render in a way that makes sense.

Focus mode is real too. Well, mode is an overstatement. There’s a hotkey for it now (t), :focus 25 works from Execute, and the timer actually shows what’s left instead of just logging minutes somewhere and moving on x3


Review got some love as well. Finishing execution closes the active block/session properly, Review has a carry-forward area, and you can start a new session without ending the whole day. If you do finish the day, there’s a small end screen now.

I also rewrote the README and prepared things for release

Still early, still very much a concept-proof, but it’s starting to feel usable! :3

Attachment
0
grm

Small update, mostly because the concept-proof version immediately started annoying me -_-


Dawnline is still very early and I’m still figuring out what the exact shape should be, but the README idea is holding: clean terminal focus center, Plan -> Execute -> Review, day/session/block/task stuff, no giant todo-app monster.

This pass was mostly UI + flow cleanup. I stripped back some of the chunky TUI boxes, made the header/footer calmer, moved the command/help overlays away from the big popup thing and started pushing the vibe closer to the premium/minimal thing I want.


Config and themes exist now too!! ~/.config/dawnline/config.toml gets created with defaults and there are early dawn, opal, and mist themes with configurable accents. These “themes” are still very, very subtle, but I really wanted to have some kind of customization already… Probably too early, but also… the app has to feel right, so whatever x3

Also fixed a bunch of behavior: tab switches timeline/tasks, pane selection actually matters, starting a block closes the previous one, finishing execution closes the active block/session and day finishing only happens from review. Event replay is scoped to today now too


And there are tests now!! Replay, task states, priority sorting, block/session finishing, config/theme stuff, some flow behavior. Not glamorous, but necessary. These were kindly provided by GPT-5.5. I know, I know… but it had to be done QwQ


So yeah, not a huge shiny feature update. Still messy, still influenced by CHARON/AETHER in places, but it’s starting to feel like its own thing :3

Attachment
Attachment
Attachment
0
grm

I did a UX pass across the frontend. Sanding down a lot of sharp edges that became very obvious once the app was running somewhere real xC Cards feel more clickable now, navigation has clearer active states, buttons/selects got a bit nicer, loading states have an animated thingy, empty states are less awkward, and there are icons in places where the UI needed a tiny bit more direction instead of just text everywhere :3


The biggest actual quality-of-life thing is toast notifications!! A bunch of actions now give proper feedback instead of silently succeeding and leaving you wondering if something’s wrong… Creating events, saving branding, managing collaborators, changing planner items, moving/expanding timeline blocks, updating socials, exporting, lifecycle actions, etc. now produce little success messages. Very basic, but it makes the app feel way more alive and less prototype-y >w<

There was also a bunch of small visual motion/interaction cleanup. Hover states are smoother, clickable surfaces are clearer, badges and alerts got icons, the select component finally looks presentable and there’s a shared loading primitive now instead of each page improvising its own “Loading…” text x3 Tiny stuff, but it matters a lot QwQ


Backend got a couple of practical fixes too. Magic-link emails are normalized to lowercase now, so logging in doesn’t randomly fail because of email casing (insane how me testing on the same email made me miss this for so long…) Event creation validation is stricter as well: slugs have better rules (and are validated at all… or will be in the near future!), timezones are validated as real IANA timezones and events can’t be created with an end date already in the past. There’s also a slug availability endpoint now, which should make the event creation flow nicer once the frontend uses it properly.


So yeah, this is mostly post-deploy polish. Still private, still needs a few more passes, but this was a good cleanup round :3

Attachment
Attachment
Attachment
0
grm

New version is deployed, although not publicly available yet. So it’s not a full release-release, but it’s there!


The big frontend migration is finished now!! The primitive/component cleanup that was still in-progress last time is done: the old base components got removed, the new UI primitives are the actual direction now, and the dashboard views are much less messy internally. There are shared surfaces, link-buttons, panel headers, status badges, role badges, form options and all those tiny repeated pieces that were previously duplicated across cards!!!


There’s also a proper logo/favicon now! Tiny thing, but it matters to me…


On the deployment side: the root project is now set up (almost?) fully. The Docker build uses Node 24 for the frontend, builds the frontend, builds the Rust backend, then ships the built frontend as static files from the backend.


So yeah, to sum it up: migration finished, private deploy exists, the app is much closer to being shown to people (you are the people!!). Next up is readmes, test accounts, ship/guide text, then making it public when it’s ready. That moment’s getting closer and closer @w@

Attachment
0
grm

Okay so, this one is mostly about making the app deployable. In the meanwhile (as always…) I’ve noticed many things that can be done in a better way, so this one is deploy + those (they’re still in progress tho…)


The backend got a pretty serious round of cleanup and hardening. API routes are now properly scoped under /api, which fixed the 404 situation, and the frontend/backend dev setup is cleaner now too. Vite proxies API calls in development, while production can serve the built frontend directly from the backend. It works. Finally QwQ


I also added configurable ports, production/local database behavior, and a seed reset flow for the demo database. The app now resets from seed.sql on startup and periodically after that, because this is a public-ish demo and someone will absolutely delete everything the moment they can. I respect the chaos, but the database now fights back >:3c


There was also a lot of schema and seed cleanup. The local/dev database now matches the newer event/planner/collaborator/socials shape better, and the seed data is kept usable for the dashboards (thanks to GPT!). Very boring sentence, very important change.


Tests also expanded a lot. Backend tests now cover much more of auth, users, events, routes, services, config/db behavior and delivery logic. Frontend tests got a big pass too: primitives, dashboard components, planner timeline pieces, socials, staff, collaborators, composables, router behavior, and view-level flows all got more coverage. Also thanks GPT! I would’ve never done this by hand in less than 100 hours 😭


On the frontend side, the planner refactor from the previous cleanup wave has now landed properly. The timeline board, creation panel, item form, and item list are split out and the dashboard itself is much less of a giant file. There were also styling fixes around the planner, Vite/auth cleanup and more small adjustments after the component migration.

In-progress

I’m still doing component cleanup around repeated status badges and little UI inconsistencies. Event statuses, planner statuses and social post statuses are being pulled into dedicated components instead of every card inventing its own mapping. There’s also some deploy/readme/runtime cleanup happening around Node 24 and the Docker build. So the next bit is basically polish the remaining visual/component stuff and finish the last cleanup pass. The deploy is done, but not fully available to public. It will be in a short time… (because FT is ending soon QwQ)

Attachment
Attachment
0
grm

Project kickoff time!! Dawnline is now a reality! At least the little part that’s already built… x3


This first run was mostly concept-proofing. I’m still not 100% sure what the exact final shape of this project is going to be and I don’t want to pretend otherwise too early. The idea is clear enough though: a minimal, clean terminal focus center. Something for shaping the day, seeing what matters now, and ending with a useful little review to keep things organized.


So for now I focused on making the concept exist in the terminal at all. There’s a Rust TUI skeleton with the main modes from the concept: Plan, Execute, and Review. It’s not polished yet, obviously, but the basic loop is there: plan blocks/tasks, execute from a more focused view, and review what happened.


A lot of the early interaction ideas (and UI components x3) are borrowed from CHARON (part of AETHER, my other flavortown project :3), because it already gave me a bunch of useful TUI patterns to steal from myself x3 Things like keyboard-first flow, command-palette-style input, modes, panes, and the general no-mouse feeling all come from lessons learned there. Dawnline is definitely its own thing, but CHARON gave it a nice little head start.


Under the hood I started with an event-sourced foundation, because Dawnline is supposed to care about the day as something that happened, not just a pile of current todo items. Tasks, blocks, notes, sessions, focus logs, completion/drop/remove actions, all of that is represented as events and replayed into the current state. For now it writes to ~/.local/share/dawnline/events.jsonl, which is very MVP and untidy, but it works!!


There’s also a tiny CLI surface already, plus a simple command palette inside the TUI. Nothing clever yet, but you can add tasks, priority tasks, blocks, notes, log focus time, start blocks, finish sessions and get a basic review. It’s definitely still concept-proof territory and not what I see in my head yet… but the bones are there!!!


So yeah, Dawnline begins here. I don’t fully know where it’s going yet, but I know the core feeling I’m chasing: calm, minimal, focused, a little premium and actually useful when the day starts getting messy. For now it’s mostly a skeleton with ambition, but at least the skeleton can run in a terminal now :3

Attachment
0
grm

This one is almost entirely frontend. It was pain. I persisted!! The UI refresh that’s been looming ominously in the distance has finally started landing for real @w@


I introduced a proper UI primitive layer, so the app is no longer relying on every dashboard hand-rolling its own slightly different buttons, panels, fields, inputs, badges, alerts, empty states, etc. There are now shared components for the common building blocks, plus cleaner themes and a flatter visual language. The old glowy glass chaos is being slowly bonked into something more consistent and usable QwQ


A lot of the existing dashboards got broken apart into smaller components. Events, event details, branding, socials, collaborators, staff, and the planner are no longer untamable giants. They now have dedicated forms, cards, panels, previews, rows, workload lists, timeline boards, timeline forms and so on. Functionally this does not sound as exciting as a shiny new feature, but it makes the app way easier to keep building without every change turning into frontend archaeology x3


The planner also got pulled into this new structure. The timeline board, item creation panel, item form, and timeline item list are now separate pieces, and they use the shared primitives too. So the Gantt/planner area should be much easier to polish and extend now, especially since it already has collaborators, assignees, statuses, colors, and scheduling all trying to coexist in one place like a tiny operational hydra (hydra would be such a cool expansion to aether btw…) :3


The app shell itself changed too: cleaner desktop sidebar, better mobile navigation, less background noise, flatter surfaces, stronger spacing, and consistent theme variables. It’s still not perfect, but the direction is finally becoming coherent. Yippee for me! x3


So yeah, this is mostly a structural + visual cleanup update, but a pretty important one. The near-future plan is now clear: polish the remaining visual inconsistencies, make sure the refreshed UI feels good across the app, and then finally deploy. Terrifying, but we are getting there x3


Before the deploy I will need to go through the security flows and check if nothing’s dumbly exposed. Wouldn’t want someone to take this pretty creation down… :C

Attachment
Attachment
0
grm

A tiny one >w< I added a Staff dashboard! It pulls event collaborators and planner timeline items together, so you can see the team, how much work is assigned, what’s blocked, and which timeline items still don’t have anyone attached to them! Each person now gets a little workload card with their assigned items, open/done/blocked counts, contact info, and timing windows. You can instantly see who’s slacking off x3 It’s still pretty basic, but the important thing is that it connects the systems that were previously separate: collaborators, roles, assigned timeline work, and blocked tasks. This means it’s actually becoming a complete, end-to-end (another word for complete… x3) system for tracking events! yippee!!


Also, in-progress: the big UI refresh has started :3 It’s not shipped yet, but the direction is finally moving away from the glowy glassy chaos (which I love, but didn’t fit the purpose of this system at all :c) and toward a cleaner primitive-based UI system. I started laying down reusable components like panels, buttons, fields, badges, alerts, page headers, selects and inputs, plus a flatter theme setup and refreshed desktop/mobile navigation. Below are some pre-release teasers into how it’ll look ;3


Also a disclaimer: the test/mock data is AI generated. This means the layout and other stuff are made by a real caffeine-fueled human, but the text and stuff is not!

Attachment
Attachment
Attachment
0
grm

Events finally have proper collaborators now! There’s a Collaborators page where event owners can manage the team for an event. For now it works with existing users: you add them by email, pick their event role (owner, organizer, staff, or volunteer), see their contact info, update their role, or remove them from the event. Non-owners can still see who’s involved, but they don’t get the fun buttons x3


The backend permissions also got tightened a lot. Accessing the event is no longer the same as modifying everything inside of it now! The role system is still very much evolving, but it’s there, so that’s progress :3


The planner got tied into this too!! Timeline items can now be assigned to actual event collaborators. The frontend loads the event team into the planner form, lets you pick who a timeline item belongs to, shows the assigned person on the chart, and the backend verifies that the selected user really belongs to that event. So the Gantt thing is no longer just a rectangle with text :3 (okay honestly it still kind of is, but let’s skip over that part for now!)


Also fixed a couple of small but annoying things while wiring this together, including the social status dropdown not reflecting the current status properly and a timeline duration math oopsie that could make bars not behave… Tiny fixes, sadly (or not!) more to come!

Attachment
Attachment
0
grm

Usability update! After getting the Gantt planner to exist last time, I went back and started making it less of a prototype… Planner timeline items can now be edited more properly instead of… not that. You can change their title, type, dates, status, owner, color and notes, plus shift items around in time and resize them a bit. It’s still not the final dream planner by any means, but it’s already getting a lot closer!


The Socials tab also got a much-needed pass!! Previously you could create posts and move their status around, but now drafts can actually be edited after creation. So if I typo the platform, title, body, or status, I don’t have to delete the whole thing and pretend that was intentional!! how cool x3


The other big thing is branding becoming properly interactive :3 Backend branding data now has more theme fields, like theme mode and background color, and the frontend can actually apply event branding to the app shell through CSS variables. So changing colors in the Branding tab can affect the event workspace instead of just living in a preview box forever. Excitinggg x3


And because all of this was starting to cause way too many repeated fetches and stale UI moments, I added a local frontend cache for event data. It caches event details, branding, planner items, timeline items, social posts and exports, refreshes things in the background, and invalidates the right pieces when mutations happen. It’s not fancy distributed systems magic or anything, but it makes the app feel snappier and way less twitchy. You have to trust me on this one, but it was really needed xC

Attachment
Attachment
0
grm

Yesterday the event workspace started feeling a lot more complete, but today is where the planner started becoming a real planner x3 The Socials tab is now properly usable: event-specific social drafts can be created, passed through statuses and removed when needed.


I also added more of the event lifecycle/ephemeral-event stuff (you know, the core… at least we’re getting there!)!! Events can now be archived, and there’s a JSON export flow that collects the event, branding, planner items, social posts, and timeline planner data. This is pretty important conceptually, because the app is supposed to care about events ending, being cleaned up, and not just living forever. So now there’s at least a real path for take your data and go :3

But the most exciting part is definitely the planner work! The old planner was basically a cute little TODO list, and now it has the start of an actual Gantt-style timeline!! It is still a little wonky, and I already know there are things I’ll need to clean up, but it exists!! The scary (for me, okay? x3) part is finally turning into code >:3c


So yeah, this feels like one of the more meaningful updates so far. Socials are usable, export/archive support the whole ephemeral concept, and the planner is no longer just a list pretending to be a plan. There’s still a lot of polish ahead, but today made the app feel way closer to an actual event operations tool QwQ


(yes, it’s still in development, hence the weird styling - it will get resolved once the functionality is fully in place QwQ)

Attachment
Attachment
Attachment
0
grm

A big one!! I spent a lot of time pushing the event workspace forward, and it finally feels less like a bunch of disconnected panels and more like an actual event-centric app. The sidebar got redesigned, the mobile nav got overhauled, the routes make a lot more sense now, and once you’re inside a specific event you can actually move around that event’s own space. I know, woahh,, It’s a pretty major structural improvement, even if a lot of it is still basic MVP functionality

Currently implemented bits are roughly:

  • Planner - I added the basic planner flow end-to-end! There’s now backend support for planner items, plus a frontend planner dashboard where items can be created, checked off, and removed. Still pretty minimal, but at least real now!! :3
  • Branding - Basic branding functionality is in too!! There’s now backend support for event branding records, and the frontend has a proper branding screen with event name override, tagline, primary and secondary colors, notes, and a live preview. I may or may not have played with the preview for a bit too long… >:3c
  • Navigation and overall structure - I reworked the app into an event-workspace shape instead of whatever the old situation was. Desktop and mobile nav both got cleaned up to reflect that (they’re still very rough, please bare with me QwQ)
  • Event flow polish - I also cleaned up the event hub/routing side of things so creating an event and dropping into its workspace feels way more natural. It is still very buggy and the UI just kind of… broke… (I promise I’ll fix this once everything is functional 😭) (there’ll be a sizeable design overhaul in a bit, after all the main flows are complete)

The planner exists, branding exists, the app structure finally makes more sense, and the whole thing feels a lot closer to an actual usable system instead!!! Hopefully it’ll become just that in the near future x3

Attachment
Attachment
0
grm

Shipped this project!

Hours: 6.21
Cookies: 🍪 180
Multiplier: 28.96 cookies/hr

AETHER is a C2 framework designed for red team engagements and educational purposes.

Components

AETHER is composed of three primary modules. Each of them is capable of running independently, but designed to work in unison.

GHOST

Modular C++ implant deployable to Linux hosts. It features toggleable capabilities mapped to the MITRE ATT&CK framework.

SHADOW

Heart of AETHER. C2 server written in Rust. It exposes a RESTful API to handle agent communication, tasking and aggregation. It also now drives the built-in replay mode used for safe demos, mocked tasking and synthetic loot generation.

CHARON

Terminal user interface written in Rust. Completes SHADOW and gives unfathomable power to any operator who takes its call. It now includes replay controls directly in the Dashboard, along with clear LIVE / REPLAY source marking for connected GHOSTs.

This ship’s highlight

This ship focuses on making AETHER much easier to demo, test and onboard with. The biggest addition is the built-in replay mode. SHADOW can now spawn synthetic GHOSTs, keep them “alive”, simulate task results and generate synthetic loot, while CHARON exposes the whole thing through the regular operator workflow. That means replayed GHOSTs can be viewed, selected and interacted with just like normal ones - only safely, on mocked data :3

Currently implemented replay presets are:

  • idle_fleet - Spawns a few idle replay GHOSTs for a quiet dashboard demo
  • task_flow - Spawns replay GHOSTs with task history already present, which makes the operator flow feel much more alive
  • loot_burst - Spawns replay GHOSTs that generate synthetic loot, which is great for testing the Loot tab and general workflow

Replay mode never executes real commands. EXEC output is mocked, IMPACT, EXFIL and STOP_HAUNT are simulated safely, and replay-generated loot is handled separately from normal operation. Nice and safe. Just how a demo environment should be :3

On top of that, the docs across AETHER, SHADOW and CHARON were updated to reflect the new workflow, and the replay/API/state flow now has much broader test coverage. Lots of plumbing, lots of cleanup, lots of synthetic ghosts doing synthetic ghost things x3

Testing

AETHER is designed to be deployed instantly using Docker Compose. It deploys SHADOW and CHARON. They use a private container network, how cool is that?

git clone --recurse-submodules https://github.com/ENIX1701/AETHER

# build and deploy the images
docker compose up --build -d

# attach to charon and try it out!
docker attach charon

If you want to test the classic sandbox flow, here’s the quick path:

# this spawns SHADOW + CHARON and 3 GHOSTs :3
docker compose --profile sandbox up --scale ghost=3

These synthetic GHOSTs work as you’d expect them to. Which is exactly as they would in real-world deploy.

If you want the quicker demo path, use the built-in replay mode from CHARON’s Dashboard. For detailed usage, head over to the CHARON Manual.

grm

This update adds the replay mode to AETHER! It gives you a safe way to demo the whole operator workflow without deploying real GHOSTs - SHADOW now spins up synthetic ones, CHARON displays them right next to the live implants, and you can interact with them on mocked (but realistic!) data. I really wanted this to feel like the normal AETHER flow rather than some weird separate toy mode, so a lot of the work here was wiring it all together properly :3


Currently implemented replay presets are as follows (per docs):

  • idle_fleet - Spawns a few idle replay GHOSTs for a quiet dashboard demo.
  • task_flow - Spawns replay GHOSTs with task history already present, so the operator flow feels a bit more alive.
  • loot_burst - Spawns replay GHOSTs that generate synthetic loot, which is great for testing the Loot tab and general workflow :3

On the CHARON side I’ve added a replay control panel directly to the Dashboard, plus a SOURCE column so you can immediately tell whether a GHOST is LIVE or REPLAY. You can now cycle presets, start or stop the replay, reset it and jump straight into the selected GHOST from the Dashboard. Replay GHOSTs also go through the regular operator flow, which was very important to me because otherwise the whole thing would’ve felt… fake :C


On the SHADOW side I’ve implemented the actual replay engine. It seeds synthetic GHOSTs, keeps them “alive”, simulates task output, generates synthetic loot and cleans all replay data up on reset. Common EXECs now return mocked output, IMPACT, EXFIL and STOP_HAUNT are simulated safely, and replay mode never executes real commands. Which is good, because I’d really rather not destroy a demo environment (again) just to show someone the UI QwQ


I’ve also updated the docs across AETHER, CHARON and SHADOW, documented replay mode as the quicker demo path in AETHER’s sandbox section and marked it as done on SHADOW’s roadmap! On top of that there’s a bunch more tests around the replay/API/state flow, so this should all be much less held together by duct tape than it was when I first started stitching it together x3

Attachment
0
grm

A smaller one. I spent this session rethinking the frontend navigation a bit, because the old flat dashboard setup was starting to feel really wrong? It technically worked, but didn’t really match how I want the app to be… So I started reshaping things around events instead of treating every panel like some unrelated entity. Events is now the real entry point, and I split out a separate event-section model for things like Overview, Planner, Branding, and Socials so the structure can revolve around a specific event rather than just dumping a pile of dashboards into the sidebar and calling it a day (yeah it did kinda be like that…)


So yeah, this one is more of an architecture/UX pass than a shiny flashy feature update, but I think it matters a lot. I cleaned up the route and section config, started stripping away some of the old top-level dashboard baggage, and generally nudged the app toward a much more event-centric shape (as intended!!). It’s still mid-transition and not fully wired end-to-end yet, but the direction already feels way better, more like a coherent app x3 No huge feature boom today, but definitely one of those quieter refactors that’ll make the next changes much less cursed in the future x3

Attachment
0
grm

Finally made the whole passwordless auth flow complete. Up until now, magic links technically existed, but actually using them for testing still felt kind of silly and awkward… so I implemented a proper delivery/outbox setup for them! There’s now a test inbox flow, which means I can request a magic link for a “tester” account and then fetch the latest still-valid one from a dedicated dev inbox instead of digging through the backend terminal x3 Considering how unusual the no-password setup is, this helps a lot 😭


I also tightened up the auth flow itself while I was there >:3c Requesting a magic link now returns a generic response instead of basically snitching on whether an email exists, and once a link is used, both the token and its inbox entry get marked as used properly. I also made the backend initialize the relevant schema on startup, because apparently “surely the table is already there” is not, in fact, a valid architectural principle x3 So yeah, the flow feels a lot more real now, and a lot less held together by hope alone


On the frontend side I gave the auth screens a much nicer pass too!! Public routes now get their own layout, the login panel looks way more intentional (and kind of AI generated, which pains me because I love glassmorphism so much 😭), there’s a dedicated dev inbox view, error handling is less janky, and the overall styling/background situation feels a lot cleaner and less placeholder-like. I also had to go back and adjust a bunch of backend and frontend unit tests to match the new behavior (well, when I say I, I really mean Opus…), but honestly that was overdue anyway.


So overall: magic links now have somewhere tangible to land, the tester flow is way less annoying, and the whole auth system feels a little less embarrassing and a little more like a real feature :3

Attachment
Attachment
0
grm

Long time no see! (again…)


The auth/roles mess I was talking about last time has finally started turning into an actual system instead of just a pile of question marks and wishful thinking x3 I sat down and reworked the permission model properly, so the placeholder silliness is gone and the app now has actual roles: Admin, Organizer, Staff, Volunteer (farewell Clown… you were iconic, but you had to go 😭). I also wrote out some proper role/permission docs, mostly because I was getting tired of re-conceptualizing the entire app every 5 minutes QwQ

The unusual nature of this project (ephemeral, passwordless, etc.) is still being a menace, but I finally have something real working!! I ended up going for a magic-link kind of flow: submit email -> get a one-time token -> verify it -> receive a JWT -> use that to access protected routes. So the whole “how do I auth people without just letting them spoof each other for fun” problem is, thankfully, no longer completely owning me >:3c (it is still somewhat problematic tho…) The user module got tightened up a lot too: routes are now protected with JWT middleware, update/delete finally respect who the caller actually is, there’s user lookup by email for auth, and I added support for stuff like availability hours. Also made a small seeding/setup flow for dev data because manually poking SQLite every time was beginning to wither my soul x3


And!!! the frontend is finally participating in society instead of just standing there looking pretty :3 There’s now an actual login panel, magic-link verification, logout, route guards, role-based navigation, and proxying so the frontend and backend can talk to each other without weird hacks or ritual sacrifice. I also went back and expanded (or rather fixed…) the tests, because last time I had that whole “there are tests!!! (they’re dying)” situation 🥀 Backend coverage is in a much healthier place now, and I even added frontend unit tests for auth, navigation, routing, and the login flow. There’s still a lot to polish, and this weird little passwordless creature of an app continues to humble me daily… but it finally feels (somewhat) like progress :3 (there’s still so much to do 😭)


(I know it’s not pretty yet but I’m really trying, okay? QwQ)

Attachment
0
grm

Shipped this project!

Hours: 108.4
Cookies: 🍪 311
Multiplier: 14.19 cookies/hr

So many cool changes with this one!

CHARON

The bulk of changes for this ship. It does everything it did before and more! Waow…

More customization in the builder

Take a look :3

Scenario mode and severity level pickers were added to the general tab of the builder menu! These let you create GHOSTs even more easily than before :3

New loot view

See it in action here

It would be nice to be able to view and search through the data exfiltrated by GHOSTs. Well, you’re in luck! The new loot menu tab allows you to do just that :3 (kind of - you still need to browse the files manually on your PC, but hey, at least now they’re there!)

GHOST

Big news! GHOST now has a built-in scenario mode!

It works as follows:

  1. You pick out a threat actor (or just a generic threat) you want to simulate
  2. You configure the accepted impact level (described here)
  3. You run the simulation manually (CHARON prepares the command, they put it into the terminal on tested machine)
  4. The implant is configured to mimic the kill chain of selected malware with configured impact level (if you want the real deal you’d select USER or SYSTEM)

CHARON also has native support for the scenario mode (and impact level!) now. Neat :)

SHADOW

It changed the least. Got adjusted to support new building options in CHARON and to expose exfiltrated data in a sensible way :3

grm

Last one before the v1.1 release and ship!

Past few hours were spent on making sure that everything works as intended. This included fixing weird bugs (like broken GATHER and EXFIL modules in GHOST, wonky UI madness in CHARON, among others x3), perfecting the deploys (Docker ones included!) and keeping the documentation up to date :3 (with fresh UI screenshots UwU).

Attachment
0
grm

A big one! This update adds the Scenario Mode to AETHER! It lets you run simulations using predefined threat-actor (or generic threat) profiles. Setting this up took quite a bit, but adding specific scenarios was so much funnn x3

Currently implemented scenarios are as follows (per docs):

  • RANSOMWARE - Very noisy. Exfiltrates data and encrypts files.
  • ESPIONAGE - Low noise. Gathers host info (sensitive data included!) and exfiltrates it over the C2 channel. Good starting point for simulating infostealer malware or APT actors :3
  • WIPER - Extreme noise. Destroys all files and self-terminates, leaving the system in an unusable state. Used to test EDR detection and reaction speed.
  • INFOSTEALER - Steals the info >:3c
  • APT - Stealhy and hands-on-keyboard’y… Also - very generic
  • APT29 - Long-term espionage. Gathers SSH keys, stablishes RunControl persistence and deploys an undetectable 4-hour beacon interval.
  • APT44 (SANDWORM) - Pure chaos. Establishes a CRON job to survive reboots and immediately wipes the system. Nothing will survive.
  • APT38 (LAZARUS) - Two stage extortion. Silent harvesting of system data and SSH keys only to drop a screaming ransomware to mask the espionage.

On top of that I’ve implemented some structural and functional changes. CHARON can now set impact levels and generate payloads using specific scenarios!! I’ve fixed some exfiltration functionality and unified the naming. Lots of small changes that will make my life a lot easier x3 (and make the system more usable!)

Attachment
0
grm

Slowly and painfully, but we’re getting somewhere! I’ve started implementing the backend. Couldn’t hold myself back anymore, the UI can wait x3 I chose the Actix + SeaORM + JWT middleware way of doing this, because I’ve never used Actix or SeaORM before, and have heard good things about them from my friends! I have to agree that it’s an amazing stack: everything’s structured, modularized, but still monolithic in nature (microservices are eww). I am also having a blast learning all the cool Rust-native mechanisms that these offer.


The unusual concept of this app (it’s ephemeral nature, no passwords, etc.) is starting to pose a real challenge, and so many problems are beginning to arise QwQ But I know I will get through no matter what!! Even if I don’t do them the best way, it’ll be an invaluable learning experience!!! hopefully x3


Currently implemented a basic user module and authentication scaffolding. At the moment I’m in the process of laying out documentation that will (hopefully…) help me conceptualize roles and permissions, because they’ve become quite a mess… (there’s still a placeholder Clown role 😭). So yeah, goals for the near future: brainstorm the correct auth roles, add a way to add “label roles” (the ones you see, but which don’t really do anything else x3), figure out a way to auth without spoofing other users (I’ve been thinking about a challenge-response kind of thing, like the YubiKey, but I’ll cross that bridge when I get there x3). That’s a lot, but hopefully these will be done soon-ish™


Also there are some tests!!! (they’re already outdated and failing because of the JWT auth and role thingy 🥀)

Attachment
0
grm

I can’t wait until this is finished, how do you frontend bros even do this 😭


Added the staff dashboard. It’s obviously not done yet, but it gives you a basic idea of the functionality it’ll provide. This took so much time, but hopefully it’s a solid enough foundation that the future backend integration is relatively easy…


I’ve also noticed that a basic design guide would be a great thing to have now. I do have an idea of how I want this to look (even some figma designs!!), but putting this into the code is a whole another story. I’ll think about how I want to go about this later… x3


The last tab I’ll do (for now) is socials. Then, if everything goes right (it won’t), I’ll start making it actually work like a website! Yippee!! Rust my beloved please save my sanity

Attachment
0
grm

Small, but insanely important log!!

  1. Fixed Docker Compose build times (kind of, just moved tests out to a separate stage)! They should build a bit faster now :3 (thanks to the shipwright reviewing my ship for pointing this out!!)
  2. Created a build script for new releases. No more manual labor!! yippiee :3
  3. Currently catching up on some newest malware campaigns to know what to add to the scenario mode =w=
Attachment
0
grm

Added new gathering module!! In MITRE it’s mapped as credential gathering, but here I wanted it to be a bit broader. Gathering system information is more of a reconnaissance thing, but I wanted it all in one place, so there’s that…

I’ve also began (more of a PoC than anything else right now, but I hope it’ll be fully functional by the next release!) implementing the scenario mode. It will let you simulate threat actors (or just generic killchains, like the ransomware and espionage ones implemented currently), which in turn will help you improve the security of your systems!! I want it to be as easy to use as possible, which is challenging, because I also want it to be parametrizable… It’s still work in progress, okay? x3 (that also means they’re not tested, so, uhhh, they may not work fully as intended yet…)

Another news is that the code now compiles with all combinations of flags (don’t ask if it didn’t before, won’t say…). The CMake tests are now adjusted to the new SCENARIO_MODE flags, and I fixed all the silly little accidents so that everything builds and compiles correctly. Yippee! They take so long to compile and run tho @w@

Attachment
0
grm

Long time no see, huh? x3 Waiting for the ship to get approved was a true test of patience, but the lovely shipwrights got to it and left some nice feedback :3 I had to create and roll out an unexpected full binary release (I kind of hoped it could be docker-only, but turns out it couldn’t…), and that took way longer than expected. Did you know how difficult statically linking basic binaries is in C++? That, or I am just special

Near future will be spent on improving GHOST. Both SHADOW and CHARON now support the core functionality needed to make GHOSTs useful, so now I’ll make the GHOSTs useful! I plan on adding an impact severity level configuration (probably through CMake flags again, will see x3) and basic XOR string obfuscation to see if the file gets flagged by Defender again. If not, we may see a Windows implant in v2!! I wouldn’t be too hopeful about that tho…

Attachment
0
grm

Looking absolutely horrendous. The beginnings are usually rought, but man… Progress on this is also painfully slow, as I haven’t touched any frontend code in months. Vue is amazing, but still, ughh…

Hopefully next devlog has some actual designs in it x3

Attachment
0
grm

Shipped this project!

Hours: 99.29
Cookies: 🍪 2689
Multiplier: 27.08 cookies/hr

AETHER is a C2 framework designed for red team engagements and educational purposes.

Components

AETHER is composed of three primary modules. Each of them is capable of running independently, but designed to work in unison.

GHOST

Modular C++ implant deployable to Linux hosts. It features toggleable capabilities mapped to the MITRE ATT&CK framework.

SHADOW

Heart of AETHER. C2 server written in Rust. It exposes a RESTful API to handle agent communication, tasking and aggregation. It also features endpoints useful for creating user interfaces. Speaking of those…

CHARON

Terminal user interface written in Rust. Completes SHADOW and gives unfathomable power to any operator who takes its call. Enables agent status visualization, payload crafting and remote command execution.

Testing

AETHER is designed to be deployed instantly using Docker Compose. It deploys SHADOW and CHARON. They use a private container network, how cool is that?

# this spawns SHADOW + CHARON and 3 GHOSTs :3 
docker compose --profile sandbox up --scale ghost=3

These synthetic GHOSTs work as you’d expect them to. Which is exactly as they would in real-world deploy. Check it out for yourself!

grm

Preparations for the final release are coming to an end. Next devlog will be v1.0 (or ship, don’t really know how those work yet). Only final touches left, tagging v1 on GitHub, and… that’s it I think.

The biggest change this time was finally creating a complete, out of the box sandbox to let all of You try it out :3 It spawns as many GHOSTs as you want, and let’s you play with them like you would in a real red-team exercise!! I can’t wait to get more peeps to try this out and give their thoughts on it aaaaa

I’ve also tried to fix CHARON’s Docker terminal quirks. Basically, any time you quit CHARON after attaching yourself to the container, your native terminal won’t clear, and you’ll be stuck with CHARON’s last view (and possibly no cursor for the rest of the session - ask me how I know…), which is suboptimal. I’ve tried quite a few things to fix it, but to no avail. I’m giving up for now, maybe when someone else takes a look they’ll see a feasible fix.

Also also: I’ve massively improved GHOST generation. CHARON now sends instructions to SHADOW, which generates and serves GHOST binaries. It also has a caching mechanism, so if a binary with the config you want has been built before, you’ll (almost) instantly get it back! How cool is that :3

Attachment
0
grm

Unit tests! This one’s amazingly quick, but, as usual, had to be done. Would you believe that these actually found a bug that I haven’t stumbled into yet? Yeah, fixed it x3

Next up I’ll go through all of AETHER and prepare them individually for the release. Then, I’ll test integrations and ease of use, and, finally, there will be an official v1.0 release! I can’t wait jfkdasfhsdjhb

But yeah, getting closer and closer!

Attachment
0
grm

Finally parametrized GHOST builder to a point where I’m satisfied with it. Has everything you’d need, you can choose not only which modules should be active, but also which techniques!!

In other news, the documentation is fairly complete for now. It has a guide on how to use CHARON, describes the architecture and code guidelines well (I think so at least…), and finally structures the whole thing.

I’ve also added auto refresh! Before that command output sent back by GHOSTs (and SHADOW as a proxy) would not get loaded until you manually switched the view and back. That should’ve never happened. Oops…

Attachment
0
grm

CHARON got refactored. It looks the same. It feels the same. But that’s good! That’s exactly the point :3

The architecture behind CHARON got completely rethought and revamped. It’s now modular, designed with the MVC (kind of) model in mind. It is now 100x more maintainable and easier to work on. I didn’t really notice how big it got until I had to refactor. This one’s done.

Now I need to create some extensive documentation. Why extensive? Well, it sounds cool, and it saved my butt in GHOST a couple of times already, so I know this one’s gonna pay dividends as well. Then, only SHADOW will be left… But I don’t think it needs much (if any) refactoring. Will look into it when I get there!! For now, enjoy the beauty of CHARON’s new heart :3

Attachment
0
grm

All good things in life take time, huh? Well, this documentation must be one of the joys of life, cause it’s taking forever to design and write. On the flip side, I’ve also finally implemented the GHOST builder in CHARON. It’s still not fully tested and not production ready, and I still need to figure out how to get it to work with the dockerized versions of CHARON and SHADOW, but I’m one step closer now!!!

Also, the documentation I made last time saved my butt this time around… Current (future) me is very thankful for that. Hopefully the docs I made now will be of at least this much use in the future x3

Also, also, guess what! Another refactor, probably… It’ll be CHARON this time, because with the new functionality the files are getting really messy. Not looking forward to that, but… it has to be done I think. So it will get done! …eventually

Attachment
0
grm

This “sprint” was almost entirely focused on finishing the GHOST refactoring and creating fresh, new, polished READMEs for all modules (my favorite, and also the most complete, is the GHOST README). What this means, by extension, is that the project is progressively getting more mature. It’s to the point, that I had to write down the coding guidelines for GHOST to not check other modules for style reference every time I need to add something. They took quite a while, but I think this time will pay dividends.

The progressing maturity of all modules marks a fast approaching release version. The TODO lists are shortening, which means we’re getting closer to the v1.0!! SHADOW and CHARON are already dockerized, and AETHER has a docker-compose file for both of them! They are already a one-click deploy, so I only need to figure how to make GHOST easy to use (I’ll figure it out soon enough…), and then think if/how I want to approach the GHOST builder for CHARON. It’s currently a problem for the future me, so I’ll leave that to him :3

Overall, I don’t think I could be more satisfied with how AETHER is turning out. It’s got more love and passion poured into it than any other project I’ve worked on before. I’m almost proud of it…

Attachment
0
grm

GHOST refactor is complete. It was surprisingly less painful than anticipated, but it obviously wasn’t a walk in the park either. While I was getting GHOST ready, I also started thinking about the v1.0, and more particularly an easy deploy option that would make even not very tech-savvy people able to try and play with these tools :3

What I’ve done in that regard is:

  • I’ve created or adjusted Dockerfiles for SHADOW and CHARON
  • I’ve created basic instructions for running them on their own
  • I’ve created a docker-compose file that deploys both of them (and assures communication between them!!), which makes this a one-command deploy

I would also like to add a GHOST builder in the near future, but I’m a bit afraid it’ll cause another GHOST refactor… On the other hand, GHOST is really modular rn, so it shouldn’t be anything major… I’ll think about it more when I get to it :3

Attachment
0
grm

Refactoring is going better than anticipated, but with the pains expected. File and project structure has been refactored in a way that makes this extendable and parametrizable, which is exactly what I want. There are still places that can be improved (for example creating an interface for encryption methods to be passed as reference to the impact function and potentially chosen compile-time), but I’m happy with how this is turning out overall.

Some adjustments here are also core design improvements, which means breaking changes for SHADOW (and potentially CHARON). I’ll fix and test those after I’m done with the GHOST’s refactoring, which will be when all functionality is moved from the old version. Then it’ll get merged into main and be a base for all future features.

Attachment
0
grm

This one’s short. Added a blueprint for the exfiltration module. While doing that I’ve noticed how tangled up this codebase has become. The Rust ones are a bit better, they don’t need many changes, but GHOST has completely derailed. This is why I’ll be refactoring it for now. It needs to be easier to add things, it needs to be parametrizable and just overall better designed. I now have the overall idea of what it should and shouldn’t be, so I’ll proceed with this knowledge and refactor the codebase to suit this need.

I hope it’ll be easier than I think…

Attachment
0
grm

More of a list this time:

  • Add killswitch to GHOST
  • CHARON can now trigger killswitch in GHOSTs
  • The killswitch removes any persistence and the binary itself
  • CHARON can now update GHOST sleep interval and jitter
  • GHOSTs now send command output immediately. CHARON shows that output and scrolls if needed
  • Revisit the initial idea and statuses of all modules

For full v1:

  • Add Dockerfile to SHADOW and CHARON
  • Improve READMEs of all modules
  • Add GHOST build functionality to CHARON
  • Add basic impact and exfiltration modules to GHOST
Attachment
0
grm

CHARON now let’s you communicate with GHOSTs and execute commands on them! This required an adjustment to the SHADOW (adding 2 new endpoints to be precise), which in turn cause a somewhat major refactoring to how tasks are stored and managed. This, of course, in turn entailed a test-suite adjustment (to not call it a rewrite…) and adding tests for new endpoints to keep the high coverage. It was tedious, exhausting and required a lot of precision, but CHARON is considered done for the time being.

Next thing to do for me is enabling GHOSTs to reregister to SHADOW with their old id (somewhat possible by design, but they need to store and read the id from somewhere, so that’s the focus now).

After that I’ll very slowly start getting ready for the first major release. This means rewriting READMEs, structuring them more uniformly, backlinking them, adding easy deploy options (Docker; possibly docker-compose for AETHER) and manually testing that everything works as expected. More functionality will probably get pushed in the meanwhile! Sorry not sorry…

Attachment
0
grm

Main focus of this stint was getting GHOST to an operational state. I’ve succeeded (mostly). It now communicates with SHADOW (but CHARON doesn’t get the output of commands - something to debug in the near future). Other than that I’ve started setting up some basic persistence functionality in a way that will be extendable and easily maintainable. I’ve also cleaned up console output so that it:

  1. Is uniform throughout the whole GHOST module (more of a pet-peeve than anything else, but it’ll certainly look a lot more polished :3)
  2. Easy to disable for production app. This is fully done in a way that keeps output for DEBUG build and disables it for other modes (production build is the only other one for now)

This overall required a lot of careful planning and made me reconsider some basic assumptions for the project, but it seeing the end result of this tedious refactoring made it all worth it.

Attachment
0
grm

I knew this day would come, and that this would be inevitable, but seeing it happen is frustrating nonetheless…

I’ve always anticipated that GHOST would eventually cause issues on Windows. Its whole job is basically simulating an infection, and with how sensitive modern AV/EDR solutions are, it was a matter of time until behavioral protections got in the way. Even though nothing here is actually malicious, Windows very much disagrees!!

From what I can tell, the main culprit is GHOST’s use of low-level networking (the winsock2.h and ws2tcpip.h sockets). This paired with some very upfront variable naming can be enough to trip hooks and land the implant in AV jail. Fixing this properly would require heavy code obfuscation, aggressive packing and bypassing user-mode EDR hooks (it’s an insanely interesting topic btw, but very very difficult at the same time). It’s not hard to notice that this is WAY out of the initial scope. I needed GHOSTs to help me reliably test AETHER, not to be state-of-the-art malware simulators.

So… pivot time!! From now on, GHOST will be linux-only. Dropping multi-platform means more advanced functionality!! New goals are outlined in README, but tl;dr: persistence, beaconing, command execution and exfiltration will now be present by-default. I also want CHARON to be able to generate configured and parametrized GHOSTs. Example use case would be generating a GHOST that doesn’t establish persistence and only dumps data to SHADOW, without all other fancy things it could do. I think this will be invaluable to red teams, since it’ll help them focus on test scope more clearly.

This also means: A LOT of refactoring. Like, a lot a lot… I’m looking very much forward to it tho, we’ll see how it pans out x3

Attachment
0
grm

Another big milestone has been achieved! I’ve successfully implemented an MVP version of CHARON. There arose a problem tho…. I can’t fully test it without having some implants handy. And the current ones don’t run on Windows without triggering AV. It shouldn’t happen, because they’re not malicious, but it’s still something I have to combat. Until I figure out how to get GHOSTs to a stable, test-ready state, I’m considering CHARON done for the moment.

Attachment
0
grm

The most tedious task so far has been finished. Well… part of it. To keep the code maintainable it’s important to create tests to ensure your quick and dirty “hotfixes” don’t end up breaking half the functionality. Tests are here to let you know when something stops working… not to assure you that something is working.

Creating them required a small refactor: API handlers and Router that previously resided in main.rs had to be moved to lib.rs. At least that’s what I’ve read is necessary, and these people probably know more than I do, so I’ll learn from them :3

I hate writing tests, but I know that future me will be forever grateful that I did. So I’ll take one for the team, at least this time ^^.

The caveat is that CHARON and GHOST should also have a reasonable test coverage, so it’s something to think about when they’re closer to the finish line…

Attachment
1

Comments

grm
grm 5 months ago

This also marks SHADOW’s MVP as finished and lets me move to another component for the time being. Chose CHARON, because I feel like it’s less work than what I want to do with GHOST, but I will probably quickly get humbled, as per usual…

CHARON it is anyways!

grm

A huge milestone has been accomplished. A basic version of the GHOST implant has been created and successfully connected to the SHADOW server!!! It’s a very work-in-progress type of achievement, but it’s huge progress already. I hope to lay out the GHOST <-> SHADOW interface next to help me structure the API correctly. Another milestone will be the ability to execute commands remotely on the system where SHADOW resides.

Attachment
0
grm

Most of current work was focused on creating a very basic baseline for the CHARON component. My main project got a “definition of done” section in the README, which clarifies what exactly needs to be done in order to ship this project. It will probably morph one way or another, but having anything there helps me focus on what matters in this project.

Attachment
0
grm

The main goals of this first stint were simple:

  • Create a broad vision of what I want to achieve with this project
  • Lay out the architectural components necessary to embody that vision
  • Go through each component and make the responsibilities of each component more specific
  • Setup the main git repository alongside component repositories (still requires some work to have a CI/CD process to update the main repo when any of subcomponents gets an update)
  • Write some simple boilerplate code, currently for the SHADOW component (I think the server will be the most important part for now, GHOST will require a lot of tinkering, and CHARON is a bit useless without the functional part, as it’s only a TUI)
Attachment
0