Системные вызовы в Windows и Native API?
-
21-09-2019 - |
Вопрос
В последнее время я использую много языка ассемблера в операционных системах * NIX.Мне было интересно узнать о домене Windows.
Соглашение о вызовах в Linux:
mov $SYS_Call_NUM, %eax
mov $param1 , %ebx
mov $param2 , %ecx
int $0x80
Вот и все.Вот как мы должны выполнить системный вызов в Linux.
Ссылка на все системные вызовы в Linux:
Относительно того, какой $SYS_Call_NUM и какие параметры мы можем использовать эту ссылку : http://docs.cs.up.ac.za/programming/asm/derick_tut/syscalls.html
ОФИЦИАЛЬНАЯ Ссылка : http://kernel.org/doc/man-pages/online/dir_section_2.html
Соглашение о вызовах в Windows:
???
Ссылка на все системные вызовы в Windows:
???
Неофициальный : http://www.metasploit.com/users/opcode/syscalls.html , но как мне использовать их в сборке, если я не знаю соглашения о вызовах.
ОФИЦИАЛЬНЫЙ :???
- Если вы скажете, что они не задокументировали это.Тогда как же можно написать libc для Windows, не зная системных вызовов?Как можно программировать на ассемблере Windows?По крайней мере, при программировании драйвера нужно это знать.верно?
Итак, что происходит с так называемым Native API?Является Native API
& System calls for windows
оба это разные термины, обозначающие одно и то же?Чтобы подтвердить это, я сравнил их из двух НЕОФИЦИАЛЬНЫХ источников
Системные вызовы: http://www.metasploit.com/users/opcode/syscalls.html
Собственный API: http://undocumented.ntinternals.net/aindex.html
Мои наблюдения:
- Все системные вызовы начинаются с букв
Nt
где as Native API состоит из множества функций, которые не начинаются с буквNt
. System Call of windows
являются подмножествомNative API
.Системные вызовы - это всего лишь часть собственного API.
Может ли кто-нибудь подтвердить это и объяснить.
Редактировать:
Был и другой ответ.Это был 2-й ответ.Мне это действительно понравилось, но я не знаю, почему ответчик удалил это.Я прошу его перепостить свой ответ.
Решение
Если вы занимаетесь программированием на ассемблере под Windows, вы не выполняете системные вызовы вручную.Вы используете NTDLL и Native API, чтобы сделать это за вас.
Собственный API - это просто оболочка вокруг того, что связано с режимом ядра.Все, что он делает, это выполняет системный вызов для правильного API.
Вам НИКОГДА не понадобится выполнять системный вызов вручную, так что весь ваш вопрос излишен.
Коды системных вызовов Linux не меняются, в отличие от Windows, вот почему вам нужно работать через дополнительный уровень абстракции (он же NTDLL).
Редактировать:
Кроме того, даже если вы работаете на уровне ассемблера, у вас по-прежнему есть полный доступ к Win32 API, нет никаких причин использовать NT API для начала!Импорт, экспорт и т.д. - все это прекрасно работает в программах ассемблера.
РЕДАКТИРОВАТЬ 2:
Если вы ДЕЙСТВИТЕЛЬНО хотите выполнять системные вызовы вручную, вам нужно будет отменить NTDLL для каждой соответствующей версии Windows, добавить определение версии (через PEB) и выполнить поиск системного вызова для каждого вызова.
Однако это было бы глупо.NTDLL существует не просто так.
Люди уже выполнили часть обратного инжиниринга:видишь https://j00ru.vexillium.org/syscalls/nt/64/ для таблицы номеров системных вызовов для каждого ядра Windows.(Обратите внимание, что более поздние строки меняются даже между версиями Windows 10.) Опять же, это плохая идея, если не считать экспериментов только для личного пользования на вашем собственном компьютере, чтобы узнать больше о asm и / или внутренних компонентах Windows.Не вставляйте системные вызовы в код, который вы распространяете кому-либо еще.
Другие советы
Еще одна вещь, которую вам нужно знать о соглашении о системных вызовах Windows, - это то, что, насколько я понимаю, таблицы системных вызовов генерируются как часть процесса сборки.Это означает, что они могут просто измениться - их никто не отслеживает.Если кто-то добавит новый в начало списка, это не имеет значения.NTDLL все еще работает, поэтому все остальные, кто вызывает NTDLL, все еще работают.
Даже механизм, используемый для выполнения системных вызовов (который называется int или sysenter), не зафиксирован в камне и менялся в прошлом, и я думаю, что когда-то в одной и той же версии Windows использовались разные библиотеки DLL, которые использовали разные механизмы ввода в зависимости от процессора на компьютере.
Системные вызовы Windows выполняются путем вызова системных библиотек DLL, таких как kernel32.dll
или gdi32.dll
, что выполняется с помощью обычных вызовов подпрограммы.Механизмы для перехода на привилегированный уровень ОС недокументированы, но это нормально, потому что библиотеки DLL, такие как kernel32.dll
сделай это для себя.
И под системными вызовами я имею в виду документированные точки входа в Windows API, такие как CreateProcess()
или GetWindowText()
.Драйверы устройств обычно используют API, отличный от Windows DDK.
Мне было интересно выполнить вызов Windows API в сборке без импорта (в качестве учебного упражнения), поэтому я написал следующую сборку FASM, чтобы делать то, что делает NtDll!NtCreateFile.Это грубая демонстрация на моей 64-разрядной версии Windows (Win10 1803 версии 10.0.17134), и она завершает работу после вызова, но возвращаемое значение системного вызова равно нулю, поэтому оно выполнено успешно.Все настраивается в соответствии с соглашением о вызовах Windows x64, затем номер системного вызова загружается в RAX, а затем это инструкция по сборке системного вызова для запуска вызова.Мой пример создает файл c:\HelloWorldFile_FASM, поэтому он должен быть запущен "от имени администратора".
format PE64 GUI 4.0
entry start
section '.text' code readable executable
start:
;puting the first four parameters into the right registers
mov rcx, _Handle
mov rdx, [_access_mask]
mov r8, objectAttributes
mov r9, ioStatusBlock
;I think we need 1 stack word of padding:
push 0x0DF0AD8B
;pushing the other params in reverse order:
push [_eaLength]
push [_eaBuffer]
push [_createOptions]
push [_createDisposition]
push [_shareAcceses]
push [_fileAttributes]
push [_pLargeInterger]
;adding the shadow space (4x8)
; push 0x0
; push 0x0
; push 0x0
; push 0x0
;pushing the 4 register params into the shadow space for ease of debugging
push r9
push r8
push rdx
push rcx
;now pushing the return address to the stack:
push endOfProgram
mov r10, rcx ;copied from ntdll!NtCreateFile, not sure of the reason for this
mov eax, 0x55
syscall
endOfProgram:
retn
section '.data' data readable writeable
;parameters------------------------------------------------------------------------------------------------
_Handle dq 0x0
_access_mask dq 0x00000000c0100080
_pObjectAttributes dq objectAttributes ; at 00402058
_pIoStatusBlock dq ioStatusBlock
_pLargeInterger dq 0x0
_fileAttributes dq 0x0000000000000080
_shareAcceses dq 0x0000000000000002
_createDisposition dq 0x0000000000000005
_createOptions dq 0x0000000000000060
_eaBuffer dq 0x0000000000000000 ; "optional" param
_eaLength dq 0x0000000000000000
;----------------------------------------------------------------------------------------------------------
align 16
objectAttributes:
_oalength dq 0x30
_rootDirectory dq 0x0
_objectName dq unicodeString
_attributes dq 0x40
_pSecurityDescriptor dq 0x0
_pSecurityQualityOfService dq securityQualityOfService
unicodeString:
_unicodeStringLength dw 0x34
_unicodeStringMaxumiumLength dw 0x34, 0x0, 0x0
_pUnicodeStringBuffer dq _unicodeStringBuffer
_unicodeStringBuffer du '\??\c:\HelloWorldFile_FASM' ; may need to "run as adinistrator" for the file create to work.
ioStatusBlock:
_status_pointer dq 0x0
_information dq 0x0
securityQualityOfService:
_sqlength dd 0xC
_impersonationLevel dd 0x2
_contextTrackingMode db 0x1
_effectiveOnly db 0x1, 0x0, 0x0
Я использовал документацию для Ntdll!NtCreateFile, и я также использовал отладчик ядра, чтобы просмотреть и скопировать множество параметров.
__kernel_entry NTSTATUS NtCreateFile(
OUT PHANDLE FileHandle,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes,
OUT PIO_STATUS_BLOCK IoStatusBlock,
IN PLARGE_INTEGER AllocationSize OPTIONAL,
IN ULONG FileAttributes,
IN ULONG ShareAccess,
IN ULONG CreateDisposition,
IN ULONG CreateOptions,
IN PVOID EaBuffer OPTIONAL,
IN ULONG EaLength
);
ОФИЦИАЛЬНОЕ соглашение о вызовах в Windows: http://msdn.microsoft.com/en-us/library/7kcdt6fy.aspx
(надеюсь, эта ссылка сохранится в будущем;если это не так, просто найдите "Соглашения о программном обеспечении x64" в MSDN).
Соглашение о вызове функции отличается в Linux и Windows x86_64.В обоих ABI параметры предпочтительно передаются через регистры, но используемые регистры отличаются.Подробнее о Linux ABI можно найти по адресу http://www.x86-64.org/documentation/abi.pdf