.net PublishSingleFile 打包程序提取

.net PublishSingleFile 打包程序提取

<PublishSingleFile>true</PublishSingleFile>

该部分内容为AI生成,仅供参考

.NET 的单文件发布模式会将所有应用程序代码、依赖项(包括运行时可能需要的依赖)以及运行时本身(如果选择自包含)都打包到一个单独的可执行文件中。这个可执行文件就像一个"容器"或"压缩包"。

  • 运行机制:当运行这个单文件应用程序时,.NET 运行时会根据需要将内部的文件解压到临时目录(例如 %TEMP%\.net\ 下特定名称的文件夹)然后加载运行,或者从内存中直接加载(.NET 5+ 更先进的模式)。
  • corehost 的角色corehost(如 hostfxrhostpolicy)是 .NET 运行时宿主组件,负责查找和初始化 .NET 运行时,解析依赖关系,并引导应用程序执行。它的主要任务是运行应用程序,

提取 Bundle 的常用方法

以下是更常用的从 .NET 单文件应用程序中提取内容的方法:

  1. 运行时提取(适用于基于磁盘解压的模式)
    这是最简单的方法,尤其适用于 .NET Core 3.x 早期版本的模式。
    步骤

    • 运行打包好的单文件 EXE 程序。
    • 在程序运行期间(切勿关闭程序),打开文件资源管理器。
    • 在地址栏输入 %TEMP% 并回车,进入当前用户的临时文件夹。
    • 在临时目录中查找类似 .net\你的应用程序名\ 或带有随机字符串名称的文件夹。
    • 在这个文件夹内,你就可以找到被解压出来的所有程序集(DLL)、配置文件(如 appsettings.json)、资源文件等。

    注意

    • 此方法需要你能成功运行目标程序。
    • 程序退出后,操作系统可能会自动清理这些临时文件。
    • 对于 .NET 5 及更高版本中使用更高阶模式(内存加载)发布的单文件,此方法可能无效,因为文件不会解压到磁盘。

分界线

工具

SingleFileExtractor (低版本)

(未测试)

Droppers/SingleFileExtractor: A tool for extracting contents (assemblies, configuration, etc.) from a single-file application to a directory, suitable for purposes like malware analysis.

SelfContainedExtractor (.NET 5+)

LukeFZ/SelfContainedExtractor: Standalone extractor for .NET 5+ self-contained executables.

(仅测试.NET 9)

修复offsetStr hex解析bug

https://github.com/LukeFZ/SelfContainedExtractor/blob/master/DotNetSelfContainedExtractor/Program.cs#L26

                var parseResult = offsetStr.StartsWith("0x")
                    ? int.TryParse(offsetStr, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out offset)
                    : int.TryParse(offsetStr, CultureInfo.InvariantCulture, out offset);

==>

                var parseResult = offsetStr.StartsWith("0x")
                    ? int.TryParse(offsetStr.Substring(2), NumberStyles.HexNumber, CultureInfo.InvariantCulture, out offset)
                    : int.TryParse(offsetStr, CultureInfo.InvariantCulture, out offset);

去除Bundle.FindBundleOffset 函数(.net 9不适用,其他版本未知),必须指定参数 [bundle file offset]

定位offset

搜索字符串:“Bundle Header Offset:”,对应源码:https://github.com/dotnet/runtime/blob/main/src/native/corehost/corehost.cpp#L232

          bundle_header_offset_ = placeholder__locator_bundle_header_offset;
          v35 = v71;
          if ( n7_6 > 7 )
            v35 = (void **)v71[0];

          trace::info_1405C81E0(L"Invoking fx resolver [%s] hostfxr_main_bundle_startupinfo", v35);
          v36 = v59;
          if ( si128.m128i_i64[1] > 7ui64 )
            v36 = (void **)v59[0];

          trace::info_1405C81E0(L"Host path: [%s]", v36);
          v37 = &v68;
          if ( n7_5 > 7 )
            v37 = (__int128 *)v68;

          trace::info_1405C81E0(L"Dotnet path: [%s]", v37);
          v38 = v57;
          if ( *((_QWORD *)&v58 + 1) > 7ui64 )
            v38 = (void **)v57[0];

          trace::info_1405C81E0(L"App path: [%s]", v38);
          trace::info_1405C81E0(L"Bundle Header Offset: [%lld]", bundle_header_offset_);

注意该指针存储的是文件偏移,(使用SelfContainedExtractor 指定参数时 不需要再计算偏移):

.data:00000001407D9CE8 ; __int64 placeholder__locator_bundle_header_offset
.data:00000001407D9CE8 placeholder__locator_bundle_header_offset dq 62C9E26h


//示例中为dq 62C9E26h,则参数可指定为0x62C9E26 或者 103587366 (10进制则无需修改SelfContainedExtractor 工具代码)
posted @ 2025-09-14 22:50  DirWangK  阅读(56)  评论(0)    收藏  举报