Windows Aplikasi Asli lan layanan Pemulihan Acronis Active

Dina iki, kita bakal nerusake crita babagan kepiye kita kerja bareng karo Universitas Innopolis kanggo ngembangake teknologi Active Restore supaya pangguna bisa nerusake kerja ing mesin kanthi cepet sawise kacilakan. Kita bakal ngrembug babagan aplikasi asli. Windows, kalebu rincian babagan digawe lan diluncurake. Ing ngisor iki ana latar mburi cilik babagan proyek kita, uga pandhuan praktis babagan carane nulis aplikasi asli.

Windows Aplikasi Asli lan layanan Pemulihan Acronis Active

Ing kiriman sadurunge kita wis ngomong babagan apa Aktif mulihake, lan carane siswa saka Innopolis berkembang layanan. Dina iki aku pengin fokus ing aplikasi asli, menyang tingkat sing pengin "ngubur" layanan pemulihan aktif. Yen kabeh bisa ditindakake, mula kita bakal bisa:

  • Bukak layanan kasebut luwih awal
  • Hubungi awan ing ngendi serep dumunung luwih awal
  • Luwih sadurunge ngerti apa mode sistem ing - boot normal utawa Recovery
  • Luwih sithik file sing bisa pulih luwih dhisik
  • Ngidini pangguna miwiti luwih cepet.

Apa iku app native?

Kanggo njawab pitakonan iki, ayo kang katon ing urutan saka telpon sistem, contone, yen programmer ing aplikasi nyoba kanggo nggawe file.

Windows Aplikasi Asli lan layanan Pemulihan Acronis Active
Pavel Yosifovich — Windows Pemrograman Kernel (2019)

Programmer nggunakake fungsi kasebut NggaweFile, sing diumumake ing file header fileapi.h lan dileksanakake ing Kernel32.dll. Nanging, fungsi iki dhewe ora nggawe file, mung mriksa argumen input lan nelpon fungsi kasebut NtCreateFile (ater-ater Nt mung nuduhake yen fungsi kasebut asli). Fungsi iki diumumake ing file header winternl.h lan dileksanakake ing ntdll.dll. Nyiyapake kanggo mlumpat menyang ruang nuklir, sawise iku nggawe telpon sistem kanggo nggawe file. Ing kasus iki, ternyata Kernel32 mung bungkus kanggo Ntdll. Salah sawijining alasan kenapa iki ditindakake yaiku Microsoft nduweni kemampuan kanggo ngganti fungsi ing donya asli, nanging ora ndemek antarmuka standar. Microsoft ora nyaranake nelpon fungsi asli langsung lan ora nyathet paling akeh. Miturut cara, fungsi undocumented bisa ditemokake kene.

Kauntungan utama aplikasi asli yaiku ntdll dimuat menyang sistem luwih awal tinimbang kernel32. Iki logis, amarga kernel32 mbutuhake ntdll bisa digunakake. Akibaté, aplikasi sing nggunakake fungsi asli bisa wiwit digunakake luwih awal.

Mangkono, Windows Aplikasi Native yaiku program sing bisa mlaku luwih awal nalika boot. WindowsDheweke mung nggunakake fungsi saka ntdll. Conto aplikasi kaya ngono: autochk sing nindakake sarana chkdisk kanggo mriksa disk kanggo kesalahan sadurunge miwiti layanan utama. Iki persis level sing dikarepake Active Restore.

Apa sing dibutuhake?

  • DDK (Kit Pengembangan Driver), saiki uga dikenal minangka WDK 7 (Windows Piranti Driver).
  • Mesin virtual (contone. Windows 7 x 64)
  • Ora perlu, nanging file header sing bisa diundhuh bisa mbantu kene

Apa ing kode?

Ayo latihan sethithik lan, contone, nulis aplikasi cilik sing:

  1. Nampilake pesen ing layar
  2. Allocates sawetara memori
  3. Ngenteni input keyboard
  4. Mbebasake memori sing digunakake

Ing aplikasi asli, titik entri ora utama utawa winmain, nanging fungsi NtProcessStartup, amarga kita langsung miwiti proses anyar ing sistem kasebut.

