Injection

Version

Grave ships with two injectors per platform: a friendly one for everyday use, and a raw one for users who want stealth.

Windows

On Windows, Grave is distributed as two binaries that load the same payload in different ways. No administrator permissions are required.

Grave.exe

The user-friendly path. Run the executable and it reflectively loads the client into a target Minecraft process, with no extra files and no setup. This is what almost everyone should use.

Grave.bin

For users who want to drive injection themselves. The .bin file is position-independent - raw bytes that execute correctly at any address. There is no PE header and no entry point in the usual sense. You read it, allocate executable memory in a host process, copy it in, and jump to its first byte.

The minimal example below shows the technique. It spawns a suspended copy of itself as a sacrificial host, writes the shellcode in, flips the page to RX, and starts a remote thread at the base of the allocation:

#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <cstdlib>

int main() {
    // 1. Read the position-independent shellcode.
    HANDLE f = CreateFileA("Grave.bin", GENERIC_READ, FILE_SHARE_READ,
                           nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr);
    DWORD size = GetFileSize(f, nullptr);
    auto* bin = (BYTE*)malloc(size);
    DWORD read = 0;
    ReadFile(f, bin, size, &read, nullptr);
    CloseHandle(f);

    // 2. Spawn a suspended process to host the payload.
    char self[MAX_PATH];
    GetModuleFileNameA(nullptr, self, sizeof(self));
    STARTUPINFOA si{ sizeof(si) };
    PROCESS_INFORMATION pi{};
    CreateProcessA(self, nullptr, nullptr, nullptr, FALSE,
                   CREATE_SUSPENDED, nullptr, nullptr, &si, &pi);

    // 3. Allocate, write, and flip to executable in the host.
    void* base = VirtualAllocEx(pi.hProcess, nullptr, size,
                                MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
    WriteProcessMemory(pi.hProcess, base, bin, size, nullptr);
    DWORD old;
    VirtualProtectEx(pi.hProcess, base, size, PAGE_EXECUTE_READWRITE, &old);
    free(bin);

    // 4. Run from the first byte and wait. The shellcode cleans up after itself.
    HANDLE th = CreateRemoteThread(pi.hProcess, nullptr, 0,
                                   (LPTHREAD_START_ROUTINE)base, nullptr, 0, nullptr);
    WaitForSingleObject(th, INFINITE);

    CloseHandle(th); CloseHandle(pi.hThread); CloseHandle(pi.hProcess);
    return 0;
}

The host process is just somewhere for the bytes to run, it does not need to be Minecraft. Once executing, the shellcode locates the Minecraft process on its own and performs injection from there. By the time WaitForSingleObject returns, the shellcode has zeroed and freed every region it used, including the allocation it ran from.

Once you're injected, browse modules in the sidebar to see what's available.