CPP 项目保护 resources 资源文件

news/2025/3/25 7:17:57/文章来源:https://www.cnblogs.com/cokefentas/p/18787885

打包并加密资源文件

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

然后运行主程序即可

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/904245.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Go红队开发—CLI框架(一)

CLI命令行工具编写基础学习(一)。CLI开发框架 命令行工具开发,主要是介绍开发用到的包,集成了一个框架,只要学会了基本每个人都能开发安全工具了。 该文章先学flags包,是比较经典的一个包,相比后面要学习的集成框架这个比较自由比较细化点,自定义可能高一些,后续会学到一…

WSL2安装Ubuntu

本文是介绍如何使用任意一台Windows主机借助WSL2创建Ubuntu虚拟系统并开放局域网内SSH连接的操作指南!先决条件拥有能够访问github.com的网络环境; 必须运行 Windows 10 版本 2004 及更高版本(内部版本 19041 及更高版本)或 Windows 11版本;安装WSL2 以管理员身份运行Powe…

人工‘够好就行’智能(AGEI)就快来了!

比尔弗兰克斯 前言:本文作者的观点是在真正的通用人工智能(AGI)到来之前,一种“够好就行”的人工智能(AGEI)就已经足以引发我们原本担心 AGI 才会带来的重大社会变革、正面效益,甚至潜在危机。 换句话说: AI 不需要达到像人类一样全面智能的程度; 只要在足够多的任务上…

List集合--java进阶day09

1.List集合以下面的例子来解释存储有序和存储重复如上图,我们是怎么添加这些字符串的,打印的时候就是按照这个顺序打印的--存取有序 并且“张三”出现了两次,也存入了两次--存储重复 因为List有索引,所以该接口有关于索引的独特的api..1.remove注意事项 List有两个remove方…

Pydantic字段级校验:解锁@validator的12种应用

title: Pydantic字段级校验:解锁@validator的12种应用 date: 2025/3/23 updated: 2025/3/23 author: cmdragon excerpt: Pydantic校验系统支持通过pre验证器实现原始数据预处理,在类型转换前完成字符清洗等操作。格式验证涵盖正则表达式匹配与枚举值约束,确保护照编号等字…

20244126 2024-2025-2 《python程序设计》实验一报告

课程:《Python程序设计》 班级:2441 姓名:马晓霞 学号:20244126 实验教师:王志强 实验日期:2025年3月23日 必修/选修:公选课 (一)实验内容 1.熟悉Python开发环境 2.练习Python运行,调试技能 3.编写技能,练习变量和类型、字符串、对象、缩进和注释等 4.编写一个猜数字…

1.6K star!这个开源文本提取神器,5分钟搞定PDF/图片/Office文档!

Kreuzberg 是一个基于 Python 的文本提取库,支持从 PDF、图像、Office 文档等 20+ 格式中提取文本内容。采用 MIT 开源协议,具备本地处理、异步架构、智能 OCR 等特性,特别适合需要隐私保护的文档处理场景。嗨,大家好,我是小华同学,关注我们获得“最新、最全、最优质”开…

leetcode每日一题:判断一个括号字符串是否有效

题目 一个括号字符串是只由 ( 和 ) 组成的 非空 字符串。如果一个字符串满足下面 任意 一个条件,那么它就是有效的:字符串为 (). 它可以表示为 AB(A 与 B 连接),其中A 和 B 都是有效括号字符串。 它可以表示为 (A) ,其中 A 是一个有效括号字符串。给你一个括号字符串 s 和…

实验2c语言分支与循环基础应用编程

任务一:1 #include <stdio.h>2 #include <stdlib.h>3 #include <time.h>4 5 #define N 56 7 int main() {8 int number;9 int i; 10 11 srand(time(0)); // 以当前系统时间作为随机种子 12 for(i = 0; i < N; ++i) { 13 nu…

矿用人员违规闯入监控报警系统

矿用人员违规闯入监控报警系统,设置警戒预警功能,巷道正在行车时,当有行人闯入时,及时抓拍、识别现场违章入侵人员同时闪光警示和音箱报警提示禁止进入,在绞车运行期间人员误入斜巷能够及时报警,自动停止绞车运行。该系统做到绞车运行和行人的安全隔离,有力保障了煤矿斜…

工厂车间人员违规闯入禁区报警系统

工厂车间人员违规闯入禁区报警系统前端设备嵌入AI人体识别算法,对人员的检测、跟踪,实现对人体检测分析识别,实时预警周界区域内人员入侵事件。当有可疑人员进入监测范围内可对其自动识别,即对其抓拍并将当时图像传输到管理中心,在管理中心输出报警信号。工厂车间人员违规…

iis备份还原工具,想要备份iis有哪些工具可以实现?

想要备份IIS(Internet Information Services),可以使用多种专门的备份还原工具。以下是一些常用的IIS备份还原工具及其简要介绍:IISBackUp 功能:专注于备份和恢复IIS站点设置,包括网站配置文件、站点绑定信息、应用程序池设置、SSL证书和密钥信息等。 特点: 提供一种方便…