Системные вызовы в windows & Native API?
Недавно я использовал много языков ассемблера в операционных системах * 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 Assembly? По крайней мере, в программировании драйвера нужно знать это. не так ли?
Теперь, что происходит с так называемым Native API? Являются ли Native API
и System calls for windows
оба термина, относящиеся к одному и тому же? Чтобы подтвердить, что я сравнил их с двумя НЕОФИЦИАЛЬНЫМИ источниками
Системные вызовы: http://www.metasploit.com/users/opcode/syscalls.html
Native API: http://undocumented.ntinternals.net/aindex.html
Мои наблюдения:
- Все системные вызовы начинаются с букв
Nt
, где, поскольку Native API состоит из множества функций, которые не начинаются с букв Nt
.
-
System Call of windows
являются подмножествами Native API
. Системные вызовы являются частью Native API.
Может ли кто-нибудь подтвердить это и объяснить.
EDIT:
Был еще один ответ. Это был второй ответ. Мне очень понравилось, но я не знаю, почему ответчик удалил его. Я прошу его передать ответ.
Ответы
Ответ 1
Если вы занимаетесь программированием на ассемблере под Windows, вы не делаете системные вызовы вручную. Вы используете NTDLL и Native API, чтобы сделать это для вас.
Native API - это просто оболочка для сторон ядра. Все, что он делает, это выполняет системный вызов для правильного API.
Вам НИКОГДА не нужно вручную выполнять системный вызов, чтобы весь ваш вопрос был излишним.
Коды системных вызовов в Linux не меняются, как в Windows, поэтому вам нужно работать через дополнительный уровень абстракции (он же NTDLL).
РЕДАКТИРОВАТЬ:
Кроме того, даже если вы работаете на уровне сборки, у вас все еще есть полный доступ к Win32 API, поэтому нет оснований использовать NT API для начала! Импорт, экспорт и т.д. Все отлично работают в программах сборки.
EDIT2:
Если вы ДЕЙСТВИТЕЛЬНО хотите выполнять системные вызовы вручную, вам нужно будет отменить NTDLL для каждой соответствующей версии Windows, добавить определение версии (через PEB) и выполнить поиск по системному вызову для каждого вызова.
Однако это было бы глупо. NTDLL существует по причине.
Люди уже сделали часть обратного инжиниринга: см. Https://j00ru.vexillium.org/syscalls/nt/64/ для таблицы номеров системных вызовов для каждого ядра Windows. (Обратите внимание, что более поздние строки меняются даже между версиями Windows 10.) Опять же, это плохая идея, кроме экспериментов только для личного использования на вашей собственной машине, чтобы узнать больше об asm и/или внутренностях Windows. Не вставляйте системные вызовы в код, который вы распространяете среди других.
Ответ 2
Другое, что вам нужно знать о конвенции syscall windows, заключается в том, что, насколько я понимаю, таблицы syscall генерируются как часть процесса сборки. Это означает, что они могут просто измениться - никто их не отслеживает. Если кто-то добавляет новый в верхней части списка, это не имеет значения. NTDLL все еще работает, поэтому все остальные, кто звонит в NTDLL, все еще работают.
Даже механизм, используемый для выполнения системных вызовов (который int или sysenter) не исправлен в камне и в прошлом не изменился, и я думаю, что когда-то одна и та же версия окон использовала разные библиотеки DLL, которые использовали разные механизмы ввода в зависимости от процессора в машине.
Ответ 3
Системные вызовы Windows выполняются путем вызова в системные DLL, такие как kernel32.dll
или gdi32.dll
, что выполняется с обычными вызовами подпрограмм. Механизмы захвата в привилегированный уровень ОС недокументированы, но это нормально, потому что DLL, например kernel32.dll
, делают это для вас.
И по системным вызовам я имею в виду документированные точки входа Windows API, такие как CreateProcess()
или GetWindowText()
. Драйверы устройств обычно используют другой API из DDK Windows.
Ответ 4
Я был заинтересован в выполнении вызова Windows API в сборке без импорта (как учебное упражнение), поэтому я написал следующую сборку FASM, чтобы сделать то, что делает NtDll! NtCreateFile. Это грубая демонстрация на моей 64-битной версии Windows (Win10 1803 Version 10.0.17134), и она вылетает после вызова, но возвращаемое значение системного вызова равно нулю, поэтому оно успешно. Все настраивается в соответствии с соглашением о вызовах Windows x64, затем номер системного вызова загружается в RAX, а затем это инструкция сборки syscall для запуска вызова. В моем примере создается файл 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
);
Ответ 5
ОФИЦИАЛЬНОЕ Соглашение о вызовах в 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