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

如何在NASM汇编中正确向Windows系统调用传递参数?

问题分析与解决

核心错误点

你的段错误主要来自两个关键问题:参数传递类型错误,以及调用约定声明不当(寄存器顺序本身是正确的)。

1. 输出参数传递错误

NtOpenProcess的第一个参数ProcessHandle是输出参数,类型为PHANDLE(即HANDLE*),需要传入变量的内存地址,而非变量本身。你代码里直接传了proc(值为NULL),系统调用会试图向NULL地址写入进程句柄,直接触发段错误。

2. Win64调用约定声明错误

Win64平台不存在真正的__stdcall调用约定,所有函数默认使用Win64调用约定(前4个参数通过寄存器传递),应使用NTAPI宏来声明函数,或直接省略调用约定声明。

3. 系统调用号的兼容性

0x26是Win10及后续版本NtOpenProcess的正确系统调用号,若使用更早Windows版本,需对应调整调用号(可通过逆向ntdll.dll导出表确认)。

修正后的代码

修正后的funcs.asm

section .text
global NtOpenProcess

NtOpenProcess:
    mov rax, 26h    ; Win10+ 下NtOpenProcess的系统调用号
    syscall
    ret

修正后的main.c

#include <windows.h>
// 使用NTAPI声明,匹配Win64调用约定
extern NTSTATUS NTAPI NtOpenProcess(
    PHANDLE ProcessHandle,
    ACCESS_MASK DesiredAccess,
    POBJECT_ATTRIBUTES ObjectAttributes,
    PCLIENT_ID ClientId
);

int main()
{
    HANDLE proc = NULL;
    OBJECT_ATTRIBUTES obj_attr = {sizeof(obj_attr), 0, NULL, 0};
    CLIENT_ID cid;
    cid.UniqueProcess = (HANDLE)316;
    cid.UniqueThread = 0; 

    // 第一个参数传入proc的地址,而非proc本身
    NTSTATUS res = NtOpenProcess(&proc, PROCESS_ALL_ACCESS, &obj_attr, &cid);
    
    // 可选:检查调用结果并清理句柄
    if (NT_SUCCESS(res) && proc != NULL) {
        CloseHandle(proc);
    }
    return 0;
}

关键说明

  • Windows x64下NT系统调用的参数寄存器顺序确实为:rcx→第一个参数、rdx→第二个、r8→第三个、r9→第四个,你的初始理解是正确的。
  • 输出参数必须传递指针,否则会导致非法内存访问,这是触发段错误的核心原因。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 03:26:00