RegOpenKeyEx 在 MASM64 中返回错误 87

Posted

技术标签:

【中文标题】RegOpenKeyEx 在 MASM64 中返回错误 87【英文标题】:RegOpenKeyEx returns error 87 in MASM64 【发布时间】:2016-11-06 12:47:09 【问题描述】:

我正在用 MASM64 (ML64.exe) 编写小型应用程序。其中一项功能是在注册表中设置值。我开始打开钥匙,但有一个错误。

函数 RegOpenKeyEx 返回错误 87,GetLastError 返回 0x36B7。

我的代码:

extrn ExitProcess : proc
extrn MessageBoxA : proc
extrn RegOpenKeyExA : proc
extrn RegSetValueExA : proc
extrn RegCloseKey : proc
extrn GetLastError : proc

.const
HKEY_CURRENT_USER equ 80000001h
KEY_SET_VALUE equ 2
KEY_CREATE_SUB_KEY equ 4
KEY_WOW64_64KEY equ 0100h
KEY_WRITE equ 00020006h
REG_SZ equ 00000001h

.data
hReg dq 0
szRegKeyName db "Software\Microsoft\Windows\CurrentVersion\Run",0

.code

    Main proc
        sub rsp, 30h
        lea rax, hReg
        push rax
        mov r9, KEY_SET_VALUE+KEY_CREATE_SUB_KEY+KEY_WOW64_64KEY
        mov r8, 0
        lea rdx, szRegKeyName
        mov rcx, HKEY_CURRENT_USER
        call RegOpenKeyExA ;returns 87
        call GetLastError ;returns 0x36B7
        add rsp, 30h

        xor rcx, rcx
        call ExitProcess
    Main endp
end

请帮助我。提前感谢您的帮助。

【问题讨论】:

你没有正确使用x64 abi,​​你不能忽略影子空间。先用C写这段代码,看看编译器生成的机器码。 除此之外,调用 GetLastError 是没有意义的。返回值是错误代码。阅读文档。 @HansPassant 那么如何修复此代码?你知道哪里错了吗? 您还忘记了 pdata 部分中的unwind codes。 【参考方案1】:

您对堆栈的操作不正确。您的主要错误 - push rax 实际上您在这里设置的不是第 5 个参数,但什么也没有。第 5 个参数是堆栈中的随机值。正确设置第 5 个参数 - mov [rsp+20h],rax 。更多地查看堆栈对齐,GetLastError 与此处无关 - Reg* 函数自己返回错误代码,但不设置 lasterror。并且不对 hReg 使用全局变量,而是在堆栈中分配它。示例可能如下所示:

extrn ExitProcess : proc
extrn MessageBoxA : proc
extrn RegOpenKeyExA : proc
extrn RegSetValueExA : proc
extrn RegCloseKey : proc

.const
HKEY_CURRENT_USER equ 80000001h
KEY_SET_VALUE equ 2
KEY_CREATE_SUB_KEY equ 4
KEY_WOW64_64KEY equ 0100h
KEY_WRITE equ 00020006h
REG_SZ equ 00000001h

.data
szRegKeyName db "Software\Microsoft\Windows\CurrentVersion\Run",0

.code

hReg equ 28h

    test proc
        sub rsp, 38h
        lea rax,[rsp+hReg]
        mov [rsp+20h],rax
        mov r9, KEY_SET_VALUE+KEY_CREATE_SUB_KEY+KEY_WOW64_64KEY
        mov r8, 0
        lea rdx, szRegKeyName
        mov rcx, HKEY_CURRENT_USER
        call RegOpenKeyExA
        test eax,eax
        jnz @@1
        mov rcx,[rsp+hReg]
        call RegCloseKey
@@1:
        add rsp, 38h
        ret
    test endp
end

【讨论】:

谢谢@RbMm。有没有办法用push 指令做到这一点?我一直使用push 和其他代码。 @Dave - 当然你使用 push 。但这在 x64 中不是很有用 再次感谢@RbMm 的回答。我认为我不了解堆栈对齐。参数 count + 返回地址必须能被 16 整除。一个参数将有:sub rsp,16(1 个参数 + 返回地址)。有两个参数会有:sub rsp、32(2个参数+返回地址+对齐)等。我想对了吗? @Dave - 如果您仍然不明白 - 第 5 个参数必须在调用时位于 rsp+20h。但在您的代码中,它位于rsp+0 - 所以push rax 在堆栈中使用错误的位置。还需要sub rsp,20h 在您推送 5,6,7,... args 之后,因为在调用时必须是 rsp==16*n - 所以如果使用 5 或 6 个 args 将有不同的对齐方式。结果 push 未在 x64 代码中使用。首先向下堆叠并对齐。然后将 mov [rsp+20h+8*n],A(n+5) 用于 arg A(n+5) 所以这是计算对齐的公式(sub rsp,X):rsp+20h+8*n?一个参数会有:sub rsp, 28h,两个参数:sub rsp, 30h等等?

以上是关于RegOpenKeyEx 在 MASM64 中返回错误 87的主要内容,如果未能解决你的问题,请参考以下文章

RegOpenKeyEx 返回错误 161

64位读取注册表与32位的区别

MASM x86-64 scanf 不读取空格

SOFTWARE\Microsoft\Windows NT\CurrentVersion\SecEdit\Reg 值的 RegOpenKeyEx 返回错误代码 2

与64位版本的Windows不兼容,masm运行不了

与64位版本的Windows不兼容,masm运行不了