c# 如何將程式加密隱藏?

c# 如何將程式加密隱藏?

居間如何通過litedb將自己的程式進行加密,實現居間一下litedb。

最后更新 2023/8/15 下午8:23
tokengo
预计阅读 6 分钟
分类
.NET
标签
.NET C#

下面將居間如何通過 litedb 將自己的程式進行加密,實現居間一下 litedb。

LiteDB

litedb 是一個輕量級的嵌入式資料庫,它是用 c#編寫的,適用於.net 平台。它的設計目標是提供一個簡單易用的資料庫解決方案,可以在各種應用程式中使用。

litedb 使用單個文件作為資料庫存儲,這個文件可以在磁碟上或內存中。它支持文檔存儲模型,類似於 nosql 資料庫,每個文檔都是一個 json 格式的對象。這意味著你可以存儲和檢索任意類型的數據,而不需要預定義模式。

litedb 提供了一組簡單的 api 來執行各種資料庫操作,包括插入、更新、刪除和查詢。它還支持事務,可以確保數據的一致性和完整性。

litedb 還提供了一些高級功能,如索引、全文搜索和文件存儲。索引可以加快查詢的速度,全文搜索可以在文本數據中進行關鍵字搜索,文件存儲可以將文件直接存儲在資料庫中。

litedb 的優點包括易於使用、輕量級、快速和可嵌入性。它的代碼庫非常小,可以很容易地集成到你的應用程式中。此外,它還具有跨平台的能力,可以在 windows、linux 和 mac 等作業系統上運行。

總之,litedb 是一個簡單易用的嵌入式資料庫,適用於各種應用程式。它提供了一組簡單的 api 來執行資料庫操作,並支持一些高級功能。如果你需要一個輕量級的資料庫解決方案,可以考慮使用 litedb。

加密封裝

创建LiteDB.Service的 WebApi 项目。

右鍵發布:

创建控制台LiteDB.Launch项目。

EntryPointDiscoverer.cs 用于寻找执行方法。

internal class EntryPointDiscoverer
{
    public static MethodInfo FindStaticEntryMethod(Assembly assembly, string? entryPointFullTypeName = null)
    {
        var candidates = new List<MethodInfo>();

        if (!string.IsNullOrWhiteSpace(entryPointFullTypeName))
        {
            var typeInfo = assembly.GetType(entryPointFullTypeName, false, false)?.GetTypeInfo();
            if (typeInfo == null)
            {
                throw new InvalidProgramException($"Could not find '{entryPointFullTypeName}' specified for Main method. See <StartupObject> project property.");
            }
            FindMainMethodCandidates(typeInfo, candidates);
        }
        else
        {
            foreach (var type in assembly
                         .DefinedTypes
                         .Where(t => t.IsClass)
                         .Where(t => t.GetCustomAttribute<CompilerGeneratedAttribute>() is null))
            {
                FindMainMethodCandidates(type, candidates);
            }
        }

        string MainMethodFullName()
        {
            return string.IsNullOrWhiteSpace(entryPointFullTypeName) ? "Main" : $"{entryPointFullTypeName}.Main";
        }

        if (candidates.Count > 1)
        {
            throw new AmbiguousMatchException(
                $"Ambiguous entry point. Found multiple static functions named '{MainMethodFullName()}'. Could not identify which method is the main entry point for this function.");
        }

        if (candidates.Count == 0)
        {
            throw new InvalidProgramException(
                $"Could not find a static entry point '{MainMethodFullName()}'.");
        }

        return candidates[0];
    }

    private static void FindMainMethodCandidates(TypeInfo type, List<MethodInfo> candidates)
    {
        foreach (var method in type
                     .GetMethods(BindingFlags.Static |
                                 BindingFlags.Public |
                                 BindingFlags.NonPublic)
                     .Where(m =>
                         string.Equals("Main", m.Name, StringComparison.OrdinalIgnoreCase)))
        {
            if (method.ReturnType == typeof(void)
                || method.ReturnType == typeof(int)
                || method.ReturnType == typeof(Task)
                || method.ReturnType == typeof(Task<int>))
            {
                candidates.Add(method);
            }
        }
    }
}

然后打开Program.cs文件,请注意修改 SaveDb 的参数为自己项目打包的地址

