Skip to content

Commit

Permalink
更新代码加固和指令优化相关文档
Browse files Browse the repository at this point in the history
  • Loading branch information
pirunxi committed Jan 13, 2024
1 parent 3334360 commit 182f8cd
Show file tree
Hide file tree
Showing 8 changed files with 274 additions and 174 deletions.
6 changes: 6 additions & 0 deletions docs/basic/aotgeneric.md
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,12 @@ public class AOTGenericReferences : UnityEngine.MonoBehaviour

## 优化补充元数据dll大小

:::tip

是否优化补充元数据不影响补充元数据机制的正常工作,推荐有包体或内存优化压力的项目执行这个操作。

:::

加载补充元数据dll不仅增加了包体或者热更新资源大小,运行时加载也消耗了可观的内存空间,详细见[内存与GC](./memory)文档。优化补充元数据dll大小
对于内存敏感的场合有积极意义。

Expand Down
41 changes: 36 additions & 5 deletions docs/business/basiccodeoptimization.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,45 @@
# 标准指令优化
# 离线指令优化

对常见的代码范式进行谨慎可靠的优化,大幅提升了变量访问(50%-100%)、数值计算(100-300%)、对象访问(50-200%)等常见指令的性能,像一些特殊代码如typeof指令的性能,提升了1000%以上。
:::warning

离线指令优化技术正开发中,目前仅可使用旧版本指令优化技术(即原来的标准指令优化技术)。
:::

离线指令优化(Offline Instruction Optimization,简称OIO)离线将原始IL指令转换为自定义的寄存器指令。
由于离线没有编译性能限制,可以使用更丰富的编译优化技术,极大提升了解释模块的性能。

优化后的指令执行性能整体提升100%-1000%(没看错,10倍以上)甚至更高,尤其是数值指令整体提升近300%。
而且由于已经提前转换,加载和指令翻译过程更快,卡顿更小。

离线指令优化技术支持代码加固方案中的虚拟化技术,极大提升了代码安全。

## 实现

由于运行时的时间及内存限制,标准指令优化只做一些无用栈消除、窥孔优化等等简单但较可靠的优化,无法执行一些复杂的优化。但由于IL指令是栈指令,即使只做了一些不复杂的常见优化,性能相比于社区的未优化版本也有巨幅提升。
高级指令优化技术包含了以下优化技术:

- 彻底的无用栈指令消除。消除掉所有不必要的栈操作
- 窥孔优化
- 常量复制优化
- 局部复制传播优化
- 全局复制传播优化
- 解释函数inline
- AOT函数inline(专利技术)
- 提供更多instinct指令,大幅提升常见的指令组合性能
- 条件检查消除技术。消除不必要的空指针检查、类型强转检查、数组越界检查
- CheckOnce运行时检查动态消除优化。例如访问静态成员变量的指令,在第2次执行时不再检查类型是否已经初始化过
- 其他优化


## 性能

TODO。

## 标准指令优化技术(将废弃)

标准指令优化技术为运行时优化技术。对常见的代码范式进行谨慎可靠的优化,大幅提升了变量访问(50%-100%)、数值计算(100-300%)、对象访问(50-200%)等常见指令的性能,像一些特殊代码如typeof指令的性能,提升了1000%以上。

[高级指令优化](./advancedcodeoptimization)相对标准指令优化,使用了复杂的离线优化技术,性能大幅优于标准指令优化技术
由于运行时的时间及内存限制,标准指令优化只做一些无用栈消除、窥孔优化等等简单但较可靠的优化,无法执行一些复杂的优化。但由于IL指令是栈指令,即使只做了一些不复杂的常见优化,性能相比于社区的未优化版本也有显著提升

## 性能数据

以下是标准指令优化相比于社区版本的解释性能提升数据(0表示性能持平,n表示提升n倍)。

