Release v1.1.0: Process Injection & Architecture Hardening

- Implement complete cross-process injection engine via snd_inj_ctx_t
- Track explicit remote_entry_point for safe thread hijacking and PE execution
- Refactor standalone syscall resolvers into a unified pipeline (scan/sort)
- Perfect status code system by purging generic fallbacks in favor of highly-specific, domain-aware error codes
- Fix minor pointer validation and parsing bugs in the reflective loader
This commit is contained in:
sibouzitoun
2026-06-28 14:14:54 +01:00
parent afffc17dfe
commit aea2eb6cfb
180 changed files with 8387 additions and 3659 deletions
+1
View File
@@ -2,6 +2,7 @@
#define SINDRI_H
#include <sindri/common.h>
#include <sindri/injection.h>
#include <sindri/loaders.h>
#include <sindri/parsers.h>
#include <sindri/primitives.h>
+4 -1
View File
@@ -2,9 +2,12 @@
#define SND_COMMON_H
#include <sindri/common/buffer.h>
#include <sindri/common/debug.h>
#include <sindri/common/disk.h>
#include <sindri/common/hash.h>
#include <sindri/common/helpers.h>
#include <sindri/common/macros.h>
#include <sindri/common/memory.h>
#include <sindri/common/status.h>
#include <sindri/common/string.h>
#endif
+12 -18
View File
@@ -1,7 +1,9 @@
#ifndef SND_COMMON_BUFFER_H
#define SND_COMMON_BUFFER_H
#include <sindri/common/helpers.h>
#include <sindri/common/macros.h>
#include <sindri/common/memory.h>
#include <stddef.h>
#include <windows.h>
SND_BEGIN_EXTERN_C
@@ -11,7 +13,6 @@ typedef struct snd_buffer_s snd_buffer_t;
/**
* @brief Function signature for the custom buffer deallocator callback.
* @param buf Pointer to the buffer structure being freed.
*/
typedef void (*snd_free_cb)(snd_buffer_t *buf);
@@ -19,8 +20,8 @@ typedef void (*snd_free_cb)(snd_buffer_t *buf);
* @brief Represents a tracked, bounds-checked memory buffer.
*/
struct snd_buffer_s {
LPVOID data;
SIZE_T size;
void *data;
size_t size;
snd_free_cb free_routine;
};
@@ -31,32 +32,25 @@ struct snd_buffer_s {
* @param size Size of the memory block.
* @param free_routine Optional callback used to safely deallocate this memory.
*/
void snd_buffer_init(snd_buffer_t *buf, LPVOID data, SIZE_T size, snd_free_cb free_routine);
void snd_buffer_init(snd_buffer_t *buf, void *data, size_t size, snd_free_cb free_routine);
/**
* @brief Frees a tracked buffer using its assigned cleanup routine and zeroes
* the structure.
* @param buf Pointer to the buffer structure to free.
* @brief Frees a tracked buffer using its assigned cleanup routine and zeroes the structure.
*/
void snd_buffer_free(snd_buffer_t *buf);
/**
* @brief Checks if a given offset and size are within the bounds of a buffer.
*
* @param buf The buffer context to check against.
* @param offset The offset from the start of the buffer.
* @param size The size of the region to check.
* @return TRUE if within bounds, FALSE otherwise.
* @return 1 if within bounds, 0 otherwise.
*/
SND_FORCE_INLINE BOOL snd_buffer_bounds_check(const snd_buffer_t *buf, SIZE_T offset, SIZE_T size) {
SND_FORCE_INLINE int snd_buffer_bounds_check(const snd_buffer_t *buf, size_t offset, size_t size) {
if (buf == NULL || buf->data == NULL || buf->size == 0)
return FALSE;
return snd_bounds_check(buf->size, offset, size);
return 0;
return snd_memory_bounds_check(buf->size, offset, size);
}
/**
* @brief Default routine for buffers allocated via HeapAlloc on the process
* heap.
* @brief Default routine for buffers allocated via HeapAlloc on the process heap.
*/
SND_FORCE_INLINE void snd_buffer_free_heap(snd_buffer_t *buf) {
if (buf && buf->data) {
+91
View File
@@ -0,0 +1,91 @@
#ifndef SND_COMMON_DEBUG_H
#define SND_COMMON_DEBUG_H
#include <sindri/common/macros.h>
#include <stdint.h>
/**
* @def SND_DEBUG
* @brief Global toggle for debug output.
*/
#ifndef SND_DEBUG
#define SND_DEBUG 0
#endif
/* * Macro block to strip diagnostic error string literals out of the .rdata
* section entirely when compiling for the production/SILENT tier.
*/
#if SND_DEBUG
#define SND_FALLBACK_STR(debug_str) debug_str
#else
#define SND_FALLBACK_STR(debug_str) ""
#endif
/**
* @def SND_USE_PRINTF
* @brief Toggles debug output destination (1 for stdout, 0 for OutputDebugStringA).
*/
#ifndef SND_USE_PRINTF
#define SND_USE_PRINTF 0
#endif
SND_BEGIN_EXTERN_C
#if SND_DEBUG
#include <stdarg.h>
#include <stdio.h>
#include <windows.h>
#if SND_USE_PRINTF
#define SND_FDEBUG_PRINT(stream, fmt, ...) \
do { \
FILE *_s = (stream) ? (FILE *)(stream) : stdout; \
fprintf(_s, fmt, ##__VA_ARGS__); \
fflush(_s); \
} while (0)
#define SND_DEBUG_PRINT(fmt, ...) SND_FDEBUG_PRINT(stdout, fmt, ##__VA_ARGS__)
#else
#define SND_DEBUG_MAX_LEN 1024
static inline void debug_print(const char *fmt, ...) {
char buf[SND_DEBUG_MAX_LEN];
va_list args;
va_start(args, fmt);
vsnprintf(buf, sizeof(buf), fmt, args);
va_end(args);
OutputDebugStringA(buf);
}
#define SND_FDEBUG_PRINT(stream, fmt, ...) debug_print(fmt, ##__VA_ARGS__)
#define SND_DEBUG_PRINT(fmt, ...) debug_print(fmt, ##__VA_ARGS__)
#endif // SND_USE_PRINTF
#else
#define SND_FDEBUG_PRINT(stream, fmt, ...) \
do { \
(void)(stream); \
} while (0)
#define SND_DEBUG_PRINT(fmt, ...) \
do { \
(void)0; \
} while (0)
#endif // SND_DEBUG
/**
* @brief Prints a combined hexadecimal and ASCII view of a byte buffer.
*/
void snd_dump_hex(const void *dat, size_t len_dat, uintptr_t base_off);
SND_END_EXTERN_C
#endif // SND_COMMON_DEBUG_H
+2 -2
View File
@@ -2,7 +2,7 @@
#define SND_COMMON_DISK_H
#include <sindri/common/buffer.h>
#include <sindri/common/helpers.h>
#include <sindri/common/macros.h>
#include <sindri/common/status.h>
SND_BEGIN_EXTERN_C
@@ -16,7 +16,7 @@ SND_BEGIN_EXTERN_C
* @note The caller is responsible for freeing the buffer using
* snd_buffer_free(out_buf).
*/
snd_status_t snd_buffer_load_from_disk(const char *path, snd_buffer_t *out_buf);
snd_status_t snd_disk_buffer_load(const char *path, snd_buffer_t *out_buf);
SND_END_EXTERN_C
+5 -5
View File
@@ -1,8 +1,8 @@
#ifndef SND_COMMON_HASH_H
#define SND_COMMON_HASH_H
#include <sindri/common/helpers.h>
#include <windows.h>
#include <sindri/common/macros.h>
#include <stdint.h>
SND_BEGIN_EXTERN_C
@@ -11,21 +11,21 @@ SND_BEGIN_EXTERN_C
* (Case-Sensitive).
* @note Use this for API names from the Export Directory.
*/
DWORD snd_hash(const char *str);
uint32_t snd_hash(const char *str);
/**
* @brief Computes the configured hash of a standard ASCII string, converting to
* lowercase.
* @note Use this for DLL names found in the PE Import Directory.
*/
DWORD snd_hash_lower(const char *str);
uint32_t snd_hash_lower(const char *str);
/**
* @brief Computes the configured hash of a wide string, converting to lowercase
* (Case-Insensitive).
* @note Use this for finding DLL module names in the PEB.
*/
DWORD snd_hash_wide_lower(const wchar_t *str);
uint32_t snd_hash_wide_lower(const wchar_t *str);
SND_END_EXTERN_C
-305
View File
@@ -1,305 +0,0 @@
#ifndef SND_COMMON_HELPERS_H
#define SND_COMMON_HELPERS_H
#include <stddef.h>
#include <windows.h>
/**
* @def SND_DEBUG
* @brief Global toggle for debug output.
* Set to 1 to enable logging macros, or 0 to compile them out entirely for
* Release builds.
*/
#ifndef SND_DEBUG
#define SND_DEBUG 0
#endif
/**
* @def SND_USE_PRINTF
* @brief Toggles the debug output destination.
* If 1, debug macros route to standard stdout via `printf`.
* If 0, debug macros route to the Windows kernel debugger via
* `OutputDebugStringA`.
*/
#ifndef SND_USE_PRINTF
#define SND_USE_PRINTF 0
#endif
/**
* @def SND_BEGIN_EXTERN_C
* @brief Opens an `extern "C"` linkage block for C++ compatibility.
*/
/**
* @def SND_END_EXTERN_C
* @brief Closes an `extern "C"` linkage block.
*/
#ifdef __cplusplus
#define SND_BEGIN_EXTERN_C extern "C" {
#define SND_END_EXTERN_C }
#else
#define SND_BEGIN_EXTERN_C
#define SND_END_EXTERN_C
#endif
SND_BEGIN_EXTERN_C
/**
* @def SND_FORCE_INLINE
* @brief Compiler-agnostic macro to force function inlining.
* Useful for embedding bounds checks and offset calculations directly into the
* caller's assembly.
*/
#if defined(_MSC_VER)
#define SND_FORCE_INLINE static __forceinline
#else
#define SND_FORCE_INLINE static inline __attribute__((always_inline))
#endif
#if SND_DEBUG
#include <stdarg.h>
#include <stdio.h>
#if SND_USE_PRINTF
/**
* @def SND_FDEBUG_PRINT
* @brief Formats and prints a debug message to a specific file stream (e.g.,
* stderr, stdout).
*/
#define SND_FDEBUG_PRINT(stream, fmt, ...) \
do { \
FILE *_s = (stream) ? (FILE *)(stream) : stdout; \
fprintf(_s, fmt, ##__VA_ARGS__); \
fflush(_s); \
} while (0)
/**
* @def SND_DEBUG_PRINT
* @brief Formats and prints a debug message to standard output.
*/
#define SND_DEBUG_PRINT(fmt, ...) SND_FDEBUG_PRINT(stdout, fmt, ##__VA_ARGS__)
#else
/**
* @def SND_DEBUG_MAX_LEN
* @brief Maximum string length for the internal debug formatting buffer.
*/
#define SND_DEBUG_MAX_LEN 1024
/**
* @brief Internal variadic wrapper to format strings for the Windows Debugger.
* @note This is completely stripped out of Release builds.
*/
static inline void snd_debug_print_internal(const char *fmt, ...) {
char buf[SND_DEBUG_MAX_LEN];
va_list args;
va_start(args, fmt);
// Safely format the string into our local buffer (requires CRT in debug mode)
vsnprintf(buf, sizeof(buf), fmt, args);
va_end(args);
// Send the formatted string to the Windows kernel debug buffer
OutputDebugStringA(buf);
}
// Map both macros to the new OutputDebugString wrapper
#define SND_FDEBUG_PRINT(stream, fmt, ...) snd_debug_print_internal(fmt, ##__VA_ARGS__)
#define SND_DEBUG_PRINT(fmt, ...) snd_debug_print_internal(fmt, ##__VA_ARGS__)
#endif // SND_USE_PRINTF
#else
// When SND_DEBUG is 0, these macros compile to empty no-ops to strip strings
// from the binary.
#define SND_FDEBUG_PRINT(stream, fmt, ...) \
do { \
(void)(stream); \
} while (0)
#define SND_DEBUG_PRINT(fmt, ...) \
do { \
(void)0; \
} while (0)
#endif // SND_DEBUG
/**
* @def SND_PTR_ADD
* @brief Safely adds a byte offset to a base pointer by casting to a BYTE
* pointer first.
*/
#define SND_PTR_ADD(base, offset) ((BYTE *)(base) + (offset))
/**
* @brief Prints a combined hexadecimal and ASCII view of a byte buffer.
* @param dat Pointer to the first byte to print.
* @param len_dat Number of bytes to dump from @p dat.
* @param base_off Base address used to compute printed relative offsets.
*
* @note Output is gated by `SND_DEBUG` through debug print macros.
*/
void snd_dump_hex(const void *dat, size_t len_dat, ULONG_PTR base_off);
/**
* @brief Checks if a given size and offset are within the bounds of a total
* size.
* @param total_size The total size of the buffer.
* @param offset The offset from the start.
* @param size The size of the region to check.
* @return TRUE if within bounds, FALSE otherwise.
*/
SND_FORCE_INLINE BOOL snd_bounds_check(SIZE_T total_size, SIZE_T offset, SIZE_T size) {
if (offset > total_size)
return FALSE;
if (size > total_size - offset)
return FALSE;
return TRUE;
}
/**
* @brief Checks if a pointer and size are within the bounds of a base pointer
* and total size.
* @param base The base pointer.
* @param total_size The total size of the base buffer.
* @param ptr The target pointer to check.
* @param size The size of the region at the target pointer.
* @return TRUE if within bounds, FALSE otherwise.
*/
SND_FORCE_INLINE BOOL snd_ptr_bounds_check(const void *base, SIZE_T total_size, const void *ptr, SIZE_T size) {
if (base == NULL || ptr == NULL)
return FALSE;
ULONG_PTR ubase = (ULONG_PTR)base;
ULONG_PTR utarget = (ULONG_PTR)ptr;
if (utarget < ubase)
return FALSE;
SIZE_T offset = (SIZE_T)(utarget - ubase);
return snd_bounds_check(total_size, offset, size);
}
/**
* @brief Bounded, CRT-independent memory zeroing routine.
* Replaces memset.
*/
SND_FORCE_INLINE void snd_memzero(void *dest, size_t size) {
if (!dest)
return;
volatile BYTE *p = (volatile BYTE *)dest;
for (size_t i = 0; i < size; i++) {
p[i] = 0;
}
}
/**
* @brief Raw byte copy routine.
* Replaces memcpy.
*/
SND_FORCE_INLINE void snd_memcpy(void *dest, const void *src, size_t count) {
if (!dest || !src)
return;
BYTE *d = (BYTE *)dest;
const BYTE *s = (const BYTE *)src;
for (size_t i = 0; i < count; i++) {
d[i] = s[i];
}
}
/**
* @brief Bounded, CRT-independent string length evaluation.
* Replaces strnlen.
*/
SND_FORCE_INLINE size_t snd_strnlen(const char *str, size_t max_len) {
if (!str)
return 0;
size_t len = 0;
while (len < max_len && str[len] != '\0') {
len++;
}
return len;
}
/**
* @brief Bounded, truncation-safe string copying.
* Replaces strncpy / strncpy_s.
*/
SND_FORCE_INLINE void snd_strncpy(char *dest, size_t dest_size, const char *src, size_t max_src_len) {
if (!dest || dest_size == 0 || !src)
return;
size_t i = 0;
while (i < (dest_size - 1) && i < max_src_len && src[i] != '\0') {
dest[i] = src[i];
i++;
}
dest[i] = '\0';
}
/**
* @brief Bounded, CRT-independent string concatenation.
* Replaces strcat / strcat_s.
*/
static inline void snd_strncat(char *dest, SIZE_T dest_size, const char *src, SIZE_T max_src_len) {
if (!dest || dest_size == 0 || !src)
return;
SIZE_T dest_len = 0;
while (dest_len < dest_size && dest[dest_len] != '\0') {
dest_len++;
}
if (dest_len >= dest_size - 1) {
dest[dest_size - 1] = '\0';
return;
}
SIZE_T i = 0;
while (i < max_src_len && src[i] != '\0' && (dest_len + i) < (dest_size - 1)) {
dest[dest_len + i] = src[i];
i++;
}
dest[dest_len + i] = '\0';
}
/**
* @brief Bounded, CRT-independent character search.
* Replaces strchr.
*/
static inline const char *snd_strnchr(const char *str, char c, SIZE_T max_len) {
if (!str)
return NULL;
for (SIZE_T i = 0; i < max_len; i++) {
if (str[i] == c) {
return &str[i];
}
if (str[i] == '\0') {
break;
}
}
return NULL;
}
/**
* @brief Bounded, CRT-independent string comparison.
* Replaces strcmp / strncmp.
*/
static inline int snd_strncmp(const char *s1, const char *s2, SIZE_T max_len) {
if (!s1 || !s2)
return (s1 == s2) ? 0 : ((s1 < s2) ? -1 : 1);
for (SIZE_T i = 0; i < max_len; i++) {
if (s1[i] != s2[i]) {
return (int)((unsigned char)s1[i] - (unsigned char)s2[i]);
}
if (s1[i] == '\0') {
return 0;
}
}
return 0;
}
SND_END_EXTERN_C
#endif // SND_COMMON_HELPERS_H
+32
View File
@@ -0,0 +1,32 @@
#ifndef SND_COMMON_MACROS_H
#define SND_COMMON_MACROS_H
/**
* @def SND_BEGIN_EXTERN_C
* @brief Opens an `extern "C"` linkage block for C++ compatibility.
*/
/**
* @def SND_END_EXTERN_C
* @brief Closes an `extern "C"` linkage block.
*/
#ifdef __cplusplus
#define SND_BEGIN_EXTERN_C extern "C" {
#define SND_END_EXTERN_C }
#else
#define SND_BEGIN_EXTERN_C
#define SND_END_EXTERN_C
#endif
/**
* @def SND_FORCE_INLINE
* @brief Compiler-agnostic macro to force function inlining.
* Useful for embedding bounds checks and offset calculations directly into the
* caller's assembly.
*/
#if defined(_MSC_VER)
#define SND_FORCE_INLINE static __forceinline
#else
#define SND_FORCE_INLINE static inline __attribute__((always_inline))
#endif
#endif // SND_COMMON_MACROS_H
+70
View File
@@ -0,0 +1,70 @@
#ifndef SND_COMMON_MEMORY_H
#define SND_COMMON_MEMORY_H
#include <sindri/common/macros.h>
#include <stddef.h>
#include <stdint.h>
SND_BEGIN_EXTERN_C
/**
* @def SND_PTR_ADD
* @brief Safely adds a byte offset to a base pointer.
*/
#define SND_PTR_ADD(base, offset) ((unsigned char *)(base) + (offset))
/**
* @brief Checks if a given size and offset are within the bounds of a total size.
* @return 1 if within bounds, 0 otherwise.
*/
SND_FORCE_INLINE int snd_memory_bounds_check(size_t total_size, size_t offset, size_t size) {
if (offset > total_size)
return 0;
if (size > total_size - offset)
return 0;
return 1;
}
/**
* @brief Checks if a pointer and size are within the bounds of a base pointer and total size.
* @return 1 if within bounds, 0 otherwise.
*/
SND_FORCE_INLINE int snd_memory_ptr_bounds_check(const void *base, size_t total_size, const void *ptr, size_t size) {
if (base == NULL || ptr == NULL)
return 0;
uintptr_t ubase = (uintptr_t)base;
uintptr_t utarget = (uintptr_t)ptr;
if (utarget < ubase)
return 0;
size_t offset = (size_t)(utarget - ubase);
return snd_memory_bounds_check(total_size, offset, size);
}
/**
* @brief Bounded, CRT-independent memory zeroing routine. Replaces memset.
*/
SND_FORCE_INLINE void snd_memzero(void *dest, size_t size) {
if (!dest)
return;
volatile unsigned char *p = (volatile unsigned char *)dest;
for (size_t i = 0; i < size; i++) {
p[i] = 0;
}
}
/**
* @brief Raw byte copy routine. Replaces memcpy.
*/
SND_FORCE_INLINE void snd_memcpy(void *dest, const void *src, size_t count) {
if (!dest || !src)
return;
unsigned char *d = (unsigned char *)dest;
const unsigned char *s = (const unsigned char *)src;
for (size_t i = 0; i < count; i++) {
d[i] = s[i];
}
}
SND_END_EXTERN_C
#endif // SND_COMMON_MEMORY_H
+55 -24
View File
@@ -1,27 +1,35 @@
#ifndef SND_COMMON_STATUS_H
#define SND_COMMON_STATUS_H
#include <windows.h>
#if SND_DEBUG
#include <stdarg.h>
#include <stdio.h>
#endif
#include <sindri/common/helpers.h>
#include <sindri/common/macros.h>
SND_BEGIN_EXTERN_C
// Maximum length for error context strings (including null terminator)
#define SND_MAX_CTX_LEN 128
#define SND_MAX_CTX_LEN 128
#define SND_FAILED(x) (x.code != SND_SUCCESS)
#define SND_SUCCEEDED(x) (x.code == SND_SUCCESS)
typedef enum _SND_STATUS_CODE {
SND_SUCCESS = 0,
SND_ERROR_GENERIC = -1,
SND_STATUS_INVALID_PARAMETER = -2,
SND_STATUS_INTEGER_OVERFLOW = -3,
SND_STATUS_UNSUPPORTED = -4,
SND_STATUS_NOT_INITIALIZED = -5,
SND_SUCCESS = 0,
SND_ERROR_GENERIC = -1,
SND_STATUS_NULL_POINTER = -2,
SND_STATUS_INTEGER_OVERFLOW = -3,
SND_STATUS_UNSUPPORTED = -4,
SND_STATUS_NOT_INITIALIZED = -5,
SND_STATUS_BUFFER_TOO_SMALL = -6,
// Core Engine Execution Errors
SND_STATUS_TOO_MANY_ARGUMENTS = 0x50,
SND_STATUS_NTDLL_NOT_INITIALIZED,
SND_STATUS_RESOLVER_NOT_INITIALIZED,
SND_STATUS_OM_NOT_INITIALIZED,
SND_STATUS_PIPELINE_EXHAUSTED,
// Command-line argument errors
SND_STATUS_MISSING_COMMAND_LINE_ARGS = 0x100,
@@ -51,6 +59,8 @@ typedef enum _SND_STATUS_CODE {
SND_STATUS_INVALID_IMPORT_TABLE_SIZE,
SND_STATUS_INVALID_FILE_OFFSET,
SND_STATUS_DIRECTORY_NOT_FOUND,
SND_STATUS_CORRUPTED_STATE,
SND_STATUS_IMAGE_NOT_MAPPED,
// Reflective loading errors
SND_STATUS_SECTION_COPY_FAILED = 0x400,
@@ -68,15 +78,32 @@ typedef enum _SND_STATUS_CODE {
SND_STATUS_EXPORT_FORWARDER_UNSUPPORTED,
SND_STATUS_MISSING_DLL_EXPORT_NAME,
SND_STATUS_INVALID_STAGE_SEQUENCE,
SND_STATUS_CORRUPTED_STATE,
SND_FAILED_TO_EXECUTE,
SND_STATUS_LOCAL_EXECUTION_BLOCKED,
// Syscall resolution errors
SND_STATUS_SSN_NOT_FOUND,
SND_STATUS_SSN_BUFFER_TOO_SMALL,
SND_STATUS_SSN_NOT_FOUND = 0x500,
// PEB
SND_STATUS_PEB_MODULE_NOT_FOUND,
SND_STATUS_PEB_MODULE_NOT_FOUND = 0x600,
SND_STATUS_PEB_PROCESS_PARAMETERS_NOT_FOUND,
// OS errors
SND_STATUS_MODULE_NOT_FOUND = 0x800,
SND_STATUS_SECTION_OPEN_FAILED,
SND_STATUS_SECTION_MAP_FAILED,
SND_STATUS_HANDLE_CLOSE_FAILED,
SND_STATUS_PROCESS_OPEN_FAILED,
SND_STATUS_VIRTUAL_ALLOC_FAILED,
SND_STATUS_VIRTUAL_WRITE_FAILED,
SND_STATUS_VIRTUAL_PROTECT_FAILED,
SND_STATUS_THREAD_CREATE_FAILED,
SND_STATUS_VIRTUAL_FREE_FAILED,
// Remote process errors
SND_STATUS_ACCESS_DENIED = 0x900,
SND_STATUS_INVALID_PAYLOAD,
SND_STATUS_INVALID_INJECTION_TARGET,
} snd_status_code_t;
typedef struct _SND_STATUS {
@@ -113,11 +140,13 @@ static inline snd_status_t _snd_make_success() {
return status;
}
#define SND_OK _snd_make_success()
#define SND_ERR(c) _snd_make_err(c, 0, __FILE__, __LINE__, NULL)
#define SND_ERR_CTX(c, ...) _snd_make_err(c, 0, __FILE__, __LINE__, __VA_ARGS__)
#define SND_ERR_W32(code) _snd_make_err(code, GetLastError(), __FILE__, __LINE__, NULL)
#define SND_ERR_W32_CTX(code, ...) _snd_make_err(code, GetLastError(), __FILE__, __LINE__, __VA_ARGS__)
#define SND_OK _snd_make_success()
#define SND_ERR(c) _snd_make_err(c, 0, __FILE__, __LINE__, NULL)
#define SND_ERR_CTX(c, ...) _snd_make_err(c, 0, __FILE__, __LINE__, __VA_ARGS__)
#define SND_ERR_W32(code) _snd_make_err(code, GetLastError(), __FILE__, __LINE__, NULL)
#define SND_ERR_W32_CTX(code, ...) _snd_make_err(code, GetLastError(), __FILE__, __LINE__, __VA_ARGS__)
#define SND_ERR_NT(code, nt_status) _snd_make_err(code, nt_status, __FILE__, __LINE__, NULL)
#define SND_ERR_NT_CTX(code, nt_status, ...) _snd_make_err(code, nt_status, __FILE__, __LINE__, __VA_ARGS__)
#else
@@ -133,11 +162,13 @@ static inline snd_status_t _snd_make_err(snd_status_code_t code, int os_error) {
return status;
}
#define SND_OK _snd_make_success()
#define SND_ERR(code) _snd_make_err(code, 0)
#define SND_ERR_CTX(code, ...) _snd_make_err(code, 0)
#define SND_ERR_W32(code) _snd_make_err(code, GetLastError())
#define SND_ERR_W32_CTX(code, ...) _snd_make_err(code, GetLastError())
#define SND_OK _snd_make_success()
#define SND_ERR(code) _snd_make_err(code, 0)
#define SND_ERR_CTX(code, ...) _snd_make_err(code, 0)
#define SND_ERR_W32(code) _snd_make_err(code, GetLastError())
#define SND_ERR_W32_CTX(code, ...) _snd_make_err(code, GetLastError())
#define SND_ERR_NT(code, nt_status) _snd_make_err(code, nt_status)
#define SND_ERR_NT_CTX(code, nt_status, ...) _snd_make_err(code, nt_status)
#endif
+174
View File
@@ -0,0 +1,174 @@
#ifndef SND_COMMON_STRING_H
#define SND_COMMON_STRING_H
#include <sindri/common/macros.h>
#include <stddef.h>
SND_BEGIN_EXTERN_C
/**
* @brief Bounded, CRT-independent string length evaluation. Replaces strnlen.
*/
SND_FORCE_INLINE size_t snd_strnlen(const char *str, size_t max_len) {
if (!str)
return 0;
size_t len = 0;
while (len < max_len && str[len] != '\0') {
len++;
}
return len;
}
/**
* @brief Bounded, truncation-safe string copying. Replaces strncpy.
*/
SND_FORCE_INLINE void snd_strncpy(char *dest, size_t dest_size, const char *src, size_t max_src_len) {
if (!dest || dest_size == 0 || !src)
return;
size_t i = 0;
while (i < (dest_size - 1) && i < max_src_len && src[i] != '\0') {
dest[i] = src[i];
i++;
}
dest[i] = '\0';
}
/**
* @brief Bounded, CRT-independent string concatenation. Replaces strncat.
*/
SND_FORCE_INLINE void snd_strncat(char *dest, size_t dest_size, const char *src, size_t max_src_len) {
if (!dest || dest_size == 0 || !src)
return;
size_t dest_len = 0;
while (dest_len < dest_size && dest[dest_len] != '\0') {
dest_len++;
}
if (dest_len >= dest_size - 1) {
dest[dest_size - 1] = '\0';
return;
}
size_t i = 0;
while (i < max_src_len && src[i] != '\0' && (dest_len + i) < (dest_size - 1)) {
dest[dest_len + i] = src[i];
i++;
}
dest[dest_len + i] = '\0';
}
/**
* @brief Bounded, CRT-independent character search. Replaces strchr.
*/
SND_FORCE_INLINE const char *snd_strnchr(const char *str, char c, size_t max_len) {
if (!str)
return NULL;
for (size_t i = 0; i < max_len; i++) {
if (str[i] == c)
return &str[i];
if (str[i] == '\0')
break;
}
return NULL;
}
/**
* @brief Bounded, CRT-independent string comparison. Replaces strncmp.
*/
SND_FORCE_INLINE int snd_strncmp(const char *s1, const char *s2, size_t max_len) {
if (!s1 || !s2)
return (s1 == s2) ? 0 : ((s1 < s2) ? -1 : 1);
for (size_t i = 0; i < max_len; i++) {
if (s1[i] != s2[i])
return (int)((unsigned char)s1[i] - (unsigned char)s2[i]);
if (s1[i] == '\0')
return 0;
}
return 0;
}
/**
* @brief Bounded, CRT-independent wide string length evaluation. Replaces wcsnlen.
*/
SND_FORCE_INLINE size_t snd_wcsnlen(const wchar_t *str, size_t max_len) {
if (!str)
return 0;
size_t len = 0;
while (len < max_len && str[len] != L'\0') {
len++;
}
return len;
}
/**
* @brief Bounded, case-insensitive wide string comparison. Replaces wcsnicmp.
*/
SND_FORCE_INLINE int snd_wcsnicmp(const wchar_t *s1, const wchar_t *s2, size_t n) {
if (n == 0)
return 0;
do {
wchar_t c1 = *s1++;
wchar_t c2 = *s2++;
if (c1 >= L'A' && c1 <= L'Z')
c1 += (L'a' - L'A');
if (c2 >= L'A' && c2 <= L'Z')
c2 += (L'a' - L'A');
if (c1 != c2)
return (int)(c1 - c2);
if (c1 == L'\0')
break;
} while (--n);
return 0;
}
/**
* @brief Bounded, truncation-safe wide string copying. Replaces wcsncpy.
*/
SND_FORCE_INLINE void snd_wcsncpy(wchar_t *dest, size_t dest_size, const wchar_t *src, size_t max_src_len) {
if (!dest || dest_size == 0 || !src)
return;
size_t i = 0;
while (i < (dest_size - 1) && i < max_src_len && src[i] != L'\0') {
dest[i] = src[i];
i++;
}
dest[i] = L'\0';
}
/**
* @brief Bounded, CRT-independent wide string concatenation. Replaces wcsncat.
*/
SND_FORCE_INLINE void snd_wcsncat(wchar_t *dest, size_t dest_size, const wchar_t *src, size_t max_src_len) {
if (!dest || dest_size == 0 || !src)
return;
size_t dest_len = 0;
while (dest_len < dest_size && dest[dest_len] != L'\0') {
dest_len++;
}
if (dest_len >= dest_size - 1) {
dest[dest_size - 1] = L'\0';
return;
}
size_t i = 0;
while (i < max_src_len && src[i] != L'\0' && (dest_len + i) < (dest_size - 1)) {
dest[dest_len + i] = src[i];
i++;
}
dest[dest_len + i] = L'\0';
}
/**
* @brief Bounded ASCII to Wide string conversion. Replaces mbstowcs.
*/
SND_FORCE_INLINE void snd_ascii_to_wide(wchar_t *dest, size_t dest_size, const char *src, size_t max_src_len) {
if (!dest || dest_size == 0 || !src)
return;
size_t i = 0;
while (i < (dest_size - 1) && i < max_src_len && src[i] != '\0') {
dest[i] = (wchar_t)(unsigned char)src[i];
i++;
}
dest[i] = L'\0';
}
SND_END_EXTERN_C
#endif // SND_COMMON_STRING_H
+8
View File
@@ -0,0 +1,8 @@
#ifndef SND_INJECTION_H
#define SND_INJECTION_H
#include <sindri/injection/classic/chain.h>
#include <sindri/injection/classic/engine.h>
#include <sindri/injection/context.h>
#endif // SND_INJECTION_H
+7
View File
@@ -0,0 +1,7 @@
#ifndef SND_INJECTION_CLASSIC_H
#define SND_INJECTION_CLASSIC_H
#include <sindri/injection/classic/chain.h>
#include <sindri/injection/classic/engine.h>
#endif // SND_INJECTION_CLASSIC_H
+37
View File
@@ -0,0 +1,37 @@
#ifndef SND_INJECTION_CLASSIC_CHAIN_H
#define SND_INJECTION_CLASSIC_CHAIN_H
#include <sindri/common/macros.h>
#include <sindri/injection/classic/engine.h>
#include <sindri/injection/context.h>
SND_BEGIN_EXTERN_C
// Forward declare the loader context so we don't have to include the loader module
typedef struct _snd_ldr_pe_ctx snd_ldr_pe_ctx_t;
/**
* @brief Executes the full classic injection pipeline.
*
* Runs: open_target -> alloc_remote -> write_payload -> set_protections -> execute.
*
* @param ctx Initialized injection context with target_pid, payload, and proc_api set.
* @return SND_OK on success, otherwise the failing stage status.
*/
snd_status_t snd_inj_classic_shell(snd_inj_ctx_t *ctx);
/**
* @brief High-level orchestrator that links a loader context and an injection context.
*
* The user initializes both contexts with their desired API backends, and this
* chain handles the inter-context data marshaling and execution flow.
*
* @param ldr_ctx Initialized PE loader context with raw_source, mem_api, and mod_api set.
* @param inj_ctx Initialized injection context with target_pid, and proc_api set.
* @return SND_OK on success, otherwise the failing stage status.
*/
snd_status_t snd_inj_classic_pe(snd_ldr_pe_ctx_t *ldr_ctx, snd_inj_ctx_t *inj_ctx);
SND_END_EXTERN_C
#endif // SND_INJECTION_CLASSIC_CHAIN_H
+47
View File
@@ -0,0 +1,47 @@
#ifndef SND_INJECTION_CLASSIC_ENGINE_H
#define SND_INJECTION_CLASSIC_ENGINE_H
#include <sindri/common/macros.h>
#include <sindri/common/status.h>
#include <sindri/injection/context.h>
SND_BEGIN_EXTERN_C
/**
* @brief Opens a handle to the target process.
* @param ctx Initialized injection context with target_pid and proc_api set.
* @return SND_OK on success, otherwise SND_STATUS_PROCESS_OPEN_FAILED.
*/
snd_status_t snd_inj_classic_open_target(snd_inj_ctx_t *ctx);
/**
* @brief Allocates memory in the remote process for the payload.
* @param ctx Context after SND_INJ_STAGE_TARGET_ACQUIRED.
* @return SND_OK on success, otherwise SND_STATUS_REMOTE_ALLOC_FAILED.
*/
snd_status_t snd_inj_classic_alloc_remote(snd_inj_ctx_t *ctx);
/**
* @brief Writes the payload buffer into the allocated remote memory.
* @param ctx Context after SND_INJ_STAGE_MEMORY_ALLOCATED.
* @return SND_OK on success, otherwise SND_STATUS_REMOTE_WRITE_FAILED.
*/
snd_status_t snd_inj_classic_write_payload(snd_inj_ctx_t *ctx);
/**
* @brief Transitions remote memory protections from RW to RX.
* @param ctx Context after SND_INJ_STAGE_PAYLOAD_WRITTEN.
* @return SND_OK on success, otherwise SND_STATUS_REMOTE_PROTECT_FAILED.
*/
snd_status_t snd_inj_classic_set_protections(snd_inj_ctx_t *ctx);
/**
* @brief Creates a remote thread at the payload base to execute the shellcode.
* @param ctx Context after SND_INJ_STAGE_PROTECTIONS_SET.
* @return SND_OK on success, otherwise SND_STATUS_THREAD_CREATE_FAILED.
*/
snd_status_t snd_inj_classic_execute(snd_inj_ctx_t *ctx);
SND_END_EXTERN_C
#endif // SND_INJECTION_CLASSIC_ENGINE_H
+47
View File
@@ -0,0 +1,47 @@
#ifndef SND_INJECTION_CONTEXT_H
#define SND_INJECTION_CONTEXT_H
#include <sindri/common/buffer.h>
#include <sindri/common/debug.h>
#include <sindri/common/macros.h>
#include <sindri/primitives/os_api.h>
#include <windows.h>
SND_BEGIN_EXTERN_C
typedef enum {
SND_INJ_STAGE_UNINITIALIZED = 0,
SND_INJ_STAGE_TARGET_ACQUIRED,
SND_INJ_STAGE_MEMORY_ALLOCATED,
SND_INJ_STAGE_PAYLOAD_WRITTEN,
SND_INJ_STAGE_PROTECTIONS_SET,
SND_INJ_STAGE_EXECUTED,
} snd_inj_stage_t;
typedef struct _snd_inj_ctx_t {
DWORD target_pid;
HANDLE target_process;
PVOID remote_base;
PVOID remote_entry_point;
SIZE_T remote_size;
HANDLE remote_thread;
snd_inj_stage_t stage;
const snd_buffer_t *payload;
const snd_process_api_t *proc_api;
} snd_inj_ctx_t;
/**
* @brief Converts an injection stage enum to a human-readable string.
*/
const char *snd_inj_stage_to_string(snd_inj_stage_t stage);
/**
* @brief Cleans up injection context: closes handles, resets state.
*/
void snd_inj_cleanup(snd_inj_ctx_t *ctx);
SND_END_EXTERN_C
#endif // SND_INJECTION_CONTEXT_H
+8
View File
@@ -0,0 +1,8 @@
#ifndef SINDRI_INTERNAL_NT_H
#define SINDRI_INTERNAL_NT_H
#include <sindri/internal/nt/api.h>
#include <sindri/internal/nt/peb.h>
#include <sindri/internal/nt/types.h>
#endif // SINDRI_INTERNAL_NT_H
+75
View File
@@ -0,0 +1,75 @@
#ifndef SND_INTERNAL_NT_API_H
#define SND_INTERNAL_NT_API_H
#include <sindri/common/macros.h>
#include <sindri/internal/nt/types.h>
#include <windows.h>
SND_BEGIN_EXTERN_C
/**
* @brief Type definition for LdrLoadDll function.
*/
typedef NTSTATUS(NTAPI *SND_LdrLoadDll_t)(PWSTR PathToFile, PULONG Flags, PSND_UNICODE_STRING ModuleFileName,
PHANDLE ModuleHandle);
/*
* @brief Type definition for NtOpenSection function.
*/
typedef NTSTATUS(NTAPI *SND_NtOpenSection_t)(PHANDLE SectionHandle, ACCESS_MASK DesiredAccess,
PSND_OBJECT_ATTRIBUTES ObjectAttributes);
/*
* @brief Type definition for NtMapViewOfSection function.
*/
typedef NTSTATUS(NTAPI *SND_NtMapViewOfSection_t)(HANDLE SectionHandle, HANDLE ProcessHandle, PVOID *BaseAddress,
ULONG_PTR ZeroBits, SIZE_T CommitSize, PLARGE_INTEGER SectionOffset,
PSIZE_T ViewSize, DWORD InheritDisposition, ULONG AllocationType,
ULONG Win32Protect);
/*
* @brief Type definition for NtClose function.
*/
typedef NTSTATUS(NTAPI *SND_NtClose_t)(HANDLE Handle);
/*
* @brief Type definition for NtAllocateVirtualMemory function.
*/
typedef NTSTATUS(NTAPI *SND_NtAllocateVirtualMemory_t)(HANDLE ProcessHandle, PVOID *BaseAddress, ULONG_PTR ZeroBits,
SIZE_T *Size, ULONG AllocationType, ULONG Win32Protect);
/*
* @brief Type definition for NtProtectVirtualMemory function.
*/
typedef NTSTATUS(NTAPI *SND_NtProtectVirtualMemory_t)(HANDLE ProcessHandle, PVOID *BaseAddress, PSIZE_T RegionSize,
ULONG NewProtect, PULONG OldProtect);
/*
* @brief Type definition for NtFreeVirtualMemory function.
*/
typedef NTSTATUS(NTAPI *SND_NtFreeVirtualMemory_t)(HANDLE ProcessHandle, PVOID *BaseAddress, PSIZE_T RegionSize,
ULONG FreeType);
/*
* @brief Type definition for NtOpenProcess function.
*/
typedef NTSTATUS(NTAPI *SND_NtOpenProcess_t)(HANDLE *ProcessHandle, ACCESS_MASK DesiredAccess, PVOID ObjectAttributes,
PVOID ClientId);
/*
* @brief Type definition for NtWriteVirtualMemory function.
*/
typedef NTSTATUS(NTAPI *SND_NtWriteVirtualMemory_t)(HANDLE ProcessHandle, PVOID BaseAddress, PVOID Buffer, SIZE_T Size,
SIZE_T *NumberOfBytesWritten);
/*
* @brief Type definition for NtCreateThreadEx function.
*/
typedef NTSTATUS(NTAPI *SND_NtCreateThreadEx_t)(HANDLE *ThreadHandle, ACCESS_MASK DesiredAccess, PVOID ObjectAttributes,
HANDLE ProcessHandle, PVOID StartRoutine, PVOID Argument,
ULONG CreateFlags, SIZE_T ZeroBits, SIZE_T StackSize,
SIZE_T MaximumStackSize, PVOID AttributeList);
SND_END_EXTERN_C
#endif // SND_INTERNAL_NT_API_H
+77
View File
@@ -0,0 +1,77 @@
#ifndef SND_INTERNAL_NT_DEFS_H
#define SND_INTERNAL_NT_DEFS_H
#include <sindri/common/macros.h>
#include <sindri/internal/nt/types.h>
#include <windows.h>
SND_BEGIN_EXTERN_C
/**
* @brief A basic representation of the current directory struct to align memory block layouts.
*/
typedef struct _SND_CURDIR {
SND_UNICODE_STRING DosPath;
HANDLE Handle;
} SND_CURDIR, *PSND_CURDIR;
/**
* @brief Process parameters structure containing environment configuration details.
*/
typedef struct _SND_RTL_USER_PROCESS_PARAMETERS {
ULONG MaximumLength;
ULONG Length;
ULONG Flags;
ULONG DebugFlags;
HANDLE ConsoleHandle;
ULONG ConsoleFlags;
HANDLE StandardInput;
HANDLE StandardOutput;
HANDLE StandardError;
SND_CURDIR CurrentDirectory;
SND_UNICODE_STRING DllPath;
SND_UNICODE_STRING ImagePathName;
SND_UNICODE_STRING CommandLine;
PVOID Environment;
} SND_RTL_USER_PROCESS_PARAMETERS, *PSND_RTL_USER_PROCESS_PARAMETERS;
/**
* @brief PEB loader data structure.
*/
typedef struct _SND_PEB_LDR_DATA {
ULONG Length;
BYTE Reserved[8];
LIST_ENTRY InLoadOrderModuleList;
LIST_ENTRY InMemoryOrderModuleList;
LIST_ENTRY InInitializationOrderModuleList;
} SND_PEB_LDR_DATA, *PSND_PEB_LDR_DATA;
/**
* @brief Loader data table entry for module tracking.
*/
typedef struct _SND_LDR_DATA_TABLE_ENTRY {
LIST_ENTRY InLoadOrderLinks;
LIST_ENTRY InMemoryOrderLinks;
LIST_ENTRY InInitializationOrderLinks;
PVOID DllBase;
PVOID EntryPoint;
ULONG SizeOfImage;
SND_UNICODE_STRING FullDllName;
SND_UNICODE_STRING BaseDllName;
} SND_LDR_DATA_TABLE_ENTRY, *PSND_LDR_DATA_TABLE_ENTRY;
/**
* @brief Process Environment Block (PEB) definition.
*/
typedef struct _SND_PEB {
BYTE Reserved1[2];
BYTE BeingDebugged;
BYTE Reserved2[1];
PVOID Reserved3[2];
PSND_PEB_LDR_DATA Ldr;
PSND_RTL_USER_PROCESS_PARAMETERS ProcessParameters;
} SND_PEB, *PSND_PEB;
SND_END_EXTERN_C
#endif // SND_INTERNAL_NT_DEFS_H
+77
View File
@@ -0,0 +1,77 @@
#ifndef SND_INTERN_NT_TYPES_H
#define SND_INTERN_NT_TYPES_H
#include <sindri/common/macros.h>
#include <windows.h>
SND_BEGIN_EXTERN_C
/**
* @brief Macro to check if an NTSTATUS indicates success.
*/
#define SND_NT_SUCCESS(s) (((NTSTATUS)(s)) >= 0)
/**
* @brief Object attribute flag indicating case-insensitive object names.
*/
#define SND_OBJ_CASE_INSENSITIVE 0x00000040L
/**
* @brief Page size used in memory allocations.
*/
#define SND_PAGE_SIZE ((SIZE_T)0x1000)
/**
* @brief Initializes an SND_OBJECT_ATTRIBUTES structure.
*/
#define SND_InitializeObjectAttributes(p, n, a, r, s) \
{ \
(p)->Length = sizeof(SND_OBJECT_ATTRIBUTES); \
(p)->RootDirectory = r; \
(p)->Attributes = a; \
(p)->ObjectName = n; \
(p)->SecurityDescriptor = s; \
(p)->SecurityQualityOfService = NULL; \
}
/**
* @brief Represents a Unicode string in the NT environment.
*/
typedef struct _SND_UNICODE_STRING {
USHORT Length;
USHORT MaximumLength;
PWSTR Buffer;
} SND_UNICODE_STRING, *PSND_UNICODE_STRING;
typedef struct _SND_OBJECT_ATTRIBUTES {
ULONG Length;
HANDLE RootDirectory;
PSND_UNICODE_STRING ObjectName;
ULONG Attributes;
PVOID SecurityDescriptor;
PVOID SecurityQualityOfService;
} SND_OBJECT_ATTRIBUTES, *PSND_OBJECT_ATTRIBUTES;
/**
* @brief Client ID structure.
*/
typedef struct _SND_CLIENT_ID {
HANDLE UniqueProcess;
HANDLE UniqueThread;
} SND_CLIENT_ID, *PSND_CLIENT_ID;
/**
* @brief Initializes a UNICODE_STRING structure from a wide string buffer and length.
* Replaces RtlInitUnicodeString.
*/
SND_FORCE_INLINE void snd_init_unicode_string(SND_UNICODE_STRING *us, const wchar_t *buf, size_t char_count) {
if (us) {
us->Buffer = (wchar_t *)buf;
us->Length = (USHORT)(char_count * sizeof(wchar_t));
us->MaximumLength = us->Length + sizeof(wchar_t);
}
}
SND_END_EXTERN_C
#endif // SND_INTERNAL_NT_TYPES_H
-92
View File
@@ -1,92 +0,0 @@
#ifndef SND_INTERNAL_NT_DEFS_H
#define SND_INTERNAL_NT_DEFS_H
#include <sindri/common/helpers.h>
#include <windows.h>
SND_BEGIN_EXTERN_C
/**
* @brief Macro to check if an NTSTATUS indicates success.
*/
#ifndef NT_SUCCESS
#define NT_SUCCESS(s) (((NTSTATUS)(s)) >= 0)
#endif
#define SND_OBJ_CASE_INSENSITIVE 0x00000040L
#define SND_PAGE_SIZE ((SIZE_T)0x1000)
/**
* @brief Represents a Unicode string in the NT environment.
*/
typedef struct _SND_UNICODE_STRING {
USHORT Length; // In BYTES
USHORT MaximumLength; // In BYTES
PWSTR Buffer;
} SND_UNICODE_STRING, *PSND_UNICODE_STRING;
/**
* @brief PEB loader data structure.
*/
typedef struct _SND_PEB_LDR_DATA {
ULONG Length;
BYTE Reserved[8];
LIST_ENTRY InLoadOrderModuleList;
LIST_ENTRY InMemoryOrderModuleList;
LIST_ENTRY InInitializationOrderModuleList;
} SND_PEB_LDR_DATA, *PSND_PEB_LDR_DATA;
/**
* @brief Process Environment Block (PEB) definition.
*/
typedef struct _SND_PEB {
BYTE Reserved1[2];
BYTE BeingDebugged;
BYTE Reserved2[1];
PVOID Reserved3[2];
PSND_PEB_LDR_DATA Ldr;
} SND_PEB, *PSND_PEB;
/**
* @brief Loader data table entry for module tracking.
*/
typedef struct _SND_LDR_DATA_TABLE_ENTRY {
LIST_ENTRY InLoadOrderLinks;
LIST_ENTRY InMemoryOrderLinks;
LIST_ENTRY InInitializationOrderLinks;
PVOID DllBase;
PVOID EntryPoint;
ULONG SizeOfImage;
SND_UNICODE_STRING FullDllName;
SND_UNICODE_STRING BaseDllName;
} SND_LDR_DATA_TABLE_ENTRY, *PSND_LDR_DATA_TABLE_ENTRY;
/**
* @brief Type definition for LdrLoadDll function (ntdll native loader, no
* kernel32 required).
*/
typedef NTSTATUS(NTAPI *LdrLoadDll_t)(PWSTR PathToFile, // optional search path (NULL = default)
PULONG Flags, // optional flags (NULL = 0)
PSND_UNICODE_STRING ModuleFileName, PHANDLE ModuleHandle);
typedef struct _SND_OBJECT_ATTRIBUTES {
ULONG Length;
HANDLE RootDirectory;
PSND_UNICODE_STRING ObjectName;
ULONG Attributes;
PVOID SecurityDescriptor;
PVOID SecurityQualityOfService;
} SND_OBJECT_ATTRIBUTES, *PSND_OBJECT_ATTRIBUTES;
#define SND_InitializeObjectAttributes(p, n, a, r, s) \
{ \
(p)->Length = sizeof(SND_OBJECT_ATTRIBUTES); \
(p)->RootDirectory = r; \
(p)->Attributes = a; \
(p)->ObjectName = n; \
(p)->SecurityDescriptor = s; \
(p)->SecurityQualityOfService = NULL; \
}
SND_END_EXTERN_C
#endif // SND_INTERNAL_NT_DEFS_H
-1
View File
@@ -1,7 +1,6 @@
#ifndef SND_LOADERS_H
#define SND_LOADERS_H
#include <sindri/loaders/knowndlls/knowndlls.h>
#include <sindri/loaders/reflective/chain.h>
#include <sindri/loaders/reflective/engine.h>
@@ -1,57 +0,0 @@
#ifndef SND_LOADERS_KNOWNDLLS_H
#define SND_LOADERS_KNOWNDLLS_H
#include <sindri/common/helpers.h>
#include <sindri/common/status.h>
#include <sindri/internal/nt_defs.h>
#include <windows.h>
SND_BEGIN_EXTERN_C
#if defined(_WIN64)
#define SND_TARGET_KNOWNDLLS_DIR L"\\KnownDlls\\"
#elif defined(_WIN32)
#define SND_TARGET_KNOWNDLLS_DIR L"\\KnownDlls32\\"
#else
#error "Unsupported architecture: SindriKit requires _WIN32 or _WIN64"
#endif
typedef snd_status_t(WINAPI *snd_knowndlls_open_section_cb)(PHANDLE SectionHandle, ACCESS_MASK DesiredAccess,
PSND_OBJECT_ATTRIBUTES ObjectAttributes);
typedef snd_status_t(WINAPI *snd_knowndlls_map_view_cb)(HANDLE SectionHandle, HANDLE ProcessHandle, PVOID *BaseAddress,
ULONG_PTR ZeroBits, SIZE_T CommitSize,
PLARGE_INTEGER SectionOffset, PSIZE_T ViewSize,
DWORD InheritDisposition, ULONG AllocationType,
ULONG Win32Protect);
typedef snd_status_t(WINAPI *snd_knowndlls_close_cb)(HANDLE Handle);
/**
* @brief Configuration structure for the KnownDlls loader mapping technique.
*/
typedef struct {
snd_knowndlls_open_section_cb open_section;
snd_knowndlls_map_view_cb map_view_of_section;
snd_knowndlls_close_cb close_handle;
} snd_knowndlls_config_t;
// Expose the available configurations to the caller
extern const snd_knowndlls_config_t snd_knowndlls_win;
extern const snd_knowndlls_config_t snd_knowndlls_native;
/**
* @brief Maps a module from the \KnownDlls object directory into memory.
*
* @param config Pointer to the injected API configuration (Win32 or Native).
* @param dll_name The exact name of the DLL in the KnownDlls directory (e.g.,
* L"ntdll.dll").
* @param out_base_address Pointer to receive the base address of the mapped
* section.
* @return SND_OK on success, or an error code on failure.
*/
snd_status_t snd_map_knowndll(const snd_knowndlls_config_t *config, const wchar_t *dll_name, PVOID *out_base_address);
SND_END_EXTERN_C
#endif // SND_LOADERS_KNOWNDLLS_H
+7
View File
@@ -0,0 +1,7 @@
#ifndef SND_LOADERS_REFLECTIVE_H
#define SND_LOADERS_REFLECTIVE_H
#include <sindri/loaders/reflective/chain.h>
#include <sindri/loaders/reflective/engine.h>
#endif // SND_LOADERS_REFLECTIVE_H
+4 -4
View File
@@ -1,7 +1,7 @@
#ifndef SND_LOADERS_REFLECTIVE_CHAIN_H
#define SND_LOADERS_REFLECTIVE_CHAIN_H
#include <sindri/common/helpers.h>
#include <sindri/common/macros.h>
#include <sindri/loaders/reflective/engine.h>
SND_BEGIN_EXTERN_C
@@ -14,7 +14,7 @@ SND_BEGIN_EXTERN_C
* @note Wraps compatibility check, copy, relocation, imports, protections, and
* TLS.
*/
snd_status_t snd_prepare_reflective_image(snd_loader_ctx_t *ctx);
snd_status_t snd_ldr_pe_prepare_image(snd_ldr_pe_ctx_t *ctx);
/**
* @brief Executes the loaded image entry point.
@@ -22,14 +22,14 @@ snd_status_t snd_prepare_reflective_image(snd_loader_ctx_t *ctx);
* @param ctx Prepared loader context.
* @return SND_OK on success, otherwise execution error.
*/
snd_status_t snd_execute_reflective_image(snd_loader_ctx_t *ctx);
snd_status_t snd_ldr_pe_execute_image(snd_ldr_pe_ctx_t *ctx);
/**
* @brief Cleans up and detaches the reflective image state.
*
* @param ctx Reflective loader context.
*/
void snd_detach_reflective_image(snd_loader_ctx_t *ctx);
void snd_ldr_pe_detach_image(snd_ldr_pe_ctx_t *ctx);
SND_END_EXTERN_C
+19 -18
View File
@@ -2,16 +2,17 @@
#define SND_LOADERS_REFLECTIVE_ENGINE_H
#include <sindri/common/buffer.h>
#include <sindri/common/helpers.h>
#include <sindri/common/macros.h>
#include <sindri/common/status.h>
#include <sindri/parsers/pe/pe_parser.h>
#include <sindri/parsers/pe/parser.h>
#include <sindri/primitives/os_api.h>
#include <windows.h>
SND_BEGIN_EXTERN_C
typedef struct {
LPVOID virtual_base;
LPVOID local_base;
LPVOID execution_base;
LONG_PTR delta_offset;
LPVOID entry_point;
SIZE_T allocated_size;
@@ -26,18 +27,18 @@ typedef enum {
SND_STAGE_IMPORTS_RESOLVED,
SND_STAGE_READY_FOR_EXECUTION,
SND_STAGE_EXECUTED,
} snd_loader_stage_t;
} snd_ldr_pe_stage_t;
typedef struct {
typedef struct _snd_ldr_pe_ctx {
const snd_buffer_t *raw_source;
snd_pe_parser_t pe;
snd_pe_target_t target;
snd_loader_stage_t stage;
snd_ldr_pe_stage_t stage;
const snd_memory_api_t *mem_api;
const snd_module_api_t *mod_api;
} snd_loader_ctx_t;
} snd_ldr_pe_ctx_t;
/**
* @brief Portable macro to resolve and call a reflectively loaded DLL export
@@ -53,7 +54,7 @@ typedef struct {
#define SND_CALL_EXPORT(ctx, name, signature, status_out, ...) \
do { \
FARPROC _proc = NULL; \
(status_out) = snd_get_proc_address((ctx), (name), &_proc); \
(status_out) = snd_ldr_pe_get_proc_address((ctx), (name), &_proc); \
if ((status_out).code == SND_SUCCESS && _proc != NULL) { \
((signature)_proc)(__VA_ARGS__); \
} \
@@ -74,7 +75,7 @@ typedef struct {
#define SND_CALL_EXPORT_RET(ctx, name, signature, status_out, ret_out, ...) \
do { \
FARPROC _proc = NULL; \
(status_out) = snd_get_proc_address((ctx), (name), &_proc); \
(status_out) = snd_ldr_pe_get_proc_address((ctx), (name), &_proc); \
if ((status_out).code == SND_SUCCESS && _proc != NULL) { \
(ret_out) = ((signature)_proc)(__VA_ARGS__); \
} \
@@ -85,7 +86,7 @@ typedef struct {
* @param ctx The loader context with parsed PE.
* @return SND_OK on match, otherwise SND_STATUS_ARCH_MISMATCH.
*/
snd_status_t snd_compatibility_check(snd_loader_ctx_t *ctx);
snd_status_t snd_ldr_pe_compatibility_check(snd_ldr_pe_ctx_t *ctx);
/**
* @brief Allocates memory and copies sections.
@@ -93,42 +94,42 @@ snd_status_t snd_compatibility_check(snd_loader_ctx_t *ctx);
* success.
* @return SND_OK on success, otherwise an allocation error.
*/
snd_status_t snd_allocate_and_copy_image(snd_loader_ctx_t *ctx);
snd_status_t snd_ldr_pe_allocate_and_copy_image(snd_ldr_pe_ctx_t *ctx);
/**
* @brief Applies base relocation fixups.
* @param ctx The loader context containing the mapped virtual base.
* @return SND_OK on success, otherwise a relocation error.
*/
snd_status_t snd_apply_relocations(snd_loader_ctx_t *ctx);
snd_status_t snd_ldr_pe_apply_relocations(snd_ldr_pe_ctx_t *ctx);
/**
* @brief Resolves imports and patches IAT.
* @param ctx The loader context.
* @return SND_OK on success, otherwise a resolution error.
*/
snd_status_t snd_resolve_imports(snd_loader_ctx_t *ctx);
snd_status_t snd_ldr_pe_resolve_imports(snd_ldr_pe_ctx_t *ctx);
/**
* @brief Applies final section page protections.
* @param ctx The loader context.
* @return SND_OK on success, otherwise a protection error.
*/
snd_status_t snd_apply_memory_protections(snd_loader_ctx_t *ctx);
snd_status_t snd_ldr_pe_apply_memory_protections(snd_ldr_pe_ctx_t *ctx);
/**
* @brief Executes TLS callbacks from a loaded image.
* @param ctx The loader context.
* @param reason The reason for the call (e.g., DLL_PROCESS_ATTACH).
*/
void snd_execute_tls_callbacks(snd_loader_ctx_t *ctx, DWORD reason);
void snd_ldr_pe_execute_tls_callbacks(snd_ldr_pe_ctx_t *ctx, DWORD reason);
/**
* @brief Resolves the entry point pointer.
* @param ctx The loader context.
* @return SND_OK on success, error code on failure.
*/
snd_status_t snd_get_entry_point(snd_loader_ctx_t *ctx);
snd_status_t snd_ldr_pe_get_entry_point(snd_ldr_pe_ctx_t *ctx);
/**
* @brief Resolves an exported symbol address.
@@ -137,13 +138,13 @@ snd_status_t snd_get_entry_point(snd_loader_ctx_t *ctx);
* @param func_addr_out Receives resolved export pointer.
* @return SND_OK on success, error code on failure.
*/
snd_status_t snd_get_proc_address(snd_loader_ctx_t *ctx, const char *func_name, FARPROC *func_addr_out);
snd_status_t snd_ldr_pe_get_proc_address(snd_ldr_pe_ctx_t *ctx, const char *func_name, FARPROC *func_addr_out);
/**
* @brief Frees memory associated with the mapped reflective image.
* @param ctx The loader context.
*/
void snd_free_mapped_image(snd_loader_ctx_t *ctx);
void snd_ldr_pe_free_mapped_image(snd_ldr_pe_ctx_t *ctx);
SND_END_EXTERN_C
+1
View File
@@ -1,6 +1,7 @@
#ifndef SND_PARSERS_H
#define SND_PARSERS_H
#include <sindri/parsers/env.h>
#include <sindri/parsers/pe.h>
#endif // SND_PARSERS_H
+6
View File
@@ -0,0 +1,6 @@
#ifndef SND_PARSERS_ENV_H
#define SND_PARSERS_ENV_H
#include <sindri/parsers/env/peb.h>
#endif // SND_PARSERS_ENV_H
+50
View File
@@ -0,0 +1,50 @@
#ifndef SND_PARSERS_ENV_PEB_H
#define SND_PARSERS_ENV_PEB_H
#include <sindri/common/macros.h>
#include <sindri/common/status.h>
#include <sindri/internal/nt/peb.h>
#include <sindri_hashes.h>
#include <windows.h>
SND_BEGIN_EXTERN_C
/**
* @brief Safely locates the base address of a loaded module by walking the PEB.
* @param module_name Case-insensitive target name (e.g., L"ntdll.dll")
* @return Base pointer to the module, or NULL if not found.
*/
snd_status_t WINAPI snd_peb_get_module_base(const wchar_t *module_name, PVOID *out_base);
/**
* @brief Safely locates the base address of a loaded module by walking the PEB
* and comparing hashes.
* @param module_hash The hash of the target name.
* @return Base pointer to the module, or NULL if not found.
*/
snd_status_t WINAPI snd_peb_get_module_base_hash(DWORD module_hash, PVOID *out_base);
/**
* @brief Dynamically retrieves the current local process Environment Block (PEB).
*/
SND_FORCE_INLINE PSND_PEB snd_peb_get_local(void) {
#if defined(_M_X64) || defined(__x86_64__)
// 64-bit Intel/AMD Windows
return (PSND_PEB)__readgsqword(0x60);
#elif defined(_M_IX86) || defined(__i386__)
// 32-bit Intel/AMD Windows
return (PSND_PEB)__readfsdword(0x30);
#elif defined(_M_ARM64) || defined(__aarch64__)
// 64-bit ARM Windows
return (PSND_PEB)__readx18qword(0x60);
#else
#error "Unsupported CPU architecture for local PEB resolution."
#endif
}
SND_END_EXTERN_C
#endif // SND_PARSERS_ENV_PEB_H
+7 -6
View File
@@ -1,10 +1,11 @@
#ifndef SND_PARSERS_PE_H
#define SND_PARSERS_PE_H
#include <sindri/parsers/pe/pe_exports.h>
#include <sindri/parsers/pe/pe_imports.h>
#include <sindri/parsers/pe/pe_parser.h>
#include <sindri/parsers/pe/pe_relocations.h>
#include <sindri/parsers/pe/pe_utils.h>
#include <sindri/parsers/pe/exports.h>
#include <sindri/parsers/pe/imports.h>
#include <sindri/parsers/pe/parser.h>
#include <sindri/parsers/pe/relocations.h>
#include <sindri/parsers/pe/section_utils.h>
#include <sindri/parsers/pe/utils.h>
#endif
#endif // SND_PARSERS_PE_H
@@ -1,11 +1,10 @@
#ifndef SND_PARSERS_PE_EXPORTS_H
#define SND_PARSERS_PE_EXPORTS_H
#include "sindri_hashes.h"
#include <sindri/common/helpers.h>
#include <sindri/common/macros.h>
#include <sindri/common/status.h>
#include <sindri/primitives/os_api.h>
#include <sindri_hashes.h>
#include <windows.h>
SND_BEGIN_EXTERN_C
@@ -51,12 +50,12 @@ snd_status_t snd_pe_get_export_address(PVOID base_address, SIZE_T size, const ch
* @param func_hash The custom hash of the exported function name.
* @param func_addr_out Pointer that receives the resolved memory address on
* success.
* @param resolver Callback function used to resolve external dependencies via
* hash if the requested export is a forwarder. If NULL, forwarders fail.
* @param resolver Callback function used to load external dependencies if the
* requested export is a forwarder. If NULL, forwarder resolution will fail.
* @returns SND_OK on success, or an error status.
*/
snd_status_t snd_pe_get_export_address_by_hash(PVOID base_address, SIZE_T size, DWORD func_hash, FARPROC *func_addr_out,
snd_module_resolver_hash_cb resolver);
snd_status_t snd_pe_get_export_address_hash(PVOID base_address, SIZE_T size, DWORD func_hash, FARPROC *func_addr_out,
snd_module_resolver_cb resolver);
SND_END_EXTERN_C
@@ -1,9 +1,9 @@
#ifndef SND_PARSERS_PE_IMPORTS_H
#define SND_PARSERS_PE_IMPORTS_H
#include <sindri/common/helpers.h>
#include <sindri/common/macros.h>
#include <sindri/common/status.h>
#include <sindri/parsers/pe/pe_parser.h>
#include <sindri/parsers/pe/parser.h>
#include <sindri/primitives/os_api.h>
#include <windows.h>
@@ -2,7 +2,7 @@
#define SND_PARSERS_PE_PARSER_H
#include <sindri/common/buffer.h>
#include <sindri/common/helpers.h>
#include <sindri/common/macros.h>
#include <sindri/common/status.h>
#include <windows.h>
@@ -1,9 +1,9 @@
#ifndef SND_PARSERS_PE_RELOCATIONS_H
#define SND_PARSERS_PE_RELOCATIONS_H
#include <sindri/common/helpers.h>
#include <sindri/common/macros.h>
#include <sindri/common/status.h>
#include <sindri/parsers/pe/pe_parser.h>
#include <sindri/parsers/pe/parser.h>
#include <windows.h>
SND_BEGIN_EXTERN_C
+35
View File
@@ -0,0 +1,35 @@
#ifndef SND_PE_SECTION_UTILS_H
#define SND_PE_SECTION_UTILS_H
#include <sindri/parsers/pe/parser.h>
#include <stddef.h>
#include <windows.h>
/**
* @brief Retrieves the name of a PE section safely, resolving COFF string
* tables if needed.
* @note Internal engine use only.
*/
void snd_pe_section_name(const snd_pe_parser_t *parser, const IMAGE_SECTION_HEADER *section, char *name_buffer,
size_t buffer_size);
/**
* @brief Calculates the exact size to copy from raw file to virtual memory.
* @note Internal engine use only.
*/
SND_FORCE_INLINE DWORD snd_pe_section_copy_size(const IMAGE_SECTION_HEADER *s) {
if (s->Misc.VirtualSize == 0) {
return s->SizeOfRawData;
}
return s->SizeOfRawData < s->Misc.VirtualSize ? s->SizeOfRawData : s->Misc.VirtualSize;
}
/**
* @brief Calculates the final allocated size of a section in virtual memory.
* @note Internal engine use only.
*/
SND_FORCE_INLINE DWORD snd_pe_section_loaded_size(const IMAGE_SECTION_HEADER *s) {
return s->Misc.VirtualSize != 0 ? s->Misc.VirtualSize : s->SizeOfRawData;
}
#endif // SND_PE_SECTION_UTILS_H
@@ -1,9 +1,9 @@
#ifndef SND_PARSERS_PE_UTILS_H
#define SND_PARSERS_PE_UTILS_H
#include <sindri/common/helpers.h>
#include <sindri/common/macros.h>
#include <sindri/common/status.h>
#include <sindri/parsers/pe/pe_parser.h>
#include <sindri/parsers/pe/parser.h>
#include <windows.h>
SND_BEGIN_EXTERN_C
+3 -1
View File
@@ -3,10 +3,12 @@
#include <sindri/primitives/ffi.h>
#include <sindri/primitives/heavens_gate.h>
#include <sindri/primitives/mapping.h>
#include <sindri/primitives/memory.h>
#include <sindri/primitives/modules.h>
#include <sindri/primitives/object_manager.h>
#include <sindri/primitives/os_api.h>
#include <sindri/primitives/peb.h>
#include <sindri/primitives/process.h>
#include <sindri/primitives/syscalls.h>
#endif // SND_PRIMITIVES_H
+2 -2
View File
@@ -1,7 +1,7 @@
#ifndef SND_PRIMITIVES_FFI_H
#define SND_PRIMITIVES_FFI_H
#include <sindri/common/helpers.h>
#include <sindri/common/macros.h>
#include <windows.h>
SND_BEGIN_EXTERN_C
@@ -24,7 +24,7 @@ SND_BEGIN_EXTERN_C
* by the assembly bridge. The caller is responsible for ensuring that
* the argument types and count are compatible with the target function.
*/
UINT_PTR snd_execute_dynamic(PVOID pFunctionAddress, DWORD dwArgCount, const UINT_PTR *pArgs);
UINT_PTR snd_ffi_execute(PVOID pFunctionAddress, DWORD dwArgCount, const UINT_PTR *pArgs);
SND_END_EXTERN_C
+1 -1
View File
@@ -1,7 +1,7 @@
#ifndef SND_PRIMITIVES_HEAVENS_GATE_H
#define SND_PRIMITIVES_HEAVENS_GATE_H
#include <sindri/common/helpers.h>
#include <sindri/common/macros.h>
#include <sindri/common/status.h>
#include <windows.h>
+16
View File
@@ -0,0 +1,16 @@
#ifndef SND_PRIMITIVES_MAPPING_H
#define SND_PRIMITIVES_MAPPING_H
#include <sindri/common/macros.h>
#include <sindri/primitives/os_api.h>
SND_BEGIN_EXTERN_C
// Expose globally available, ready-to-use WinAPI capabilities
extern const snd_mapping_api_t snd_map_win;
extern const snd_mapping_api_t snd_map_nt;
extern const snd_mapping_api_t snd_map_sys;
SND_END_EXTERN_C
#endif // SND_PRIMITIVES_MAPPING_H
+3 -2
View File
@@ -1,14 +1,15 @@
#ifndef SND_PRIMITIVES_MEMORY_H
#define SND_PRIMITIVES_MEMORY_H
#include <sindri/common/helpers.h>
#include <sindri/common/macros.h>
#include <sindri/primitives/os_api.h>
SND_BEGIN_EXTERN_C
// Expose globally available, ready-to-use WinAPI capabilities
extern const snd_memory_api_t snd_mem_win;
extern const snd_memory_api_t snd_mem_native;
extern const snd_memory_api_t snd_mem_nt;
extern const snd_memory_api_t snd_mem_sys;
SND_END_EXTERN_C
+2 -2
View File
@@ -1,14 +1,14 @@
#ifndef SND_PRIMITIVES_MODULES_H
#define SND_PRIMITIVES_MODULES_H
#include <sindri/common/helpers.h>
#include <sindri/common/macros.h>
#include <sindri/primitives/os_api.h>
SND_BEGIN_EXTERN_C
// Expose globally available, ready-to-use WinAPI capabilities
extern const snd_module_api_t snd_mod_win;
extern const snd_module_api_t snd_mod_native;
extern const snd_module_api_t snd_mod_nt;
SND_END_EXTERN_C
@@ -0,0 +1,33 @@
#ifndef SND_PRIMITIVES_OBJECT_MANAGER_H
#define SND_PRIMITIVES_OBJECT_MANAGER_H
#include <sindri/common/macros.h>
#include <sindri/common/status.h>
#include <sindri/primitives/os_api.h>
#include <windows.h>
SND_BEGIN_EXTERN_C
#if defined(_WIN64)
#define SND_TARGET_KNOWNDLLS_DIR L"\\KnownDlls\\"
#elif defined(_WIN32)
#define SND_TARGET_KNOWNDLLS_DIR L"\\KnownDlls32\\"
#else
#error "Unsupported architecture: SindriKit requires _WIN32 or _WIN64"
#endif
/**
* @brief Maps a module from the \KnownDlls object directory into memory.
*
* @param config Pointer to the injected API configuration (Win32 or Native).
* @param dll_name The exact name of the DLL in the KnownDlls directory (e.g.,
* L"ntdll.dll").
* @param out_base_address Pointer to receive the base address of the mapped
* section.
* @return SND_OK on success, or an error code on failure.
*/
snd_status_t snd_om_knowndll_map(const snd_mapping_api_t *config, const wchar_t *dll_name, PVOID *out_base_address);
SND_END_EXTERN_C
#endif // SND_PRIMITIVES_OBJECT_MANAGER_H
+39 -3
View File
@@ -1,7 +1,7 @@
#ifndef SND_PRIMITIVES_OS_API_H
#define SND_PRIMITIVES_OS_API_H
#include <sindri/common/helpers.h>
#include <sindri/common/macros.h>
#include <sindri/common/status.h>
#include <windows.h>
@@ -19,10 +19,26 @@ typedef snd_status_t(WINAPI *snd_module_get_proc_cb)(HMODULE hModule, const char
typedef snd_status_t(WINAPI *snd_module_resolver_cb)(const wchar_t *module_name, PVOID *out_base);
// Module Capabilities (Hashes)
typedef snd_status_t(WINAPI *snd_module_load_hash_cb)(DWORD module_hash, HMODULE *out_module);
typedef snd_status_t(WINAPI *snd_module_get_proc_hash_cb)(HMODULE hModule, DWORD proc_hash, FARPROC *out_proc);
typedef snd_status_t(WINAPI *snd_module_resolver_hash_cb)(DWORD module_hash, PVOID *out_base);
// Mapping Capabilities
typedef snd_status_t(WINAPI *snd_mapping_open_cb)(const wchar_t *section_name, HANDLE *out_handle);
typedef snd_status_t(WINAPI *snd_mapping_view_cb)(HANDLE section_handle, PVOID *out_base, SIZE_T *out_size);
typedef snd_status_t(WINAPI *snd_mapping_close_cb)(HANDLE handle);
// Process Capabilities
typedef snd_status_t(WINAPI *snd_process_open_cb)(DWORD pid, DWORD desired_access, HANDLE *out_process);
typedef snd_status_t(WINAPI *snd_process_alloc_remote_cb)(HANDLE process, SIZE_T size, DWORD allocation_type,
DWORD protect, PVOID *out_address);
typedef snd_status_t(WINAPI *snd_process_write_remote_cb)(HANDLE process, PVOID base_address, const void *buffer,
SIZE_T size, SIZE_T *bytes_written);
typedef snd_status_t(WINAPI *snd_process_protect_remote_cb)(HANDLE process, PVOID base_address, SIZE_T size,
DWORD new_protect, DWORD *old_protect);
typedef snd_status_t(WINAPI *snd_process_create_thread_cb)(HANDLE process, PVOID start_address, PVOID parameter,
HANDLE *out_thread);
typedef snd_status_t(WINAPI *snd_process_close_cb)(HANDLE handle);
/**
* @brief Local Memory Management API table.
*/
@@ -42,11 +58,31 @@ typedef struct {
snd_module_resolver_cb get_module_base;
// Hash-based resolution
snd_module_load_hash_cb load_library_hash;
snd_module_get_proc_hash_cb get_proc_address_hash;
snd_module_resolver_hash_cb get_module_base_hash;
} snd_module_api_t;
/**
* @brief Mapping API table.
*/
typedef struct {
snd_mapping_open_cb open;
snd_mapping_view_cb view;
snd_mapping_close_cb close;
} snd_mapping_api_t;
/**
* @brief Remote Process Operations API table.
*/
typedef struct {
snd_process_open_cb open_process;
snd_process_alloc_remote_cb alloc_remote;
snd_process_write_remote_cb write_remote;
snd_process_protect_remote_cb protect_remote;
snd_process_create_thread_cb create_remote_thread;
snd_process_close_cb close_handle;
} snd_process_api_t;
SND_END_EXTERN_C
#endif // SND_PRIMITIVES_OS_API_H
-29
View File
@@ -1,29 +0,0 @@
#ifndef SND_PEB_H
#define SND_PEB_H
#include "sindri_hashes.h"
#include <sindri/common/helpers.h>
#include <sindri/common/status.h>
#include <windows.h>
SND_BEGIN_EXTERN_C
/**
* @brief Safely locates the base address of a loaded module by walking the PEB.
* @param module_name Case-insensitive target name (e.g., L"ntdll.dll")
* @return Base pointer to the module, or NULL if not found.
*/
snd_status_t WINAPI snd_peb_get_module_base(const wchar_t *module_name, PVOID *out_base);
/**
* @brief Safely locates the base address of a loaded module by walking the PEB
* and comparing hashes.
* @param module_hash The hash of the target name.
* @return Base pointer to the module, or NULL if not found.
*/
snd_status_t WINAPI snd_peb_get_module_base_by_hash(DWORD module_hash, PVOID *out_base);
SND_END_EXTERN_C
#endif // SND_PEB_H
+18
View File
@@ -0,0 +1,18 @@
#ifndef SND_PRIMITIVES_PROCESS_H
#define SND_PRIMITIVES_PROCESS_H
#include <sindri/common/macros.h>
#include <sindri/common/status.h>
#include <sindri/primitives/os_api.h>
#include <windows.h>
SND_BEGIN_EXTERN_C
// Expose globally available, ready-to-use WinAPI capabilities
extern const snd_process_api_t snd_proc_win;
extern const snd_process_api_t snd_proc_nt;
extern const snd_process_api_t snd_proc_sys;
SND_END_EXTERN_C
#endif // SND_PRIMITIVES_PROCESS_H
+12 -17
View File
@@ -1,14 +1,16 @@
#ifndef SND_PRIMITIVES_SYSCALLS_COMMON_H
#define SND_PRIMITIVES_SYSCALLS_COMMON_H
#include <sindri/common/helpers.h>
#include <sindri/common/macros.h>
#include <sindri/common/status.h>
#include <sindri/internal/nt_defs.h>
#include <sindri/primitives/os_api.h>
#include <windows.h>
SND_BEGIN_EXTERN_C
#define SND_MAX_SYSCALLS 500
#define SND_MAX_SYS_NAME_LEN 256
/**
* @brief Syscall entry structure holding the address, hash, and syscall number.
*/
@@ -33,6 +35,7 @@ typedef struct {
PVOID arg8;
PVOID arg9;
PVOID arg10;
PVOID arg11;
} snd_syscall_args_t;
/**
@@ -41,35 +44,27 @@ typedef struct {
*/
typedef snd_status_t (*snd_syscall_resolver_t)(PVOID ntdll_base, DWORD func_hash, snd_syscall_entry_t *entry_out);
snd_status_t snd_hell_extract_syscall(PVOID ntdll_base, DWORD func_hash, snd_syscall_entry_t *entry_out);
snd_status_t snd_halo_extract_syscall(PVOID ntdll_base, DWORD func_hash, snd_syscall_entry_t *entry_out);
snd_status_t snd_tartarus_extract_syscall(PVOID ntdll_base, DWORD func_hash, snd_syscall_entry_t *entry_out);
snd_status_t snd_veles_extract_syscall(PVOID ntdll_base, DWORD func_hash, snd_syscall_entry_t *entry_out);
snd_status_t snd_syscall_resolve_ssn_scan(PVOID ntdll, DWORD func_hash, snd_syscall_entry_t *entry_out);
snd_status_t snd_syscall_resolve_ssn_sort(PVOID ntdll, DWORD func_hash, snd_syscall_entry_t *entry_out);
/**
* @brief Sets the primary syscall resolution strategy using a function pointer.
* @param resolver The resolver function to use as the primary strategy.
*/
void snd_set_syscall_strategy(snd_syscall_resolver_t resolver);
void snd_syscall_strategy_set(snd_syscall_resolver_t resolver);
/**
* @brief Adds a fallback syscall resolution strategy to the pipeline.
* @param resolver The fallback resolver function to add.
* @return SND_OK on success, or an error if the pipeline is full.
*/
snd_status_t snd_add_syscall_strategy(snd_syscall_resolver_t resolver);
snd_status_t snd_syscall_strategy_add(snd_syscall_resolver_t resolver);
/**
* @brief Sets the global base address of the ntdll.dll module.
* @param ntdll_base The base address of the ntdll module.
*/
void snd_set_ntdll(PVOID ntdll_base);
/**
* @brief Retrieves the global base address of the ntdll.dll module.
* @return The base address of the ntdll module, or NULL if not set.
*/
PVOID snd_get_ntdll(void);
void snd_syscall_set_ntdll(PVOID ntdll_base);
/**
* @brief Core resolution entrypoint (evaluates the internal fallback chain
@@ -79,14 +74,14 @@ PVOID snd_get_ntdll(void);
* @param entry_out Pointer to the entry structure to populate.
* @return SND_OK on success, or an error code if resolution fails.
*/
snd_status_t snd_resolve_syscall(DWORD func_hash, snd_syscall_entry_t *entry_out);
snd_status_t snd_syscall_resolve(DWORD func_hash, snd_syscall_entry_t *entry_out);
/**
* @brief ASM stub for invoking syscalls.
* @param args Pointer to the syscall arguments structure.
* @return The NTSTATUS returned by the syscall.
*/
extern NTSTATUS snd_invoke_syscall_asm(snd_syscall_args_t *args);
extern NTSTATUS snd_syscall_invoke_asm(snd_syscall_args_t *args);
SND_END_EXTERN_C