د وینډوز اصلي غوښتنلیکونه او اکرونیس فعال بیا رغونه خدمت

نن ورځ موږ دې کیسې ته دوام ورکوو چې څنګه موږ د انوپولیس پوهنتون هلکانو سره یوځای د فعال بیا رغونې ټیکنالوژي رامینځته کوو ترڅو کارونکي ته اجازه ورکړي چې د ناکامۍ وروسته ژر تر ژره په خپل ماشین کار پیل کړي. موږ به د اصلي وینډوز غوښتنلیکونو په اړه وغږیږو، په شمول د دوی د جوړولو او پیل کولو ځانګړتیاوې. د کټ لاندې زموږ د پروژې په اړه لږ څه دي، په بیله بیا د اصلي غوښتنلیکونو لیکلو څرنګوالي په اړه عملي لارښود.

د وینډوز اصلي غوښتنلیکونه او اکرونیس فعال بیا رغونه خدمت

په تیرو پوسټونو کې موږ دمخه د دې په اړه خبرې کړې چې دا څه دي فعال بیا رغونه، او څنګه د Innopolis زده کونکي وده کوي خدمت. نن زه غواړم په اصلي غوښتنلیکونو تمرکز وکړم، هغه کچې ته چې موږ غواړو زموږ د فعال بیا رغونې خدمت "دفن" کړو. که هرڅه سم وي، نو موږ به وکولی شو:

  • خدمت پخپله ډیر دمخه پیل کړئ
  • د بادل سره اړیکه ونیسئ چیرې چې بیک اپ ډیر دمخه موقعیت لري
  • ډیر دمخه پوهیدل چې سیسټم په کوم حالت کې دی - نورمال بوټ یا رغونه
  • ډیر لږ فایلونه مخکې له مخکې بیرته ترلاسه کول
  • کارونکي ته اجازه ورکړئ چې حتی ګړندي پیل وکړي.

په هرصورت اصلي ایپ څه شی دی؟

د دې پوښتنې ځواب لپاره، راځئ چې د تلیفونونو ترتیب وګورو چې سیسټم یې کوي، د بیلګې په توګه، که چیرې یو پروګرامر په خپل غوښتنلیک کې د فایل جوړولو هڅه وکړي.

د وینډوز اصلي غوښتنلیکونه او اکرونیس فعال بیا رغونه خدمت
پاول یوسیفوویچ - د وینډوز کرنل برنامه کول (2019)

پروګرامر د فعالیت څخه کار اخلي فایل جوړ کړئ، کوم چې د سرلیک فایل fileapi.h کې اعلان شوی او په Kernel32.dll کې پلي کیږي. په هرصورت، دا فنکشن پخپله فایل نه جوړوي، دا یوازې د ان پټ دلیلونه ګوري او فنکشن ته زنګ وهي NtCreateFile (پریفکس Nt یوازې دا په ګوته کوي چې فنکشن اصلي دی). دا فعالیت د winternl.h سرلیک فایل کې اعلان شوی او په ntdll.dll کې پلي کیږي. دا اټومي فضا ته د کودتا لپاره چمتو کوي، وروسته له هغه چې دا د فایل جوړولو لپاره سیسټم ته زنګ وهي. په دې حالت کې، دا معلومه شوه چې Kernel32 یوازې د Ntdll لپاره یو ریپر دی. د دې کار کولو یو دلیل دا دی چې مایکروسافټ پدې توګه د دې وړتیا لري چې د اصلي نړۍ دندې بدل کړي ، مګر معیاري انٹرفیسونو ته لمس نه کوي. مایکروسافټ په مستقیم ډول د اصلي دندو غږولو وړاندیز نه کوي او ډیری یې مستند نه کوي. په لاره کې، غیر مستند شوي دندې موندل کیدی شي دلته.

د اصلي غوښتنلیکونو اصلي ګټه دا ده چې ntdll د kernel32 څخه ډیر دمخه په سیسټم کې بار شوی. دا منطقي ده، ځکه چې kernel32 د کار کولو لپاره ntdll ته اړتیا لري. د پایلې په توګه، هغه غوښتنلیکونه چې اصلي دندې کاروي کولی شي ډیر دمخه کار پیل کړي.

