Inspiration

Security monitoring tools and cyber ranges need believable user activity, but most traffic generators leave obvious fingerprints: a cmd.exe or script interpreter as the parent of every app, and metronome-regular delays. We wanted an agent whose Sysmon and Windows Event Log telemetry looks like a person sat down and did some work.

What it does

Synthetic Colleague runs a ~15-minute "day at the desk" on a Windows VM. Each run performs complete, end-to-end tasks:

  • Documents: opens OpenOffice Writer, types a multi-paragraph document with pauses, occasional typos and backspaces, saves it under a plausible filename, and closes it.
  • Spreadsheets: opens Calc, builds a small table with per-row formulas and a SUM footer, revises a cell, bolds the header, saves as .ods. The saved file is read back and every cell and formula is checked.
  • Web: opens Chrome, visits several sites, scrolls in bursts with reading pauses, follows a link and comes back, uses find-on-page, saves a page, and closes the browser.

A sequencer shuffles the block order every run, picks a random persona (focused, casual or distracted) that sets the pace, inserts idle gaps and an away-from-keyboard pause, and lands the run on the time budget. No two runs look the same.

How we built it

  • Authentic process chains. Apps are launched through the Windows Run dialog (Win+R) driven by SendInput, so the parent in Sysmon is explorer.exe. We tested os.startfile first, saw python.exe as the parent, and rejected it. The agent itself starts from a desktop shortcut running pythonw.exe, so its own parent is explorer.exe too. No subprocess, Start-Process or Task Scheduler anywhere.
  • Human timing. Every human-facing delay is sampled from a log-normal distribution with a heavy right tail. Idle gaps are heavy-tailed, and personas scale the pace per run.
  • Cold-launch discipline. Each app is fully closed before it is launched again, so every launch produces a fresh explorer.exe -> app process-create event.
  • Lean by design. Pure Python standard library, no third-party packages, and no LLM in the loop, so the agent adds almost nothing to the VM's CPU and RAM graph.
  • Safety net. A STOP file halts the run within about a second, known dialogs such as OpenOffice Document Recovery are handled automatically, and a failed block never crashes the run.
  • Self-validation. validate.ps1 reads the Sysmon log and prints a PASS/FAIL checklist: parent processes, no script or shell parents, cold launches, apps closed at end, run length, timing spread and saved documents. make_histogram.py produces a timing report from the run's delays.

Challenges we ran into

  • Getting the parent process right. Launch methods that look natural in code (os.startfile) produced the wrong parent in Sysmon, which pushed us to the Run dialog approach.
  • Cold-launch behaviour: launching an app that is already open attaches to the existing instance and logs no new process event, so every block closes its app cleanly first.
  • OpenOffice quirks: Document Recovery dialogs after a killed run, Calc AutoInput silently completing typed text, and slow cold starts.
  • The mock browsing sites had expired certificates for part of the build, and deep links on them sometimes returned 404, so link-click recovery had to behave like a person pressing Back.

Accomplishments that we're proud of

  • Validated runs where every Chrome and Writer launch is explorer.exe-parented and the validator reports PASS.
  • Runs that land on 900 seconds with all three task types completed and verified on disk.
  • An agent whose own overhead is negligible, with the only load on the Proxmox graph coming from the real applications.

What we learned

Process lineage and timing shape are what telemetry actually shows, so effort goes there rather than into per-keystroke polish. Validating against the real Sysmon log, not our own logs, caught problems that unit tests never would.

What's next

Overlapping apps with Alt+Tab, email and download tasks, mixed launch methods (Start search, taskbar), and richer site interaction.

Built With

  • apache-openoffice
  • chrome
  • ctypes
  • powershell
  • proxmox
  • python
  • sysmon
  • windows-event-log
  • windows-sendinput
Share this project:

Updates

Submission history