Expand Down
170 changes: 94 additions & 76 deletions docs/business/basicencryption.md
Original file line number Diff line number Diff line change
@@ -1,77 +1,95 @@
# 标准代码加固

社区版本直接加载原始dll,使得开发者不得不携带和下载原始dll,而这些原始dll能够被ILSpy之类的工具反编译
,进行产生严重的安全问题。即使开发者做了加密也很容易被内存中拦截而获得解密后的dll内容。

标准代码加固提供了一定程度的混淆和加密功能,保障了代码安全。

## 实现

开启标准代码加固后,会重构和打乱hybridclr代码,同时改变了dll的解析方式,只能加载加密后的dll。
标准代码加固不仅加密了dll本身,也单独对IL进行了随机变换,即使解密了dll本身也无法被ILSpy之类的
工具解析,可以有效阻止代码被轻松破解。

标准代码加固不像高级代码加固那样做了不可逆的指令集转换,因此防护程度不如高级代码加固。

## 配置

在HybridCLRSettings中启用`enableEncryption`选项,即开启了标准代码加固。开启指令加固后,需要同时配置`encryptionSeed`字段。
该字段是一个int类型值,提供了一个默认值,强烈建议开发者修改此值。

每个不同的`encryptionSeed`会导致`HybridCLR/Genrate/EncryptXXX`指令生成完全不同的hybridclr代码。

## 打包流程

- `HybridCLR/Generate/All`
- 使用`HybridCLR.Editor.Encryption.DllEncrypter`类对 补充元数据dll及热更新dll加密(即使补充元数据dll也需要加密!)
- 将加密后的dll加入你项目的资源管理系统
- 其他与社区版本操作完全相同

## 加密dll

使用`HybridCLR.Editor.Encryption.DllEncrypter`类对 补充元数据dll及热更新dll加密。 下面代码中EncryptDll演示了
如何加密一个dll,EncryptDllsInDirectory演示了如何加密多个dll。

```csharp

public static class EncryptDllCommand
{
public static void EncryptDll(string originalDllFile, string encryptedDllFile)
{
int seed = SettingsUtil.EncryptionSeedOrZeroWhileDisable;
if (seed == 0)
{
Debug.LogWarning($"enableEncryption is false or encryptionSeed == 0, encryption is skipped");
return;
}
var encryptor = new DllEncryptor(seed);
byte[] originBytes = File.ReadAllBytes(originalDllFile);
byte[] encryptedBytes = encryptor.EncryptDll(originBytes);
File.WriteAllBytes(encryptedDllFile, encryptedBytes);
}

public static void EncryptDllsInDirectory(string dllDir)
{
int seed = SettingsUtil.EncryptionSeedOrZeroWhileDisable;
if (seed == 0)
{
Debug.LogWarning($"enableEncryption is false or encryptionSeed == 0, encryption is skipped");
return;
}
var encryptor = new DllEncryptor(seed);
foreach (var dllFile in Directory.GetFiles(dllDir, "*.dll.bytes"))
{
byte[] originBytes = File.ReadAllBytes(dllFile);
byte[] encryptedBytes = encryptor.EncryptDll(originBytes);
File.WriteAllBytes(dllFile, encryptedBytes);
Debug.Log($"EncryptDllsInDirectory {dllFile} length:{encryptedBytes.Length}");
}
}
}
```

## 运行时加载

与社区版本完全相同,直接调用Assembly.Load或RuntimeApi.LoadMetadataForAOTAssembly加载加密后的dll文件内容。
hybridclr会在内部解密,不需要开发者执行额外的解密操作。
# 代码加固

社区版本直接加载原始dll,使得开发者不得不携带和下载原始dll。这些原始dll能够被ILSpy之类的工具反编译
,产生严重的安全问题。即使开发者做了加密也很容易被内存中拦截而获得解密后的dll内容。

我们提供了业内顶级的托管代码加固技术,有效阻止了代码被恶意第三方破解和篡改。