// 用于打包指定程序。
SaveDb(@"E:\Project\LiteDB-Application\LiteDB.Service\bin\Release\net7.0\publish");

// 打开db
var db = new LiteDatabase("Launch.db");

// 打开表。
var files = db.GetCollection<FileAssembly>("files");

// 接管未找到的程序集处理
AppDomain.CurrentDomain.AssemblyResolve += (sender, eventArgs) =>
{
    try
    {
        var name = eventArgs.Name.Split(",")[0];
        if (!name.EndsWith(".dll"))
        {
            name += ".dll";
        }

        var file = files.FindOne(x => x.Name == name);

        return file != null ? Assembly.Load(file.Bytes) : default;
    }
    catch (Exception)
    {
        return default;
    }
};

// 启动程序。
StartServer("LiteDB.Service", new string[] { });

Console.ReadKey();

void StartServer(string assemblyName, string[] args)
{
    var value = files!.FindOne(x => x.Name == assemblyName + ".dll");
    var assembly = Assembly.Load(value!.Bytes);

    var entryPoint = EntryPointDiscoverer.FindStaticEntryMethod(assembly);

    try
    {
        var parameters = entryPoint.GetParameters();
        if (parameters.Length != 0)
        {
            var parameterValues = parameters.Select(p =>
                    p.ParameterType.IsValueType ? Activator.CreateInstance(p.ParameterType) : null)
                .ToArray();
            entryPoint.Invoke(null, parameterValues);
        }
        else
        {
            entryPoint.Invoke(null, null);
        }
    }
    catch (Exception e)
    {

    }
}


// 扫描指定目录下所有文件和子目录,保存到LiteDB数据库中。
void SaveDb(string path)
{
    var files = ScanDirectory(path);
    using var db = new LiteDatabase("Launch.db");
    var col = db.GetCollection<FileAssembly>("files");
    col.InsertBulk(files);
}

// 实现一个方法,扫描指定目录下所有文件和子目录,返回一个集合。
List<FileAssembly> ScanDirectory(string path)
{
    var files = new List<FileAssembly>();
    var dir = new DirectoryInfo(path);
    var fileInfos = dir.GetFiles("*", SearchOption.AllDirectories);
    foreach (var fileInfo in fileInfos)
    {
        var file = new FileAssembly
        {
            Name = fileInfo.Name,
            Bytes = File.ReadAllBytes(fileInfo.FullName)
        };
        files.Add(file);
    }

    return files;
}

class FileAssembly
{
    /// <summary>
    /// 文件名
    /// </summary>
    public string Name { get; set; }

    /// <summary>
    /// 文件的内容
    /// </summary>
    public byte[] Bytes { get; set; }
}

点击LiteDB.Launch项目文件,添加 LiteDB 依赖,并且修改 SDK 为Microsoft.NET.Sdk.Web

<Project Sdk="Microsoft.NET.Sdk.Web">

    <PropertyGroup>
        <OutputType>Exe</OutputType>
        <TargetFramework>net7.0</TargetFramework>
        <ImplicitUsings>enable</ImplicitUsings>
        <Nullable>enable</Nullable>
    </PropertyGroup>

    <ItemGroup>
      <PackageReference Include="LiteDB" Version="5.0.17" />
    </ItemGroup>

</Project>

在启动项目的时候先将LiteDB.Service发布一下。然后修改SaveDb参数为发布的目录(会自动扫描所有文件打包到 LiteDB 的文件中。)

然後啟動項目;

当我们启动了LiteDB.Launch以后在StartServer方法里面就会打开创建的 LiteDB 文件中搜索到指定的启动程序集。

然后在AppDomain.CurrentDomain.AssemblyResolve中会将启动程序集缺少的程序集加载到域中。

AppDomain.CurrentDomain.AssemblyResolve会在未找到依赖的时候触发的一个事件。

在存储到 LiteDB 的时候可以对于存储的内容进行加密,然后在AppDomain.CurrentDomain.AssemblyResolve触发的时候将读取 LiteDB 的文件的内容的时候进行解密。

結尾

來自 token 的分享

qq 技術交流群:737776595

Keep Exploring

延伸阅读

更多文章
同分类 / 同标签 2026/2/7

aot使用經驗總結

從項目創建伊始,就應養成良好的習慣,即只要添加了新功能或使用了較新的語法,就及時進行 aot 發布測試。

继续阅读