په دې توګه، د وینډوز اصلي غوښتنلیکونه هغه پروګرامونه دي چې د وینډوز بوټ په پیل کې پیل کیدی شي. دوی یوازې د ntdll افعال کاروي. د دې ډول غوښتنلیک یوه بیلګه: autochk څوک ترسره کوي د chkdisk اسانتیا د اصلي خدماتو پیل کولو دمخه د غلطیو لپاره ډیسک چیک کول. دا دقیقا هغه کچه ده چې موږ غواړو زموږ فعال بیا رغونه وي.

موږ به څه ته اړتیا ولرو؟

  • DDK (د ډرایور پرمختیا کټ)، اوس د WDK 7 (وینډوز ډرایور کټ) په نوم هم پیژندل کیږي.
  • مجازی ماشین (د مثال په توګه، وینډوز 7 x64)
  • اړین ندي، مګر د سرلیک فایلونه چې ډاونلوډ کیدی شي مرسته وکړي دلته

په کوډ کې څه دي؟

راځئ چې لږ تمرین وکړو او د مثال په توګه یو کوچنی غوښتنلیک ولیکئ چې:

  1. په سکرین کې یو پیغام ښکاره کوي
  2. یو څه حافظه تخصیص کوي
  3. د کیبورډ داخلیدو ته انتظار باسي
  4. کارول شوې حافظه خلاصوي

په اصلي غوښتنلیکونو کې، د ننوتلو نقطه اصلي یا winmain نه ده، مګر د 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);

راځئ چې د کیبورډ ان پټ لپاره انتظار ته لاړ شو.

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

ټول هغه څه چې موږ یې کارولو ته اړتیا لرو 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);
}

PS: موږ کولی شو په اسانۍ سره زموږ په کوډ کې د DbgBreakPoint() فنکشن وکاروو ترڅو دا په ډیبګر کې ودروو. ریښتیا، تاسو به اړتیا ولرئ WinDbg د کرنل ډیبګ کولو لپاره مجازی ماشین سره وصل کړئ. د دې کولو څرنګوالي په اړه لارښوونې موندل کیدی شي دلته یا یوازې وکاروئ VirtualKD.

تالیف او مجلس

د اصلي غوښتنلیک جوړولو لپاره ترټولو اسانه لاره کارول دي DDK (د موټر چلوونکي پرمختیا کټ). موږ پخوانۍ اوومې نسخې ته اړتیا لرو، ځکه چې وروستي نسخې یو څه توپیر لري او د لید سټوډیو سره نږدې کار کوي. که موږ DDK وکاروو، نو زموږ پروژه یوازې میک فایل او سرچینو ته اړتیا لري.

تشکیلول

!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) کیدی شي، نو د ساحې ارزښت باید ډرایور وي، که کتابتون (.lib) وي، نو ارزښت یې LIBRARY دی. زموږ په قضیه کې، موږ د اجرا وړ فایل (.exe) ته اړتیا لرو، نو موږ ارزښت پروګرام ته ټاکو.
  • UMTYPE - د دې ساحې لپاره ممکنه ارزښتونه: د کنسول غوښتنلیک لپاره کنسول، په کړکۍ حالت کې د کار کولو لپاره وینډوز. مګر موږ اړتیا لرو چې د اصلي غوښتنلیک ترلاسه کولو لپاره nt مشخص کړو.
  • BUFFER_OVERFLOW_CHECKS - د بفر اوور فلو لپاره سټیک چیک کول ، له بده مرغه زموږ قضیه نده ، موږ یې بند کوو.
  • MINWIN_SDK_LIB_PATH - دا ارزښت د SDK_LIB_PATH متغیر ته اشاره کوي، اندیښنه مه کوئ چې تاسو داسې سیسټم متغیر اعلان نلرئ، کله چې موږ د DDK څخه چک شوي جوړونه چلوو، دا متغیر به اعلان شي او اړین کتابتونونو ته به اشاره وکړي.
  • سرچینې - ستاسو د پروګرام لپاره د سرچینو لیست.
  • شامل دي - د سرلیک فایلونه چې د مجلس لپاره اړین دي. دلته دوی عموما هغه فایلونو ته لاره په ګوته کوي چې د DDK سره راځي، مګر تاسو کولی شئ نور نور هم مشخص کړئ.
  • TARGETLIBS - د کتابتونونو لیست چې اړتیا لري تړل شي.
  • USE_NTDLL یو اړین ساحه ده چې باید د واضح دلیلونو لپاره 1 ته وټاکل شي.
  • USER_C_FLAGS - هر هغه بیرغونه چې تاسو یې د غوښتنلیک کوډ چمتو کولو پرمهال د پری پروسیسر لارښوونو کې کارولی شئ.

