SunriseLib - Windows-ориентированный C/C++ SDK для низкоуровневых проектов, которым нужен компактный runtime-слой без прямой зависимости от стандартных WinAPI/CRT/std-вызовов в основном коде приложения.
Основная идея библиотеки: дать одну точку входа через Sunrise.h, сохранить стиль, близкий к C, C++, WinAPI и NT API, но по возможности вести работу через собственные реализации, lazy import и прямые системные вызовы. Это помогает уменьшить зависимость от обычных импортов и снизить риск перехвата или отслеживания вызовов, которые делает приложение.
SunriseLib полезна, когда проекту важны:
- прямой контроль над Windows API, NT-level механизмами и syscall-first сценариями;
- работа как в обычных CRT-compatible конфигурациях, так и в NoCRT-сценариях без стандартного runtime;
- единый набор типов, макросов, C/C++ helpers и compatibility-заголовков;
- компактные filesystem, memory, thread, sync и network утилиты;
- lazy import, syscall helpers и compile-time obfuscation строк, целых чисел и чисел с плавающей запятой;
- возможность подключать SDK рядом с обычными Windows-заголовками.
Библиотека ориентирована на Windows и x64-сборки под MSVC и Clang.
include/Sunrise.h- основной umbrella-header, который подключает C, C++, CExt, CPPExt и PP-слои.include/C/- C/CRT/WinAPI-compatible заголовки, типы и объявления.include/CExt/- project-level C helpers: память, файлы, пути, консоль, процессы, синхронизация, DNS, HTTP, TCP/IPv4 и NT primitives, включая сценарии работы через системные вызовы.include/CPP/- C++ compatibility/std-like слой с контейнерами, строками, filesystem/fstream,expectedи related utilities.include/CPPExt/- C++ расширения:TcpClient,TcpListener,DnsClient,HttpClient,FileSystem,LazyImport,Syscall,Obfuscator,Random,NoCRTи другие helpers.include/PP/- препроцессорная инфраструктура, import-макросы, документационные метки и служебные compile-time helpers.Examples/- минимальные CRT и NoCRT примеры интеграции.Tests/- C и C++ тесты, включая сценарии подключения после стандартных Windows-заголовков.- Готовые release-библиотеки для MSVC/Clang в CRT-compatible и NoCRT-compatible вариантах.
Если include/ добавлен в include paths проекта, минимальный CRT-compatible entry point может выглядеть так:
#include <Sunrise.h>
int main(int argc, char** argv) {
(void)argc;
(void)argv;
return _SR_ObfInt(0);
}Если include path не настроен, можно подключить заголовок относительно корня репозитория:
#include "include/Sunrise.h"
int main(int argc, char** argv) {
(void)argc;
(void)argv;
return _SR_ObfInt(0);
}То же подключение можно использовать в C translation units:
#include <Sunrise.h>
int main(int argc, char** argv) {
(void)argc;
(void)argv;
return _SR_ObfInt(0);
}В NoCRT EXE entry point задаётся без стандартного CRT startup. В готовом примере Examples/NoCRTBase/ для этого используется NoCRTMain:
#include <Sunrise.h>
int NoCRTMain(void) {
int argc = _SR_ObfInt(0);
wchar_t** argv = nullptr;
if (!Sunrise::CPP::NoCRT::BuildWideArgv(&argc, &argv)) {
return _SR_ObfInt(1);
}
(void)argv;
return argc > _SR_ObfInt(0) ? _SR_ObfInt(0) : _SR_ObfInt(2);
}Для CRT-compatible DLL используется обычный DllMain:
#include <Sunrise.h>
_SR_BOOL WINAPI DllMain(_SR_HMODULE hModule, _SR_DWORD reason, _SR_PVOID param) {
(void)hModule;
(void)param;
if (reason != _SR_ObfInt(DLL_PROCESS_ATTACH)) {
return (_SR_BOOL)_SR_ObfInt(TRUE);
}
return (_SR_BOOL)_SR_ObfInt(TRUE);
}Для NoCRT DLL вместо DllMain определяется NoCRTDllMain:
#include <Sunrise.h>
int NoCRTDllMain(_SR_HMODULE hModule, _SR_DWORD reason, _SR_PVOID param) {
(void)hModule;
(void)param;
if (reason != _SR_ObfInt(DLL_PROCESS_ATTACH)) {
return _SR_ObfInt(TRUE);
}
return _SR_ObfInt(TRUE);
}Дальнейшие примеры используют int main(int argc, char** argv) как короткую CRT-compatible форму. В NoCRT EXE тот же полезный код обычно переносится в тело NoCRTMain, а аргументы командной строки принимаются через Sunrise::CPP::NoCRT::BuildWideArgv. В CRT-compatible DLL код размещается в DllMain, а в NoCRT DLL - в NoCRTDllMain.
Для старта с готовой конфигурацией удобнее открыть один из примеров:
Examples/CRTBase/- обычная CRT-compatible сборка сmainиDllMain.Examples/NoCRTBase/- минимальная NoCRT-oriented сборка сNoCRTMainиNoCRTDllMain.
При линковке с готовыми библиотеками выбирайте вариант под ваш compiler и runtime mode. Для CRT-compatible сборок используются SunriseLib-MSVC-Release-CRT.lib и SunriseLib-Clang-Release-CRT.lib; для NoCRT-compatible сборок - SunriseLib-MSVC-Release.lib и SunriseLib-Clang-Release.lib.
SunriseLib не привязывает основной код к обычному CRT allocator. Базовая memory-policy проекта задаётся тремя функциями, которые должно определить приложение или integration-пример:
#include <Sunrise.h>
void* _SR_MemAlloc(_SR_size_t size, bool zeroMemory) {
return _SR_MemHeapAlloc(size, zeroMemory);
}
void* _SR_MemReAlloc(void* ptr, _SR_size_t newSize, bool zeroMemory) {
return _SR_MemHeapReAlloc(ptr, newSize, zeroMemory);
}
void _SR_MemFree(void* ptr) {
_SR_MemHeapFree(ptr);
}_SR_MemHeapAlloc, _SR_MemHeapReAlloc и _SR_MemHeapFree используют внутреннюю heap-систему Sunrise, работающую поверх низкоуровневых NT/system-call primitives. Через _SR_MemAlloc/_SR_MemReAlloc/_SR_MemFree эту политику используют C helpers, CRT-compatible malloc/calloc/realloc/free, C++ std-like контейнеры, строки и части CPPExt, которым нужна динамическая память.
Если нужно полностью контролировать область выделения, можно завести memory region вручную. Например, буфер байт может лежать в стеке или статической памяти, а default allocator проекта будет выдавать память только из этого региона:
#include <Sunrise.h>
static _SR_BYTE gMemory[64 * 1024];
static const _SR_StackRegion gRegion = { gMemory, sizeof(gMemory) };
void* _SR_MemAlloc(_SR_size_t size, bool zeroMemory) {
return _SR_MemStackAlloc(&gRegion, size, zeroMemory);
}
void* _SR_MemReAlloc(void* ptr, _SR_size_t newSize, bool zeroMemory) {
return _SR_MemStackReAlloc(&gRegion, ptr, newSize, zeroMemory);
}
void _SR_MemFree(void* ptr) {
_SR_MemStackFree(&gRegion, ptr);
}Для более гибкого C++ сценария часть std-like контейнеров принимает _SR_IAllocatorVtbl: так можно использовать heap по умолчанию для одних объектов и отдельный stack-backed или custom allocator для других. Если allocator привязан к конкретному _SR_StackRegion, адаптер обычно хранит выбранный регион рядом с таблицей функций или в другой контролируемой области состояния.
#include <Sunrise.h>
int main(int argc, char** argv) {
(void)argc;
(void)argv;
using Sunrise::CPP::FileSystem::ReadFile;
using Sunrise::CPP::std::vector;
auto data = ReadFile<vector<char>>(_SR_ObfWStr(L"data.bin").CStr());
if (!data.has_value()) {
return _SR_ObfInt(1);
}
return data.value().empty() ? _SR_ObfInt(2) : _SR_ObfInt(0);
}FileSystem::ReadFile, WriteFile и AppendFile работают с контейнерами и возвращают Sunrise::CPP::std::expected, чтобы ошибка оставалась явной частью результата.
#include <Sunrise.h>
int main(int argc, char** argv) {
(void)argc;
(void)argv;
using Sunrise::CPP::Network::IPv4Endpoint;
using Sunrise::CPP::Network::TcpClient;
TcpClient client = {};
auto connected = client.Connect(IPv4Endpoint::Loopback(_SR_ObfInt(8080)));
if (!connected.has_value()) {
return _SR_ObfInt(1);
}
const auto message = _SR_ObfStr("ping");
auto sent = client.SendAll(reinterpret_cast<const _SR_BYTE*>(message.CStr()), (_SR_ULONG)_SR_strlen(message.CStr()));
return sent.has_value() ? _SR_ObfInt(0) : _SR_ObfInt(2);
}Network-слой также содержит TcpListener, DnsClient, HttpClient, IPv4Address, IPv4Endpoint, HttpUrl и HttpResponse. Там, где это возможно, сетевой слой опирается на NT/syscall-подход вместо прямых вызовов обычных WinAPI-функций.
#include <Sunrise.h>
int main(int argc, char** argv) {
(void)argc;
(void)argv;
Sunrise::CPP::Network::HttpClient http = {};
auto response = http.Get(_SR_ObfStr("http://example.com/"));
if (!response.has_value()) {
return _SR_ObfInt(1);
}
return response.value().Ok() ? _SR_ObfInt(0) : _SR_ObfInt(2);
}HttpClient предназначен для компактных HTTP GET сценариев и построен поверх network helpers библиотеки.
#include <windows.h>
#include <Sunrise.h>
int main(int argc, char** argv) {
(void)argc;
(void)argv;
auto messageBoxW = Sunrise::CPP::LazyImport<L"user32.dll", MessageBoxW>(
_SR_ObfWStr(L"user32.dll")
);
if (!messageBoxW) {
return _SR_ObfInt(1);
}
messageBoxW(nullptr, _SR_ObfWStr(L"Hello"), _SR_ObfWStr(L"SunriseLib"), _SR_ObfInt(MB_OK));
return _SR_ObfInt(0);
}LazyImport используется, когда проекту нужно получить адрес export-функции лениво, без обычного прямого вызова через import table. Для короткой записи также есть алиас _SR_LazyImport.
В SDK есть helpers для compile-time obfuscation строк, целых чисел и чисел с плавающей запятой. Их удобно использовать для литералов, которые не должны лежать в бинаре в прямом виде:
#include <Sunrise.h>
int main(int argc, char** argv) {
(void)argc;
(void)argv;
auto text = _SR_ObfStr("hidden text");
int value = _SR_ObfInt(42);
return text.CStr()[_SR_ObfInt(0)] == _SR_ObfInt('h') && value == _SR_ObfInt(42) ? _SR_ObfInt(0) : _SR_ObfInt(1);
}Для .c файлов предусмотрены отдельные C-compatible obfuscator macros в include/CExt/Obfuscator/. C++ слой также поддерживает обфускацию строк, целых чисел и чисел с плавающей запятой на стадии компиляции с расшифровкой при использовании значения.
Часть функций и helpers помечается в SR-документации мета-полем uses-external-api. Такая метка помогает быстро понять, где реализация может обращаться к обычным внешним API-функциям, а не только к собственному коду библиотеки или системным вызовам.
Форма <meta name="uses-external-api" /> означает, что внешний API-вызов используется всегда. Если внутри meta-тега есть текст, он описывает условие, при котором такой вызов возможен, например загрузку модуля только когда он ещё не найден среди уже загруженных.
include/- заголовки SDK.Examples/CRTBase/- базовый CRT-compatible пример сmainиDllMain.Examples/NoCRTBase/- базовый NoCRT-oriented пример сNoCRTMainиNoCRTDllMain.Tests/- наборы C и C++ тестов.SunriseLib-MSVC-Release-CRT.lib- release-библиотека для MSVC CRT-compatible сборок.SunriseLib-Clang-Release-CRT.lib- release-библиотека для Clang CRT-compatible сборок.SunriseLib-MSVC-Release.lib- release-библиотека для MSVC NoCRT-compatible сборок.SunriseLib-Clang-Release.lib- release-библиотека для Clang NoCRT-compatible сборок.LICENSE- текст лицензии.
В репозитории есть Visual Studio project/solution files для примеров и тестов. Для проверки интеграции можно использовать:
Tests/Tests.sln;Examples/CRTBase/CRTBase.sln;Examples/NoCRTBase/NoCRTBase.sln.
Основной сценарий использования: подключить include/, выбрать подходящую release-библиотеку под ваш compiler и CRT/NoCRT режим, затем линковать её вместе с приложением или библиотекой.
Проект распространяется по кастомной лицензии Sunrise Reciprocal Application License 1.0.
Это не Apache License 2.0 и не OSI-approved open source license. Лицензия требует предоставлять Licensor исходный код производных или интегрированных приложений по запросу и предоставляет Licensor широкие права на использование, изменение, публикацию и распространение таких приложений и связанных материалов.
Полный текст лицензии: LICENSE