புரோஹோஸ்டர் > Блог > நிர்வாகம் > Windows Native Applications மற்றும் Acronis Active Restore சேவை
Windows Native Applications மற்றும் Acronis Active Restore சேவை
இன்னோபோலிஸ் பல்கலைக்கழகத்தைச் சேர்ந்த தோழர்களுடன் சேர்ந்து, செயலில் உள்ள மீட்டெடுப்பு தொழில்நுட்பத்தை எவ்வாறு உருவாக்குகிறோம் என்பதை இன்று நாங்கள் தொடர்கிறோம். சொந்த விண்டோஸ் பயன்பாடுகளைப் பற்றி பேசுவோம், அவற்றின் உருவாக்கம் மற்றும் துவக்கத்தின் அம்சங்கள் உட்பட. வெட்டுக்குக் கீழே எங்கள் திட்டத்தைப் பற்றி கொஞ்சம் உள்ளது, அத்துடன் சொந்த பயன்பாடுகளை எவ்வாறு எழுதுவது என்பதற்கான நடைமுறை வழிகாட்டி.
முந்தைய பதிவுகளில் அது என்ன என்பதைப் பற்றி ஏற்கனவே பேசினோம் செயலில் மீட்பு, மற்றும் இன்னோபோலிஸின் மாணவர்கள் எவ்வாறு உருவாகிறார்கள் சேவை. இன்று நான் நேட்டிவ் அப்ளிகேஷன்களில் கவனம் செலுத்த விரும்புகிறேன், எங்களின் செயலில் உள்ள மீட்பு சேவையை "புதைக்க" விரும்பும் அளவிற்கு. எல்லாம் செயல்பட்டால், எங்களால் முடியும்:
சேவையை மிகவும் முன்னதாகவே தொடங்கவும்
காப்புப்பிரதி மிகவும் முன்னதாக அமைந்துள்ள மேகக்கணியைத் தொடர்புகொள்ளவும்
கணினி எந்த பயன்முறையில் உள்ளது என்பதைப் புரிந்துகொள்வதற்கு மிகவும் முன்னதாகவே - சாதாரண துவக்கம் அல்லது மீட்பு
முன்கூட்டியே மீட்டெடுப்பதற்கு மிகக் குறைவான கோப்புகள்
இன்னும் வேகமாக தொடங்க பயனரை அனுமதிக்கவும்.
சொந்த பயன்பாடு என்றால் என்ன?
இந்த கேள்விக்கு பதிலளிக்க, கணினி செய்யும் அழைப்புகளின் வரிசையைப் பார்ப்போம், எடுத்துக்காட்டாக, ஒரு புரோகிராமர் தனது பயன்பாட்டில் ஒரு கோப்பை உருவாக்க முயற்சித்தால்.
பாவெல் யோசிஃபோவிச் - விண்டோஸ் கர்னல் புரோகிராமிங் (2019)
புரோகிராமர் செயல்பாட்டைப் பயன்படுத்துகிறார் கோப்பு உருவாக்கு, இது fileapi.h என்ற தலைப்புக் கோப்பில் அறிவிக்கப்பட்டு Kernel32.dll இல் செயல்படுத்தப்படுகிறது. இருப்பினும், இந்த செயல்பாடு கோப்பை உருவாக்காது, இது உள்ளீட்டு வாதங்களை மட்டுமே சரிபார்த்து செயல்பாட்டை அழைக்கிறது NtCreateFile (Nt முன்னொட்டு செயல்பாடு சொந்தமானது என்பதைக் குறிக்கிறது). இந்த செயல்பாடு winternl.h தலைப்பு கோப்பில் அறிவிக்கப்பட்டு ntdll.dll இல் செயல்படுத்தப்படுகிறது. இது அணுக்கரு விண்வெளியில் குதிக்கத் தயாராகிறது, அதன் பிறகு ஒரு கோப்பை உருவாக்க கணினி அழைப்பு செய்கிறது. இந்த வழக்கில், Kernel32 என்பது Ntdll க்கான ஒரு ரேப்பர் என்று மாறிவிடும். மைக்ரோசாப்ட் பூர்வீக உலகின் செயல்பாடுகளை மாற்றும் திறனைக் கொண்டுள்ளது, ஆனால் நிலையான இடைமுகங்களைத் தொடாதது இது செய்யப்படுவதற்கான காரணங்களில் ஒன்றாகும். மைக்ரோசாப்ட் நேட்டிவ் ஃபங்க்ஷன்களை நேரடியாக அழைப்பதை பரிந்துரைக்கவில்லை மற்றும் பெரும்பாலானவற்றை ஆவணப்படுத்தாது. மூலம், ஆவணமற்ற செயல்பாடுகளை காணலாம் இங்கே.
நேட்டிவ் அப்ளிகேஷன்களின் முக்கிய நன்மை என்னவென்றால் ntdll ஆனது kernel32 ஐ விட மிகவும் முன்னதாகவே கணினியில் ஏற்றப்பட்டது. இது தர்க்கரீதியானது, ஏனெனில் kernel32 க்கு ntdll வேலை செய்ய வேண்டும். இதன் விளைவாக, சொந்த செயல்பாடுகளைப் பயன்படுத்தும் பயன்பாடுகள் மிகவும் முன்னதாகவே செயல்படத் தொடங்கும்.
எனவே, விண்டோஸ் நேட்டிவ் அப்ளிகேஷன்கள் என்பது விண்டோஸ் துவக்கத்தில் ஆரம்பத்தில் தொடங்கக்கூடிய நிரல்களாகும். அவை ntdll இலிருந்து செயல்பாடுகளை மட்டுமே பயன்படுத்துகின்றன. அத்தகைய பயன்பாட்டின் எடுத்துக்காட்டு: autochk யார் நிகழ்த்துகிறார் chkdisk பயன்பாடு முக்கிய சேவைகளைத் தொடங்குவதற்கு முன் பிழைகள் உள்ளதா என வட்டில் சரிபார்க்கவும். எங்கள் செயலில் மீட்டமைக்கப்பட வேண்டும் என்று நாங்கள் விரும்பும் நிலை இதுதான்.
நமக்கு என்ன தேவை?
டி.டி.கே (டிரைவர் டெவலப்மெண்ட் கிட்), இப்போது WDK 7 (Windows Driver Kit) என்றும் அழைக்கப்படுகிறது.
மெய்நிகர் இயந்திரம் (உதாரணமாக, விண்டோஸ் 7 x64)
தேவையில்லை, ஆனால் பதிவிறக்கம் செய்யக்கூடிய தலைப்பு கோப்புகள் உதவக்கூடும் இங்கே
குறியீட்டில் என்ன இருக்கிறது?
கொஞ்சம் பயிற்சி செய்வோம், எடுத்துக்காட்டாக, ஒரு சிறிய பயன்பாட்டை எழுதுங்கள்:
திரையில் ஒரு செய்தியைக் காட்டுகிறது
சில நினைவகத்தை ஒதுக்குகிறது
விசைப்பலகை உள்ளீட்டிற்காக காத்திருக்கிறது
பயன்படுத்திய நினைவகத்தை விடுவிக்கிறது
சொந்த பயன்பாடுகளில், நுழைவு புள்ளி முக்கிய அல்லது வின்மைன் அல்ல, ஆனால் NtProcessStartup செயல்பாடு, நாங்கள் உண்மையில் கணினியில் புதிய செயல்முறைகளை நேரடியாக தொடங்குவதால்.
திரையில் ஒரு செய்தியைக் காண்பிப்பதன் மூலம் தொடங்குவோம். இதற்கு நாம் ஒரு சொந்த செயல்பாடு உள்ளது NtDisplayString, இது UNICODE_STRING கட்டமைப்பு பொருளுக்கு ஒரு சுட்டியை வாதமாக எடுத்துக்கொள்கிறது. RtlInitUnicodeString அதை துவக்க உதவும். இதன் விளைவாக, திரையில் உரையைக் காட்ட, இந்த சிறிய செயல்பாட்டை எழுதலாம்:
//usage: WriteLn(L"Here is my textn");
void WriteLn(LPWSTR Message)
{
UNICODE_STRING string;
RtlInitUnicodeString(&string, Message);
NtDisplayString(&string);
}
ntdll இலிருந்து செயல்பாடுகள் மட்டுமே எங்களுக்குக் கிடைக்கின்றன, மேலும் நினைவகத்தில் வேறு எந்த நூலகங்களும் இல்லை, நினைவகத்தை எவ்வாறு ஒதுக்குவது என்பதில் எங்களுக்கு நிச்சயமாக சிக்கல்கள் இருக்கும். புதிய ஆபரேட்டர் இன்னும் இல்லை (ஏனென்றால் இது C++ இன் மிக உயர்ந்த உலகத்திலிருந்து வருகிறது), மேலும் malloc செயல்பாடு எதுவும் இல்லை (இதற்கு இயக்க நேர C நூலகங்கள் தேவை). நிச்சயமாக, நீங்கள் ஒரு அடுக்கை மட்டுமே பயன்படுத்த முடியும். ஆனால் நாம் நினைவகத்தை மாறும் வகையில் ஒதுக்க வேண்டும் என்றால், அதை குவியலில் (அதாவது குவியல்) செய்ய வேண்டும். எனவே நமக்கென்று ஒரு குவியலை உருவாக்கி, நமக்குத் தேவைப்படும் போதெல்லாம் அதிலிருந்து நினைவகத்தை எடுத்துக் கொள்வோம்.
செயல்பாடு இந்த பணிக்கு ஏற்றது RtlCreateHeap. அடுத்து, RtlAllocateHeap மற்றும் RtlFreeHeap ஐப் பயன்படுத்தி, நமக்குத் தேவைப்படும்போது நினைவகத்தை ஆக்கிரமித்து இலவச நினைவகத்தை உருவாக்குவோம்.
PVOID memory = NULL;
PVOID buffer = NULL;
ULONG bufferSize = 42;
// create heap in order to allocate memory later
memory = RtlCreateHeap(
HEAP_GROWABLE,
NULL,
1000,
0, NULL, NULL
);
// allocate buffer of size bufferSize
buffer = RtlAllocateHeap(
memory,
HEAP_ZERO_MEMORY,
bufferSize
);
// free buffer (actually not needed because we destroy heap in next step)
RtlFreeHeap(memory, 0, buffer);
RtlDestroyHeap(memory);
நமக்குத் தேவையானது பயன்படுத்துவதுதான் NtReadFile ஒரு திறந்த சாதனத்தில், மற்றும் விசைப்பலகை எங்களுக்கு எந்த அழுத்தும் திரும்பும் வரை காத்திருக்கவும். ESC விசையை அழுத்தினால், நாங்கள் தொடர்ந்து வேலை செய்வோம். சாதனத்தைத் திறக்க, நாம் NtCreateFile செயல்பாட்டை அழைக்க வேண்டும் (நாம் DeviceKeyboardClass0 ஐ திறக்க வேண்டும்). நாங்களும் அழைப்போம் NtCreateEventகாத்திருக்கும் பொருளை துவக்க. விசைப்பலகை தரவைக் குறிக்கும் KEYBOARD_INPUT_DATA கட்டமைப்பை நாமே அறிவிப்போம். இது எங்கள் வேலையை எளிதாக்கும்.
நேட்டிவ் அப்ளிகேஷன் ஒரு செயல்பாட்டு அழைப்போடு முடிவடைகிறது NtTerminateProcessஏனென்றால் நாம் நமது சொந்த செயல்முறையை மட்டும் கொல்கிறோம்.
எங்கள் சிறிய பயன்பாட்டிற்கான அனைத்து குறியீடுகளும்:
#include "ntifs.h" // WinDDK7600.16385.1incddk
#include "ntdef.h"
//------------------------------------
// Following function definitions can be found in native development kit
// but I am too lazy to include `em so I declare it here
//------------------------------------
NTSYSAPI
NTSTATUS
NTAPI
NtTerminateProcess(
IN HANDLE ProcessHandle OPTIONAL,
IN NTSTATUS ExitStatus
);
NTSYSAPI
NTSTATUS
NTAPI
NtDisplayString(
IN PUNICODE_STRING String
);
NTSTATUS
NtWaitForSingleObject(
IN HANDLE Handle,
IN BOOLEAN Alertable,
IN PLARGE_INTEGER Timeout
);
NTSYSAPI
NTSTATUS
NTAPI
NtCreateEvent(
OUT PHANDLE EventHandle,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
IN EVENT_TYPE EventType,
IN BOOLEAN InitialState
);
// https://docs.microsoft.com/en-us/windows/win32/api/ntddkbd/ns-ntddkbd-keyboard_input_data
typedef struct _KEYBOARD_INPUT_DATA {
USHORT UnitId;
USHORT MakeCode;
USHORT Flags;
USHORT Reserved;
ULONG ExtraInformation;
} KEYBOARD_INPUT_DATA, *PKEYBOARD_INPUT_DATA;
//----------------------------------------------------------
// Our code goes here
//----------------------------------------------------------
// usage: WriteLn(L"Hello Native World!n");
void WriteLn(LPWSTR Message)
{
UNICODE_STRING string;
RtlInitUnicodeString(&string, Message);
NtDisplayString(&string);
}
void NtProcessStartup(void* StartupArgument)
{
// it is important to declare all variables at the beginning
HANDLE hKeyBoard, hEvent;
UNICODE_STRING skull, keyboard;
OBJECT_ATTRIBUTES ObjectAttributes;
IO_STATUS_BLOCK Iosb;
LARGE_INTEGER ByteOffset;
KEYBOARD_INPUT_DATA kbData;
PVOID memory = NULL;
PVOID buffer = NULL;
ULONG bufferSize = 42;
//use it if debugger connected to break
//DbgBreakPoint();
WriteLn(L"Hello Native World!n");
// inialize variables
RtlInitUnicodeString(&keyboard, L"DeviceKeyboardClass0");
InitializeObjectAttributes(&ObjectAttributes, &keyboard, OBJ_CASE_INSENSITIVE, NULL, NULL);
// open keyboard device
NtCreateFile(&hKeyBoard,
SYNCHRONIZE | GENERIC_READ | FILE_READ_ATTRIBUTES,
&ObjectAttributes,
&Iosb,
NULL,
FILE_ATTRIBUTE_NORMAL,
0,
FILE_OPEN,FILE_DIRECTORY_FILE,
NULL, 0);
// create event to wait on
InitializeObjectAttributes(&ObjectAttributes, NULL, 0, NULL, NULL);
NtCreateEvent(&hEvent, EVENT_ALL_ACCESS, &ObjectAttributes, 1, 0);
WriteLn(L"Keyboard readyn");
// create heap in order to allocate memory later
memory = RtlCreateHeap(
HEAP_GROWABLE,
NULL,
1000,
0, NULL, NULL
);
WriteLn(L"Heap readyn");
// allocate buffer of size bufferSize
buffer = RtlAllocateHeap(
memory,
HEAP_ZERO_MEMORY,
bufferSize
);
WriteLn(L"Buffer allocatedn");
// free buffer (actually not needed because we destroy heap in next step)
RtlFreeHeap(memory, 0, buffer);
RtlDestroyHeap(memory);
WriteLn(L"Heap destroyedn");
WriteLn(L"Press ESC to continue...n");
while (TRUE)
{
NtReadFile(hKeyBoard, hEvent, NULL, NULL, &Iosb, &kbData, sizeof(KEYBOARD_INPUT_DATA), &ByteOffset, NULL);
NtWaitForSingleObject(hEvent, TRUE, NULL);
if (kbData.MakeCode == 0x01) // if ESC pressed
{
break;
}
}
NtTerminateProcess(NtCurrentProcess(), 0);
}
சோசலிஸ்ட் கட்சி: பிழைத்திருத்தத்தில் அதை நிறுத்த, DbgBreakPoint() செயல்பாட்டை நமது குறியீட்டில் எளிதாகப் பயன்படுத்தலாம். உண்மை, கர்னல் பிழைத்திருத்தத்திற்காக நீங்கள் WinDbg ஐ மெய்நிகர் கணினியுடன் இணைக்க வேண்டும். இதை எப்படி செய்வது என்பதற்கான வழிமுறைகளைக் காணலாம் இங்கே அல்லது பயன்படுத்தவும் VirtualKD.
தொகுப்பு மற்றும் சட்டசபை
சொந்த பயன்பாட்டை உருவாக்க எளிதான வழி பயன்படுத்த வேண்டும் டி.டி.கே (டிரைவர் டெவலப்மெண்ட் கிட்). நமக்கு பண்டைய ஏழாவது பதிப்பு தேவை, ஏனெனில் பிந்தைய பதிப்புகள் சற்று வித்தியாசமான அணுகுமுறை மற்றும் விஷுவல் ஸ்டுடியோவுடன் நெருக்கமாக வேலை செய்கின்றன. நாங்கள் DDK ஐப் பயன்படுத்தினால், எங்கள் திட்டப்பணிக்கு Makefile மற்றும் ஆதாரங்கள் மட்டுமே தேவை.
செய்வது Makefile
!INCLUDE $(NTMAKEENV)makefile.def
ஆதாரங்கள்:
TARGETNAME = MyNative
TARGETTYPE = PROGRAM
UMTYPE = nt
BUFFER_OVERFLOW_CHECKS = 0
MINWIN_SDK_LIB_PATH = $(SDK_LIB_PATH)
SOURCES = source.c
INCLUDES = $(DDK_INC_PATH);
C:WinDDK7600.16385.1ndk;
TARGETLIBS = $(DDK_LIB_PATH)ntdll.lib
$(DDK_LIB_PATH)nt.lib
USE_NTDLL = 1
உங்கள் Makefile சரியாக இருக்கும், ஆனால் ஆதாரங்களை இன்னும் கொஞ்சம் விரிவாகப் பார்ப்போம். இந்தக் கோப்பு உங்கள் நிரலின் ஆதாரங்கள் (.c கோப்புகள்), உருவாக்க விருப்பங்கள் மற்றும் பிற அளவுருக்களைக் குறிப்பிடுகிறது.
TARGETNAME – இறுதியில் உருவாக்கப்பட வேண்டிய இயங்கக்கூடிய கோப்பின் பெயர்.
TARGETTYPE – இயங்கக்கூடிய கோப்பு வகை, அது ஒரு இயக்கி (.sys) ஆக இருக்கலாம், பின்னர் புல மதிப்பு DRIVER ஆக இருக்க வேண்டும், நூலகம் (.lib) எனில், மதிப்பு லைப்ரரி. எங்கள் விஷயத்தில், எங்களுக்கு இயங்கக்கூடிய கோப்பு (.exe) தேவை, எனவே மதிப்பை நிரலுக்கு அமைக்கிறோம்.
UMTYPE - இந்த புலத்திற்கான சாத்தியமான மதிப்புகள்: கன்சோல் பயன்பாட்டிற்கான கன்சோல், சாளர பயன்முறையில் வேலை செய்வதற்கான சாளரங்கள். ஆனால் நேட்டிவ் அப்ளிகேஷனைப் பெற nt ஐக் குறிப்பிட வேண்டும்.
BUFFER_OVERFLOW_CHECKS - இடையக வழிதல் ஸ்டாக்கை சரிபார்க்கிறது, துரதிர்ஷ்டவசமாக எங்கள் விஷயத்தில் இல்லை, நாங்கள் அதை அணைக்கிறோம்.
MINWIN_SDK_LIB_PATH – இந்த மதிப்பு SDK_LIB_PATH மாறியைக் குறிக்கிறது, உங்களிடம் அத்தகைய கணினி மாறி இல்லை என்று கவலைப்பட வேண்டாம், DDK இலிருந்து சரிபார்க்கப்பட்ட கட்டமைப்பை இயக்கும்போது, இந்த மாறி அறிவிக்கப்பட்டு தேவையான நூலகங்களை சுட்டிக்காட்டும்.
ஆதாரங்கள் - உங்கள் நிரலுக்கான ஆதாரங்களின் பட்டியல்.
அசெம்பிளிக்குத் தேவையான தலைப்புக் கோப்புகளை உள்ளடக்கியது. இங்கே அவை வழக்கமாக DDK உடன் வரும் கோப்புகளுக்கான பாதையைக் குறிக்கின்றன, ஆனால் நீங்கள் கூடுதலாக வேறு எதையும் குறிப்பிடலாம்.
TARGETLIBS - இணைக்கப்பட வேண்டிய நூலகங்களின் பட்டியல்.
USE_NTDLL என்பது வெளிப்படையான காரணங்களுக்காக 1 ஆக அமைக்கப்பட வேண்டிய ஒரு புலமாகும்.
USER_C_FLAGS - பயன்பாட்டுக் குறியீட்டைத் தயாரிக்கும் போது, முன்செயலி வழிமுறைகளில் நீங்கள் பயன்படுத்தக்கூடிய கொடிகள்.
எனவே உருவாக்க, நாம் x86 (அல்லது x64) சரிபார்க்கப்பட்ட பில்டை இயக்க வேண்டும், வேலை செய்யும் கோப்பகத்தை ப்ராஜெக்ட் கோப்புறைக்கு மாற்றி Build கட்டளையை இயக்க வேண்டும். ஸ்கிரீன்ஷாட்டில் உள்ள முடிவு, எங்களிடம் ஒரு இயங்கக்கூடிய கோப்பு இருப்பதைக் காட்டுகிறது.
இந்தக் கோப்பை அவ்வளவு எளிதாகத் தொடங்க முடியாது, பின்வரும் பிழையுடன் அதன் நடத்தையைப் பற்றி சிந்திக்க கணினி சபித்து நம்மை அனுப்புகிறது:
சொந்த பயன்பாட்டை எவ்வாறு தொடங்குவது?
autochk தொடங்கும் போது, நிரல்களின் தொடக்க வரிசை பதிவு விசையின் மதிப்பால் தீர்மானிக்கப்படுகிறது:
அமர்வு மேலாளர் இந்த பட்டியலிலிருந்து நிரல்களை ஒவ்வொன்றாக செயல்படுத்துகிறார். அமர்வு மேலாளர் கணினி 32 கோப்பகத்தில் இயங்கக்கூடிய கோப்புகளைத் தேடுகிறார். பதிவேட்டில் முக்கிய மதிப்பு வடிவம் பின்வருமாறு:
autocheck autochk *MyNative
மதிப்பு ஹெக்ஸாடெசிமல் வடிவத்தில் இருக்க வேண்டும், வழக்கமான ASCII அல்ல, எனவே மேலே காட்டப்பட்டுள்ள விசை வடிவமைப்பில் இருக்கும்:
நிறுவி மறுதொடக்கம் செய்த பிறகு, பயனர் தேர்வுத் திரை தோன்றும் முன்பே, பின்வரும் படத்தைப் பெறுவோம்:
இதன் விளைவாக
அத்தகைய சிறிய பயன்பாட்டின் உதாரணத்தைப் பயன்படுத்தி, விண்டோஸ் நேட்டிவ் மட்டத்தில் பயன்பாட்டை இயக்குவது மிகவும் சாத்தியம் என்று நாங்கள் நம்பினோம். அடுத்து, இன்னோபோலிஸ் பல்கலைக்கழகத்தைச் சேர்ந்த தோழர்களும் நானும் எங்கள் திட்டத்தின் முந்தைய பதிப்பை விட டிரைவருடன் தொடர்பு கொள்ளும் செயல்முறையைத் தொடங்கும் ஒரு சேவையைத் தொடர்ந்து உருவாக்குவோம். வின்32 ஷெல்லின் வருகையுடன், ஏற்கனவே உருவாக்கப்பட்ட ஒரு முழு அளவிலான சேவைக்கு கட்டுப்பாட்டை மாற்றுவது தர்க்கரீதியானதாக இருக்கும் (இதைப் பற்றி மேலும் இங்கே).
அடுத்த கட்டுரையில், ஆக்டிவ் ரீஸ்டோர் சேவையின் மற்றொரு கூறு, அதாவது யுஇஎஃப்ஐ இயக்கியைத் தொடுவோம். எங்கள் வலைப்பதிவிற்கு குழுசேரவும், எனவே நீங்கள் அடுத்த இடுகையைத் தவறவிடாதீர்கள்.