我正在尝试使用 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
经过几个小时的尝试和失败后,来自 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