首页
社区
课程
招聘
[原创]native app开发小结
发表于: 2010-7-30 15:12 29615

[原创]native app开发小结

2010-7-30 15:12
29615

没什么技术含量,开发小结而已。

Native app 程序开发
                        By microDebug
程序类型

关于程序级别的分类,大概可以分为三层:
应用层程序,即普通的APP程序;
Native App程序,如常见的chkdsk工具,PQ分区工具等,都属于这类,它是在win子系统未启动起来就执行的程序,执行环境比较纯净,只能调用ntdll.dll导出的函数;
Driver 内核驱动程序,因功能不同也分为若干类,如设备驱动程序,内核扩展程序,文件系统驱动,过滤驱动等,同属于内核态程序;
其中,native app在项目开发中用的较少,所用的函数接口MS也均未公开,开发难度和驱动相当,所以很少有人问津。但是,事实上,在某些应用场景下,用native app来实现是非常完美的,比如:接管winodws的开机启动界面和密码输入界面,需要native app;在开机前,执行磁盘修复,需要native app;开机前,执行杀毒,或者磁盘整理,因为此时环境比较纯净,需要native app。诸如此类~
最近,开发一个Native App项目,其规模和复杂度也不一般。期间遇到很多问题,在逐一解决的时候也收获了很多东西。现在略作整理,以备将来查用,二来与大家分享之~

Native app 基本工作原理

这里,只想简单的描述下。
Windows的设计是基于分层模型的,在设计之初,内核NT支持三个子系统,OS/2,posix,win32,这些子系统同属于一个层面上,它们公用windows nt提供的系统API和例程。其中,在某一个子系统上的API调用,都会经过NT”native”API同windowsNT进行通信。这些native API就是ntdll.dll导出的函数,因为它导出的大部分函数都只是起一个从子系统到NT内核的转发传递作用,所以也成为stub函数,这些函数的原型大多是未公开的,在早期的DDK里会有相关的描述,但是现在没了,取而代之的是内核实现的zw*,nt*开头的驱动函数。这里表明了MS的一个态度,不希望第三方在native app上干涉windows的太多工作,比如,接管了开机启动系统,接管了登录密码界面:D. 后来,因为种种历史原因,对OS/2和posix子系统的支持逐渐被淡忘。但是这种分层模型仍然存在,native app就是工作在子系统未启动之前,此时的系统环境很纯净,权限也相对较高;另外,对操作系统来说,支持native app也是一种必须,因为在子系统启动之前,很多功能的程序只能以native app来呈现,比如登录界面,CSRSS~
具体的启动时机:
Native app由启动会话管理器(smss.exe)来启动,如果想通知smss来执行一个native app程序,只需要修改一个注册表项,smss在每次启动的时候会去检查该项,确保该项下面的每个native app程序依次执行。注册表项为:HKLM\System\CurrentControlSet\Control\Session Manager\BootExecute ,其类型为MULTI_SZ, 又是MS玩的一种字符串类型—多字符串类型,也就是说,这个MULTI_SZ字符串包含多个以\0结尾的子字符串,而整个字符串以\0\0结尾。在该注册表项后面添加要注册的native 程序名和参数就可以了。
关于native app的更多详细介绍,可以参考Mark Russinovich的一篇关于native的文章。

