从程序集中调用 WinAPI 的 InternetOpenA() 时发生访问冲突

问题描述 投票:0回答:1

我正在尝试使用 Windows API 从程序集建立 HTTP 连接。 代码如下:

%include "const.asm"
%define u(x) __utf16__(x) 
%define w(x) __utf32__(x) 

; Externs
extern InternetOpenA

extern GetLastError

section .data
    curProc   db 0
    hInternet dq 0

    lpszAgent db "Mozilla/5.0", 0

section .text
global Start
Start:
    sub rsp, 8

    sub rsp, 32 + 1 * 8
    lea rcx, [REL lpszAgent]                            ; lpszAgentW (WIDE STRING)
    mov rdx, 4        ; dwAccessType (DWORD)
    mov r8,  NULL                                       ; lpszProxy (DWORD)
    mov r9,  NULL                                       ; pszProxyBypassW (DWORD)
    mov dword [rsp + 4 * 8], NULL                       ; dwFlags (DWORD)
    call InternetOpenA

    mov [REL hInternet], rax 
    add rsp, 32 + 1 * 8                                 ; hInternet parameter
    cmp rax, NULL
    je error_handler

    ; Stop
    jmp exit


error_handler:
    sub rsp, 32
    call GetLastError                                    ; Load more error info
    add rsp, 32 + 8
    ret


exit:                                                    ; Graceful shutdowns
    xor rax, rax
    add rsp, 8
    ret

对应的Makefile为:

INCLUDES := kernel32.lib user32.lib wininet.lib

.PHONY: all compile link clean

all: build

compile:
    @echo "Compiling assembly"
    nasm -f win64 main.asm -o main.o

link: compile
    @echo "Linking assembly"
    polink /ENTRY:Start /SUBSYSTEM:CONSOLE /LIBPATH:C:\lib64 $(INCLUDES) main.o

build: link

clean:
    @echo "Cleaning up"
    del main.o

当我运行它时,返回的错误代码是

-1073741819
0xC0000005
正如@selbie 指出的,或者也称为访问冲突。我在创建句柄时收到了
wininet
winhttp
的段错误。我附上一段简短的 C 代码,准确地显示了我想要做的事情: (程序集不应该有打印。它只是在 C 源代码中用于调试目的)

#include "windows.h"
#include "wininet.h"
#include <stdio.h>

int main() {
    const char *agent = "Mozilla/5.0";
    HINTERNET handler =  InternetOpenA(agent, INTERNET_OPEN_TYPE_PRECONFIG_WITH_NO_AUTOPROXY, 0, 0, 0);
    if (handler) {
        return 0;
    }
    printf("%d", GetLastError());
    return 1;
}

为了清楚起见,我正在针对 64 位 Windows 进行编译。我也静态链接,如

Makefile
中所示。 干杯

编辑:一些调试代码:

[BITS 64]

%include "const.asm"
%define u(x) __utf16__(x) 
%define w(x) __utf32__(x) 

; Externs
extern InternetOpenA

extern GetLastError

extern GetStdHandle
extern WriteFile

section .data
    curProc   db 0
    hInternet dq 0

    lpszAgent db "Mozilla/5.0", 0

    NtlpBuffer:        db    'Hello, World!', 0
    NtnNBytesToWrite:  dq    0eh


section .text
global Start
Start:

    sub rsp, 8
    mov rax, rsp    
    mov rbx, 8 
    xor rdx, rdx
    div rbx
    cmp rdx, 0
    je main

    sub rsp, 32 + 1 * 8
    and rsp, -16
    lea rcx, [REL lpszAgent]                            ; lpszAgentW (WIDE STRING)
    mov rdx, 4                                          ; dwAccessType (DWORD)
    mov r8,  NULL                                       ; lpszProxy (DWORD)
    mov r9,  NULL                                       ; pszProxyBypassW (DWORD)
    mov dword [rsp + 4 * 8], NULL                       ; dwFlags (DWORD)
    
    call InternetOpenA

    mov [REL hInternet], rax 
    add rsp, 32 + 1 * 8                                 ; hInternet parameter
    cmp rax, NULL
    je error_handler

    ; Stop
    jmp exit


error_handler:
    sub rsp, 32
    call GetLastError                                    ; Load more error info
    add rsp, 32 + 8
    ret


exit:                                                    ; Graceful shutdowns
    xor rax, rax
    add rsp, 8
    ret

main:
    sub     rsp, 32
    mov     ecx, -11
    call    GetStdHandle

    mov     rcx, rax
    lea rdx, [rel NtlpBuffer]
    mov     r8, [REL NtnNBytesToWrite]
    mov     r9, NULL
    mov     qword [rsp + 32], 00h
    call    WriteFile
    add     rsp, 32

ExitProgram:
    xor     eax, eax
    add rsp, 8
    ret
assembly winapi segmentation-fault nasm
1个回答
0
投票

经过几个小时的尝试和失败后,来自 Discord 的一位汇编程序员同事帮助我调试了它——有趣的是,没有任何调试器。正如 @Peter Cordes 已经指出的那样,问题确实在于我的堆栈指针处理。这是固定代码的完整版本。谢谢您的帮助!

BITS 64

%include "const.asm"
%define u(x) __utf16__(x) 
%define w(x) __utf32__(x) 

; Externs
extern InternetOpenA

extern GetLastError

extern GetStdHandle
extern WriteFile

extern ExitProcess

section .data
    curProc   db 0
    hInternet dq 0

    lpszAgent db "Mozilla/5.0", 0

    NtlpBuffer:        db    'Hello, World!', 0
    NtnNBytesToWrite:  dq    0eh


section .text
global Start
Start:
    push    rbp
    mov     rbp, rsp
    sub     rsp, 48
    
    lea     rcx, [REL lpszAgent]                            ; lpszAgentW (WIDE STRING)
    mov     rdx, 4                                          ; dwAccessType (DWORD)
    mov     r8,  NULL                                       ; lpszProxy (DWORD)
    mov     r9,  NULL                                       ; pszProxyBypassW (DWORD)
    mov     dword [rsp + 4 * 8], NULL                       ; dwFlags (DWORD)
    call    InternetOpenA
    
    mov     [REL hInternet], rax                            ; hInternet parameter
    cmp     rax, NULL
    je      error_handler

    jmp     exit


error_handler:
    call    GetLastError                                    ; Load more error info
    jmp     exit


exit:
    call    print
    xor     rcx, rcx
    call    ExitProcess
    
print:
    sub     rsp, 40
    mov     ecx, -11
    call    GetStdHandle

    mov     rcx, rax
    lea     rdx, [rel NtlpBuffer]
    mov     r8, [REL NtnNBytesToWrite]
    mov     r9, NULL
    mov     qword [rsp + 32], 00h
    call    WriteFile
    add     rsp, 40
    ret
© www.soinside.com 2019 - 2024. All rights reserved.