打包并加密资源文件
tar czvf - /resources | openssl enc -aes-256-cbc -pbkdf2 -out /resources.enc -k YOUR_SECRET_KEY
创建透明解密加载层
#include <dlfcn.h>
#include <openssl/evp.h>
#include <zlib.h>
#include <unordered_map>
#include <vector>
#include <string>
#include <cstdlib>
#include <cstring>
#include <stdexcept>
#include <sys/mman.h>
#include <fstream>
#include <unistd.h>
#include <fcntl.h>
#include <map>
#include <mutex>// Memory file descriptor information
struct MemFD {const char* data; // Pointer to resource datasize_t size; // Size of the resource datasize_t pos; // Current read position
};static std::unordered_map<std::string, std::vector<char>> g_resources;
static std::string g_resource_dir;
static int g_virtual_fd_counter = 10000; // Starting value for virtual file descriptors
static std::map<int, MemFD> g_fd_map; // Mapping of virtual file descriptors
static std::mutex g_fd_mutex; // Mutex for thread safety// Original system call declarations
static int (*real_open)(const char*, int, ...) = nullptr;
static ssize_t (*real_read)(int, void*, size_t) = nullptr;
static off_t (*real_lseek)(int, off_t, int) = nullptr;
static int (*real_close)(int) = nullptr;// AES-256 key
static const unsigned char key[32] = { 0xA9, 0x50, 0x6D, 0x57, 0xF4, 0x11, 0x8D, 0x79, 0xBB, 0x2A, 0xC8, 0xC0, 0x4E, 0x07, 0x0E, 0x57, 0xED, 0xBF, 0x9C, 0xD6, 0x4F, 0x40, 0x0E, 0x18, 0xE5, 0x37, 0x20, 0xBE, 0x44, 0x01, 0x0E, 0x31
};// Decrypt function
std::vector<unsigned char> aes_decrypt(const std::vector<char>& encrypted) {EVP_CIPHER_CTX* ctx = EVP_CIPHER_CTX_new();unsigned char iv[16];memcpy(iv, encrypted.data(), 16);EVP_DecryptInit_ex(ctx, EVP_aes_256_cbc(), nullptr, key, iv);int out_len = 0;std::vector<unsigned char> decrypted(encrypted.size() + EVP_MAX_BLOCK_LENGTH);EVP_DecryptUpdate(ctx, decrypted.data(), &out_len,reinterpret_cast<const unsigned char*>(encrypted.data()) + 16,encrypted.size() - 16);int final_len = 0;EVP_DecryptFinal_ex(ctx, decrypted.data() + out_len, &final_len);decrypted.resize(out_len + final_len);EVP_CIPHER_CTX_free(ctx);return decrypted;
}// GZIP decompress function
std::vector<char> gzip_decompress(const std::vector<unsigned char>& compressed) {z_stream strm{};strm.zalloc = Z_NULL;strm.zfree = Z_NULL;strm.opaque = Z_NULL;strm.avail_in = compressed.size();strm.next_in = const_cast<Bytef*>(compressed.data());if (inflateInit2(&strm, 16 + MAX_WBITS) != Z_OK) {throw std::runtime_error("zlib init failed");}std::vector<char> decompressed(4096);size_t total = 0;int ret = Z_OK;do {strm.avail_out = decompressed.size() - total;strm.next_out = reinterpret_cast<Bytef*>(decompressed.data() + total);ret = inflate(&strm, Z_NO_FLUSH);if (ret == Z_DATA_ERROR || ret == Z_MEM_ERROR) {inflateEnd(&strm);throw std::runtime_error("zlib inflate error");}total = decompressed.size() - strm.avail_out;if (strm.avail_out == 0) {decompressed.resize(decompressed.size() * 2);}} while (ret != Z_STREAM_END);inflateEnd(&strm);decompressed.resize(total);return decompressed;
}// Initialize resources
__attribute__((constructor)) static void init_resources() {try {const char* env_dir = getenv("RBP_VIS_RESOURCES_DIR");if (!env_dir) throw std::runtime_error("RBP_VIS_RESOURCES_DIR not set");g_resource_dir = std::string(env_dir) + "/";const std::string enc_path = g_resource_dir + ".enc";std::ifstream fin(enc_path, std::ios::binary);if (!fin) throw std::runtime_error("Cannot open resource package");std::vector<char> encrypted((std::istreambuf_iterator<char>(fin)),std::istreambuf_iterator<char>());auto decrypted = aes_decrypt(encrypted);auto decompressed = gzip_decompress(decrypted);// Parse TAR file (you should implement this or use a third-party library)// Assume decompressed contains the unpacked file content// Replace with actual TAR parsing logicg_resources["example.txt"] = std::vector<char>(decompressed.begin(),decompressed.end());// Lock memoryfor (auto& entry : g_resources) {auto& data = entry.second;if (!data.empty() && mlock(data.data(), data.size()) != 0) {perror("mlock failed");}}} catch (const std::exception& e) {fprintf(stderr, "[FATAL] Resource init failed: %s\n", e.what());abort();}// Initialize system call interceptionreal_open = reinterpret_cast<int(*)(const char*, int, ...)>(dlsym(RTLD_NEXT, "open"));real_read = reinterpret_cast<ssize_t(*)(int, void*, size_t)>(dlsym(RTLD_NEXT, "read"));real_lseek = reinterpret_cast<off_t(*)(int, off_t, int)>(dlsym(RTLD_NEXT, "lseek"));real_close = reinterpret_cast<int(*)(int)>(dlsym(RTLD_NEXT, "close"));
}// Intercept open system call
extern "C" int open(const char* path, int flags, ...) {// Handle only read requests and non-create modesif ((flags & O_ACCMODE) != O_RDONLY || (flags & O_CREAT)) {return real_open(path, flags);}// Check if the resource path is validif (strncmp(path, g_resource_dir.c_str(), g_resource_dir.size()) != 0) {return real_open(path, flags);}std::lock_guard<std::mutex> lock(g_fd_mutex);// Extract relative pathstd::string rel_path(path + g_resource_dir.size());auto it = g_resources.find(rel_path);if (it == g_resources.end()) {errno = ENOENT;return -1;}// Allocate virtual file descriptorint fd = g_virtual_fd_counter++;g_fd_map[fd] = {.data = it->second.data(),.size = it->second.size(),.pos = 0};return fd;
}// Intercept read system call
extern "C" ssize_t read(int fd, void* buf, size_t count) {std::lock_guard<std::mutex> lock(g_fd_mutex);auto entry = g_fd_map.find(fd);if (entry != g_fd_map.end()) {MemFD& mfd = entry->second;size_t bytes_left = mfd.size - mfd.pos;size_t to_read = std::min(bytes_left, count);if (to_read > 0) {memcpy(buf, mfd.data + mfd.pos, to_read);mfd.pos += to_read;return to_read;}return 0; // EOF}return real_read(fd, buf, count);
}// Intercept lseek system call
extern "C" off_t lseek(int fd, off_t offset, int whence) {std::lock_guard<std::mutex> lock(g_fd_mutex);auto entry = g_fd_map.find(fd);if (entry != g_fd_map.end()) {MemFD& mfd = entry->second;switch (whence) {case SEEK_SET: mfd.pos = offset; break;case SEEK_CUR: mfd.pos += offset; break;case SEEK_END: mfd.pos = mfd.size + offset; break;default: errno = EINVAL;return -1;}mfd.pos = std::min(mfd.pos, mfd.size);return mfd.pos;}return real_lseek(fd, offset, whence);
}// Intercept close system call
extern "C" int close(int fd) {std::lock_guard<std::mutex> lock(g_fd_mutex);auto entry = g_fd_map.find(fd);if (entry != g_fd_map.end()) {g_fd_map.erase(fd);return 0;}return real_close(fd);
}
编译为动态库
g++ -shared -fPIC -o libresource_loader.so resource_loader.cpp -lcrypto -lz -ldl
export LD_PRELOAD=libresource_loader.so
然后运行主程序即可