Я занимался исследованиями внутренних компонентов Windows и только недавно узнал о системных вызовах, и мне интересно, возможно ли использовать эти системные вызовы как функции? Я понимаю, что они не предназначены для внешнего доступа.
Например: NtUserEmptyClipboard
системный вызов в Win32k.sys, и его адрес 0x117f
Если бы я хотел использовать этот вызов как функцию, как я мог это сделать?
То, что вы хотите сделать, во многом зависит от архитектуры, которая вас интересует, но важно знать, что ntdll.dll
это батут в пользовательском режиме для каждого системного вызова, то есть единственный, кто фактически делает системные вызовы в конце дня, это ntdll.
Итак, давайте разберем один из этих методов в WinDbg, открыв любой старый exe (я выбрал блокнот). Во-первых, используйте x ntdll!*
чтобы найти символы, экспортируемые ntdll:
0:000> x ntdll!*
00007ff9`ed1aec20 ntdll!RtlpMuiRegCreateLanguageList (void)
00007ff9`ed1cf194 ntdll!EtwDeliverDataBlock (void)
00007ff9`ed20fed0 ntdll!shortsort_s (void)
00007ff9`ed22abbf ntdll!RtlUnicodeStringToOemString$fin$0 (void)
00007ff9`ed1e9af0 ntdll!LdrpAllocateDataTableEntry (void)
...
Итак, давайте выберем один наугад, NtReadFile
выглядит аккуратно. Давайте разберем это:
0:000> uf ntdll!NtReadFile
ntdll!NtReadFile:
00007ff9`ed21abe0 4c8bd1 mov r10,rcx
00007ff9`ed21abe3 b805000000 mov eax,5
00007ff9`ed21abe8 0f05 syscall
00007ff9`ed21abea c3 ret
Здесь мы видим, что мы разбираемся rcx
, введите номер системного вызова в eax
затем позвоните syscall
инструкция. Каждый системный вызов имеет номер, который произвольно назначается Windows (то есть этот номер является секретным рукопожатием между ntdll и ядром и изменяется всякий раз, когда Microsoft хочет)
Ни одна из этих инструкций не является «волшебной», вы также можете выполнить их непосредственно в своем приложении (но, разумеется, для этого нет никаких практических причин — просто ради забавы)
EmptyClipboard
является одним из так называемых «Win32 API» и NtUserEmptyClipboard
это соответствующий «нативный API».
В отличие от Linux syscall(2)
Мы редко должны прямо называть «нативный API». Я слышал, что они в ntdll.dll
скорее, чем win32k.sys
, Но мы должны иметь возможность вызывать их так же, как обычные функции, определенные в обычной DLL.
Я сильно сомневаюсь что 0x117f
это адрес ты ищешь. Я подозреваю, что это может быть значение, которое вам нужно передать GetProcAddress
, Но я не знаю наверняка, так как эти вещи различаются в разных версиях Windows (именно поэтому обычные люди вместо этого используют документированные функции)
Основная часть нативного API экспортируется через обычные функции из ntdll.dll. Вы можете загрузить эту dll в ваш процесс и вызывать эти функции, как и любые другие функции API. Пока у вас есть правильные прототипы функций и параметры, вызовы будут работать отлично. Внутри они переходят из режима пользователя в режим ядра, а затем используют смещение в таблице дескрипторов системных служб (SSDT), чтобы найти адрес функции в памяти режима ядра, и затем вызывается функция. Есть проект с открытым исходным кодом http://nativetest.codeplex.com/ это делает вызовы к нативному API, к которому вы можете обратиться.
Функции в win32k.sys не отображаются в ntdll.dll. Насколько я могу судить, они нигде не выставлены. Адрес, который вы перечислили — я считаю — на самом деле является смещением в SSDT. Если вам действительно нужно вызвать эту функцию, вам придется выполнить переход от пользовательского режима к режиму ядра самостоятельно, поместив все параметры функции и смещение SSDT в правильные места.
Как и другие рекомендовали, я бы предложил найти API пользовательского режима, чтобы помочь выполнить то, что вы хотите сделать. FWIW, в user32.dll функция EmptyClipboard, по-видимому, перенаправляет непосредственно в NtUserEmptyClipboard, в соответствии с выводом link / dump.
1731 DF 0002018A EmptyClipboard = _NtUserEmptyClipboard@0