mirror of
https://github.com/Whispergate/JanusLoader
synced 2026-07-22 11:23:12 +00:00
Initial commit!
This commit is contained in:
@@ -0,0 +1,38 @@
|
||||
cmake_minimum_required(VERSION 3.20)
|
||||
project(JanusPayload C CXX ASM)
|
||||
|
||||
# Requires a RISC-V cross-compiler:
|
||||
# apt install gcc-riscv64-linux-gnu g++-riscv64-linux-gnu
|
||||
# Or pass -DCMAKE_TOOLCHAIN_FILE=../cmake/riscv64.cmake
|
||||
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
|
||||
add_executable(payload
|
||||
crt0.S
|
||||
main.cpp
|
||||
)
|
||||
|
||||
target_compile_options(payload PRIVATE
|
||||
-nostdlib
|
||||
-fno-exceptions
|
||||
-fno-rtti
|
||||
-fPIC
|
||||
-Os
|
||||
-march=rv64imac
|
||||
-mabi=lp64
|
||||
)
|
||||
|
||||
target_link_options(payload PRIVATE
|
||||
-nostdlib
|
||||
-static
|
||||
-fuse-ld=lld # requires: sudo apt install lld
|
||||
-T ${CMAKE_CURRENT_SOURCE_DIR}/link.ld
|
||||
)
|
||||
|
||||
# After build, generate flat binary + run embed_payload.py
|
||||
add_custom_command(TARGET payload POST_BUILD
|
||||
COMMAND python3 ${CMAKE_SOURCE_DIR}/../tools/embed_payload.py
|
||||
$<TARGET_FILE:payload>
|
||||
${CMAKE_SOURCE_DIR}/../src/loader/payload_blob.cpp
|
||||
COMMENT "Embedding payload into loader"
|
||||
)
|
||||
@@ -0,0 +1,25 @@
|
||||
.section .text
|
||||
.global _start
|
||||
_start:
|
||||
# Set up global pointer (linker relaxation)
|
||||
.option push
|
||||
.option norelax
|
||||
la gp, __global_pointer$
|
||||
.option pop
|
||||
|
||||
# Zero .bss
|
||||
la a0, __bss_start
|
||||
la a1, __bss_end
|
||||
.Lbss_loop:
|
||||
bge a0, a1, .Lbss_done
|
||||
sb zero, 0(a0)
|
||||
addi a0, a0, 1
|
||||
j .Lbss_loop
|
||||
.Lbss_done:
|
||||
|
||||
# sp already set by loader (top of stack region)
|
||||
call janus_main
|
||||
|
||||
li a7, 3 # ECALL_EXIT
|
||||
li a0, 0
|
||||
ecall
|
||||
@@ -0,0 +1,59 @@
|
||||
#pragma once
|
||||
typedef unsigned long long uintptr_t;
|
||||
typedef unsigned long long uint64_t;
|
||||
|
||||
// Inline wrappers for Janus ECALLs from payload code.
|
||||
// These must stay header-only so the payload has no external deps.
|
||||
|
||||
static inline void* janus_get_peb() {
|
||||
void* r;
|
||||
asm volatile (
|
||||
"li a7, 0\n"
|
||||
"ecall\n"
|
||||
"mv %0, a0\n"
|
||||
: "=r"(r) :: "a7", "a0", "memory"
|
||||
);
|
||||
return r;
|
||||
}
|
||||
|
||||
// fn: function pointer obtained via janus_resolve
|
||||
// args: array of uintptr_t on the stack, argc: element count
|
||||
static inline uintptr_t janus_host_call(void* fn, uintptr_t* args, int argc) {
|
||||
uintptr_t r;
|
||||
asm volatile (
|
||||
"li a7, 1\n"
|
||||
"mv a0, %1\n"
|
||||
"mv a1, %2\n"
|
||||
"mv a2, %3\n"
|
||||
"ecall\n"
|
||||
"mv %0, a0\n"
|
||||
: "=r"(r)
|
||||
: "r"(fn), "r"(args), "r"((uintptr_t)argc)
|
||||
: "a7", "a0", "a1", "a2", "memory"
|
||||
);
|
||||
return r;
|
||||
}
|
||||
|
||||
static inline void* janus_resolve(const char* mod, const char* sym) {
|
||||
void* r;
|
||||
asm volatile (
|
||||
"li a7, 2\n"
|
||||
"mv a0, %1\n"
|
||||
"mv a1, %2\n"
|
||||
"ecall\n"
|
||||
"mv %0, a0\n"
|
||||
: "=r"(r)
|
||||
: "r"(mod), "r"(sym)
|
||||
: "a7", "a0", "a1", "memory"
|
||||
);
|
||||
return r;
|
||||
}
|
||||
|
||||
static inline void janus_exit(int code) {
|
||||
asm volatile (
|
||||
"li a7, 3\n"
|
||||
"mv a0, %0\n"
|
||||
"ecall\n"
|
||||
:: "r"((uintptr_t)code) : "a7", "a0", "memory"
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
OUTPUT_ARCH(riscv)
|
||||
ENTRY(_start)
|
||||
|
||||
SECTIONS {
|
||||
. = 0x0;
|
||||
__base = .;
|
||||
|
||||
.text : { *(.text .text.*) }
|
||||
.rodata : { *(.rodata .rodata.*) }
|
||||
|
||||
. = ALIGN(8);
|
||||
.data : { *(.data .data.*) }
|
||||
|
||||
. = ALIGN(8);
|
||||
__bss_start = .;
|
||||
.bss : { *(.bss .bss.*) *(COMMON) }
|
||||
__bss_end = .;
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
#include "ecall.hpp"
|
||||
|
||||
// Example payload: resolve and call MessageBoxA via the VM's syscall layer.
|
||||
// On Windows: a dialog box pops. On Linux test (stub syscalls): a0 returns 0.
|
||||
|
||||
extern "C" void janus_main() {
|
||||
void* msgbox = janus_resolve("user32.dll", "MessageBoxA");
|
||||
if (!msgbox) return;
|
||||
|
||||
const char* text = "JanusLoader: RISC-V VM shellcode running";
|
||||
const char* caption = "JanusLoader";
|
||||
|
||||
uintptr_t args[4] = {
|
||||
0, // hWnd = NULL
|
||||
(uintptr_t)text,
|
||||
(uintptr_t)caption,
|
||||
0, // MB_OK
|
||||
};
|
||||
janus_host_call(msgbox, args, 4);
|
||||
}
|
||||
Reference in New Issue
Block a user