Aplikasi Windows Native sareng jasa Acronis Active Restore
Dinten ieu kami neruskeun carita kumaha urang, bareng jeung guys ti Innopolis Universitas, ngamekarkeun téhnologi Active Mulangkeun pikeun ngidinan pamaké pikeun ngamimitian gawé dina mesin maranéhanana pas mungkin sanggeus gagal. Urang bakal ngobrol ngeunaan aplikasi Windows asli, kalebet fitur ciptaan sareng peluncuranana. Di handap ieu potongan sakedik ngeunaan proyék kami, ogé pituduh praktis ngeunaan cara nyerat aplikasi asli.
Dina tulisan sateuacana urang parantos nyarioskeun naon éta Aktip Mulangkeun, jeung kumaha siswa ti Innopolis ngamekarkeun palayanan. Dinten abdi hoyong difokuskeun aplikasi asli, ka tingkat nu urang hoyong "ngubur" jasa recovery aktip urang. Upami sadayana leres, maka urang bakal tiasa:
Ngajalankeun jasa sorangan leuwih awal
Kontak awan dimana cadangan lokasina leuwih saméméhna
Teuing saméméhna ngartos naon mode sistem - boot normal atawa recovery
Langkung sakedik file pikeun pulih sateuacanna
Ngidinan pangguna pikeun ngamimitian langkung gancang.
Naon ari aplikasi asli?
Pikeun ngajawab patarosan ieu, hayu urang nempo runtuyan panggero sistem, contona, lamun programmer dina aplikasi na nyoba nyieun file.
Pavel Yosifovich - Pemrograman Kernel Windows (2019)
Programmer ngagunakeun fungsi JieunFile, anu dinyatakeun dina file header fileapi.h sareng dilaksanakeun dina Kernel32.dll. Nanging, fungsi ieu nyalira henteu nyiptakeun file, éta ngan ukur pariksa argumen input sareng nyauran fungsina NtCreateFile (awalan Nt ngan nunjukkeun yén fungsina asli). Pungsi ieu dinyatakeun dina file lulugu winternl.h sarta dilaksanakeun dina ntdll.dll. Nyiapkeun pikeun luncat kana rohangan nuklir, saatos éta nelepon sistem pikeun nyiptakeun file. Dina hal ieu, tétéla yén Kernel32 ngan ukur bungkus pikeun Ntdll. Salah sahiji alesan naha ieu dipigawé nyaéta yén Microsoft sahingga mibanda kamampuhan pikeun ngarobah fungsi tina dunya asli, tapi teu noél interfaces baku. Microsoft henteu nyarankeun nyauran fungsi asli sacara langsung sareng henteu ngadokumentasikeun kalolobaanana. Ku jalan kitu, fungsi undocumented bisa kapanggih di dieu.
Kauntungan utama tina aplikasi asli nyaéta ntdll dimuat kana sistem langkung awal tibatan kernel32. Ieu logis, sabab kernel32 merlukeun ntdll jalan. Hasilna, aplikasi anu nganggo pungsi asli tiasa ngamimitian dianggo langkung awal.
Ku kituna, Windows Native Applications mangrupikeun program anu tiasa ngamimitian awal dina boot Windows. Aranjeunna ngan nganggo fungsi tina ntdll. Conto aplikasi sapertos kieu: autochk anu ngalaksanakeun chkdisk utiliti pikeun mariksa disk pikeun kasalahan sateuacan ngamimitian jasa utama. Ieu persis tingkat urang hayang Active Mulangkeun janten.
Urang peryogi naon?
DDK (Driver Development Kit), ayeuna ogé katelah WDK 7 (Windows Driver Kit).
Mesin virtual (contona, Windows 7 x64)
Teu perlu, tapi file lulugu nu bisa diundeur bisa mantuan di dieu
Naon dina kode?
Hayu urang latihan saeutik tur, contona, nulis aplikasi leutik nu:
Mintonkeun pesen dina layar
Allocates sababaraha memori
Ngadagoan input keyboard
Frees nepi memori dipaké
Dina aplikasi asli, titik éntri teu utama atawa winmain, tapi fungsi NtProcessStartup, saprak urang sabenerna langsung ngajalankeun prosés anyar dina sistem.
Hayu urang mimitian ku mintonkeun pesen dina layar. Pikeun ieu kami ngagaduhan fungsi asli NtDisplayString, nu nyokot salaku argumen hiji pointer ka obyék struktur UNICODE_STRING. RtlInitUnicodeString bakal ngabantosan urang ngamimitian. Hasilna, pikeun mintonkeun téks dina layar urang bisa nulis fungsi leutik ieu:
//usage: WriteLn(L"Here is my textn");
void WriteLn(LPWSTR Message)
{
UNICODE_STRING string;
RtlInitUnicodeString(&string, Message);
NtDisplayString(&string);
}
Kusabab ngan ukur fungsi tina ntdll anu sayogi pikeun urang, sareng ngan saukur teu aya perpustakaan anu sanés dina mémori, urang pasti bakal ngagaduhan masalah sareng kumaha alokasi mémori. The operator anyar teu acan aya (sabab asalna ti dunya teuing tinggi-tingkat C ++), tur euweuh fungsi malloc (merlukeun runtime perpustakaan C). Tangtosna, anjeun ngan ukur tiasa nganggo tumpukan. Tapi lamun urang kudu dinamis allocate memori, urang kudu ngalakukeun hal eta dina numpuk (ie numpuk). Ku kituna hayu urang nyieun tumpukan pikeun diri urang sorangan sarta nyandak memori ti eta iraha wae urang butuh eta.
Fungsina cocog pikeun tugas ieu RtlCreateHeap. Salajengna, nganggo RtlAllocateHeap sareng RtlFreeHeap, urang bakal ngeusian sareng ngosongkeun mémori nalika urang peryogina.
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);
Hayu urang ngaléngkah ka ngantosan input keyboard.
Sadaya anu urang peryogikeun nyaéta nganggo NtReadFile dina alat nu kabuka, sarta antosan nepi ka keyboard balik pencét sagala ka kami. Lamun kenop ESC dipencet, urang bakal neruskeun gawé. Pikeun muka alat, urang kedah nyauran fungsi NtCreateFile (urang kedah muka DeviceKeyboardClass0). Urang ogé bakal nelepon NtCreateEventpikeun initialize obyek ngantosan. Urang bakal nyatakeun struktur KEYBOARD_INPUT_DATA sorangan, anu ngagambarkeun data keyboard. Ieu bakal ngagampangkeun padamelan urang.
Aplikasi asli ditungtungan ku telepon fungsi NtTerminateProcesssabab urang ngan saukur maéhan prosés urang sorangan.
Sadaya kode pikeun aplikasi leutik kami:
#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);
}
PS: Urang bisa kalayan gampang ngagunakeun fungsi DbgBreakPoint () dina kode urang eureun di debugger nu. Leres, anjeun kedah nyambungkeun WinDbg ka mesin virtual pikeun debugging kernel. Pitunjuk ngeunaan cara ngalakukeun ieu tiasa dipendakan di dieu atawa ngan ngagunakeun VirtualKD.
Kompilasi jeung assembly
Cara panggampangna pikeun ngawangun aplikasi asli nyaéta ngagunakeun DDK (Supir Development Kit). Urang peryogi versi katujuh kuna, saprak versi engké boga pendekatan rada béda jeung dianggo raket jeung Visual Studio. Upami kami nganggo DDK, maka proyék kami ngan ukur peryogi Makefile sareng sumber.
Ngadamel
!INCLUDE $(NTMAKEENV)makefile.def
sumber:
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 anjeun bakal persis sarua, tapi hayu urang nempo sumber dina leuwih jéntré saeutik. Berkas ieu netepkeun sumber program anjeun (.c file), pilihan ngawangun, sareng parameter sanésna.
TARGETNAME - nami file anu tiasa dieksekusi anu kedah dilakukeun dina tungtungna.
TARGETTYPE - tipe file laksana, éta bisa jadi supir (.sys), lajeng nilai widang kedah supir, lamun perpustakaan (.lib), lajeng nilaina PUSTAKA. Dina kasus urang, urang peryogi file anu tiasa dieksekusi (.exe), ku kituna urang nyetél nilai kana PROGRAM.
UMTYPE - nilai anu mungkin pikeun widang ieu: konsol pikeun aplikasi konsol, windows pikeun digawé dina modeu windowed. Tapi urang kudu nangtukeun nt pikeun meunangkeun aplikasi asli.
BUFFER_OVERFLOW_CHECKS - mariksa tumpukan pikeun panyangga mudal, hanjakalna teu bisi urang, urang mareuman.
MINWIN_SDK_LIB_PATH - nilai ieu nujul kana SDK_LIB_PATH variabel, ulah salempang nu teu boga sistem sapertos variabel dinyatakeun, nalika urang ngajalankeun dipariksa ngawangun ti DDK, variabel ieu bakal dinyatakeun sarta bakal nunjuk ka perpustakaan perlu.
SUMBER – daptar sumber pikeun program anjeun.
Kaasup - file lulugu anu diperlukeun pikeun assembly. Di dieu aranjeunna biasana nunjukkeun jalur ka file anu aya dina DDK, tapi anjeun ogé tiasa netepkeun anu sanés.
TARGETLIBS - daptar perpustakaan anu kedah dikaitkeun.
USE_NTDLL mangrupakeun widang diperlukeun nu kudu disetel ka 1 alesan atra.
USER_C_FLAGS - sagala umbul nu bisa Anjeun pake dina directives preprocessor nalika Nyiapkeun kode aplikasi.
Ku kituna pikeun ngawangun, urang kudu ngajalankeun x86 (atawa x64) dipariksa Build, ngarobah diréktori gawé ka folder proyék tur ngajalankeun paréntah Bangun. Hasil dina layar nunjukkeun yén urang gaduh hiji file anu tiasa dieksekusi.
Berkas ieu henteu tiasa diluncurkeun kalayan gampang, sistem kutukan sareng ngirimkeun urang mikirkeun paripolahna kalayan kasalahan ieu:
Kumaha ngajalankeun aplikasi asli?
Nalika autochk dimimitian, urutan ngamimitian program ditangtukeun ku nilai konci pendaptaran:
Pangatur sési ngaéksekusi program tina daptar ieu hiji-hiji. Pangatur sési milarian file anu tiasa dieksekusi sorangan dina diréktori system32. Format nilai konci pendaptaran nyaéta kieu:
autocheck autochk *MyNative
Nilaina kedah dina format héksadesimal, sanés ASCII biasa, janten konci anu dipidangkeun di luhur bakal aya dina format:
Saatos instalasi sareng reboot, bahkan sateuacan layar pamilihan pangguna muncul, urang bakal nampi gambar ieu:
hasil
Nganggo conto aplikasi leutik sapertos kitu, kami yakin yén éta cukup mungkin pikeun ngajalankeun aplikasi dina tingkat Windows Native. Salajengna, urang ti Universitas Innopolis sareng kuring bakal teras-terasan ngawangun jasa anu bakal ngamimitian prosés interaksi sareng supir langkung awal tibatan dina versi sateuacana tina proyék kami. Sareng ku mecenghulna cangkang win32, éta logis pikeun mindahkeun kontrol ka layanan pinuh anu parantos dikembangkeun (langkung seueur ngeunaan ieu. di dieu).
Dina tulisan salajengna urang bakal nyabak komponén séjén tina jasa Active Restore, nyaéta supir UEFI. Ngalanggan blog kami supados anjeun henteu sono kana postingan salajengna.