首页
课程
问答
CTF
社区
招聘
峰会
发现
排行榜
知识库
工具下载
看雪20年
看雪商城
证书查询
登录
注册
首页
社区
课程
招聘
发现
问答
CTF
排行榜
知识库
工具下载
峰会
看雪商城
证书查询
社区
逆向工程
发新帖
0
2
[原创]Windows Flutter加载app.so过程
发表于: 2026-8-3 21:28
365
[原创]Windows Flutter加载app.so过程
WolfSpicy
2026-8-3 21:28
365
# Windows Flutter 是怎么加载 app.so 的? > 从 `wWinMain` 一路跟到 `Dart_LoadELF`:为什么 Windows 上会出现一个「不像 Windows」的 `.so` 遇到 Windows 版 Flutter 程序时,我一直有个疑问: **`data\app.so` 明明不是 PE,Windows 也不能 `LoadLibrary` 这种东西,它到底是怎么被加载进来的?** 结论先说: - `app.so` 本质是 **ELF 壳子包着的 Dart AOT 快照** - Windows 不会拿系统加载器去加载它 - Flutter / Dart 自己实现了一套 **ELF Loader**,用 `CreateFileMapping` / `MapViewOfFile` 一类接口把文件映射进进程 - 映射完以后,再从里面抽出 VM / Isolate 的 snapshot 数据,交给 Dart VM 跑 下面按源码调用链,从 exe 入口一路跟到真正打开 `app.so` 的地方。 示例程序以常见 Flutter Windows runner 为准(文中用 `Reqable.exe` 作示意),源码主要来自 Flutter / Engine / Dart SDK 公开仓库。 --- ## 0. 总体流程先看一眼 先把整条链路摊开,后面每一节都在填这个骨架: ```text wWinMain [YourApp.exe] DartProject(L"data") FlutterWindow::Create / OnCreate │ ▼ FlutterViewController(w, h, project) [client_wrapper,链进 exe] │ new FlutterEngine(project) │ FlutterDesktopEngineCreate(&props) ← IAT → flutter_windows.dll │ FlutterDesktopViewControllerCreate ▼ flutter_windows.dll FlutterProjectBundle(props) ← 相对路径 → 绝对路径 FlutterWindowsEngine::Run │ LoadAotData() │ FlutterEngineCreateAOTData(ElfPath = ...\data\app.so) ▼ CreateFileMapping / MapViewOfFile ← 按 ELF 映射,不是 LoadLibrary │ ▼ 进程中出现 app.so 映射区,Dart AOT 开始跑 ``` 读这条链路时,抓住两个分界就够了: 1. **exe → dll**:`FlutterDesktopEngineCreate` 开始,真正进 `flutter_windows.dll` 2. **路径 → 内存**:`FlutterEngineCreateAOTData` → `Dart_LoadELF`,这里才真正「打开」`app.so` --- ## 1. 入口:`wWinMain` 模板源码: <a href="elink@f84K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6Y4K9i4c8Z5N6h3u0Q4x3X3g2U0L8$3#2Q4x3V1k6X3L8s2g2@1N6r3g2J5i4K6u0r3k6X3I4#2N6s2c8W2M7W2)9J5c8X3u0D9L8$3u0Q4x3V1k6E0j5i4y4@1k6i4u0Q4x3V1k6H3j5h3y4C8j5h3N6W2M7#2)9J5c8X3k6D9N6i4c8@1k6i4u0Q4y4h3k6@1L8$3!0D9M7#2)9J5c8Y4c8W2L8i4m8D9j5i4c8W2M7#2)9J5c8X3q4H3M7q4)9J5c8Y4N6A6L8X3c8G2N6%4y4Q4x3X3g2@1L8i4m8D9i4K6u0r3M7Y4g2F1L8X3g2J5i4K6u0r3L8h3q4A6L8W2)9J5k6h3y4H3M7q4)9J5k6i4c8E0M7r3H3`."><mark class="encrypted">b4bK9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6Y4K9i4c8Z5N6h3u0Q4x3X3g2U0L8$3#2Q4x3V1k6X3L8s2g2@1N6r3g2J5i4K6u0r3k6X3I4#2N6s2c8W2M7W2)9J5c8X3u0D9L8$3u0Q4x3V1k6E0j5i4y4@1k6i4u0Q4x3V1k6H3j5h3y4C8j5h3N6W2M7#2)9J5c8X3k6D9N6i4c8@1k6i4u0Q4y4h3k6@1L8$3!0D9M7#2)9J5c8Y4c8W2L8i4m8D9j5i4c8W2M7#2)9J5c8X3q4H3M7q4)9J5c8Y4N6A6L8X3c8G2N6%4y4Q4x3X3g2@1L8i4m8D9i4K6u0r3M7Y4g2F1L8X3g2J5i4K6u0r3L8h3q4A6L8W2)9J5k6h3y4H3M7q4)9J5k6i4c8E0M7r3H3`.</mark></a>  *图 1 `main.cpp`:红线标出的三行,才是后续整条链路的起点* 核心代码: ```cpp int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev, _In_ wchar_t *command_line, _In_ int show_command) { if (!::AttachConsole(ATTACH_PARENT_PROCESS) && ::IsDebuggerPresent()) { CreateAndAttachConsole(); } ::CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED); flutter::DartProject project(L"data"); std::vector<std::string> command_line_arguments = GetCommandLineArguments(); project.set_dart_entrypoint_arguments(std::move(command_line_arguments)); FlutterWindow window(project); Win32Window::Point origin(10, 10); Win32Window::Size size(1280, 720); if (!window.Create(L"{{projectName}}", origin, size)) { return EXIT_FAILURE; } window.SetQuitOnClose(true); ::MSG msg; while (::GetMessage(&msg, nullptr, 0, 0)) { ::TranslateMessage(&msg); ::DispatchMessage(&msg); } ::CoUninitialize(); return EXIT_SUCCESS; } ``` 真正要盯的是这三行: ```cpp flutter::DartProject project(L"data"); FlutterWindow window(project); if (!window.Create(L"{{projectName}}", origin, size)) { ``` 大白话: 1. 告诉 Flutter:「资源目录就在 exe 旁边的 `data`」 2. 把这个 project 塞进窗口对象 3. `Create` 时才会真正拉起引擎、建视图、后面才会碰到 `app.so` 前面那些 `AttachConsole` / `CoInitializeEx` / 消息循环,都是普通 Win32 壳子,跟 `app.so` 加载关系不大。 --- ## 2. `DartProject("data")`:把三个关键文件路径拼出来 头文件: <a href="elink@c55K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6Y4K9i4c8Z5N6h3u0Q4x3X3g2U0L8$3#2Q4x3V1k6X3L8s2g2@1N6r3g2J5i4K6u0V1N6r3g2S2L8g2)9J5k6r3q4J5j5$3S2A6N6X3g2Q4x3V1k6W2L8X3N6A6L8X3g2Q4x3V1k6T1L8r3!0T1i4K6u0r3L8h3q4A6L8W2)9J5c8Y4y4Z5k6h3I4D9i4K6u0r3M7r3I4S2N6r3k6G2M7X3#2Q4x3V1k6%4K9h3&6V1L8%4N6K6i4K6u0r3j5$3I4A6k6h3&6@1i4K6g2X3N6%4u0S2M7s2m8W2M7W2)9J5c8X3W2F1j5$3I4#2k6r3g2Q4x3V1k6X3L8s2g2@1N6r3g2J5i4K6u0r3k6r3q4J5N6q4)9#2k6Y4m8J5L8$3A6W2j5%4c8Q4x3X3g2Z5"><mark class="encrypted">847K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6Y4K9i4c8Z5N6h3u0Q4x3X3g2U0L8$3#2Q4x3V1k6X3L8s2g2@1N6r3g2J5i4K6u0V1N6r3g2S2L8g2)9J5k6r3q4J5j5$3S2A6N6X3g2Q4x3V1k6W2L8X3N6A6L8X3g2Q4x3V1k6T1L8r3!0T1i4K6u0r3L8h3q4A6L8W2)9J5c8Y4y4Z5k6h3I4D9i4K6u0r3M7r3I4S2N6r3k6G2M7X3#2Q4x3V1k6%4K9h3&6V1L8%4N6K6i4K6u0r3j5$3I4A6k6h3&6@1i4K6g2X3N6%4u0S2M7s2m8W2M7W2)9J5c8X3W2F1j5$3I4#2k6r3g2Q4x3V1k6X3L8s2g2@1N6r3g2J5i4K6u0r3k6r3q4J5N6q4)9#2k6Y4m8J5L8$3A6W2j5%4c8Q4x3X3g2Z5</mark></a>  *图 2 传入 `"data"` 后,直接拼出 `flutter_assets` / `icudtl.dat` / `app.so`* ```cpp explicit DartProject(const std::wstring& path) { assets_path_ = path + L"\\flutter_assets"; icu_data_path_ = path + L"\\icudtl.dat"; aot_library_path_ = path + L"\\app.so"; } ``` 也就是说,传进去的 `"data"` 会立刻变成: | 成员 | 相对路径 | 用途 | | --- | --- | --- | | `assets_path_` | `data\flutter_assets` | 资源、字体、AssetManifest 等 | | `icu_data_path_` | `data\icudtl.dat` | ICU 数据,国际化 / 文本相关 | | `aot_library_path_` | `data\app.so` | **Dart AOT 快照本体** | 注意:这里还只是「相对路径字符串」,还没映射文件,更没有进 Dart VM。 后面 `FlutterProjectBundle` 才会拿 exe 所在目录,把它们补成绝对路径。 --- ## 3. `window.Create` → `FlutterWindow::OnCreate` 模板源码: <a href="elink@cfbK9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6Y4K9i4c8Z5N6h3u0Q4x3X3g2U0L8$3#2Q4x3V1k6X3L8s2g2@1N6r3g2J5i4K6u0r3k6X3I4#2N6s2c8W2M7W2)9J5c8X3u0D9L8$3u0Q4x3V1k6E0j5i4y4@1k6i4u0Q4x3V1k6H3j5h3y4C8j5h3N6W2M7#2)9J5c8X3k6D9N6i4c8@1k6i4u0Q4y4h3k6@1L8$3!0D9M7#2)9J5c8Y4c8W2L8i4m8D9j5i4c8W2M7#2)9J5c8X3q4H3M7q4)9J5c8Y4N6A6L8X3c8G2N6%4y4Q4x3X3g2@1L8i4m8D9i4K6u0r3M7Y4g2F1L8X3g2J5i4K6u0r3k6X3I4#2N6s2c8W2M7W2)9#2k6Y4N6A6L8X3c8G2N6#2)9J5k6h3y4H3M7l9`.`."><mark class="encrypted">532K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6Y4K9i4c8Z5N6h3u0Q4x3X3g2U0L8$3#2Q4x3V1k6X3L8s2g2@1N6r3g2J5i4K6u0r3k6X3I4#2N6s2c8W2M7W2)9J5c8X3u0D9L8$3u0Q4x3V1k6E0j5i4y4@1k6i4u0Q4x3V1k6H3j5h3y4C8j5h3N6W2M7#2)9J5c8X3k6D9N6i4c8@1k6i4u0Q4y4h3k6@1L8$3!0D9M7#2)9J5c8Y4c8W2L8i4m8D9j5i4c8W2M7#2)9J5c8X3q4H3M7q4)9J5c8Y4N6A6L8X3c8G2N6%4y4Q4x3X3g2@1L8i4m8D9i4K6u0r3M7Y4g2F1L8X3g2J5i4K6u0r3k6X3I4#2N6s2c8W2M7W2)9#2k6Y4N6A6L8X3c8G2N6#2)9J5k6h3y4H3M7l9`.`.</mark></a>  *图 3 窗口创建成功后,马上 new 一个 `FlutterViewController`* ```cpp bool FlutterWindow::OnCreate() { if (!Win32Window::OnCreate()) { return false; } RECT frame = GetClientArea(); flutter_controller_ = std::make_unique<flutter::FlutterViewController>( frame.right - frame.left, frame.bottom - frame.top, project_); if (!flutter_controller_->engine() || !flutter_controller_->view()) { return false; } RegisterPlugins(flutter_controller_->engine()); SetChildContent(flutter_controller_->view()->GetNativeWindow()); flutter_controller_->engine()->SetNextFrameCallback([&]() { this->Show(); }); flutter_controller_->ForceRedraw(); return true; } ``` 这里的关键动作只有一句: ```cpp flutter_controller_ = std::make_unique<flutter::FlutterViewController>(...); ``` 窗口本身不负责加载 `app.so`。 它只是在 OnCreate 时把 `project_` 交给 `FlutterViewController`,后面的引擎初始化、Run、加载 AOT,都从这里开始往下掉。 --- ## 4. `FlutterViewController`:创建 Engine,再创建 View 源码: <a href="elink@db0K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6Y4K9i4c8Z5N6h3u0Q4x3X3g2U0L8$3#2Q4x3V1k6X3L8s2g2@1N6r3g2J5i4K6u0V1N6r3g2S2L8g2)9J5k6r3q4J5j5$3S2A6N6X3g2Q4x3V1k6W2L8X3N6A6L8X3g2Q4x3V1k6T1L8r3!0T1i4K6u0r3L8h3q4A6L8W2)9J5c8Y4y4Z5k6h3I4D9i4K6u0r3M7r3I4S2N6r3k6G2M7X3#2Q4x3V1k6%4K9h3&6V1L8%4N6K6i4K6u0r3j5$3I4A6k6h3&6@1i4K6g2X3N6%4u0S2M7s2m8W2M7W2)9J5c8X3k6D9N6i4c8@1k6i4u0Q4y4h3k6$3K9h3g2%4i4K6g2X3j5$3!0F1N6s2u0G2L8r3I4W2M7W2)9J5k6h3y4U0"><mark class="encrypted">922K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6Y4K9i4c8Z5N6h3u0Q4x3X3g2U0L8$3#2Q4x3V1k6X3L8s2g2@1N6r3g2J5i4K6u0V1N6r3g2S2L8g2)9J5k6r3q4J5j5$3S2A6N6X3g2Q4x3V1k6W2L8X3N6A6L8X3g2Q4x3V1k6T1L8r3!0T1i4K6u0r3L8h3q4A6L8W2)9J5c8Y4y4Z5k6h3I4D9i4K6u0r3M7r3I4S2N6r3k6G2M7X3#2Q4x3V1k6%4K9h3&6V1L8%4N6K6i4K6u0r3j5$3I4A6k6h3&6@1i4K6g2X3N6%4u0S2M7s2m8W2M7W2)9J5c8X3k6D9N6i4c8@1k6i4u0Q4y4h3k6$3K9h3g2%4i4K6g2X3j5$3!0F1N6s2u0G2L8r3I4W2M7W2)9J5k6h3y4U0</mark></a>  *图 4 先 `FlutterEngine(project)`,再 `FlutterDesktopViewControllerCreate`* ```cpp FlutterViewController::FlutterViewController(int width, int height, const DartProject& project) { engine_ = std::make_shared<FlutterEngine>(project); controller_ = FlutterDesktopViewControllerCreate(width, height, engine_->RelinquishEngine()); if (!controller_) { std::cerr << "Failed to create view controller." << std::endl; return; } view_ = std::make_unique<FlutterView>( FlutterDesktopViewControllerGetView(controller_)); } ``` 顺序很重要: 1. **先造 Engine**:把 `assets / icu / app.so` 路径塞进引擎属性 2. **再造 ViewController**:把引擎和窗口视图绑在一起,并在合适时机 `Run()` 可以把它理解成: - Engine = 脑子(Dart VM + AOT) - View = 脸(HWND / 渲染表面) - ViewController = 把脑子和脸接起来的中间层 --- ## 5. `FlutterEngine`:组装属性,准备跨进 dll 源码: <a href="elink@351K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6Y4K9i4c8Z5N6h3u0Q4x3X3g2U0L8$3#2Q4x3V1k6X3L8s2g2@1N6r3g2J5i4K6u0r3k6h3&6Y4K9h3&6W2i4K6u0r3j5X3I4G2j5W2)9J5c8X3#2S2K9h3&6Q4x3V1k6K6K9r3g2D9L8q4)9J5c8Y4m8D9j5i4c8X3L8%4u0E0i4K6u0r3N6$3W2F1k6r3!0%4M7#2)9J5c8X3y4D9K9h3g2F1N6q4)9#2k6Y4N6J5j5i4m8H3k6i4u0Q4x3V1k6X3L8s2g2@1N6r3g2J5i4K6g2X3k6h3&6Y4K9h3&6W2i4K6u0W2j5$3x3`."><mark class="encrypted">244K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6Y4K9i4c8Z5N6h3u0Q4x3X3g2U0L8$3#2Q4x3V1k6X3L8s2g2@1N6r3g2J5i4K6u0r3k6h3&6Y4K9h3&6W2i4K6u0r3j5X3I4G2j5W2)9J5c8X3#2S2K9h3&6Q4x3V1k6K6K9r3g2D9L8q4)9J5c8Y4m8D9j5i4c8X3L8%4u0E0i4K6u0r3N6$3W2F1k6r3!0%4M7#2)9J5c8X3y4D9K9h3g2F1N6q4)9#2k6Y4N6J5j5i4m8H3k6i4u0Q4x3V1k6X3L8s2g2@1N6r3g2J5i4K6g2X3k6h3&6Y4K9h3&6W2i4K6u0W2j5$3x3`.</mark></a>  *图 5 把 project 里的路径填进 C 结构体,然后调用 `FlutterDesktopEngineCreate`* ```cpp FlutterEngine::FlutterEngine(const DartProject& project) { FlutterDesktopEngineProperties c_engine_properties = {}; c_engine_properties.assets_path = project.assets_path().c_str(); c_engine_properties.icu_data_path = project.icu_data_path().c_str(); c_engine_properties.aot_library_path = project.aot_library_path().c_str(); c_engine_properties.dart_entrypoint = project.dart_entrypoint().c_str(); // ... 处理 dart_entrypoint_argc / argv ... engine_ = FlutterDesktopEngineCreate(&c_engine_properties); auto core_messenger = FlutterDesktopEngineGetMessenger(engine_); messenger_ = std::make_unique<BinaryMessengerImpl>(core_messenger); } ``` 到这里为止,代码大多还在 **exe 侧的 client_wrapper**。 真正的分水岭是: ```cpp engine_ = FlutterDesktopEngineCreate(&c_engine_properties); ``` 这个符号来自 `flutter_windows.dll`。 对 PE 来说,就是 IAT 里的一次跨模块调用:**exe 把路径信息递过去,dll 接手后面的事。** --- ## 6. 进入 `flutter_windows.dll`:`FlutterDesktopEngineCreate` 源码: <a href="elink@9d1K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6Y4K9i4c8Z5N6h3u0Q4x3X3g2U0L8$3#2Q4x3V1k6X3L8s2g2@1N6r3g2J5i4K6u0r3k6h3&6Y4K9h3&6W2i4K6u0r3j5X3I4G2j5W2)9J5c8X3#2S2K9h3&6Q4x3V1k6K6K9r3g2D9L8q4)9J5c8Y4m8D9j5i4c8X3L8%4u0E0i4K6u0r3N6$3W2F1k6r3!0%4M7#2)9J5c8X3k6D9N6i4c8@1k6i4u0Q4y4h3k6%4K9h3&6V1L8%4N6K6i4K6u0W2j5$3x3`."><mark class="encrypted">09cK9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6Y4K9i4c8Z5N6h3u0Q4x3X3g2U0L8$3#2Q4x3V1k6X3L8s2g2@1N6r3g2J5i4K6u0r3k6h3&6Y4K9h3&6W2i4K6u0r3j5X3I4G2j5W2)9J5c8X3#2S2K9h3&6Q4x3V1k6K6K9r3g2D9L8q4)9J5c8Y4m8D9j5i4c8X3L8%4u0E0i4K6u0r3N6$3W2F1k6r3!0%4M7#2)9J5c8X3k6D9N6i4c8@1k6i4u0Q4y4h3k6%4K9h3&6V1L8%4N6K6i4K6u0W2j5$3x3`.</mark></a>  *图 6 exe → dll 的分界点* ```cpp FlutterDesktopEngineRef FlutterDesktopEngineCreate( const FlutterDesktopEngineProperties* engine_properties) { flutter::FlutterProjectBundle project(*engine_properties); auto engine = std::make_unique<flutter::FlutterWindowsEngine>(project); return HandleForEngine(engine.release()); } ``` 两件事: 1. `FlutterProjectBundle(props)`:整理 / 解析路径 2. `new FlutterWindowsEngine(project)`:创建真正的 Windows 嵌入层引擎对象 此时 `app.so` 还没加载,只是「引擎对象已经在 dll 里活下来了」。 --- ## 7. `FlutterProjectBundle`:相对路径变绝对路径 源码: <a href="elink@df8K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6Y4K9i4c8Z5N6h3u0Q4x3X3g2U0L8$3#2Q4x3V1k6X3L8s2g2@1N6r3g2J5i4K6u0r3k6h3&6Y4K9h3&6W2i4K6u0r3j5X3I4G2j5W2)9J5c8X3#2S2K9h3&6Q4x3V1k6K6K9r3g2D9L8q4)9J5c8Y4m8D9j5i4c8X3L8%4u0E0i4K6u0r3N6$3W2F1k6r3!0%4M7#2)9J5c8X3k6D9N6i4c8@1k6i4u0Q4y4h3k6H3M7X3!0B7k6h3y4@1i4K6g2X3j5Y4g2F1k6r3I4W2i4K6u0W2j5$3x3`."><mark class="encrypted">247K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6Y4K9i4c8Z5N6h3u0Q4x3X3g2U0L8$3#2Q4x3V1k6X3L8s2g2@1N6r3g2J5i4K6u0r3k6h3&6Y4K9h3&6W2i4K6u0r3j5X3I4G2j5W2)9J5c8X3#2S2K9h3&6Q4x3V1k6K6K9r3g2D9L8q4)9J5c8Y4m8D9j5i4c8X3L8%4u0E0i4K6u0r3N6$3W2F1k6r3!0%4M7#2)9J5c8X3k6D9N6i4c8@1k6i4u0Q4y4h3k6H3M7X3!0B7k6h3y4@1i4K6g2X3j5Y4g2F1k6r3I4W2i4K6u0W2j5$3x3`.</mark></a>  *图 7 `data\app.so` 在这里变成 `C:\...\YourApp\data\app.so`* ```cpp FlutterProjectBundle::FlutterProjectBundle( const FlutterDesktopEngineProperties& properties) : assets_path_(properties.assets_path), icu_path_(properties.icu_data_path) { if (properties.aot_library_path != nullptr) { aot_library_path_ = std::filesystem::path(properties.aot_library_path); } // ... entrypoint 参数处理 ... // Resolve any relative paths. if (assets_path_.is_relative() || icu_path_.is_relative() || (!aot_library_path_.empty() && aot_library_path_.is_relative())) { std::filesystem::path executable_location = GetExecutableDirectory(); if (executable_location.empty()) { FML_LOG(ERROR) << "Unable to find executable location to resolve resource paths."; assets_path_ = std::filesystem::path(); icu_path_ = std::filesystem::path(); } else { assets_path_ = std::filesystem::path(executable_location) / assets_path_; icu_path_ = std::filesystem::path(executable_location) / icu_path_; if (!aot_library_path_.empty()) { aot_library_path_ = std::filesystem::path(executable_location) / aot_library_path_; } } } } ``` `properties.aot_library_path` 就是外面一路传下来的 `data\app.so`。 这里做的事情非常朴素: ```text exe 目录 + data\app.so → 绝对路径 ``` 后面所有「打开文件 / 映射文件」都以这个绝对路径为准。 所以你在 x64dbg / Process Hacker 里看模块/映射区时,看到的也通常是带完整路径的那个 `app.so`。 --- ## 8. `FlutterDesktopViewControllerCreate`:准备 Run 源码同在 `flutter_windows.cc`:  *图 8 对外 API 很薄,真正逻辑在 `CreateViewController`* ```cpp FlutterDesktopViewControllerRef FlutterDesktopViewControllerCreate( int width, int height, FlutterDesktopEngineRef engine) { return CreateViewController(engine, width, height, /*owns_engine=*/true); } ``` 继续看同文件里的 `CreateViewController`:  *图 9 红圈处:`controller->engine()->Run()`,引擎真正启动* ```cpp static FlutterDesktopViewControllerRef CreateViewController( FlutterDesktopEngineRef engine_ref, int width, int height, bool owns_engine) { flutter::FlutterWindowsEngine* engine_ptr = EngineFromHandle(engine_ref); std::unique_ptr<flutter::WindowBindingHandler> window_wrapper = std::make_unique<flutter::FlutterWindow>( width, height, engine_ptr->windows_proc_table()); std::unique_ptr<flutter::FlutterWindowsEngine> engine; if (owns_engine) { engine = std::unique_ptr<flutter::FlutterWindowsEngine>(engine_ptr); } std::unique_ptr<flutter::FlutterWindowsView> view = engine_ptr->CreateView(std::move(window_wrapper)); if (!view) { return nullptr; } auto controller = std::make_unique<flutter::FlutterWindowsViewController>( std::move(engine), std::move(view)); // Launch the engine if it is not running already. if (!controller->engine()->running()) { if (!controller->engine()->Run()) { return nullptr; } } controller->view()->SendInitialBounds(); controller->engine()->UpdateAccessibilityFeatures(); return HandleForViewController(controller.release()); } ``` 重点就这一句: ```cpp controller->engine()->Run(); ``` 前面那么长的链路,本质都是在给 `Run()` 准备参数和对象。 真正开始「加载 AOT、拉起 Dart」是从这里起步的。 --- ## 9. `FlutterWindowsEngine::Run` → `LoadAotData` 源码: <a href="elink@589K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6Y4K9i4c8Z5N6h3u0Q4x3X3g2U0L8$3#2Q4x3V1k6X3L8s2g2@1N6r3g2J5i4K6u0r3k6h3&6Y4K9h3&6W2i4K6u0r3j5X3I4G2j5W2)9J5c8X3#2S2K9h3&6Q4x3V1k6K6K9r3g2D9L8q4)9J5c8Y4m8D9j5i4c8X3L8%4u0E0i4K6u0r3N6$3W2F1k6r3!0%4M7#2)9J5c8X3k6D9N6i4c8@1k6i4u0Q4y4h3k6%4K9h3&6V1L8%4N6K6i4K6g2X3k6h3&6Y4K9h3&6W2i4K6u0W2j5$3x3`."><mark class="encrypted">280K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6Y4K9i4c8Z5N6h3u0Q4x3X3g2U0L8$3#2Q4x3V1k6X3L8s2g2@1N6r3g2J5i4K6u0r3k6h3&6Y4K9h3&6W2i4K6u0r3j5X3I4G2j5W2)9J5c8X3#2S2K9h3&6Q4x3V1k6K6K9r3g2D9L8q4)9J5c8Y4m8D9j5i4c8X3L8%4u0E0i4K6u0r3N6$3W2F1k6r3!0%4M7#2)9J5c8X3k6D9N6i4c8@1k6i4u0Q4y4h3k6%4K9h3&6V1L8%4N6K6i4K6g2X3k6h3&6Y4K9h3&6W2i4K6u0W2j5$3x3`.</mark></a> `Run()` 本身比较长,这里不整段粘贴。对加载 `app.so` 来说,只要盯住这一句: ```cpp aot_data_ = project_->LoadAotData(embedder_api_); ```  *图 10 引擎 Run 时,会让 project 去加载 AOT 数据* 含义很直白: - `project_` 知道 `aot_library_path_`(也就是绝对路径版 `app.so`) - `embedder_api_` 提供 `CreateAOTData` 这类函数指针 - `LoadAotData` 负责把「路径」变成「可交给 Dart VM 的 AOT 数据结构」 --- ## 10. `LoadAotData`:声明「我要加载的是 ELF 路径」 源码仍在: <a href="elink@a18K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6Y4K9i4c8Z5N6h3u0Q4x3X3g2U0L8$3#2Q4x3V1k6X3L8s2g2@1N6r3g2J5i4K6u0r3k6h3&6Y4K9h3&6W2i4K6u0r3j5X3I4G2j5W2)9J5c8X3#2S2K9h3&6Q4x3V1k6K6K9r3g2D9L8q4)9J5c8Y4m8D9j5i4c8X3L8%4u0E0i4K6u0r3N6$3W2F1k6r3!0%4M7#2)9J5c8X3k6D9N6i4c8@1k6i4u0Q4y4h3k6H3M7X3!0B7k6h3y4@1i4K6g2X3j5Y4g2F1k6r3I4W2i4K6u0W2j5$3x3`."><mark class="encrypted">8b6K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6Y4K9i4c8Z5N6h3u0Q4x3X3g2U0L8$3#2Q4x3V1k6X3L8s2g2@1N6r3g2J5i4K6u0r3k6h3&6Y4K9h3&6W2i4K6u0r3j5X3I4G2j5W2)9J5c8X3#2S2K9h3&6Q4x3V1k6K6K9r3g2D9L8q4)9J5c8Y4m8D9j5i4c8X3L8%4u0E0i4K6u0r3N6$3W2F1k6r3!0%4M7#2)9J5c8X3k6D9N6i4c8@1k6i4u0Q4y4h3k6H3M7X3!0B7k6h3y4@1i4K6g2X3j5Y4g2F1k6r3I4W2i4K6u0W2j5$3x3`.</mark></a>  *图 11 红圈:明确告诉引擎,AOT 源是 ELF 文件路径* ```cpp UniqueAotDataPtr FlutterProjectBundle::LoadAotData( const FlutterEngineProcTable& engine_procs) { if (aot_library_path_.empty()) { FML_LOG(ERROR) << "Attempted to load AOT data, but no aot_library_path was provided."; return UniqueAotDataPtr(nullptr, nullptr); } if (!std::filesystem::exists(aot_library_path_)) { FML_LOG(ERROR) << "Can't load AOT data from " << aot_library_path_.u8string() << "; no such file."; return UniqueAotDataPtr(nullptr, nullptr); } std::string path_string = aot_library_path_.u8string(); FlutterEngineAOTDataSource source = {}; source.type = kFlutterEngineAOTDataSourceTypeElfPath; source.elf_path = path_string.c_str(); FlutterEngineAOTData data = nullptr; auto result = engine_procs.CreateAOTData(&source, &data); if (result != kSuccess) { FML_LOG(ERROR) << "Failed to load AOT data from: " << path_string; return UniqueAotDataPtr(nullptr, nullptr); } return UniqueAotDataPtr(data, engine_procs.CollectAOTData); } ``` 这里有两个很值的点: 1. **先检查文件在不在** 所以你把 `data\app.so` 删了 / 改名了,程序往往直接起不来,日志也会很直白。 2. **source.type 写死是 `ElfPath`** 说明 Flutter 从一开始就没打算把它当 Windows DLL 处理,而是明确按 **ELF 文件** 去读。 接下来就进入 embedder 层的 `FlutterEngineCreateAOTData`。 --- ## 11. `FlutterEngineCreateAOTData` → `Dart_LoadELF` 源码: <a href="elink@f7cK9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6Y4K9i4c8Z5N6h3u0Q4x3X3g2U0L8$3#2Q4x3V1k6X3L8s2g2@1N6r3g2J5i4K6u0r3k6h3&6Y4K9h3&6W2i4K6u0r3j5X3I4G2j5W2)9J5c8X3#2S2K9h3&6Q4x3V1k6K6K9r3g2D9L8q4)9J5c8Y4m8D9j5i4c8X3L8%4u0E0i4K6u0r3k6h3#2T1k6h3c8V1k6i4u0Q4x3V1k6W2L8h3u0W2k6r3c8W2M7W2)9J5k6h3y4U0"><mark class="encrypted">306K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6Y4K9i4c8Z5N6h3u0Q4x3X3g2U0L8$3#2Q4x3V1k6X3L8s2g2@1N6r3g2J5i4K6u0r3k6h3&6Y4K9h3&6W2i4K6u0r3j5X3I4G2j5W2)9J5c8X3#2S2K9h3&6Q4x3V1k6K6K9r3g2D9L8q4)9J5c8Y4m8D9j5i4c8X3L8%4u0E0i4K6u0r3k6h3#2T1k6h3c8V1k6i4u0Q4x3V1k6W2L8h3u0W2k6r3c8W2M7W2)9J5k6h3y4U0</mark></a>  *图 12 红圈:Windows 上真正打开 app.so 的关键调用* ```cpp FlutterEngineResult FlutterEngineCreateAOTData( const FlutterEngineAOTDataSource* source, FlutterEngineAOTData* data_out) { if (!flutter::DartVM::IsRunningPrecompiledCode()) { return LOG_EMBEDDER_ERROR(kInvalidArguments, "AOT data can only be created in AOT mode."); } else if (!source) { return LOG_EMBEDDER_ERROR(kInvalidArguments, "Null source specified."); } else if (!data_out) { return LOG_EMBEDDER_ERROR(kInvalidArguments, "Null data_out specified."); } switch (source->type) { case kFlutterEngineAOTDataSourceTypeElfPath: { if (!source->elf_path || !fml::IsFile(source->elf_path)) { return LOG_EMBEDDER_ERROR(kInvalidArguments, "Invalid ELF path specified."); } auto aot_data = std::make_unique<_FlutterEngineAOTData>(); const char* error = nullptr; #if OS_FUCHSIA Dart_LoadedElf* loaded_elf = nullptr; #else Dart_LoadedElf* loaded_elf = Dart_LoadELF( source->elf_path, // file path 0, // file offset &error, // error (out) &aot_data->vm_snapshot_data, // vm snapshot data (out) &aot_data->vm_snapshot_instrs, // vm snapshot instr (out) &aot_data->vm_isolate_data, // vm isolate data (out) &aot_data->vm_isolate_instrs // vm isolate instr (out) ); #endif if (loaded_elf == nullptr) { return LOG_EMBEDDER_ERROR(kInvalidArguments, error); } aot_data->loaded_elf.reset(loaded_elf); *data_out = aot_data.release(); return kSuccess; } } return LOG_EMBEDDER_ERROR( kInvalidArguments, "Invalid FlutterEngineAOTDataSourceType type specified."); } ``` 到这里,谜底基本揭开了: ### 11.1 为什么 Windows 上也叫 `app.so`? 因为 Flutter / Dart 的 AOT 产物,跨平台统一用了 **ELF 容器** 来打包 snapshot。 名字带 `.so`,不代表它要走 Linux 动态链接那一套,更不代表 Windows 会当 DLL 加载。 ### 11.2 为什么不是 `LoadLibrary`? 因为 `LoadLibrary` 只认 PE。 `app.so` 是 ELF,系统加载器直接拒绝。Flutter 的选择是: > **自己解析 ELF,自己映射段,自己把 snapshot 指针交回给 Dart VM。** 实现入口就在 Dart SDK: <a href="elink@119K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6Y4K9i4c8Z5N6h3u0Q4x3X3g2U0L8$3#2Q4x3V1k6V1j5i4u0@1i4K6u0V1L8r3q4F1k6#2)9J5c8Y4y4V1K9#2)9J5c8X3u0D9L8$3u0Q4x3V1k6E0j5h3W2F1i4K6u0r3M7Y4g2F1N6r3W2E0k6g2)9J5c8X3u0A6L8W2)9J5c8X3g2D9k6W2)9#2k6X3I4G2j5h3c8W2M7W2)9J5k6h3y4U0"><mark class="encrypted">41fK9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6Y4K9i4c8Z5N6h3u0Q4x3X3g2U0L8$3#2Q4x3V1k6V1j5i4u0@1i4K6u0V1L8r3q4F1k6#2)9J5c8Y4y4V1K9#2)9J5c8X3u0D9L8$3u0Q4x3V1k6E0j5h3W2F1i4K6u0r3M7Y4g2F1N6r3W2E0k6g2)9J5c8X3u0A6L8W2)9J5c8X3g2D9k6W2)9#2k6X3I4G2j5h3c8W2M7W2)9J5k6h3y4U0</mark></a> 在 Windows 上,这套自研 loader 最终会落到文件映射一类 API(你在概览里写的 `CreateFileMapping` / `MapViewOfFile`),而不是 `LoadLibrary`。 ### 11.3 `Dart_LoadELF` 吐出来的四块是什么? | 输出 | 大致含义 | | --- | --- | | `vm_snapshot_data` | VM 快照数据(只读数据为主) | | `vm_snapshot_instrs` | VM 快照指令 | | `vm_isolate_data` | Isolate 快照数据(应用侧对象/元数据更多在这边) | | `vm_isolate_instrs` | Isolate 快照指令(应用 AOT 代码主要在这边) | 可以粗暴理解成: - 前两块更偏 **Dart VM 自己** - 后两块更偏 **你的 App 逻辑** 所以后面做符号恢复、池分析、看伪代码,很多时候真正关心的就是从这份 AOT 快照里挖出来的东西。 --- ## 12. 串起来:一句话复盘 把整条链压缩成人话: 1. `wWinMain` 里用 `DartProject("data")` 声明资源目录 2. `DartProject` 直接拼出 `data\app.so` 3. `FlutterWindow::OnCreate` 创建 `FlutterViewController` 4. `FlutterEngine` 组装属性,经 IAT 跨进 `flutter_windows.dll` 5. `FlutterProjectBundle` 把相对路径补成绝对路径 6. `ViewController` 创建时调用 `engine->Run()` 7. `Run` → `LoadAotData` → `FlutterEngineCreateAOTData` 8. 最终 `Dart_LoadELF(app.so)`:按 ELF 映射文件,抽出 4 块 snapshot 9. Dart VM 拿到预编译快照,AOT 代码开始跑 所以回到最初那个问题: > **Windows Flutter 为什么能加载一个不符合 Windows 格式的 `app.so`?** 因为它根本没让 Windows 去「加载模块」,而是让 Dart 自己把这个 ELF 快照文件 **映射进进程、解析出 snapshot、喂给 VM**。 --- ## 13. 对逆向有什么直接帮助 如果你后面要跟 Windows Flutter: 1. **先确认目录特征** `data\app.so` + `flutter_windows.dll` + `flutter_assets`,基本就能定性。 2. **别指望 IDA 直接当普通 DLL 看懂 `app.so`** 它不是常规导入导出那套语义,核心在 Dart AOT。 3. **动态看加载点** 关注 `FlutterEngineCreateAOTData` / `Dart_LoadELF` 前后,进程里会出现 `app.so` 的映射区。 4. **静态跟链路时记住分界** exe 侧 client_wrapper 只是壳;真正加载发生在 `flutter_windows.dll` + Dart ELF loader。 5. **符号问题另说** 映射进来不等于可读。要把函数名/对象池弄出来,还得靠 Blutter 一类基于同版本 Dart VM 的导出方案(Windows 适配是另一条线)。 --- ## 参考链接 - runner 入口模板: <a href="elink@19bK9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6Y4K9i4c8Z5N6h3u0Q4x3X3g2U0L8$3#2Q4x3V1k6X3L8s2g2@1N6r3g2J5i4K6u0r3k6X3I4#2N6s2c8W2M7W2)9J5c8X3u0D9L8$3u0Q4x3V1k6E0j5i4y4@1k6i4u0Q4x3V1k6H3j5h3y4C8j5h3N6W2M7#2)9J5c8X3k6D9N6i4c8@1k6i4u0Q4y4h3k6@1L8$3!0D9M7#2)9J5c8Y4c8W2L8i4m8D9j5i4c8W2M7#2)9J5c8X3q4H3M7q4)9J5c8Y4N6A6L8X3c8G2N6%4y4Q4x3X3g2@1L8i4m8D9i4K6u0r3M7Y4g2F1L8X3g2J5i4K6u0r3L8h3q4A6L8W2)9J5k6h3y4H3M7q4)9J5k6i4c8E0M7r3H3`.">main.cpp.tmpl</a> - `DartProject`: <a href="elink@782K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6Y4K9i4c8Z5N6h3u0Q4x3X3g2U0L8$3#2Q4x3V1k6X3L8s2g2@1N6r3g2J5i4K6u0V1N6r3g2S2L8g2)9J5k6r3q4J5j5$3S2A6N6X3g2Q4x3V1k6W2L8X3N6A6L8X3g2Q4x3V1k6T1L8r3!0T1i4K6u0r3L8h3q4A6L8W2)9J5c8Y4y4Z5k6h3I4D9i4K6u0r3M7r3I4S2N6r3k6G2M7X3#2Q4x3V1k6%4K9h3&6V1L8%4N6K6i4K6u0r3j5$3I4A6k6h3&6@1i4K6g2X3N6%4u0S2M7s2m8W2M7W2)9J5c8X3W2F1j5$3I4#2k6r3g2Q4x3V1k6X3L8s2g2@1N6r3g2J5i4K6u0r3k6r3q4J5N6q4)9#2k6Y4m8J5L8$3A6W2j5%4c8Q4x3X3g2Z5">dart_project.h</a> - `FlutterWindow::OnCreate`: <a href="elink@3b7K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6Y4K9i4c8Z5N6h3u0Q4x3X3g2U0L8$3#2Q4x3V1k6X3L8s2g2@1N6r3g2J5i4K6u0r3k6X3I4#2N6s2c8W2M7W2)9J5c8X3u0D9L8$3u0Q4x3V1k6E0j5i4y4@1k6i4u0Q4x3V1k6H3j5h3y4C8j5h3N6W2M7#2)9J5c8X3k6D9N6i4c8@1k6i4u0Q4y4h3k6@1L8$3!0D9M7#2)9J5c8Y4c8W2L8i4m8D9j5i4c8W2M7#2)9J5c8X3q4H3M7q4)9J5c8Y4N6A6L8X3c8G2N6%4y4Q4x3X3g2@1L8i4m8D9i4K6u0r3M7Y4g2F1L8X3g2J5i4K6u0r3k6X3I4#2N6s2c8W2M7W2)9#2k6Y4N6A6L8X3c8G2N6#2)9J5k6h3y4H3M7l9`.`.">flutter_window.cpp</a> - `FlutterViewController`: <a href="elink@3f8K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6Y4K9i4c8Z5N6h3u0Q4x3X3g2U0L8$3#2Q4x3V1k6X3L8s2g2@1N6r3g2J5i4K6u0V1N6r3g2S2L8g2)9J5k6r3q4J5j5$3S2A6N6X3g2Q4x3V1k6W2L8X3N6A6L8X3g2Q4x3V1k6T1L8r3!0T1i4K6u0r3L8h3q4A6L8W2)9J5c8Y4y4Z5k6h3I4D9i4K6u0r3M7r3I4S2N6r3k6G2M7X3#2Q4x3V1k6%4K9h3&6V1L8%4N6K6i4K6u0r3j5$3I4A6k6h3&6@1i4K6g2X3N6%4u0S2M7s2m8W2M7W2)9J5c8X3k6D9N6i4c8@1k6i4u0Q4y4h3k6$3K9h3g2%4i4K6g2X3j5$3!0F1N6s2u0G2L8r3I4W2M7W2)9J5k6h3y4U0">flutter_view_controller.cc</a> - `FlutterEngine`: <a href="elink@97cK9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6Y4K9i4c8Z5N6h3u0Q4x3X3g2U0L8$3#2Q4x3V1k6X3L8s2g2@1N6r3g2J5i4K6u0r3k6h3&6Y4K9h3&6W2i4K6u0r3j5X3I4G2j5W2)9J5c8X3#2S2K9h3&6Q4x3V1k6K6K9r3g2D9L8q4)9J5c8Y4m8D9j5i4c8X3L8%4u0E0i4K6u0r3N6$3W2F1k6r3!0%4M7#2)9J5c8X3y4D9K9h3g2F1N6q4)9#2k6Y4N6J5j5i4m8H3k6i4u0Q4x3V1k6X3L8s2g2@1N6r3g2J5i4K6g2X3k6h3&6Y4K9h3&6W2i4K6u0W2j5$3x3`.">flutter_engine.cc</a> - Windows embedder API: <a href="elink@4d1K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6Y4K9i4c8Z5N6h3u0Q4x3X3g2U0L8$3#2Q4x3V1k6X3L8s2g2@1N6r3g2J5i4K6u0r3k6h3&6Y4K9h3&6W2i4K6u0r3j5X3I4G2j5W2)9J5c8X3#2S2K9h3&6Q4x3V1k6K6K9r3g2D9L8q4)9J5c8Y4m8D9j5i4c8X3L8%4u0E0i4K6u0r3N6$3W2F1k6r3!0%4M7#2)9J5c8X3k6D9N6i4c8@1k6i4u0Q4y4h3k6%4K9h3&6V1L8%4N6K6i4K6u0W2j5$3x3`.">flutter_windows.cc</a> - `FlutterProjectBundle` / `LoadAotData`: <a href="elink@e7bK9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6Y4K9i4c8Z5N6h3u0Q4x3X3g2U0L8$3#2Q4x3V1k6X3L8s2g2@1N6r3g2J5i4K6u0r3k6h3&6Y4K9h3&6W2i4K6u0r3j5X3I4G2j5W2)9J5c8X3#2S2K9h3&6Q4x3V1k6K6K9r3g2D9L8q4)9J5c8Y4m8D9j5i4c8X3L8%4u0E0i4K6u0r3N6$3W2F1k6r3!0%4M7#2)9J5c8X3k6D9N6i4c8@1k6i4u0Q4y4h3k6H3M7X3!0B7k6h3y4@1i4K6g2X3j5Y4g2F1k6r3I4W2i4K6u0W2j5$3x3`.">flutter_project_bundle.cc</a> - `FlutterWindowsEngine::Run`: <a href="elink@3bfK9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6Y4K9i4c8Z5N6h3u0Q4x3X3g2U0L8$3#2Q4x3V1k6X3L8s2g2@1N6r3g2J5i4K6u0r3k6h3&6Y4K9h3&6W2i4K6u0r3j5X3I4G2j5W2)9J5c8X3#2S2K9h3&6Q4x3V1k6K6K9r3g2D9L8q4)9J5c8Y4m8D9j5i4c8X3L8%4u0E0i4K6u0r3N6$3W2F1k6r3!0%4M7#2)9J5c8X3k6D9N6i4c8@1k6i4u0Q4y4h3k6%4K9h3&6V1L8%4N6K6i4K6g2X3k6h3&6Y4K9h3&6W2i4K6u0W2j5$3x3`.">flutter_windows_engine.cc</a> - `FlutterEngineCreateAOTData`: <a href="elink@0f6K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6Y4K9i4c8Z5N6h3u0Q4x3X3g2U0L8$3#2Q4x3V1k6X3L8s2g2@1N6r3g2J5i4K6u0r3k6h3&6Y4K9h3&6W2i4K6u0r3j5X3I4G2j5W2)9J5c8X3#2S2K9h3&6Q4x3V1k6K6K9r3g2D9L8q4)9J5c8Y4m8D9j5i4c8X3L8%4u0E0i4K6u0r3k6h3#2T1k6h3c8V1k6i4u0Q4x3V1k6W2L8h3u0W2k6r3c8W2M7W2)9J5k6h3y4U0">embedder.cc</a> - `Dart_LoadELF`: <a href="elink@647K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6Y4K9i4c8Z5N6h3u0Q4x3X3g2U0L8$3#2Q4x3V1k6V1j5i4u0@1i4K6u0V1L8r3q4F1k6#2)9J5c8Y4y4V1K9#2)9J5c8X3u0D9L8$3u0Q4x3V1k6E0j5h3W2F1i4K6u0r3M7Y4g2F1N6r3W2E0k6g2)9J5c8X3u0A6L8W2)9J5c8X3g2D9k6W2)9#2k6X3I4G2j5h3c8W2M7W2)9J5k6h3y4U0">elf_loader.cc</a> --- *— 完 —* > 学习研究用途。文中示例程序名仅作示意,请支持正版软件。
传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!!
收藏
・
0
点赞
・
2
打赏
分享
分享到微信
分享到QQ
分享到微博
赞赏记录
参与人
雪币
留言
时间
梧桐生
非常支持你的观点!
2026-8-4 10:01
新气象
谢谢你的细致分析,受益匪浅!
2026-8-4 00:14
查看更多
赞赏
×
1 雪花
5 雪花
10 雪花
20 雪花
50 雪花
80 雪花
100 雪花
150 雪花
200 雪花
支付方式:
微信支付
赞赏留言:
快捷留言
感谢分享~
精品文章~
原创内容~
精彩转帖~
助人为乐~
感谢分享~
最新回复
(
0
)
游客
登录
|
注册
方可回帖
回帖
表情
雪币赚取及消费
高级回复
返回
WolfSpicy
6
发帖
4
回帖
0
RANK
关注
私信
他的文章
[原创]Windows Flutter加载app.so过程
365
[原创]1.13.7Typora离线授权逆向
1177
[原创]typora的launch.dist.js解读
954
[原创]V8 JSC反编译成JS
1534
[原创]x64dbg追踪完美解决方案
1593
关于我们
联系我们
企业服务
看雪公众号
专注于PC、移动、智能设备安全研究及逆向工程的开发者社区
看原图
赞赏
×
雪币:
+
留言:
快捷留言
为你点赞!
返回
顶部