Public release 0.1

This commit is contained in:
Adam Macdonald
2025-01-31 18:28:43 +00:00
commit 984b49d683
19 changed files with 1538 additions and 0 deletions

View File

@@ -0,0 +1,39 @@
set(
SHELLCODE_INCLUDE_DIR
"${CMAKE_CURRENT_BINARY_DIR}/shellcode/"
PARENT_SCOPE
)
set(
SHELLCODE_OUT_DIR
${CMAKE_CURRENT_BINARY_DIR}/shellcode
)
add_custom_command(
OUTPUT ${SHELLCODE_OUT_DIR}/dlopen_shellcode.o
COMMAND as --64 -o ${SHELLCODE_OUT_DIR}/dlopen_shellcode.o ./dlopen_shellcode.s
DEPENDS ./dlopen_shellcode.s
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
COMMENT "Assemble dlopen() shellcode (x86_64)"
)
add_custom_command(
OUTPUT ${SHELLCODE_OUT_DIR}/dlopen_shellcode.bin
COMMAND objcopy -j .text -O binary ${SHELLCODE_OUT_DIR}/dlopen_shellcode.o ${SHELLCODE_OUT_DIR}/dlopen_shellcode.bin
DEPENDS ${SHELLCODE_OUT_DIR}/dlopen_shellcode.o
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
COMMENT "Copy dlopen() shellcode to binary file (x86_64)"
)
add_custom_command(
OUTPUT ${SHELLCODE_OUT_DIR}/dlopen_shellcode.hpp
COMMAND python bin2cppheader.py ${SHELLCODE_OUT_DIR}/dlopen_shellcode.bin
DEPENDS ${SHELLCODE_OUT_DIR}/dlopen_shellcode.bin
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
COMMENT "Convert dlopen() shellcode binary to C++ header (x86_64)"
)
add_custom_target(
shellcode
DEPENDS ${SHELLCODE_OUT_DIR}/dlopen_shellcode.hpp
)

View File

@@ -0,0 +1,71 @@
# bin2cppheader.py
# Convert a binary file to its static std::array representation as an
# includable header file in your C++ project.
# Author: Adam Macdonald [https://github.com/twokilohertz]
usage = "Usage: python bin2cppheader.py in_file [out_file]"
import sys
import mmap
from pathlib import Path
# Helper function for printing to stderr
def eprint(*args, **kwargs):
return print(*args, file=sys.stderr, **kwargs)
def read_bin(bin_path):
ret_buf = []
with open(bin_path, "rb") as f:
with mmap.mmap(f.fileno(), length=0, prot=mmap.PROT_READ) as mm:
ret_buf = mm.read()
return ret_buf
return ret_buf
def bin_to_header(data, symbol_name, namespace = "bin"):
ret_str = "#pragma once\n#include <array>\n#include <cstdint>\nnamespace " + namespace + " { constexpr const std::array<std::uint8_t, "+ str(len(data)) + "> " + symbol_name + " {"
for b in data:
ret_str += "{:#04x}".format(b) + ", "
ret_str = ret_str[:-2]
ret_str += "};}"
return ret_str
if __name__ == "__main__":
if len(sys.argv) < 2:
eprint(usage)
exit(1)
# Some validation on the input path
in_path = Path(sys.argv[1])
if not in_path.exists():
eprint("input path does not exist")
exit(1)
if not in_path.is_file():
eprint("input path is not a file")
exit(1)
# Read data & convert to a string of valid C++
data = read_bin(in_path)
header_str = bin_to_header(data, in_path.stem)
out_path = Path()
if len(sys.argv) == 3:
out_path = Path(sys.argv[2])
if not out_path.exists():
eprint("output path does not exist")
exit(1)
if not out_path.is_dir():
eprint("output path is not a directory")
exit(1)
else:
out_path = in_path.parents[0] / f"{in_path.stem}.hpp"
with open(out_path, "w") as f:
f.write(header_str)
exit(0)

View File

@@ -0,0 +1,32 @@
# dlopen() shellcode
# - Calls dlopen() on our library filepath
# - Signature: void shellcode(void* dlopen_fn_ptr, char* lib_path_sz);
# dlopen_fn_ptr - RDI
# lib_path_sz - RSI
.org 0x0
.global _start
.section .text
_start:
movq %rdi, %r11 # Temporarily remove dlopen_fn_ptr
# Set up dlopen() call
movq %rsi, %rdi # Move path string ready for dlopen()
movq $2, %rsi # RTLD_NOW
call *%r11
# Check if dlopen() returned NULL
cmpq $0, %rax
jz set_sigusr2
# Prepare kill() syscall
set_sigusr1:
movq $10, %rsi # SIGUSR1 = 10
jmp signal_injector
set_sigusr2:
movq $12, %rsi # SIGUSR2 = 12
signal_injector:
movq $62, %rax # kill() syscall
movq $0, %rdi # PID, dummy value - the kill() syscall
syscall # is replaced with munmap() anyway