You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用NASM汇编直接调用NtOpenProcess时遇访问违规求助

直接系统调用NtOpenProcess触发访问违规(0xc000005)排查

问题背景

我想要开发一个基于直接系统调用的小型工具包,用NASM汇编调用Windows原生API(如NtOpenProcess)打开进程并显示信息,要求:

  • 使用直接系统调用
  • 采用NASM汇编

我的初始代码如下:

section .bss
    CI resb 16         ; Client ID (CI) - 16 bytes
    OA resb 40         ; OBJECT_ATTRIBUTES (OA) - 40 bytes
    h_process resb 8   ; Handle to opened process - 8 bytes

section .text
global main

main:
    ; Setup stack frame
    push rbp
    mov rbp, rsp
    sub rsp, 60h       ; Allocate 96 bytes for stack shadow

    ; -------------------------
    ; Initialize Client ID (CI)
    ; -------------------------
    mov qword [rel CI], 790h            ; Process ID set to 790h
    mov qword [rel CI + 8], 0x0         ; Thread ID set to 0

    ; -------------------------------------------
    ; Initialize OBJECT_ATTRIBUTES (OA) structure
    ; -------------------------------------------
    mov dword [rel OA], 0x30            ; Length = 0x30 (48 bytes)
    mov qword [rel OA + 8], 0x0         ; RootDirectory = NULL
    mov qword [rel OA + 16], 0x0        ; ObjectName = NULL
    mov dword [rel OA + 24], 0x0        ; Attributes = 0
    mov qword [rel OA + 32], 0x0        ; SecurityDescriptor = NULL
    mov qword [rel OA + 40], 0x0        ; SecurityQualityOfService = NULL

    ; --------------------------------
    ; Initialize process handle to 0
    ; --------------------------------
    mov qword [rel h_process], 0x0      ; h_process = NULL

    ; -----------------------------
    ; Call NtOpenProcess syscall
    ; -----------------------------
    lea rcx, [rel h_process]            ; rcx = address of h_process
    mov rdx, 1FFFFFh                    ; rdx = access mask (all permissions)
    lea r9, [rel CI]                    ; r9 = address of Client ID (CI)
    lea r8, [rel OA]                    ; r8 = address of OBJECT_ATTRIBUTES (OA)
    mov rax, 0x26                       ; rax = NtOpenProcess syscall number

代码编译正常,但调用NtOpenProcess后返回状态码0xc000005(访问违规),已对齐并初始化相关结构,参数传递顺序自认为正确,需要排查问题原因。

问题排查与修复

1. 系统调用参数顺序错误

Windows x64系统调用的参数传递规则为:前4个参数依次放入RCX、RDX、R8、R9。而NtOpenProcess的函数原型是:

NTSTATUS NtOpenProcess(
    OUT PHANDLE ProcessHandle,
    IN ACCESS_MASK DesiredAccess,
    IN POBJECT_ATTRIBUTES ObjectAttributes,
    IN PCLIENT_ID ClientId OPTIONAL
);

你的代码将第3个参数ObjectAttributes放到了R8,第4个参数ClientId放到了R9,顺序完全颠倒,这会导致内核接收到错误的指针,直接触发访问违规。正确的参数顺序应为:

  • RCX = 指向h_process的指针
  • RDX = 权限掩码(1FFFFFh)
  • R8 = 指向OBJECT_ATTRIBUTES的指针
  • R9 = 指向CLIENT_ID的指针

2. OBJECT_ATTRIBUTES结构长度不匹配

你在.bss段定义OA为resb 40,但初始化时设置Length为0x30(48字节),这会导致写入OA+40的位置时越界,覆盖后续的h_process内存空间,引发内存访问错误。64位系统下OBJECT_ATTRIBUTES的实际大小就是48字节,因此.bss段应改为OA resb 48。

3. 缺少系统调用执行指令

代码仅设置了系统调用号到RAX,但没有执行syscall指令,这会导致后续代码执行混乱,同样可能触发访问违规。必须在参数设置完成后添加syscall指令来触发系统调用。

4. 硬编码系统调用号存在兼容性问题

0x26是Windows 10早期版本的NtOpenProcess系统调用号,Windows 11或更新版本的调用号可能已变更。建议通过动态方式获取调用号(比如从ntdll.dll导出的函数中提取),避免硬编码导致的错误。

修复后的代码片段

section .bss
    CI resb 16         ; Client ID (CI) - 16 bytes
    OA resb 48         ; OBJECT_ATTRIBUTES (OA) - 48 bytes (修正长度)
    h_process resb 8   ; Handle to opened process - 8 bytes

section .text
global main

main:
    ; Setup stack frame
    push rbp
    mov rbp, rsp
    sub rsp, 60h       ; Allocate 96 bytes for stack shadow

    ; -------------------------
    ; Initialize Client ID (CI)
    ; -------------------------
    mov qword [rel CI], 790h            ; Process ID set to 790h
    mov qword [rel CI + 8], 0x0         ; Thread ID set to 0

    ; -------------------------------------------
    ; Initialize OBJECT_ATTRIBUTES (OA) structure
    ; -------------------------------------------
    mov dword [rel OA], 0x30            ; Length = 0x30 (48 bytes)
    mov qword [rel OA + 8], 0x0         ; RootDirectory = NULL
    mov qword [rel OA + 16], 0x0        ; ObjectName = NULL
    mov dword [rel OA + 24], 0x0        ; Attributes = 0
    mov qword [rel OA + 32], 0x0        ; SecurityDescriptor = NULL
    mov qword [rel OA + 40], 0x0        ; SecurityQualityOfService = NULL

    ; --------------------------------
    ; Initialize process handle to 0
    ; --------------------------------
    mov qword [rel h_process], 0x0      ; h_process = NULL

    ; -----------------------------
    ; Call NtOpenProcess syscall
    ; -----------------------------
    lea rcx, [rel h_process]            ; rcx = ProcessHandle (OUT)
    mov rdx, 1FFFFFh                    ; rdx = DesiredAccess (IN)
    lea r8, [rel OA]                    ; r8 = ObjectAttributes (IN)
    lea r9, [rel CI]                    ; r9 = ClientId (IN)
    mov rax, 0x26                       ; rax = NtOpenProcess syscall number
    syscall                             ; 执行系统调用

    ; 后续可处理返回值,比如检查RAX是否为STATUS_SUCCESS(0)
    ; ...

内容的提问来源于stack exchange,提问作者katysha

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 22:43:20