28

最近我在*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 ,但是除非我知道调用约定,否则我如何在程序集中使用它们。

官方的 : ???

  • 如果你说,他们没有记录它。那么如何在不知道系统调用的情况下为 windows 编写 libc 呢?一个人将如何进行 Windows 汇编编程?至少在驱动程序编程中需要知道这些。对?

现在,所谓的 Native API 是怎么回事?Native API&两者是System calls for windows指同一事物的不同术语吗?为了确认我比较了来自两个非官方来源的这些

系统调用:http ://www.metasploit.com/users/opcode/syscalls.html

原生 API:http ://undocumented.ntinternals.net/aindex.html

我的观察:

  1. 所有系统调用都以字母开头Nt,因为 Native API 由许多不以字母开头的函数组成Nt
  2. System Call of windows是 的子集Native API。系统调用只是 Native API 的一部分。

任何人都可以证实这一点并解释一下。

编辑:

还有另一个答案。这是第二个答案。我真的很喜欢它,但我不知道为什么回答者删除了它。我要求他重新发布他的答案。

4

5 回答 5

31

如果您在 Windows 下进行汇编编程,则无需进行手动系统调用。您使用 NTDLL 和 Native API 来为您做这件事。

Native API 只是内核模式方面的包装器。它所做的只是为正确的 API 执行系统调用。

您永远不需要手动系统调用,因此您的整个问题都是多余的。

Linux 系统调用代码不会改变,Windows 会改变,这就是为什么你需要通过一个额外的抽象层(又名 NTDLL)来工作。

编辑:

此外,即使您在汇编级别工作,您仍然可以完全访问 Win32 API,没有理由一开始就使用 NT API!导入、导出等在汇编程序中都可以正常工作。

编辑2:

如果您真的想要手动进行系统调用,您将需要为每个相关的 Windows 版本反转 NTDLL,添加版本检测(通过 PEB),并为每个调用执行系统调用查找。

但是,那将是愚蠢的。NTDLL 的存在是有原因的。

人们已经完成了逆向工程部分:请参阅https://j00ru.vexillium.org/syscalls/nt/64/以获取每个 Windows 内核的系统调用号表。(请注意,即使在 Windows 10 的版本之间,后面的行也会发生变化。)同样,在您自己的机器上进行仅供个人使用的实验以了解有关 asm 和/或 Windows 内部的更多信息之外,这是一个坏主意。不要将系统调用内联到您分发给其他任何人的代码中。

于 2010-03-22T04:07:11.483 回答
8

关于 Windows 系统调用约定,您需要了解的另一件事是,据我了解,系统调用表是作为构建过程的一部分生成的。这意味着它们可以简单地改变——没有人跟踪它们。如果有人在列表顶部添加了一个新的,那没关系。NTDLL 仍然有效,因此调用 NTDLL 的其他人仍然有效。

甚至用于执行系统调用(int 或 sysenter)的机制也不是一成不变的,并且在过去发生了变化,我认为曾几何时,相同版本的 windows 使用不同的 DLL,这些 DLL 使用不同的入口机制,具体取决于机器中的 CPU。

于 2010-04-30T19:28:41.640 回答
2

我有兴趣在没有导入的情况下在程序集中进行 Windows API 调用(作为教育练习),因此我编写了以下 FASM 程序集来执行 NtDll!NtCreateFile 所做的事情。在我的64位版本Windows(Win10 1803 Version 10.0.17134)上粗略演示,调用后崩溃了,但是syscall的返回值为零所以成功。一切都按照 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
);
于 2018-07-23T15:35:07.373 回答
1

Windows 系统调用是通过调用诸如kernel32.dllor之类的系统 DLL 来执行的gdi32.dll,这是通过普通的子例程调用来完成的。陷入操作系统特权层的机制没有记录,但这没关系,因为 DLL 喜欢kernel32.dll为您执行此操作。

通过系统调用,我指的是记录在案的 Windows API 入口点,例如CreateProcess()or GetWindowText()。设备驱动程序通常使用与 Windows DDK 不同的 API。

于 2010-03-22T03:37:22.500 回答
-3

Windows 中的官方调用约定:http: //msdn.microsoft.com/en-us/library/7kcdt6fy.aspx

(希望这个链接在未来仍然存在;如果没有,只需在 MSDN 上搜索“x64 Software Conventions”)。

Linux 和 Windows x86_64 中的函数调用约定不同。在这两种 ABI 中,参数最好通过寄存器传递,但使用的寄存器不同。有关 Linux ABI 的更多信息,请访问 http://www.x86-64.org/documentation/abi.pdf

于 2010-03-23T19:23:48.633 回答