README cooked

This commit is contained in:
Print3M
2025-11-02 10:32:32 +01:00
parent 44c611570d
commit e81fcfdbc0
6 changed files with 36 additions and 94 deletions
+30 -28
View File
@@ -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
![EPIC flow chart](_img/img-1.jpg)
// 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 youre 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 builtin 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
View File
@@ -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 youre 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`.
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 72 KiB

+1
View File
@@ -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 {
+5
View File
@@ -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)
-1
View File
@@ -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