|技术|安全指数|
|-|-|
|元数据加密|:star::star::star::star:|
|结构随机化|:star::star::star:|
|加密随机化|:star::star::star:|
|延迟解密|:star::star::star:|
|虚拟化|:star::star::star::star::star:|
|dll签名|:star::star::star:|

## 元数据加密

|技术|结构随机化|加密随机化|延迟解密|安全指数|
|-|-|-|-|-|
|自定义dll文件结构||||:star:|
|~string流加密||||:star::star:|
|~blob流加密||||:star::star:|
|~US流加密||||:star::star::star:|
|~table流加密||||:star::star::star::star:|
|method body数据加密||||:star::star::star:|


### 自定义dll文件结构

原始dll文件为PE格式,我们改为自定义文件结构,无法使用ILSpy等反编译工具打开。

支持结构随机化技术,也就是每个版本的dll结构都可以完全不一样,显著增加了破解成本。

### ~string流加密

~string流保存了元数据内部使用的字符串,如类型名、字段名之类。对~string流数据加密使得无法从dll文件中直接获得元数据字符串。

支持加密随机化技术,显著增加了离线破解难度。

### ~blob流加密

~blob流保存了一些复杂元数据(如类型签名)。对~blob流加密使得无法从dll文件中直接获得原始lob数据。

支持加密随机化技术,显著增加了离线破解成本。

### ~US流加密

~US流中保存了用户字符串(即代码中使用的字符串)元数据。

支持加密随机化技术,阻止了破解者从dll文件中直接获得原始~US元数据。

支持延迟解密,阻止破解者使用内存dump技术直接还原出所有数据。

### ~table流加密

~table流保存了大多数结构化的元数据。

支持结构随机化技术,每个版本都使用不同的元数据数据结构,大幅增加了破解成本,即使被破解也无法通过简单的数据移动或者复制还原为原始的~table流结构。

支持加密随机化,显著提升了破解成本。

支持延迟解密,阻止破解者使用内存dump技术直接还原出所有数据。


### method body数据加密

method body中保存了函数体元数据信息。

支持加密随机化,显著提升了破解成本。

支持延迟解密,阻止破解者使用内存dump技术直接还原出所有数据。

## 结构随机化技术

结构随机化技术指每次使用完全不同的文件或者元数据的结构,使得破解者需要每个版本都重新破解,极大提升了破解者的成本。

## 加密随机化技术

加密随机化技术指每次使用完全不同的加密技术,使得破解者需要每个版本都重新破解,极大提升了破解者的成本。

## 延迟解密技术

延迟解密技术指第一次才解密数据,有效防止破解者hook关键路径,直接内存dump出完整的原始数据。

## 虚拟化技术

虚拟化技术指将原始IL指令转换为自定义的寄存器虚拟机指令,有效阻止破解者使用现成的反编译工具分析出原始代码。

虚拟化技术支持指令随机化技术,每个版本指令的指令号和长度都不一样,极大增加了破解者的成本。

## dll签名技术

加载dll时检查dll签名,确保来自官方。恶意第三方即使破解了代码,也无法执行篡改后的代码,极大提升了代码安全性。
6 changes: 2 additions & 4 deletions docs/business/intro.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,10 @@
|[完全泛型共享](./fullgenericsharing)|||||
|团结引擎和鸿蒙平台|仅支持2022.3.2t3||||
|[元数据优化](./metadataoptimization.md)|||||
|[标准指令优化](./basiccodeoptimization)|||||
|[标准代码加固](./basicencryption)|||||
|[高级代码加固](./advancedencryption)|||||
|[离线指令优化](./basiccodeoptimization)|||||
|[代码加固](./basicencryption)|||||
|[热重载](./reload/hotreloadassembly)|||||
|[访问控制机制](./accesspolicy)|||||
|[高级指令优化(实验性)](./advancedcodeoptimization)|||||
|[**DHE技术**](./differentialhybridexecution)|||||
|技术支持||1年|2年|2年|

