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

FASM编写的ELF64 Socket程序Nmap无法检测指定IP问题求助

ELF64 Socket程序绑定失败问题排查与修复

我用FASM编写了ELF64架构的Socket程序,绑定IP为192.168.0.17,但Nmap无法检测到该端口。尝试过小端序处理仍无效,怀疑问题出在地址或端口配置上。代码参考Chromium OS编写,使用syscall而非32位int 0x80指令,原始代码如下:

format ELF64
section '.data'
    IPPROTO_TCP equ 0x06
    SOCK_STREAM equ 0x01
    AF_INET equ 0x02
    message db 'welcome',0xA,0
    message_lenght = $-message
    struc sockaddr sin_family,sin_port,sin_addr
    {
        .sin_family dw sin_family
        .sin_port dw sin_port; 1461
        .sin_addr dd sin_addr; 192.168.0.17
    }
    sockaddr_in sockaddr 0x02,0x05B5,0x1100A8C0
    sizeSockaddr = 0x02+0x05B5+0x1100A8C0
section '.text' executable
_start:
    ;socket
    mov rax,0x29 ;socket 
    mov rdi, AF_INET
    mov rsi, SOCK_STREAM
    mov rdx, IPPROTO_TCP
    syscall
    mov rbx,rax

    ;binding
    mov rax,0x31 ;bind
    mov rdi,rbx
    lea rsi,[sockaddr_in]
    mov rdx,sizeSockaddr
    syscall

    ;listening
    mov rax,0x32 ; listen
    mov rdi,rbx ;descriptor
    mov rsi,1
    syscall

    ;accept
    mov rax,43 ;accept
    mov rdi,rbx ;descriptor
    syscall
    ;welcome
    mov rax,1
    mov rdi,1;sys_write
    mov rsi,message 
    mov rdx,message_lenght
    syscall

    ;close socket
    mov rax,3 ;close
    mov rbx,rdi
    syscall

    ;exit program
    mov rax,60
    mov rdi,0
    syscall

问题分析

  • sizeSockaddr计算完全错误:当前代码将结构体成员的数值相加得到地址长度,这不符合结构体大小的计算逻辑。sockaddr_in的标准大小是16字节,正确计算方式应为sizeSockaddr = $ - sockaddr_in,用结构体结束位置减起始位置得到实际字节数,错误的长度会直接导致bind调用失败。
  • IP地址字节序错误:192.168.0.17的网络字节序(大端)十六进制值为0xC0A80011,代码中写的0x1100A8C0是小端存储的内存布局,直接赋值会导致实际绑定IP变为17.0.168.192,而非预期地址。
  • 端口字节序错误:要绑定的1461端口,网络字节序需将主机小端序转换为大端序,正确值应为0xB505,代码中使用的0x05B5会导致实际绑定端口变为46341,而非目标端口。
  • 缺少错误检查:未对socket、bind、listen等系统调用的返回值做校验,无法快速定位调用失败环节。
  • accept参数未初始化:原始代码中accept的rsi和rdx参数未赋值,可能引发未定义行为。

修正后的代码

format ELF64
section '.data'
    IPPROTO_TCP equ 0x06
    SOCK_STREAM equ 0x01
    AF_INET equ 0x02
    message db 'welcome',0xA,0
    message_length = $-message
    ; 定义标准sockaddr_in结构体,补充填充字段保证大小为16字节
    struc sockaddr_in
        .sin_family dw ?
        .sin_port dw ?
        .sin_addr dd ?
        .pad rb 8
    endstruc
    ; 初始化:AF_INET协议、1461端口(网络字节序0xB505)、192.168.0.17(网络字节序0xC0A80011)
    sockaddr_in_inst sockaddr_in AF_INET, 0xB505, 0xC0A80011
    sizeSockaddr = $ - sockaddr_in_inst ; 正确计算结构体大小

section '.text' executable
_start:
    ; 创建socket
    mov rax, 0x29
    mov rdi, AF_INET
    mov rsi, SOCK_STREAM
    mov rdx, IPPROTO_TCP
    syscall
    test rax, rax
    js exit_on_error
    mov rbx, rax

    ; 绑定地址
    mov rax, 0x31
    mov rdi, rbx
    lea rsi, [sockaddr_in_inst]
    mov rdx, sizeSockaddr
    syscall
    test rax, rax
    js exit_on_error

    ; 监听连接
    mov rax, 0x32
    mov rdi, rbx
    mov rsi, 1
    syscall
    test rax, rax
    js exit_on_error

    ; 接受连接,忽略客户端地址
    mov rax, 0x2B
    mov rdi, rbx
    xor rsi, rsi
    xor rdx, rdx
    syscall
    test rax, rax
    js exit_on_error
    mov rcx, rax

    ; 向客户端发送欢迎消息
    mov rax, 1
    mov rdi, rcx
    mov rsi, message
    mov rdx, message_length
    syscall

    ; 关闭客户端socket
    mov rax, 3
    mov rdi, rcx
    syscall

    ; 关闭监听socket
    mov rax, 3
    mov rdi, rbx
    syscall

    ; 正常退出
    mov rax, 60
    mov rdi, 0
    syscall

exit_on_error:
    ; 错误退出,返回码1
    mov rax, 60
    mov rdi, 1
    syscall

关键修正说明

  • 结构体添加pad字段,确保sockaddr_in大小符合Linux系统要求的16字节。
  • 端口和IP均使用正确的网络字节序值,保证绑定的是预期的192.168.0.17:1461。
  • 新增错误检查逻辑,系统调用失败时立即退出并返回错误码,便于排查问题。
  • 补全accept的参数初始化,避免未定义行为。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 08:33:11