开发相关
Native app程序结构
Native app程序结构很简单,就好像我们写hello world,需要写一个main函数入口一样,native app的入口函数是NtProcessStartup,形如:
void NtProcessStartup( PSTARTUP_ARGUMENT Argument )
其中,参数PSTARTUP_ARGUMENT是一个结构体,用来存放传入参数。
程序退出时,主动调用函数NtProcessTerminate退出,它不会像普通应用程序一样一个返回return就退出了。
基本的结构就是这样了:
void NtProcessStartup( PSTARTUP_ARGUMENT Argument )
{
        // do something else
        NtProcessTerminate( NtCurrentProcess(), 0 );
}
当然现在还没有包含头文件之类的。
开发语言及第三方的库
        Native app支持的开发语言有C/ASM/C++,并且完美的支持C++的类特性,不过要像编写驱动一样,需要重载new,delete等内存分配函数。
        在内存使用上,可以使用两套接口:堆函数接口,以及虚拟内存函数接口,但是根据我的经验,使用堆函数接口,更高效并且内存bug出现的频率会大大降低。举个例子:我在调试native app的时候,一切正常,且全部通过,但是双机调试的时候,功能代码都运行完了,在子系统起来的时候,提示memory_corruption错误,这个问题整整找了好几天都没有找到,到最后,无意间屏蔽掉了系统的DbgPrint函数,memory错误才解决。其原因是,native gui图形模块的debug消息打印的太快太频繁,导致调试缓冲被溢出,当屏蔽了系统DbgPrint的时候,也就是在windbg 下bp DbgPrint,然后a eip,ret后,就正常了。虽然这个现象和程序无关,但是,用了虚拟内存的话,这个问题会更加容易重现。关于这个问题的重现很容易,就是在native 环境下双机调试,target机器一直打印消息,当打印到10W条以上时,调试缓冲就“爆”了。这真不知道是ms的bug,还是自己~~
       
关于new,delete的重载。
使用堆函数过程如下:首先创建一个全局堆,然后在这个全局堆上分配和释放局部堆。
HANDLE hGlobalHeap = NULL; // for globle call
void* __cdecl operator new(size_t size)
{
        if(hGlobalHeap == NULL)
                return NULL;
        return RtlAllocateHeap(hGlobalHeap,0/*HEAP_ZERO_MEMORY*/,size);
}
void __cdecl operator delete(void* addr)
{
        if(hGlobalHeap && addr) (void)RtlFreeHeap(hGlobalHeap,0,addr);
}
       
        关于NDK:前面说到,native app用的是ntdll.dll的导出函数,而这些函数MS并没有公开接口声明,那么我们使用的时候,首先必须要自己定义函数声明。NDK就是这样的一个类库,它几乎定义了ntdll.dll导出的全部函数的声明以及一些常用的数据结构的定义,我们只需要包含相应的头文件,导入ntdll.lib库,就可以像使用普通的API函数一样开发native app了。
        关于DLL:native app可以调用同一级别的DLL,使大型的项目开发更加容易,更加容易划分模块。注意,DLL的编译环境要和native app一致。
        关于native app的编译:可以选择用vs环境,也可以用DDK/WDK,但是推荐使用WDK。用VS环境的话,需要简单的设置下,随意创建一个类型的工程,然后修改Linker->system->Native,就可以了。如果用WDK编译,需要写一个SOURCE模板,如:
TARGETNAME=defrag
TARGETPATH=obj
TARGETTYPE=PROGRAM
INCLUDES=$(PUBLIC_ROOT)\inc\ddk
SOURCES=defrag.cpp
        注意:上面说的DLL的编译环境和native app的编译环境要一致,指的是不要用WDK编译的native去尝试链接VS编译的DLL,反之亦然。

Native GUI
在native app执行环境下画界面是不可行的,但是不是说做不到。
前面说了,可以写一个native app来接管windows的启动界面和密码输入界面,那么这个界面是如何画的呢?也有从驱动里实现的。但是,事实上,MS提供了一个native级别的动态库,名为:Bootvid.dll,用来实现GUI启动屏幕的引导视频驱动,这个dll导出了一些函数,可以实现画图,贴图功能,当然,这些函数接口仍然是未公开的。呵呵~
另外,在native app程序,可以利用一个函数向屏幕打印输出字符串,名为:
        //NTSTATUS
        //NTAPI NtDisplayString( PUNICODE_STRING String);
但是,事实上,这个函数已经不推荐使用了,在用WDK编译native app的时候,会提示一个警告信息,deprecated~~