Ayo miwiti kanthi nampilake pesen ing layar. Kanggo iki kita duwe fungsi asli NtDisplayString, sing njupuk minangka argumen pointer menyang obyek struktur UNICODE_STRING. RtlInitUnicodeString bakal mbantu kita miwiti. Akibaté, kanggo nampilake teks ing layar kita bisa nulis fungsi cilik iki:

//usage: WriteLn(L"Here is my textn");
void WriteLn(LPWSTR Message)
{
    UNICODE_STRING string;
    RtlInitUnicodeString(&string, Message);
    NtDisplayString(&string);
}

Wiwit mung fungsi saka ntdll kasedhiya kanggo kita, lan mung ana perpustakaan liyane ing memori durung, kita mesthi bakal duwe masalah karo carane nyedhiakke memori. Operator anyar durung ana (amarga asalé saka donya tingkat dhuwur banget C ++), lan ora ana fungsi malloc (mbutuhake runtime perpustakaan C). Mesthi, sampeyan mung bisa nggunakake tumpukan. Nanging yen kita kudu mbosenke nyedhiakke memori, kita kudu nindakake ing numpuk (ie numpuk). Dadi ayo nggawe tumpukan kanggo awake dhewe lan njupuk memori saka iku kapan wae kita butuh.

Fungsi kasebut cocog kanggo tugas iki RtlCreateHeap. Sabanjure, nggunakake RtlAllocateHeap lan RtlFreeHeap, kita bakal ngenggoni lan mbebasake memori nalika kita butuh.

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

Ayo pindhah menyang ngenteni 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;
	}
}

Kabeh sing dibutuhake yaiku nggunakake NtReadFile ing piranti sing mbukak, lan ngenteni nganti keyboard ngasilake penet kanggo kita. Yen tombol ESC dipencet, kita bakal terus kerja. Kanggo mbukak piranti, kita kudu nelpon fungsi NtCreateFile (kita kudu mbukak DeviceKeyboardClass0). Kita uga bakal nelpon NtCreateEventkanggo initialize obyek ngenteni. Kita bakal ngumumake struktur KEYBOARD_INPUT_DATA dhewe, sing nggambarake data keyboard. Iki bakal nggawe karya kita luwih gampang.

Aplikasi native rampung karo telpon fungsi NtTerminateProcessamarga kita mung mateni proses kita dhewe.

Kabeh kode kanggo aplikasi cilik kita:

#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: Kita bisa gampang nggunakake fungsi DbgBreakPoint () ing kode kanggo mungkasi ing debugger. Bener, sampeyan kudu nyambungake WinDbg menyang mesin virtual kanggo debugging kernel. Pandhuan babagan carane nindakake iki bisa ditemokake kene utawa mung nggunakake VirtualKD.

Kompilasi lan perakitan

Cara paling gampang kanggo mbangun aplikasi asli yaiku nggunakake DDK (Driver Development Kit). Kita butuh versi kapitu kuna, amarga versi mengko duwe pendekatan sing rada beda lan bisa digunakake kanthi rapet karo Visual Studio. Yen kita nggunakake DDK, mula proyek kita mung butuh Makefile lan sumber.

makefile