نو د جوړولو لپاره ، موږ اړتیا لرو چې x86 (یا x64) چیک شوی جوړ چل کړو ، کاري لارښود د پروژې فولډر ته بدل کړو او د جوړونې کمانډ چلوو. په سکرین شاټ کې پایله ښیې چې موږ یو د اجرا وړ فایل لرو.

د وینډوز اصلي غوښتنلیکونه او اکرونیس فعال بیا رغونه خدمت

دا فایل دومره په اسانۍ سره نه شي پیل کیدی، سیسټم لعنت کوي او موږ ته د لاندې غلطۍ سره د دې چلند په اړه فکر کولو ته لیږو:

د وینډوز اصلي غوښتنلیکونه او اکرونیس فعال بیا رغونه خدمت

څنګه یو اصلي غوښتنلیک پیل کړئ؟

کله چې آټوچک پیل شي ، د برنامو پیل کولو ترتیب د راجسټری کیلي ارزښت لخوا ټاکل کیږي:

HKLMSystemCurrentControlSetControlSession ManagerBootExecute

د غونډې مدیر د دې لیست څخه پروګرامونه یو له بل سره اجرا کوي. د سیشن مدیر پخپله د سیسټم 32 لارښود کې د اجرا وړ فایلونو لټون کوي. د راجستر کلیدي ارزښت بڼه په لاندې ډول ده:

autocheck autochk *MyNative

ارزښت باید د هیکساډیسیمل بڼه کې وي، نه د معمول ASCII، نو پورته ښودل شوي کلیدي به په بڼه کې وي:

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

د سرلیک بدلولو لپاره، تاسو کولی شئ آنلاین خدمت وکاروئ، د بیلګې په توګه، دا.

د وینډوز اصلي غوښتنلیکونه او اکرونیس فعال بیا رغونه خدمت
دا معلومه شوه چې د اصلي غوښتنلیک پیلولو لپاره، موږ اړتیا لرو:

  1. د اجرا وړ فایل سیسټم 32 فولډر ته کاپي کړئ
  2. راجسټری ته کیلي اضافه کړئ
  3. ماشین بیا پیل کړئ

د اسانتیا لپاره، دلته د اصلي غوښتنلیک نصبولو لپاره چمتو شوی سکریپټ دی:

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

د نصب او ریبوټ وروسته ، حتی مخکې لدې چې د کارونکي انتخاب سکرین څرګند شي ، موږ به لاندې عکس ترلاسه کړو:

د وینډوز اصلي غوښتنلیکونه او اکرونیس فعال بیا رغونه خدمت

نتیجه

د داسې کوچني غوښتنلیک مثال په کارولو سره ، موږ ډاډه شو چې دا د وینډوز اصلي کچه کې غوښتنلیک چلول خورا امکان لري. بیا ، د انوپولیس پوهنتون هلکان او زه به د داسې خدمت رامینځته کولو ته دوام ورکړو چې زموږ د پروژې پخوانۍ نسخې په پرتله به د ډرایور سره د متقابل عمل پروسه پیل کړي. او د win32 شیل په راتګ سره، دا به منطقي وي چې کنټرول بشپړ شوي خدمت ته انتقال کړي چې لا دمخه رامینځته شوی (په دې اړه نور دلته).

په راتلونکې مقاله کې به موږ د فعال بیا رغولو خدمت بلې برخې سره اړیکه ونیسو، یعنې د UEFI ډرایور. زموږ بلاګ کې ګډون وکړئ ترڅو تاسو راتلونکی پوسټ له لاسه ورنکړئ.

سرچینه: www.habr.com

Add a comment