Native app的灵活性
native app由于受到调用函数接口未公开,以及开发难度和调试难度不小的原因,很少有项目问津,但是,事实上,它仍然是一种工作于ring3的用户态程序,只是在子系统启动之前运行,所以,native app程序一般不会引起系统蓝屏的问题。也正是如此,native 程序工作在一个相对纯净的环境下,可以访问任何文件,甚至搬移MFT,系统元文件等。
        Ntdll.dll为native app导出的函数虽少,但是可以完成很多的功能。这些导出函数,基本上和内核的系统例程都是一一对应的。结合其他的模块,driver,应用程app,在加之native独特的运行环境和执行能力,往往会达到一个良好的效果。在这里,仅仅是一个普及~

具体应用及实例
        在开发native app之前,我想,最好有开发驱动的基础。因为native app程序的编写规范基本上和驱动一样,除了入口函数,调试方法也一样,必须要双机调试。当然,只是说编写规则一样,驱动特有的函数例程以及工作原理,二者是毫不相干的。举个例子,操作注册表,文件IO,线程创建,内存使用,二者基本上是一致的,具体的在使用中自己体会吧。
作为入门例子
作为入门我想还是用Mark Russinovich的例子吧,就好像Hello World的作用一样,让你真切的感受下native app程序。该程序在系统启动时,蓝屏界面上输出一行字符串信息。程序在附件,没什么过多的需要解释的。

实际开发
实际开发中,有不少的应用例子。比如,影子系统的启动界面,PQ分区工具,win系统自带的chkdsk工具,都属于这类程序。
下面说下自己的一些经历吧:
项目中有个需要,对特定文件进行磁盘整理。我们知道,文件系统导出了一组函数接口,用于对磁盘上的文件进行搬移操作,使文件内碎片和外碎片减少,提高IO吞吐率和磁盘访问率。唯一的限制是,pagefile.sys和日志文件不能整理,其他的文件,如MFT,系统元文件都可以整理。对于文件整理,更重要的是算法和稳定法,当然,这是另外一个话题了。根据prefreth原理,一个应用程序的工作集页面在运行时基本上是趋于稳定的,那么这些稳定的页面如果位于不同的文件(可能是链接库之类),且这些文件在磁盘上比较分散,那么就会影响程序的启动时间了,虽然prefretch做了改善,会自动的激发系统的磁盘整理来对“相关”的文件紧密排放,但仍然是不够的。所以,关于这种性能的改善看起来微乎其微,但是做好了,价值是不可估量的。这仅仅是一个方面,当然,项目中的主要目的并不是这个,虽然也是为了提高性能。
在native app下操作文件,考虑的情况是比较单一的,不会担心文件或目录被锁,从而出现不能访问的情况,也不会考虑过多的并发问题。所以,功能会更加集中,运行效率会更高,操作的空间和权限也更大。
仅限于此,就到这吧~~
                                                        By microdebug

DOC格式粘贴在这里,咋就这么乱?
可参考:http://hi.baidu.com/316526334/blog
native_back.rar
native app.doc


