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

Windows平台x64 MASM汇编调用CreateFileA/WriteFile写文件失败求助

x64 MASM 中 CreateFileA + WriteFile 写入失败问题排查与修复

问题描述

在Windows x64平台使用MASM编写汇编代码,调用CreateFileA打开文件后,WriteFile返回RAX=0(执行失败),无法正确写入内容。

原代码片段

INCLUDELIB kernel32.lib
ExitProcess PROTO
CreateFileA PROTO
WriteFile PROTO

clearRegisters MACRO
    XOR RAX, RAX
    XOR RDX, RDX
    XOR RCX, RCX
    XOR R8, R8
    XOR R9, R9
ENDM

GENERIC_WRITE    EQU 04000000h   ;Solution 040000000h
FILE_SHARE_READ  EQU 1
FILE_SHARE_WRITE EQU 2
OPEN_ALWAYS      EQU 4
FILE_ATTRIBUTE_NORMAL EQU 128

.DATA
    filePath BYTE "D:/thanks/ASSEMBLY.txt", 0
    fileHandle QWORD ?
    txt BYTE "Learning Assembly for shellcode development.", 0
    num DWORD ?

.CODE
main PROC
    clearRegisters
    SUB RSP, 64
    
    LEA RCX, filePath
    MOV RDX, GENERIC_WRITE
    MOV R8, FILE_SHARE_READ OR FILE_SHARE_WRITE
    MOV R9, 0

    MOV QWORD PTR [RSP+32], OPEN_ALWAYS
    MOV QWORD PTR [RSP+40], FILE_ATTRIBUTE_NORMAL
    MOV QWORD PTR [RSP+48], 0

    CALL CreateFileA
    MOV fileHandle, RAX

    clearRegisters
    MOV RCX, fileHandle
    LEA RDX, txt
    MOV R8, LENGTHOF txt
    LEA R9, num
    MOV QWORD   PTR [   RSP+32  ],  0

    CALL WriteFile
    TEST RAX, RAX

    CALL ExitProcess
main ENDP

END

问题分析与修复点

1. 修正GENERIC_WRITE常量值

Windows API中GENERIC_WRITE的正确十六进制值为040000000h(即0x40000000),原代码少写一位,导致无法获取正确的文件写入权限,CreateFileA返回无效句柄。

2. 添加CreateFileA返回值检查

CreateFileA失败时会返回INVALID_HANDLE_VALUE(值为-1),必须先检查句柄有效性,再执行后续写入操作,否则无效句柄会直接导致WriteFile失败。

3. 优化写入长度计算

LENGTHOF txt会包含字符串末尾的空字节,写入文件时通常不需要该字符,改用SIZEOF txt - 1计算有效内容长度。

4. 栈参数传递确认

x64 Windows调用约定要求剩余参数按从右到左顺序压入栈,原代码的栈参数位置符合要求,但需确保调用API前栈保持16字节对齐(原代码SUB RSP,64已满足,64是16的倍数)。

修复后的代码

INCLUDELIB kernel32.lib
ExitProcess PROTO
CreateFileA PROTO
WriteFile PROTO

clearRegisters MACRO
    XOR RAX, RAX
    XOR RDX, RDX
    XOR RCX, RCX
    XOR R8, R8
    XOR R9, R9
ENDM

GENERIC_WRITE       EQU 040000000h  ; 修正为正确的写入权限常量
FILE_SHARE_READ     EQU 1
FILE_SHARE_WRITE    EQU 2
OPEN_ALWAYS         EQU 4
FILE_ATTRIBUTE_NORMAL EQU 128
INVALID_HANDLE_VALUE EQU -1

.DATA
    filePath BYTE "D:/thanks/ASSEMBLY.txt", 0
    fileHandle QWORD ?
    txt BYTE "Learning Assembly for shellcode development.", 0
    num DWORD ?

.CODE
main PROC
    clearRegisters
    SUB RSP, 64  ; 分配栈空间,保证16字节对齐
    
    ; 调用CreateFileA打开文件
    LEA RCX, filePath               ; 参数1: 文件名指针
    MOV RDX, GENERIC_WRITE          ; 参数2: 写入权限
    MOV R8, FILE_SHARE_READ OR FILE_SHARE_WRITE  ; 参数3: 共享模式
    MOV R9, 0                       ; 参数4: 安全属性(NULL)
    MOV QWORD PTR [RSP+32], OPEN_ALWAYS          ; 参数5: 创建/打开方式
    MOV QWORD PTR [RSP+40], FILE_ATTRIBUTE_NORMAL ; 参数6: 文件属性
    MOV QWORD PTR [RSP+48], 0       ; 参数7: 模板文件句柄(NULL)

    CALL CreateFileA
    MOV fileHandle, RAX

    ; 检查文件句柄是否有效
    CMP RAX, INVALID_HANDLE_VALUE
    JE exit_program  ; 若无效则直接退出

    ; 调用WriteFile写入内容
    clearRegisters
    MOV RCX, fileHandle             ; 参数1: 文件句柄
    LEA RDX, txt                    ; 参数2: 写入内容指针
    MOV R8, SIZEOF txt - 1          ; 参数3: 有效内容长度(去掉末尾空字节)
    LEA R9, num                     ; 参数4: 实际写入字节数指针
    MOV QWORD PTR [RSP+32], 0       ; 参数5: 重叠结构(NULL)

    CALL WriteFile
    ; 可根据RAX值判断写入结果,添加后续处理逻辑

exit_program:
    CALL ExitProcess
main ENDP

END

验证注意事项

确保D:/thanks/目录已存在,否则CreateFileA会因路径不存在失败;编译运行后,检查D:/thanks/ASSEMBLY.txt是否包含指定内容。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 09:27:04