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.

Aplikasi Windows Native sareng jasa Acronis Active Restore

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.

Aplikasi Windows Native sareng jasa Acronis Active Restore
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:

  1. Mintonkeun pesen dina layar
  2. Allocates sababaraha memori
  3. Ngadagoan input keyboard
  4. 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.

// 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;

//...

HANDLE hKeyBoard, hEvent;
UNICODE_STRING skull, keyboard;
OBJECT_ATTRIBUTES ObjectAttributes;
IO_STATUS_BLOCK Iosb;
LARGE_INTEGER ByteOffset;
KEYBOARD_INPUT_DATA kbData;

// 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);

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;
	}
}

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.

Aplikasi Windows Native sareng jasa Acronis Active Restore

Berkas ieu henteu tiasa diluncurkeun kalayan gampang, sistem kutukan sareng ngirimkeun urang mikirkeun paripolahna kalayan kasalahan ieu:

Aplikasi Windows Native sareng jasa Acronis Active Restore

Kumaha ngajalankeun aplikasi asli?

Nalika autochk dimimitian, urutan ngamimitian program ditangtukeun ku nilai konci pendaptaran:

HKLMSystemCurrentControlSetControlSession ManagerBootExecute

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:

61,75,74,6f,63,68,65,63,6b,20,61,75,74,6f,63,68,6b,20,2a,00,4d,79,4e,61,74,69,76,65,00,00

Pikeun ngarobah judul, anjeun tiasa nganggo jasa online, contona, ieu.

Aplikasi Windows Native sareng jasa Acronis Active Restore
Tétéla pikeun ngaluncurkeun aplikasi asli, urang peryogi:

  1. Nyalin file laksana ka folder system32
  2. Tambahkeun konci pikeun pendaptaran
  3. Reboot mesin

Pikeun genah, ieu mangrupikeun skrip anu siap pikeun masang aplikasi asli:

install.bat

@echo off
copy MyNative.exe %systemroot%system32.
regedit /s add.reg
echo Native Example Installed
pause

add.reg

REGEDIT4

[HKEY_LOCAL_MACHINESYSTEMCurrentControlSetControlSession Manager]
"BootExecute"=hex(7):61,75,74,6f,63,68,65,63,6b,20,61,75,74,6f,63,68,6b,20,2a,00,4d,79,4e,61,74,69,76,65,00,00

Saatos instalasi sareng reboot, bahkan sateuacan layar pamilihan pangguna muncul, urang bakal nampi gambar ieu:

Aplikasi Windows Native sareng jasa Acronis Active Restore

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.

sumber: www.habr.com

Tambahkeun komentar