如何从头开始写一个 Native App

date
Dec 18, 2023
slug
how-to-write-first-native-app
status
Published
tags
Windows Internals
Native App
summary
这篇内容介绍了如何在Windows中编写第一个本地应用程序(Native App)
type
Post

引言

在 Windows 中,我们的进程通常都运行在一个叫 Windows 的子系统上。在 Windows 子系统上分为 console、GUI 等子系统。进程如果想要调用系统 API,通常都需要先调用子系统的 API,来做一次转换。简单结构如下:
notion image
而这里我们说的 Native App 呢,它是不依赖任何子系统,可以直接通过 ntdll.dll 来调用系统 API 的。简单结构如下:
notion image

Native App 的优势

对比普通的 Win32 或者说其他子系统应用,主要有以下几个优势
  • 性能好。使用 native 接口,可以绕过标准 Windows 应用程序接口,从而去掉一个软件层,可以加快运行速度。
  • 功能强大。标准 Windows Api 无法提供的功能,也可能通过 Native Api 来实现。
  • 依赖少。不依赖子系统的 dll,减少很多依赖。
  • 灵活性好。此应用不依赖子系统,所以不用等子系统启动后才能运行。

开发 Hello Native

创建项目

VS 中是没有 native 应用的模板的,所以这里我们先创建一个 console app,然后基于 cosnole app 来进行修改部分配置即可。
notion image
创建完成后,选择项目,鼠标右键弹出菜单,选择【属性】,如下图:
notion image

开始修改配置

按如下图配置,依次修改:
notion image
notion image
notion image
然后我们要处理一下默认依赖了:
首先将 【Ignore All Default Libraries】选择【Yes】
然后,添加其他的依赖。
这里需要注意的是,由于在标准的 ntdll.lib 中没有列出 ntdll.dll 中实现的 CRT 函数,因此链接可能出现问题。所以这里我们采用一个三方库:
ntdll
FyyreUpdated Feb 27, 2024
Clone 下来,编译下就好了:
编译后,会生成 ntdll64.libntdll86.lib 。在 Windows 64 位系统上,选择 ntdll64.lib 即可。然后再 额外依赖中添加对应的 lib 文件即可。
总体配置如下:
notion image
💡
这里也可以通过 LdrGetDllHandleLdrGetProcedureAddress 来做。但相对比较麻烦。如果不需要用到 swprintf_s 是不需要这一步的,用普通的 ntdll.dll 就可以

开始写代码

不同于普通应用,Native App 的入口函数是 NtProcessStartup ,这里我们给出简单的示例:
这里逻辑是先获取系统版本号,然后将它打印在屏幕上。
有读者可能会好奇,phnt_windows 和 phnt 是什么?
由于 Windows 中各种头文件的依赖,所以直接采用一个三方的头文件库。
phnt
winsiderssUpdated Mar 15, 2024

通过 vcpkg.exe 安装 phnt

  • clone 源代码
  • 运行安装脚本
  • 集成到 VS
  • 安装 phnt

编译

然后就可以编译通过啦。会得到一个 exe 文件。如下图:
notion image

怎么跑起来

当你双击这个 exe 尝试运行的时候,会发现根本无法运行。
notion image
这是因为 Native app 没法在子系统模式下运行。这里我们可以参考 autochk 的运行方式。
将 exe 文件拷贝到 system32 文件夹中,然后再打开注册表编辑器,切换到 HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager ,在 BootExecute key 上添加一个 HelloNative。如下图:
notion image
然后重启,就可以看到在用户登录之前,显示 Windows 版本的提示了。
notion image
也就是我们的第一个 native app。

© Frend Guo 2022 - 2024