[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

上传的附件:
收藏
免费 7
支持
分享
最新回复 (31)
雪    币: 1259
活跃值: (38)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
stu
2
谢谢楼主分享。
2010-7-30 17:07
0
雪    币: 2743
活跃值: (1049)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
3
本想潜水一下。。。。但看到如此好贴——不顶不行啊!!!
2010-7-30 17:24
0
雪    币: 392
活跃值: (89)
能力值: ( LV9,RANK:280 )
在线值:
发帖
回帖
粉丝
4
谢谢,分享快乐
2010-7-30 21:37
0
雪    币: 291
活跃值: (169)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
好啊,谢谢了啊
2010-7-30 22:13
0
雪    币: 3053
活跃值: (891)
能力值: ( LV13,RANK:1300 )
在线值:
发帖
回帖
粉丝
6
好帖,得顶。
2010-7-30 22:17
0
雪    币: 452
活跃值: (72)
能力值: ( LV9,RANK:330 )
在线值:
发帖
回帖
粉丝
7
native的木马岂不是很可怕,比如纪录windows登录密码
2010-7-30 22:52
0
雪    币: 392
活跃值: (89)
能力值: ( LV9,RANK:280 )
在线值:
发帖
回帖
粉丝
8
native 程序必须要利用注册表项才能注册启动,安全软件只要监控这一项就可以了;另外,native程序启动的时候,如果不利用bootvid显示画图的话,会自动的切换到VGA的16色蓝屏模式下,很容易被发觉~~
2010-7-30 23:20
0
雪    币: 222
活跃值: (25)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
9
谢谢分享,之前不知道,,下了你的附件文件翻译了下
ENVIRONMENT_INFORMATION        STRUCT
  Unknown        DD 21 DUP (?)
  CommandLine     UNICODE_STRING<>
  ImageFile        UNICODE_STRING <>
ENVIRONMENT_INFORMATION ENDS

PSTARTUP_ARGUMENT        STRUCT
  Unknown        DD 3 DUP (?)
  Environment        ENVIRONMENT_INFORMATION <>
PSTARTUP_ARGUMENT ENDS
.const
CCOUNTED_UNICODE_STRING "123456789101234567891012345678910", g_pTxt, 4
.code
start:
NtProcessStartup proc Argument:PSTARTUP_ARGUMENT

        invoke NtDisplayString,addr g_pTxt
        invoke NtTerminateProcess,NtCurrentProcess,0
ret
NtProcessStartup endp
2010-7-31 10:01
0
雪    币: 1312
活跃值: (5169)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
10
收藏!!!!
2010-10-2 04:45
0
雪    币: 1790
活跃值: (3786)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
11
楼主,想问下。好像VISTA和WIN7都不可以用了吧?
2010-10-3 14:16
0
雪    币: 199
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
12
吸收精华,成长菜鸟.
2010-10-6 11:38
0
雪    币: 218
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
13
确是好文,解了我心中一个疑问。
2010-10-7 21:21
0
雪    币: 2548
活跃值: (965)
能力值: ( LV12,RANK:1010 )
在线值:
发帖
回帖
粉丝
14
强烈支持啊,感谢楼主,好贴
2010-10-10 13:04
0
雪    币: 266
活跃值: (15)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
15
坚持了5天还是没看 干脆mark一下吧
2010-11-11 15:02
0
雪    币: 392
活跃值: (89)
能力值: ( LV9,RANK:280 )
在线值:
发帖
回帖
粉丝
16
当然可以用;
前一阵子开发的项目,native app部分就是支持WIN7,VISTA的,并且支持64位
2010-11-11 18:18
0
雪    币: 109
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
17
越看越心惊,越看心越凉,不会的太多了……
2010-11-17 11:51
0
雪    币: 31
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
18
一定要学习。。。。
2010-11-18 09:10
0
雪    币: 394
活跃值: (131)
能力值: ( LV5,RANK:70 )
在线值:
发帖
回帖
粉丝
19
瑞星杀毒软件安装之后在system32目录下生成一个bsmain.exe,应该属于Native app吧,输入表就NTDLL.DLL一个,但为什么用OD无法打开。
2010-11-18 09:53
0
雪    币: 106
活跃值: (276)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
20
感谢分享这么好的文章
2011-3-11 20:06
0
雪    币: 52
活跃值: (56)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
21
一个全新的领域,让我开了眼界了。
2011-3-20 22:31
0
雪    币: 51
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
22
这种方法还是有一定用处的。就是深入的人很少
2011-8-31 15:49
0
雪    币: 27
活跃值: (77)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
23
请问楼主 NDK 哪里可以下载
2011-9-1 09:11
0
雪    币: 216
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
24
下来看看   谢谢LS
2011-9-22 08:04
0
雪    币: 35
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
25
micro,很善于总结。学习下。
2011-12-12 13:11
0
游客
登录 | 注册 方可回帖
返回
//