大部分的加密方式选择异或加密比较简单
1:xlua 签名和加密?
思路:签名xlua下载提供了签名的工具。加密代码和解密代码使用AB bundle 方式
签名流程:
?xlua 工具目录:?\xLua-master\xLua-master\Tools
?生成私钥公钥和签名工具放在需要签名的xlua 代码文件同级目录。
文本编辑bat执行下面语句
cd /d %~dp0
@REM 签名后的文件拷贝到LuaSing
rmdir /q /s LuaSign
"FilesSignature.exe" "Lua" "LuaSign"
执行后在读取lua代码的地方前添加下述代码:
lua的签名加载方式:
PUBLIC_KEY 从生成的公钥key_ras.pub 双击查看
SignatureLoader sl = new SignatureLoader(PUBLIC_KEY, LoadLuaFile);
LuaEnv.AddLoader(sl);
签名的结果是会在签名的代码开始前加一段文本
Lua 代码的加密方式是外部读取文本流加密,解密是读取lua得到字节流解密
加密部分代码:
string key = "yhjm";
byte[] key_char = System.Text.Encoding.Unicode.GetBytes(key);
File.Copy(f, newpath, true);
byte[] bytes = File.ReadAllBytes(newpath);
for (i = 0; i < bytes.Length; i++)
{
bytes[i] = (byte)(bytes[i] ^ key_char[i % key_char.Length]);
}
File.WriteAllBytes(newpath, bytes);
File.Copy(f, newhxpath, true);
File.WriteAllBytes(newhxpath, bytes);
lua部分解密和签名验证代码:
LuaEnv.AddLoader(new SignatureLoader(aabb, (ref string filePath) =>
{
string orgPath = filePath;
byte[] tmpBytes = LuaHelper.Inst.ReadFile(ref filePath);
byte[] key_char = System.Text.Encoding.Unicode.GetBytes("yhjm");
for (int i = 0; i < tmpBytes.Length; i++)
{
tmpBytes[i] = (byte)(tmpBytes[i] ^ key_char[i % key_char.Length]);
}
return tmpBytes;
}));
加密方式可以选择,目前只是简单的处理
2:AB包资源加密
这方式比较简单:
使用自带的方式处理,加密后资源用AssetStudio无法直接查看资源
AB 包打包添加
BuildPipeline.SetAssetBundleEncryptKey("ssssssssbytes01");
读取AB 包添加
AssetBundle.SetAssetBundleDecryptKey("ssssssssbytes01");
3:so文件的加密
so加密两种方式:一种是通过直接加密so 文件,在读取的路口解密。目前采用加密so映射文件global-metadata.dat,解密是通过在global=metadata.data文件的地方解密,这种方式比较容易实现。
使用HxD Hex Editor工具查看global-metadata.data
?
文件加密:
// test.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include <iostream>
#include <sstream>
#include <string>
#include <fstream>
#include <Windows.h>
using namespace std;
#define FLUSH_NUM 8
//获取文件长度
int getLeng(char* src)
{
long l, m;
ifstream fio(src, ios::in);
l = fio.tellg();
fio.seekg(0, ios::end);
m = fio.tellg();
return m - l;
}
// 加密 文件
void copyFile(const char* src, const char* dst)
{
char a[5] = "hxhz";
unsigned char b = (unsigned char)a;
ifstream in(src, ios::in | ios::out | ios::binary);
if (!in.is_open()) {
cout << "error open file " << src << endl;
exit(EXIT_FAILURE);
}
char *bytes;
int length_ = getLeng((char*)src);
bytes = (char *)malloc(length_);
in.read(bytes, length_);
//读取字节流 异或加密
for (int i = 0; i < length_; i++)
{
bytes[i] = bytes[i] ^ a[i % 5];
}
int totalBytes = 0;
in.close();
ofstream out(dst, ios::binary);
if (!out.is_open()) {
cout << "error open file " << dst << endl;
exit(EXIT_FAILURE);
}
out.write(bytes, length_);
out.close();
}
//得到执行路径
string GetProgramDir()
{
wchar_t exeFullPath[MAX_PATH]; // Full path
string strPath = "";
GetModuleFileName(NULL, exeFullPath, MAX_PATH);
char CharString[MAX_PATH];
size_t convertedChars = 0;
wcstombs_s(&convertedChars, CharString, MAX_PATH, exeFullPath, _TRUNCATE);
strPath = (string)CharString; // Get full path of the file
int pos = strPath.find_last_of('\\', strPath.length());
return strPath.substr(0, pos); // Return the directory without the file name
}
int main()
{
//获取编译路径 和global-metadata.dat 同一级目录可以直接执行
string path = GetProgramDir();
string rel = (std::string(path) + string("/global-metadata.dat"));
cout << rel << endl;
copyFile(rel.c_str(), rel.c_str());
}
解密方式:
需要修改编辑器代码:
unity 安装路径:
unity\Editor\Data\il2cpp\libil2cpp\vm? ?对应??MetadataLoader.cpp
unity\Editor\Data\il2cpp\libil2cpp\utils? 对应? ? ? MemoryMappedFile.cpp
修改的地方 MetadataLoader.cpp:
void* il2cpp::vm::MetadataLoader::LoadMetadataFile(const char* fileName)
{
std::string resourcesDirectory = utils::PathUtils::Combine(utils::Runtime::GetDataDir(), utils::StringView<char>("Metadata"));
std::string resourceFilePath = utils::PathUtils::Combine(resourcesDirectory, utils::StringView<char>(fileName, strlen(fileName)));
#if __ENABLE_UNITY_PLUGIN__
if (g_get_global_metadata != 0 && fileName[1] == 'a')
{
return g_get_global_metadata(resourceFilePath.c_str());
}
#endif // __ENABLE_UNITY_PLUGIN__
int error = 0;
os::FileHandle* handle = os::File::Open(resourceFilePath, kFileModeOpen, kFileAccessRead, kFileShareRead, kFileOptionsNone, &error);
if (error != 0)
{
utils::Logging::Write("ERROR: Could not open %s", resourceFilePath.c_str());
return NULL;
}
int64_t length = 0;
int error2 = 0;
length = os::File::GetLength(handle, &error2);
void* fileBuffer = utils::MemoryMappedFile::Map(handle);
os::File::Close(handle, &error);
if (error != 0)
{
utils::MemoryMappedFile::Unmap(fileBuffer);
fileBuffer = NULL;
return NULL;
}
//添加的部分
char *data = (char*)malloc(length);
memcpy(data, fileBuffer, length);//拷贝
//解密返回
void* result= utils::MemoryMappedFile::DecryptFile(data, length);
return (void*)result; 返回解密的结果
}
修改MemoryMappedFile.cpp
添加的部分
//混淆文件的字节 返回解密结果
void* MemoryMappedFile::DecryptFile(char* data, int64_t length)
{
char *result;
result = (char*)malloc(length);
char a[5] = "hxhz";
for (int i = 0; i < length; i++)
{
result[i] = data[i] ^ a[i%5];
}
return result;
}
4:dex加密
参考文章:https://blog.csdn.net/LVEfrist/article/details/101061370
原理和流程都有,也是用过这个方式实现项目dex的加密和解密。保持一个疑问,就是Android版本问题,提供的接口可能不存在,需要多版本测试。
基本看文章就可以实现。下面只是做些补充:
?
5:Java 混淆? ? ? ?
Android自带的混淆方式
?
?gradle.properties添加android.enableR8 =true
工具:AssetStudio,HxD Hex Editor ,apktool,ILSpy,IDA ,dex2jar,il2cppdumper
? ? ??
|