Expand Down
Original file line number Diff line number Diff line change
@@ -1,19 +1,50 @@
# Standard Code Optimization
# Offline Instruction Optimization

Careful and reliable optimization of common code paradigms has greatly improved the performance of common instructions such as variable access (50%-100%), numerical calculations (100-300%), object access (50-200%), etc., like some special The performance of codes such as typeof instructions has been improved by more than 1000%.
:::warning

## Implementation
The offline instruction optimization technology is under development, and currently only the old version of the instruction optimization technology (i.e. the original standard instruction optimization technology) can be used.
:::

Due to runtime time and memory constraints, standard instruction optimization only does some simple but reliable optimizations such as useless stack elimination and peephole optimization, and cannot perform some complex optimizations. However, since the IL instruction is a stack instruction, even if only some common and uncomplicated optimizations are made, the performance is greatly improved compared to the community's unoptimized version.
Offline Instruction Optimization (OIO) converts original IL instructions into customized register instructions offline.
Since there is no compilation performance limit offline, richer compilation optimization technologies can be used, which greatly improves the performance of the interpretation module.

[Advanced instruction optimization] (./advancedcodeoptimization) compared with standard instruction optimization, using complex offline optimization technology, the performance is much better than standard instruction optimization technology.
After optimization, the overall instruction execution performance is improved by 100%-1000% (yes, more than 10 times) or even higher, especially the overall improvement of numerical instructions by nearly 300%.
And because it has been converted in advance, the loading and instruction translation process is faster and the lag is smaller.

## Performance data
Offline instruction optimization technology supports virtualization technology in code reinforcement solutions, greatly improving code security.

The following is the performance improvement data of standard instruction optimization compared to the community version (0 means the performance is the same, n means n times improvement).
## accomplish

Advanced instruction optimization technology includes the following optimization technologies:

- Complete elimination of useless stack instructions. Eliminate all unnecessary stack operations
- Peephole optimization
- Constant copy optimization
- Optimization of local copy propagation
- Global copy propagation optimization
- Explain function inline
- AOT function inline (patented technology)
- Provide more instinct instructions to greatly improve the performance of common instruction combinations
- Conditional check elimination technology. Eliminate unnecessary null pointer checks, type cast checks, and array out-of-bounds checks
- CheckOnce runtime checks dynamically eliminate optimizations. For example, an instruction that accesses a static member variable will no longer check whether the type has been initialized during the second execution.
- Other optimizations


## Performance

TODO.

## Standard instruction optimization technology (will be obsolete)

Standard instruction optimization techniques are runtime optimization techniques. Careful and reliable optimization of common code paradigms has greatly improved the performance of common instructions such as variable access (50%-100%), numerical calculations (100-300%), object access (50-200%), etc., like some special The performance of codes such as typeof instructions has been improved by more than 1000%.

Due to runtime time and memory limitations, standard instruction optimization only performs simple but reliable optimizations such as useless stack elimination and peephole optimization, and cannot perform some complex optimizations. However, since the IL instruction is a stack instruction, even if only some uncomplicated common optimizations are made, the performance is significantly improved compared to the community's unoptimized version.


The following is the performance improvement data of the standard instruction optimization compared to the community version (0 means the performance is the same, n means n times improvement).

![interpreter_optimization](/img/hybridclr/interpreter_optimization.jpg)

The following is a performance comparison between native and standard instruction optimization in terms of numerical calculations. The ordinate is time consumption. The standard instruction optimized addition is about 7-16 times that of the native one, the multiplication is 4 times, and the division is 2 times.

![benchmark_numeric](/img/hybridclr/benchmark_numeric.jpg)
![benchmark_numeric](/img/hybridclr/benchmark_numeric.jpg)
Loading

0 comments on commit 182f8cd

Please sign in to comment.