mirror of
https://github.com/Print3M/epic
synced 2026-06-06 16:34:33 +00:00
README cooked
This commit is contained in:
@@ -1,28 +1,28 @@
|
||||
# EPIC
|
||||
|
||||
EPIC (*Extensible Position Independent Code*) ...
|
||||
EPIC (*Extensible Position Independent Code*) – PIC shellcode development and building framework designed for developer experience, predictability, and modularity. *Write code, EPIC will take care of the rest!*
|
||||
|
||||
// TODO: IMG ze schematem działania
|
||||

|
||||
|
||||
// TODO: Short description - what problem it solves.
|
||||
// TODO: Features
|
||||
|
||||
EPIC (Extensible Position Independent Code) – implant development and shellcode-building framework designed for developer experience, predictability, and modularity.
|
||||
|
||||
// TODO: A stable and convenient tool for building your project.
|
||||
|
||||
EPIC transforms complex shellcode engineering into a seamless process — building fully position-independent payloads with zero hidden magic, zero heap reliance, and maximal clarity. Whether you’re crafting stealth implants or high-level modular payloads, EPIC ensures your binaries remain elegant, efficient, and exact.
|
||||
EPIC is a robust single-executable toolkit for the complete PIC shellcode development workflow — offering quick project initialization, compilation, and payload linking with a rich set of built‑in features. It makes building stealth modular implants effortless.
|
||||
|
||||
- Built-in modularity – you choose what you want to include.
|
||||
- Built-in global context support – no memory permission changes!
|
||||
- Built-in dead-code elimination – the smallest payload on the market.
|
||||
- Predictable PIC generation — no implicit syscalls, no unexpected code.
|
||||
- Predictable PIC compilation — no implicit syscalls, no unexpected code.
|
||||
- Built-in minimal `libc` and `win32` written for PIC compatibility.
|
||||
- Built-in mixing C and C++ support.
|
||||
- Built-in C and C++ (and mixing) support.
|
||||
- More...
|
||||
|
||||
## Quick Start
|
||||
|
||||
Download EPIC from [release page](http://Test.pl). It's a single executable tool.
|
||||
|
||||
Requirements:
|
||||
|
||||
- Windows, Linux, or MacOS
|
||||
- Latest MinGW-w64 tool-chain (`gcc`, `ld`, `objcopy`)
|
||||
|
||||
```bash
|
||||
# 1. Create initial project structure
|
||||
mkdir project/
|
||||
@@ -45,7 +45,7 @@ That's it! At this point, you can take the generated `payload.bin` and inject it
|
||||
epic loader payload.bin -o output/
|
||||
```
|
||||
|
||||
The compiled loader.exe is ready to execute. If your payload works here, it will work everywhere.
|
||||
The compiled `loader.exe` is ready to execute. If your payload works here, it will work everywhere.
|
||||
|
||||
## Documentation
|
||||
|
||||
@@ -69,7 +69,8 @@ Compiles all source files from the project at `<path>` and saves object files to
|
||||
|
||||
Flags:
|
||||
|
||||
* `-o / --output <path>` [required] – Output path for compiled object files.
|
||||
- `-o / --output <path>` [required] – Output path for compiled object files.
|
||||
- `--strict` – Enable all compiler checks (`-Wall`, `-Wextra`, `-pedantic`).
|
||||
|
||||
#### `pic-link <path>`
|
||||
|
||||
@@ -81,8 +82,8 @@ Links core and selected modules from `<path>` into a standalone PIC payload. The
|
||||
|
||||
Flag:
|
||||
|
||||
* `-o / --output <path>` [required] – Output path for the payload.
|
||||
* `-m / --modules <modules>` – Comma-separated list of modules to link (named after their folders in `modules/`).
|
||||
- `-o / --output <path>` [required] – Output path for the payload.
|
||||
- `-m / --modules <modules>` – Comma-separated list of modules to link (named after their folders in `modules/`).
|
||||
|
||||
#### `loader <path>`
|
||||
|
||||
@@ -94,7 +95,7 @@ Injects your payload from `<path>` into a loader template and compiles it to a W
|
||||
|
||||
Flags:
|
||||
|
||||
* `-o / --output <path>` [required] – Output path for the loader executable.
|
||||
- `-o / --output <path>` [required] – Output path for the loader executable.
|
||||
|
||||
#### `monolith <path>`
|
||||
|
||||
@@ -104,18 +105,18 @@ Compiles your project into a standard non-PIC executable (called a "monolith" in
|
||||
|
||||
Flags:
|
||||
|
||||
* `-o / --output <path>` [required] - Output path for the monolith executable.
|
||||
- `-o / --output <path>` [required] - Output path for the monolith executable.
|
||||
|
||||
#### Global flags
|
||||
|
||||
The following optional flags can be used with any command:
|
||||
|
||||
* `--debug` – Enable verbose debug mode.
|
||||
* `--mingw-w64-gcc <path>` – Specify path to MinGW-w64 GCC.
|
||||
* `--mingw-w64-ld <path>` – Specify path to MinGW-w64 ld.
|
||||
* `--mingw-w64-objcopy <path>` – Specify path to MinGW-w64 objcopy.
|
||||
* `--no-banner` - Disable EPIC banner.
|
||||
* `--no-color` - Disable colored output.
|
||||
- `--debug` – Enable verbose debug mode.
|
||||
- `--mingw-w64-gcc <path>` – Specify path to MinGW-w64 GCC.
|
||||
- `--mingw-w64-ld <path>` – Specify path to MinGW-w64 ld.
|
||||
- `--mingw-w64-objcopy <path>` – Specify path to MinGW-w64 objcopy.
|
||||
- `--no-banner` - Disable EPIC banner.
|
||||
- `--no-color` - Disable colored output.
|
||||
|
||||
### EPIC Coding Guide
|
||||
|
||||
@@ -295,8 +296,9 @@ If nothing helps, you are cooked.
|
||||
|
||||
#### EPIC Limitations
|
||||
|
||||
* Supported architecture: x86-64 only
|
||||
* Supported languages: C and C++
|
||||
- Supported target OS: Windows
|
||||
- Supported architecture: x86-64
|
||||
- Supported languages: C and C++
|
||||
|
||||
#### Module function doesn't execute
|
||||
|
||||
@@ -366,5 +368,5 @@ objdump -D -b binary -m i386:x86-64 -M intel payload.bin
|
||||
|
||||
## Credits
|
||||
|
||||
* c-to-shellcode.py
|
||||
* Stardust
|
||||
- [Stardust by 5pider](https://github.com/Cracked5pider/Stardust) for inspiration.
|
||||
- - [c-to-shellcode.py](https://github.com/Print3M/c-to-shellcode) – EPIC is basically a follow-up to my previous PoC.
|
||||
|
||||
-65
@@ -1,65 +0,0 @@
|
||||
# EPIC — Extensible Position Independent Code Framework
|
||||
|
||||
EPIC (Extensible Position Independent Code) – implant development and shellcode-building framework designed for developer experience, predictability, and modularity.
|
||||
|
||||
EPIC transforms complex shellcode engineering into a seamless process — building fully position-independent payloads with zero hidden magic, zero heap reliance, and maximal clarity. Whether you’re crafting stealth implants or high-level modular payloads, EPIC ensures your binaries remain elegant, efficient, and exact.
|
||||
|
||||
- Built-in modularity – you choose what you want to include.
|
||||
- Built-in global context support – no memory permission changes!
|
||||
- Built-in dead-code elimination – the smallest payload on the market.
|
||||
- Predictable PIC generation — no implicit syscalls, no unexpected code.
|
||||
- Built-in minimal `libc` and `win32` written for PIC compatibility.
|
||||
- Built-in mixing C and C++ support.
|
||||
- More...
|
||||
|
||||
// - A stable and convenient tool for building your project.
|
||||
TODO: wygodny i przewidywalny CI/CD
|
||||
|
||||
## Interesting Observations
|
||||
|
||||
I tried two approaches to linking functions:
|
||||
|
||||
1. With `__attribute__((section(".func")))` on the every function in the code and the `*(.func)` in the linker script.
|
||||
|
||||
2. With no attribute in code but with `-ffunction-sections` parameter during compilation and `--gc-sections` during linking.
|
||||
|
||||
The first option creates smaller paylaod but doesn't provide dead function elimination.
|
||||
|
||||
The second option creates a little bit larger payload but provides dead function elimination.
|
||||
|
||||
Why does the second option create a little bit larger payload? I'm not sure but I have a feeling. In the second approach each function is placed in a separate section. This is the outcome of using `-ffunction-sections` parameter. Each section typically requires some alignment. If you have many small functions, you accumulate significant padding after each one.
|
||||
|
||||
## Disassembly payload.bin
|
||||
|
||||
```bash
|
||||
objdump -D -b binary -m i386:x86-64 -M intel payload.bin
|
||||
```
|
||||
|
||||
## Linker map
|
||||
|
||||
It's possible to generate map of linked sections. Great tool for deep inspection of linker's work. Use `-Map=linker.map` parameter. This file shows which sections (section == function when used with `-ffunction-sections`) are discarded and which are linked into the final payload. It shows the layout of linked sections and their size. Great tool for debugging.
|
||||
|
||||
## Dead code elimination doesn't work
|
||||
|
||||
Dead code elimination doesn't work for linker output "binary".
|
||||
|
||||
To hack this I use MinGW-w64 toolchain `gcc` with custom linker script (`ld`) to PE and then extracting PIC `.text` section using `objdump` to final `payload.bin` output. It works like a charm. This way the final payload is smaller then ever.
|
||||
|
||||
## Stack alignment for Win API
|
||||
|
||||
Mingw-w64 automatically handles stack alignment when function is defined with `WINAPI` attribute.
|
||||
|
||||
## `main()` and `__main()` functions
|
||||
|
||||
If you implement `main()` function no matter how hard I tried it's always treated special by GCC compiler. No matter how many compiler flags, function attributes and linker scripting I used there's always generated unnecessary call to `__main()` at the beginning of `main()`. It means you need to implement this stupid `__main()` somehow, otherwise there's an linker error. The reason for this is behaviour is unknonw and I found no way to disable it.
|
||||
|
||||
Solution to this problem is using `main()` as entry point and implement dummy empty `__main() {}` function. It works, but honestly I wanted my code to be as clean as possible with no dummy functions!
|
||||
|
||||
Second solution is not to use `main()` at all. Create a not-main function (e.g. `__main_pic`) and use it as a entry point. It works this way.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
1. Clean output/ directory.
|
||||
2. Test monolith version (more reliable).
|
||||
3. Check if you follow EPIC Guidebook.
|
||||
4. Run `--debug`.
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 72 KiB |
@@ -54,6 +54,7 @@ func init() {
|
||||
rootCmd.AddCommand(compileCmd)
|
||||
|
||||
compileCmd.Flags().StringVarP(&pc.OutputPath, "output", "o", "", "output path (required)")
|
||||
compileCmd.Flags().BoolVar(&pc.Strict, "strict", false, "enable all compiler checks (-Wall, -Wextra, -pedantic)")
|
||||
|
||||
// Mark required flags
|
||||
if err := compileCmd.MarkFlagRequired("output"); err != nil {
|
||||
|
||||
@@ -12,6 +12,7 @@ import (
|
||||
type PICCompiler struct {
|
||||
ProjectPath string
|
||||
OutputPath string
|
||||
Strict bool
|
||||
}
|
||||
|
||||
func (pc *PICCompiler) ValidateProjectPath() error {
|
||||
@@ -142,6 +143,10 @@ func (pc *PICCompiler) compileProjectDirectory(targetDir string) {
|
||||
params = append(params, "-std=c17")
|
||||
}
|
||||
|
||||
if pc.Strict {
|
||||
params = append(params, "-Wall", "-Wextra", "-pedantic")
|
||||
}
|
||||
|
||||
output := utils.MingwGcc(params...)
|
||||
if len(output) > 0 {
|
||||
fmt.Println(output)
|
||||
|
||||
@@ -6,7 +6,6 @@ import (
|
||||
)
|
||||
|
||||
// TODO:
|
||||
// - Add cool README
|
||||
// - Automatically obtain address of start and end of payload (in memory)
|
||||
// - Implement custom symbols for compilation
|
||||
|
||||
|
||||
Reference in New Issue
Block a user