!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 sampeyan bakal persis padha, nanging ayo ndeleng sumber kanthi luwih rinci. Berkas iki nemtokake sumber program (.c file), opsi mbangun, lan paramèter liyane.

  • TARGETNAME – jeneng file eksekusi sing kudu diprodhuksi ing pungkasan.
  • TARGETTYPE - jinis file eksekusi, bisa dadi driver (.sys), banjur nilai lapangan kudu DRIVER, yen perpustakaan (.lib), banjur nilai LIBRARY. Ing kasus kita, kita butuh file eksekusi (.exe), mula kita nyetel nilai kasebut menyang PROGRAM.
  • UMTYPE - nilai sing bisa ditrapake kanggo lapangan iki: konsol kanggo aplikasi konsol, windows kanggo digunakake ing mode windowed. Nanging kita kudu nemtokake nt kanggo njaluk aplikasi asli.
  • BUFFER_OVERFLOW_CHECKS - mriksa tumpukan kanggo buffer overflow, sayangé ora cilik, kita mateni.
  • MINWIN_SDK_LIB_PATH - Nilai iki nuduhake SDK_LIB_PATH variabel, aja padha sumelang yen sampeyan ora duwe kuwi variabel sistem ngumumaké, nalika kita mbukak dicenthang mbangun saka DDK, variabel iki bakal ngumumaké lan bakal nuduhake perpustakaan perlu.
  • SUMBER – dhaptar sumber kanggo program sampeyan.
  • Klebet - file header sing dibutuhake kanggo perakitan. Kene padha biasane nuduhake path menyang file sing teka karo DDK, nanging sampeyan uga bisa nemtokake liyane.
  • TARGETLIBS - dhaptar perpustakaan sing kudu disambung.
  • USE_NTDLL minangka kolom sing dibutuhake sing kudu disetel dadi 1 amarga alasan sing jelas.
  • USER_C_FLAGS – gendera apa wae sing bisa digunakake ing arahan preprocessor nalika nyiapake kode aplikasi.

Dadi kanggo mbangun, kita kudu mbukak x86 (utawa x64) Priksa Mbangun, ngganti direktori kerja menyang folder proyek lan mbukak printah Mbangun. Asil ing gambar nuduhake yen kita duwe siji file eksekusi.

Windows Aplikasi Asli lan layanan Pemulihan Acronis Active

File iki ora bisa diluncurake kanthi gampang, sistem ngipat-ipati lan ngirim kita mikir babagan prilaku kanthi kesalahan ing ngisor iki:

Windows Aplikasi Asli lan layanan Pemulihan Acronis Active

Kepiye cara miwiti aplikasi asli?

Nalika autochk diwiwiti, urutan wiwitan program ditemtokake dening nilai kunci registri:

HKLMSystemCurrentControlSetControlSession ManagerBootExecute

Manajer sesi nglakokake program saka dhaptar iki siji-siji. Pangatur sesi nggoleki file eksekusi dhewe ing direktori system32. Format nilai kunci registri kaya ing ngisor iki:

autocheck autochk *MyNative

Nilai kasebut kudu ana ing format heksadesimal, dudu ASCII sing biasa, mula tombol sing ditampilake ing ndhuwur bakal ana ing 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

Kanggo ngowahi judhul, sampeyan bisa nggunakake layanan online, contone, iki.

Windows Aplikasi Asli lan layanan Pemulihan Acronis Active
Ternyata kanggo mbukak aplikasi asli, kita kudu:

  1. Nyalin file eksekusi menyang folder system32
  2. Tambah tombol menyang pendaptaran
  3. Urip maneh mesin

Kanggo penak, iki skrip sing wis siap kanggo nginstal aplikasi asli:

nginstal.bat

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

nambah.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

Sawise instalasi lan urip maneh, sanajan sadurunge layar pilihan pangguna katon, kita bakal entuk gambar ing ngisor iki:

Windows Aplikasi Asli lan layanan Pemulihan Acronis Active

Asile

Nggunakake aplikasi cilik iki minangka conto, kita yakin manawa ngluncurake aplikasi ing level Windows Native pancen bisa. Sabanjure, aku lan kanca-kanca saka Universitas Innopolis bakal terus mbangun layanan sing bakal miwiti interaksi karo driver luwih awal tinimbang versi proyek sadurunge. Lan kanthi anane shell Win32, bakal logis kanggo mindhah kontrol menyang layanan lengkap sing wis dikembangake (liyane mengko). kene).

Ing artikel sabanjure, kita bakal ndemek komponen liyane saka layanan Active Restore, yaiku driver UEFI. Langganan ing blog kita supaya sampeyan ora kantun kiriman sabanjure.

Source: www.habr.com

Tuku hosting sing dipercaya kanggo situs kanthi proteksi DDoS, server VPS VDS 🔥 Tuku hosting situs web sing bisa dipercaya nganggo proteksi DDoS, server VPS VDS | ProHoster