-
Notifications
You must be signed in to change notification settings - Fork 32
/
Copy pathNative.cpp
254 lines (212 loc) · 6.75 KB
/
Native.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
#include "pch.h"
#include "Native.h"
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <fstream>
#include <sys/stat.h>
#include <random>
#include <climits>
#include <sstream>
#include <direct.h>
#include "File.hpp"
using namespace std;
static random_device s_seed; //硬件生成随机种子
static ranlux48 s_randomEngine(s_seed()); //利用种子生成随机数引擎
static uniform_int_distribution<unsigned int> s_uint_distrib(UINT_MAX / 2, UINT_MAX);
static LogCallback s_logCallback = NULL;
static char version[] = "1.0.0";
unsigned int get_random_uint() {
return s_uint_distrib(s_randomEngine);
}
void CopyTo(const char* s, const char* d) {
std::ifstream src(s, std::ios::binary);
std::ofstream dst(d, std::ios::binary);
dst << src.rdbuf();
}
bool Contain(const char* path, const char* dest) {
std::ifstream infile(path, std::ios::in | std::ios::binary | std::ios::ate);
size_t size = infile.tellg();
infile.seekg(0, std::ios::beg);
char* buffer = new char[size];
infile.read(buffer, size);
infile.close();
std::string alltext(buffer, size);
delete[] buffer;
return alltext.find(dest) != std::string::npos;
}
//加密混淆核心逻辑
char* encrtypt_file(char* src, size_t& file_size) {
//随机密钥长度
uniform_int_distribution<int> key_distrib(130, 140);
int kl = key_distrib(s_randomEngine);
//随机密钥的数组指针
unsigned int* p_passwordArr = new unsigned int[kl];
for (int i = 0; i < kl; i++)
{
p_passwordArr[i] = get_random_uint();
}
//加密区长度 单位:int指针
int klsize = (kl + 1) * sizeof(uint32_t);
const int safe_size = 1024;//安全区大小
//加密区大小
const size_t encrtypt_size = file_size - safe_size;
//申请一个新的内存卡 它将包含密码和源文件
char* des = (char*)malloc(file_size + klsize);
//将安全区代码Cpy到新的内存块
memcpy(des, src, safe_size);
//密文区指针
unsigned int* da = (unsigned int*)(des + safe_size);
//加密源码区指针
unsigned int* db = (unsigned int*)(src + safe_size);
//密文区首四个字节低十六位为加密密文数组长度
*(da++) = (get_random_uint() & 0xFFFF0000) | (kl & 0xFFFF);
//写入密码组
memcpy(da, p_passwordArr, kl * sizeof(uint32_t));
//指向加密区
da += kl;
for (size_t i = 0; i < encrtypt_size; i += 4) {
int index = (i + (i / kl)) % kl;
da[i / 4] = p_passwordArr[index] ^ db[i / 4];
}
file_size += klsize;
delete[] p_passwordArr;
return des;
}
//大端转换小端
int get_little_endian(unsigned int x) {
return ((x >> 24) & 0xff) | ((x << 8) & 0xff0000) | ((x >> 8) & 0xff00) | ((x << 24) & 0xff000000);
}
//文件是否存在
bool file_exist(const char* path) {
struct stat _Stat;
if (stat(path, &_Stat) != 0) {
return false;
}
return true;
}
//输出日志
void Log(const char* fmt, ...) {
if (s_logCallback == NULL)return;
char acLogStr[512];// = { 0 };
va_list ap;
va_start(ap, fmt);
vsprintf(acLogStr, fmt, ap);
va_end(ap);
s_logCallback(acLogStr, strlen(acLogStr));
}
//外部调用
void OverrideLoader(char* path) {
Log("override Loader code...");
char* workpath = _getcwd(NULL, 0);
Log(workpath);
if (NULL == path || strcmp(path, "") == 0) {
free(workpath);
workpath = NULL;
return;
}
string localpath = workpath;
string new_loaderCpp = localpath + "\\Assets/EasyObfuscation/Editor/local/vm_MetadataLoader.cpp";
string new_memoryMappedFileH = localpath + "\\Assets/EasyObfuscation/Editor/local/utils_MemoryMappedFile.h";
string new_memoryMappedFileCpp = localpath + "\\Assets/EasyObfuscation/Editor/local/utils_MemoryMappedFile.cpp";
if (!file_exist(new_loaderCpp.c_str()))
{
Log("miss: %s", new_loaderCpp.c_str());
return;
}
if (!file_exist(new_memoryMappedFileH.c_str()))
{
Log("miss: %s", new_memoryMappedFileH.c_str());
return;
}
if (!file_exist(new_memoryMappedFileCpp.c_str()))
{
Log("miss: %s", new_memoryMappedFileCpp.c_str());
return;
}
string dest = path;
string dest_loaderCpp = dest + "\\unityLibrary\\src\\main\\Il2CppOutputProject\\IL2CPP\\libil2cpp\\vm\\MetadataLoader.cpp";
string dest_memoryMappedFileH = dest + "\\unityLibrary\\src\\main\\Il2CppOutputProject\\IL2CPP\\libil2cpp\\utils\\MemoryMappedFile.h";
string dest_memoryMappedFileCpp = dest + "\\unityLibrary\\src\\main\\Il2CppOutputProject\\IL2CPP\\libil2cpp\\utils\\MemoryMappedFile.cpp";
if (!file_exist(dest_loaderCpp.c_str()))
{
Log("error: not found dest loaderCpp");
return;
}
if (!file_exist(dest_memoryMappedFileH.c_str()))
{
Log("error: not found dest memoryMapped head file");
return;
}
if (!file_exist(dest_memoryMappedFileCpp.c_str()))
{
Log("error: not found dest memoryMapped source file");
return;
}
if (File::Extract((dest + "\\unityLibrary\\src\\main\\assets\\bin\\Data\\data.unity3d").c_str(), 0x12, 11) != "2021.3.22f1") {
//避免不同版本il2cpp源码不同 导致可能能正常跑起来 但是线上会引发崩溃
Log("version erro: must be 2021.3.22f1");
return;
}
CopyTo(new_loaderCpp.c_str(), dest_loaderCpp.c_str());
CopyTo(new_memoryMappedFileCpp.c_str(), dest_memoryMappedFileCpp.c_str());
CopyTo(new_memoryMappedFileH.c_str(), dest_memoryMappedFileH.c_str());
if (workpath != NULL) {
free(workpath);
workpath = NULL;
}
Log("owner: 31games");
Log("anchor: https://geek7.blog.csdn.net/");
Log("email: [email protected]");
Log("override Loader code complete.");
}
//外部调用
void EncryptionCode(char* export_android_path)
{
if (NULL == export_android_path || strcmp(export_android_path, "") == 0) {
Log("export android path is null: %s", export_android_path);
return;
}
//wait input
string global_metadata_path = export_android_path;
if (NULL == strstr(global_metadata_path.c_str(), "global-metadata.dat")) {
global_metadata_path += "\\unityLibrary\\src\\main\\assets\\bin\\Data\\Managed\\Metadata\\global-metadata.dat";
}
//cheack file vaild
if (!file_exist(global_metadata_path.c_str())) {
Log("file not found: %s\n", global_metadata_path);
return;
}
Log("EasyObfuscation version: %s", version);
//load file
ifstream infile(global_metadata_path, ios::in | ios::binary | ios::ate);
size_t size = infile.tellg();
infile.seekg(0, ios::beg);
char* buffer = new char[size];
infile.read(buffer, size);
infile.close();
//encrtypt
size_t srcsize = size;
char* encbuffer = encrtypt_file(buffer, size);
ofstream outfile(global_metadata_path, ios::out | ios::binary | ios::ate);
if (!outfile) {
Log("open file fail: %s\n", global_metadata_path);
return;
}
//log
unsigned int* hex_buffer = (unsigned int*)buffer;
unsigned int* hex_encbuffer = (unsigned int*)encbuffer;
unsigned int src_value = get_little_endian(*hex_buffer);
unsigned int enc_value = get_little_endian(*hex_encbuffer);
Log("src: %x\tsrc buffer size: %ld\nenc: %x\tenc buffer size: %ld", src_value, srcsize, enc_value, size);
outfile.write(encbuffer, size);
outfile.close();
delete[] buffer;
free(encbuffer);
Log("call cpp complete.");
}
//日志回调接口
void SetDisplayLog(LogCallback callback)
{
s_logCallback = callback;
}