http://orlando.blogbus.com/logs/17043966.html
A brief introduction to native application
Published: March 15, 2008
Author: Orlando
Introduction:As everyone sees ,these years most Anti-virus companies had released the new edition of their software with boot scan before you login the system, they are running before the Win32 subsystem. “autochk” is the most obvious example of native application, which run disk scan
at the blue screen before login. In this article I’ll tell you what is the native application, how can I write a native application, how to build it and how to run it in a brief and simple way, also with a simple demo indispensably.
What is the native application?The native application is a kind of application which is different from the windows normal application and the driver. Why it different? Because it uses the NT native API and can’t use the win32 environment APIs .The native API are mostly undocumented and the major runtime environment is provided by ntdll.dll. The native application can do something you can’t do in win32 subsystem, just like Norton partition magic can create, resize, copy partitions at that blue screen before login. Actually the native can do almost everything, what it can do sometimes just confined by your imagination.
How can I write a native application?Unlike other windows applications, the windows native application start with its own entry called NtProcessStartup() , NtProcessStartup() can have arguments like this :
void NtProcessStartup( PSTARTUP_ARGUMENT Argument)
{ // ADD your codes here}
The PSTARTUP_ARGUMENT structure contains environment information, which includes command line and image file name and passed as NtProcessStartup()'s parameter.
The ENVIRONMENT_INFORMATION structure which used by STARTUP_ARGUMENT structure and contains the information about command line and image file name:typedef struct
{
ULONG Unknown[21];
UNICODE_STRING CommandLine;
UNICODE_STRING ImageFile;
} ENVIRONMENT_INFORMATION, *PENVIRONMENT_INFORMATION;
The ENVIRONMENT_INFORMATION structure which passed as NtProcessStartup() 's parameter:
typedef struct {
ULONG Unknown[3];
PENVIRONMENT_INFORMATION Environment;
} STARTUP_ARGUMENT, *PSTARTUP_ARGUMENT;
And also unlike other application the native application ends with the NtTerminateProcess() to kill itself.(the native must terminate itself to let the application exit)
NTSTATUS NTAPI NtTerminateProcess(
HANDLE ProcessHandle,
LONG ExitStatus
);
Since these native APIs are undocumented, you must declare the API function yourself.
Usually we end the NT native application like this NtTerminateProcess( NtCurrentProcess(),0);In native application we must manage the heap by ourselves, that is to say if we want to display a string we must allocate the heap for the storage. To create heap and allocate heap we can use the function RtlCreateHeap() and RtlAllocateHeap() . The RtlCreateHeap() function can create a heap :
HANDLE NTAPI RtlCreateHeap(
ULONG Flags,
PVOID BaseAddress,
ULONG SizeToReserve,
ULONG SizeToCommit,
PVOID Unknown,
PRTL_HEAP_DEFINITION Definition
);
The RtlAllocateHeap() function allocates the memory for storage:
PVOID NTAPI RtlAllocateHeap(
HANDLE Heap,
ULONG Flags,
ULONG Size
);
After using the heap you should using the RtlFreeHeap() to free the memory:
BOOLEAN NTAPI RtlFreeHeap(
HANDLE Heap,
ULONG Flags,
PVOID Address
);
Thus you have known the basic knowledge of the native application, if you want do something with native application you should look up the “Windows NT 2000 Native API Reference” then find the function you may use and just use these function you can do anything you want. For example if I want to delete a certain file but it was protected in the ring3 model ,we can look up the function about deleting file, then we get NtDeleteFile()
NTSYSAPI NTSTATUSNTAPINtDeleteFile(IN POBJECT_ATTRIBUTES ObjectAttributes );
So we can just use it as the declaration, and then delete the file.
How to build it?
The NT native application should build with the DDK. So the first step is to download a DDK from MS download website. Using DDK to build execute file is not as easy as in the Visual Studio, you must write the makefile and SOURCES by yourself. The makefile and SOURCES you can see in the demo at the end of this article. Be attention that TARGETTYPE=PROGRAM, thus the DDK can compile the exe file.
How to run it?
After you have built the file you must want to run it to see whether it works well, but when you double clicked it you may be disappointed, because it surely alerted a box it said this application can’t run in the win32 model. Why this happened? The NT native application can not run in the win32 environment, it runs between the time that NT’s boot and system start drivers are loaded,and when paging is turned on.So we can use the session manage to execute it just as the autochk do. The reg value HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Control/Session Manager
is a MULTI_SZ value, contains name ,exe_name, argument, for example the autochk’s reg value is autochk autochk * ,the first autochk is the name of it ,the second autochk is the nem of exe file ,* is the argument.So if you want to execute the NT native application you can simply copy your exe file to the system32 folder the modify the reg key, then restart youcomputer.
Example: This example can del the file “Orlando.exe” in “ D:/test” folder
----------------------------------------------------------------------------------------------------------
MAKEFILE
===========================================================================
-!INCLUDE $(NTMAKEENV)/makefile.def
---------------------------------------------------------------------------------------------------------
----------------------------------------------------------------------------------------------------------
SOURCES
===========================================================================
TARGETNAME=damo
TARGETPATH=OBJ
TARGETTYPE=PROGRAM
INCLUDES=$(DDK_INC_PATH)
SOURCES=Demo_orlando.c
---------------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------------
Demo_orlando.h
===========================================================================
//// Environment information, which includes command line and
// image file name
//
typedef struct {
ULONG
Unknown[21];
UNICODE_STRING CommandLine;
UNICODE_STRING ImageFile;
} ENVIRONMENT_INFORMATION, *PENVIRONMENT_INFORMATION;
//// This structure is passed as NtProcessStartup's parameter
//
typedef struct {
ULONG Unknown[3];
PENVIRONMENT_INFORMATION Environment;
} STARTUP_ARGUMENT, *PSTARTUP_ARGUMENT;
//// Data structure for heap definition. This includes various
// sizing parameters and callback routines, which, if left NULL,
// result in default behavior
//
typedef struct {
ULONG Length;
ULONG Unknown[11];
} RTL_HEAP_DEFINITION, *PRTL_HEAP_DEFINITION;
//// Native NT API functions
//NTSTATUS NTAPI NtTerminateProcess(
HANDLE ProcessHandle,
LONG ExitStatus
);
NTSTATUS NTAPI NtDisplayString(
PUNICODE_STRING String
);
HANDLE NTAPI RtlCreateHeap(
ULONG Flags,
PVOID BaseAddress,
ULONG SizeToReserve,
ULONG SizeToCommit,
PVOID Unknown,
PRTL_HEAP_DEFINITION Definition
);
PVOID
NTAPI
RtlAllocateHeap(
HANDLE Heap,
ULONG Flags,
ULONG Size
);
BOOLEAN
NTAPI
RtlFreeHeap(
HANDLE Heap,
ULONG Flags,
PVOID Address
);
NTSYSAPI
NTSTATUS
NTAPI
NtDeleteFile(
IN POBJECT_ATTRIBUTES ObjectAttributes
);
-------------------------------------------------------------------------------------------------
Demo_orlando.c
-------------------------------------------------------------------------------------------------
//by: Orlando
//for the demo of native application uncover
// March 15, 2008
#include "ntddk.h"
#include "Damo_orlando.h"
HANDLE Heap;
PWCHAR fileNameStringBuffer;
RTL_HEAP_DEFINITION heapParams;
UNICODE_STRING filePathString;
OBJECT_ATTRIBUTES ObjectAttributes;
UNICODE_STRING del_SUCCEEDED,del_ERROR;
PWCHAR success_stringBuffer,error_stringbuffer;
void kill(PWCHAR name){
NTSTATUS status;
filePathString.Buffer=fileNameStringBuffer;
filePathString.Length=wcslen( name ) * sizeof(WCHAR); filePathString.MaximumLength=filePathString.Length + sizeof(WCHAR);
ObjectAttributes.Length = sizeof(OBJECT_ATTRIBUTES);
ObjectAttributes.RootDirectory=NULL;
ObjectAttributes.ObjectName=&filePathString;
ObjectAttributes.Attributes = OBJ_CASE_INSENSITIVE| OBJ_INHERIT; ObjectAttributes.SecurityQualityOfService=NULL;
ObjectAttributes.SecurityDescriptor=NULL;
status=NtDeleteFile(&ObjectAttributes);
if ((NTSTATUS)(status) >= 0) {
NtDisplayString(&filePathString);
NtDisplayString(&del_SUCCEEDED);
}
else
{
NtDisplayString(&del_ERROR);
}
}
void NtProcessStartup( PSTARTUP_ARGUMENT Argument){
memset( &heapParams, 0, sizeof( RTL_HEAP_DEFINITION ));
heapParams.Length = sizeof( RTL_HEAP_DEFINITION );
Heap = RtlCreateHeap( 2, 0, 0x100000, 0x1000, 0, &heapParams );
fileNameStringBuffer= RtlAllocateHeap( Heap, 0, 256 );
success_stringBuffer=RtlAllocateHeap(Heap,0,20);
success_stringBuffer=L"....Deleted!/n";
del_SUCCEEDED.Buffer=success_stringBuffer;
del_SUCCEEDED.Length=wcslen( success_stringBuffer ) * sizeof(WCHAR); del_SUCCEEDED.MaximumLength = del_SUCCEEDED.Length + sizeof(WCHAR); error_stringbuffer=RtlAllocateHeap(Heap,0,20);
error_stringbuffer=L"....ERROR!/n";
del_ERROR.Buffer=error_stringbuffer;
del_ERROR.Length=wcslen(error_stringbuffer) * sizeof(WCHAR);
del_ERROR.MaximumLength = del_ERROR.Length + sizeof(WCHAR);
fileNameStringBuffer=L"//??//D://test//orlando.exe";
kill(fileNameStringBuffer);
RtlFreeHeap( Heap, 0, fileNameStringBuffer );
NtTerminateProcess( NtCurrentProcess(), 0 );
}
-------------------------------------------------------------------------------------------
Reference:
Inside Native Application
------------ 1998 Mark Russinovich
Undocumented Windows 2000 Secret-
----------- SVEN B. SCHREIBER
Windows NT 2000 Native API Reference
------------ Gary Nebbett