نن ورځ موږ دې کیسې ته دوام ورکوو چې څنګه موږ د انوپولیس پوهنتون هلکانو سره یوځای د فعال بیا رغونې ټیکنالوژي رامینځته کوو ترڅو کارونکي ته اجازه ورکړي چې د ناکامۍ وروسته ژر تر ژره په خپل ماشین کار پیل کړي. موږ به د اصلي وینډوز غوښتنلیکونو په اړه وغږیږو، په شمول د دوی د جوړولو او پیل کولو ځانګړتیاوې. د کټ لاندې زموږ د پروژې په اړه لږ څه دي، په بیله بیا د اصلي غوښتنلیکونو لیکلو څرنګوالي په اړه عملي لارښود.
په تیرو پوسټونو کې موږ دمخه د دې په اړه خبرې کړې چې دا څه دي
- خدمت پخپله ډیر دمخه پیل کړئ
- د بادل سره اړیکه ونیسئ چیرې چې بیک اپ ډیر دمخه موقعیت لري
- ډیر دمخه پوهیدل چې سیسټم په کوم حالت کې دی - نورمال بوټ یا رغونه
- ډیر لږ فایلونه مخکې له مخکې بیرته ترلاسه کول
- کارونکي ته اجازه ورکړئ چې حتی ګړندي پیل وکړي.
په هرصورت اصلي ایپ څه شی دی؟
د دې پوښتنې ځواب لپاره، راځئ چې د تلیفونونو ترتیب وګورو چې سیسټم یې کوي، د بیلګې په توګه، که چیرې یو پروګرامر په خپل غوښتنلیک کې د فایل جوړولو هڅه وکړي.
پاول یوسیفوویچ - د وینډوز کرنل برنامه کول (2019)
پروګرامر د فعالیت څخه کار اخلي
د اصلي غوښتنلیکونو اصلي ګټه دا ده چې ntdll د kernel32 څخه ډیر دمخه په سیسټم کې بار شوی. دا منطقي ده، ځکه چې kernel32 د کار کولو لپاره ntdll ته اړتیا لري. د پایلې په توګه، هغه غوښتنلیکونه چې اصلي دندې کاروي کولی شي ډیر دمخه کار پیل کړي.
په دې توګه، د وینډوز اصلي غوښتنلیکونه هغه پروګرامونه دي چې د وینډوز بوټ په پیل کې پیل کیدی شي. دوی یوازې د ntdll افعال کاروي. د دې ډول غوښتنلیک یوه بیلګه:
موږ به څه ته اړتیا ولرو؟
DDK (د ډرایور پرمختیا کټ)، اوس د WDK 7 (وینډوز ډرایور کټ) په نوم هم پیژندل کیږي.- مجازی ماشین (د مثال په توګه، وینډوز 7 x64)
- اړین ندي، مګر د سرلیک فایلونه چې ډاونلوډ کیدی شي مرسته وکړي
دلته
په کوډ کې څه دي؟
راځئ چې لږ تمرین وکړو او د مثال په توګه یو کوچنی غوښتنلیک ولیکئ چې:
- په سکرین کې یو پیغام ښکاره کوي
- یو څه حافظه تخصیص کوي
- د کیبورډ داخلیدو ته انتظار باسي
- کارول شوې حافظه خلاصوي
په اصلي غوښتنلیکونو کې، د ننوتلو نقطه اصلي یا winmain نه ده، مګر د NtProcessStartup فعالیت، ځکه چې موږ واقعیا په سیسټم کې نوي پروسې پیل کوو.
راځئ چې په سکرین کې د پیغام په ښودلو سره پیل وکړو. د دې لپاره موږ یو اصلي فعالیت لرو
//usage: WriteLn(L"Here is my textn");
void WriteLn(LPWSTR Message)
{
UNICODE_STRING string;
RtlInitUnicodeString(&string, Message);
NtDisplayString(&string);
}
څرنګه چې یوازې د ntdll فعالیت موږ ته شتون لري، او په ساده ډول په حافظه کې نور کتابتونونه شتون نلري، موږ به خامخا د حافظې تخصیص کولو کې ستونزې ولرو. نوی آپریټر لاهم شتون نلري (ځکه چې دا د C++ د خورا لوړې کچې نړۍ څخه راځي) ، او هیڅ malloc فعالیت شتون نلري (دا د چلولو وخت C کتابتونونو ته اړتیا لري). البته، تاسو کولی شئ یوازې یو سټیک وکاروئ. مګر که موږ په متحرک ډول حافظه تخصیص کولو ته اړتیا لرو ، نو موږ باید دا په هپ (د بیلګې په توګه) کې ترسره کړو. نو راځئ چې د ځان لپاره یوه مجموعه جوړه کړو او هرکله چې ورته اړتیا لرو له هغې څخه حافظه واخلو.
فعالیت د دې دندې لپاره مناسب دی
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;
}
}
ټول هغه څه چې موږ یې کارولو ته اړتیا لرو
اصلي غوښتنلیک د فنکشن کال سره پای ته رسیږي
زموږ د کوچني غوښتنلیک لپاره ټول کوډ:
#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 د کرنل ډیبګ کولو لپاره مجازی ماشین سره وصل کړئ. د دې کولو څرنګوالي په اړه لارښوونې موندل کیدی شي
تالیف او مجلس
د اصلي غوښتنلیک جوړولو لپاره ترټولو اسانه لاره کارول دي
تشکیلول
!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
د سرلیک بدلولو لپاره، تاسو کولی شئ آنلاین خدمت وکاروئ، د بیلګې په توګه،
دا معلومه شوه چې د اصلي غوښتنلیک پیلولو لپاره، موږ اړتیا لرو:
- د اجرا وړ فایل سیسټم 32 فولډر ته کاپي کړئ
- راجسټری ته کیلي اضافه کړئ
- ماشین بیا پیل کړئ
د اسانتیا لپاره، دلته د اصلي غوښتنلیک نصبولو لپاره چمتو شوی سکریپټ دی:
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