I would be grateful if someone could help with this coding, many thanks in advance.
It is a small Native application, the main problem is NtSetSystemTime() failed, although I have the SeSystemtimePrivilege enabled.
Another issue if sprintf failed to prepared the string needed for NtWriteFile() to work, because a test string ("Testing string for NtWriteFile") can be written into time.txt via NtWriteFile(). So I guess that sprintf did not work under Native environment (i.e. before Windows starts). So the string has to be converted without "stdio.h".
Some background is included in the code for easy reading.
Code://======================native.c v2====================================
/*****************What it can do and cannot ****************************
1. It fails to set the system time to new time with NtSetSystemTime().
2. It creates c:\time.txt but fails to write the old time with NtWriteFile().
Tested: It can be successfully compiled using
Windows Server 2003 SP1 DDK on WINDOWS XP SP3>>
Build Environments >> Win XP Checked (free) Build Environment
***********************************************************************/
#include "ntddk.h"
#include "stdio.h"
NTSTATUS NTAPI NtDisplayString(PUNICODE_STRING String);
NTSTATUS NTAPI NtTerminateProcess(HANDLE ProcessHandle, LONG ExitStatus);
// SystemTime [out]: A pointer to a LARGE_INTEGER structure
// that receives the system time.
// This value means number of 100-nanosecond units since 1600, 1 January.
// Time is incremented 10.000.000 times per second.,i.e 1s=10.000.000
NTSTATUS NTAPI NtQuerySystemTime(
OUT PLARGE_INTEGER SystemTime);
/* NtSetSystemTime() is similar to NtQuerySystemTime()
STATUS_SUCCESS is returned if the service is successfully executed.
STATUS_PRIVILEGE_NOT_HELD is returned if the caller does not have the privilege
to set the system time.
STATUS_ACCESS_VIOLATION is returned if the input parameter for the system time
cannot be read or the output parameter for the system time cannot be written.
STATUS_INVALID_PARAMETER is returned if the input system time is negative.
SeSystemtimePrivilege is required to set the system time!!!
*/
NTSTATUS NTAPI NtSetSystemTime(
IN PLARGE_INTEGER SystemTime,
OUT PLARGE_INTEGER PreviousTime);
// converts 64-bit time to user-readable structure TIME_FIELDS.
NTSYSAPI VOID NTAPI RtlTimeToTimeFields(
IN PLARGE_INTEGER Time,
OUT PTIME_FIELDS TimeFields);
// converts user-readable structure TIME_FIELDS to 64-bit integer
NTSYSAPI BOOLEAN NTAPI RtlTimeFieldsToTime(
IN PTIME_FIELDS TimeFields,
OUT PLARGE_INTEGER Time);
NTSTATUS NTAPI NtCreateFile(
OUT PHANDLE FileHandle,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes,
OUT PIO_STATUS_BLOCK IoStatusBlock,
IN PLARGE_INTEGER AllocationSize,
IN ULONG FileAttributes,
IN ULONG ShareAccess,
IN ULONG CreateDisposition,
IN ULONG CreateOptions,
IN PVOID EaBuffer,
IN ULONG EaLength);
NTSTATUS NTAPI NtWriteFile(
IN HANDLE FileHandle,
IN HANDLE Event,
IN PIO_APC_ROUTINE ApcRoutine,
IN PVOID ApcContext,
OUT PIO_STATUS_BLOCK IoStatusBlock,
IN PVOID Buffer,
IN ULONG Length,
IN PLARGE_INTEGER ByteOffset,
IN PULONG Key);
NTSYSAPI NTSTATUS NTAPI NtClose(
IN HANDLE Handle);
// Store the current time
LARGE_INTEGER MySystemTime;
// The time to be set
LARGE_INTEGER MySystemTimeNew;
// The time (=MySystemTime) before being set to MySystemTimeNew
LARGE_INTEGER MySystemTimeOld;
//
TIME_FIELDS TimeFields;
TIME_FIELDS MyTimeFields;
TIME_FIELDS MyTimeFieldsOld;
/* when included, error "'struct' type redefinition"
typedef struct _TIME_FIELDS {
USHORT Year;
USHORT Month;
USHORT Day;
USHORT Hour;
USHORT Minute;
USHORT Second;
USHORT Milliseconds;
USHORT Weekday;
} TIME_FIELDS, *PTIME_FIELDS;
*/
UNICODE_STRING wszPath;
UNICODE_STRING ErrorMonitor;
NTSTATUS Status;
HANDLE hFile;
OBJECT_ATTRIBUTES objAttr;
IO_STATUS_BLOCK IoStatusBlock;
LARGE_INTEGER FilePos;
CHAR *strMessage=NULL;
void NtProcessStartup(PPEB ppeb)
{
//get the current system time
Status = NtQuerySystemTime(&MySystemTime);
if (!NT_SUCCESS(Status)) // not succesful
{
//just to check if NtQuerySystemTime() worked.
RtlInitUnicodeString(&ErrorMonitor,L"Failed to get system time!\n");
NtDisplayString(&ErrorMonitor);
}
else // succesful
{
//just to show something on the screen. these two lines can be removed.
RtlInitUnicodeString(&ErrorMonitor,L"Got system time successfully!\n");
NtDisplayString(&ErrorMonitor);
// converts 64-bit time to user-readable structure TIME_FIELDS.
RtlTimeToTimeFields(&MySystemTime,&MyTimeFields);
// *************The time (31/12/2009) to be set***************
// better to take Argument like "native.exe 31/12/2009"
// but I do not know how to do it. So I use this way:
MyTimeFields.Year=2009;
MyTimeFields.Month=12;
MyTimeFields.Day=31;
//converts user-readable structure TIME_FIELDS to 64-bit integer
RtlTimeFieldsToTime(&MyTimeFields,&MySystemTimeNew);
// set new time and the old time is in MySystemTimeOld
// but testing showed the time was not set to 31/12/2009!!!
//NtSetSystemTime(&MySystemTimeNew,NULL);
Status = NtSetSystemTime(&MySystemTimeNew,&MySystemTimeOld);
if (!NT_SUCCESS(Status)) // not succesful
{
//just to check if NtSetSystemTime() worked.
RtlInitUnicodeString(&ErrorMonitor,L"Failed to set system time!\n");
NtDisplayString(&ErrorMonitor);
}
else // succesful
{
//just to check if NtSetSystemTime() worked.
RtlInitUnicodeString(&ErrorMonitor,L"System time has been set successfully!\n");
NtDisplayString(&ErrorMonitor);
// converts 64-bit time to user-readable structure TIME_FIELDS.
RtlTimeToTimeFields(&MySystemTimeOld,&MyTimeFieldsOld);
// The old time in MyTimeFieldsOld is written into c:\time.txt
RtlInitUnicodeString(&wszPath, L"\\??\\c:\\Time.txt");
InitializeObjectAttributes(&objAttr, &wszPath, OBJ_OPENIF, NULL, NULL);
NtCreateFile(&hFile, FILE_GENERIC_WRITE, &objAttr, &IoStatusBlock,0,
FILE_ATTRIBUTE_NORMAL,FILE_SHARE_WRITE, FILE_OVERWRITE_IF,
FILE_RANDOM_ACCESS|FILE_NON_DIRECTORY_FILE|FILE_SYNCHRONOUS_IO_NONALERT,
NULL, 0);
/* The following was modified from codes found
@ http://software.itags.org/software-application/4470/
it means to formt strMessage from MyTimeFieldsOld,
but ExAllocatePool (or ExAllocatePoolWithTag) returned an error
NtQuerySystemTime(&MySystemTime);
RtlTimeToTimeFields(&MySystemTime,&TimeFields);
strMessage = (CHAR *)ExAllocatePoolWithTag( NonPagedPool, 99 * sizeof(CHAR),'1gaT');
RtlZeroMemory( strMessage, 99 * sizeof(CHAR));
sprintf(strMessage, "%4d-%02d-%02d %02d:%02d:%02d\t%s\r\n",
TimeFields.Year,
TimeFields.Month,
TimeFields.Day,
TimeFields.Hour,
TimeFields.Minute,
TimeFields.Second,
"0123456789"
);
*/
//use this to test NtWriteFile()
strMessage = "Testing string for NtWriteFile";
// write the old time into the Time.txt file.
// but testing showed nothing was written to the file !!!!
NtWriteFile(hFile, NULL, NULL, NULL, &IoStatusBlock,
strMessage,strlen(strMessage), &FilePos, NULL);
//just to show something on the screen. these two lines can be removed.
//RtlInitUnicodeString(&helloWorld,L"Hello World!\n");
//NtDisplayString(&helloWorld);
}
}
NtClose(&hFile);
//Terminate
NtTerminateProcess( NtCurrentProcess(), 0 );
}
//===========================end======================================