Initial commit!

This commit is contained in:
hunterino-sec
2026-07-19 04:43:07 -04:00
parent 6ad57783ee
commit e25b2e2a78
24 changed files with 1037 additions and 0 deletions
+38
View File
@@ -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"
)
+25
View File
@@ -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
+59
View File
@@ -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"
);
}
+18
View File
@@ -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 = .;
}
+20
View File
@@ -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);
}