あなたの問題は、connect syscall へのパラメーターをリトル エンディアンとしてエンコードしている一方で、それらの一部はビッグ エンディアンである必要があることです。さらに、sin_family と sin_port メンバーの両方が 32 ビットとしてエンコードされ、16 ビットである必要があり、その構造体にはパディングが必要なようです。 16バイトまで。
PSアセンブラを使用したい場合があります。いつでもobjdump -x -D $binary
オペコードを取得できます。gcc -c -x assembler-with-cpp -o hello-net.o hello-net.S && ld -o hello-net hello-net.o
さらに、プリプロセッサも使用できるようにコンパイルします。
PS2 : でコードを実行してみることをお勧めしstrace
ます。これは、作成している実際のシステムコールを示しています。
たとえば、このテストプログラムは私(x86_64)で機能します:
#include <asm/unistd.h>
#define AF_INET 2
#define SOCK_STREAM 1
hellostr:
.ascii "Hello world!\n" # 'Hello world!' plus a linefeed character
.equ helloLen, . - hellostr # Length of the 'Hello world!' string
.align 8
home_addr:
# AF_INET (native-endian)
.short AF_INET
# big-endian port 4444
.byte 0x11, 0x5c
# big-endian 127.0.0.1
.byte 0x7f, 0x00, 0x00, 0x01
# required padding to 16 bytes
.space 16 - (. - home_addr)
.equ home_len, . - home_addr
.globl _start
_start:
# syscall(SYS_socket, AF_INET, SOCK_STREAM, 0)
mov $__NR_socket, %rax
mov $AF_INET, %rdi
mov $SOCK_STREAM, %rsi
mov $0, %rdx
syscall
# syscall(SYS_connect, socket, [127.0.0.1:4444], sizeof(addr))
mov %rax, %rdi
mov $__NR_connect, %rax
mov $home_addr, %rsi
mov $home_len, %rdx
syscall
# syscall(SYS_write, socket, hellostr, strlen(hellostr))
mov $__NR_write, %rax
mov $hellostr, %rsi # Put the offset of hello in ecx
mov $helloLen, %rdx # helloLen is a constant, so we don't need to say
# mov edx,[helloLen] to get it's actual value
syscall # Call the kernel (syscall num in %rax)
mov $__NR_exit, %rax
xor %rdi, %rdi # Exit with return code of 0 (no error)
syscall
同じことですが、x86 (32 ビット) で動作するように変更されています。
#include <asm/unistd.h>
#define AF_INET 2
#define SOCK_STREAM 1
#define SYS_SOCKET 1 /* sys_socket(2) */
#define SYS_CONNECT 3 /* sys_connect(2) */
hellostr:
.ascii "Hello world!\n" # 'Hello world!' plus a linefeed character
.equ helloLen, . - hellostr # Length of the 'Hello world!' string
.align 8
home_addr:
# AF_INET (native-endian)
.short AF_INET
# big-endian port 4444
.byte 0x11, 0x5c
# big-endian 127.0.0.1
.byte 0x7f, 0x00, 0x00, 0x01
# required padding to 16 bytes
.space 16 - (. - home_addr)
.equ home_len, . - home_addr
.align 8
sys_socket_args:
.int AF_INET
.int SOCK_STREAM
.int 0
.globl _start
_start:
# syscall(SYS_socketcall, SYS_SOCKET, {AF_INET, SOCK_STREAM, 0})
mov $__NR_socketcall, %eax
mov $SYS_SOCKET, %ebx
mov $sys_socket_args, %ecx
int $0x80
# syscall(SYS_socketcall, SYS_CONNECT, {socket, [127.0.0.1:4444], sizeof(addr)})
# Allocate 12 bytes of stack space (required for arguments to connect(2))
sub $12, %esp
mov %eax, (%esp) # sys_connect_args.fd = return-value
movl $home_addr, 4(%esp) # sys_connect_args.addr = &home_addr
movl $home_len, 8(%esp) # sys_connect_args.addrlen = sizeof(home_addr)
mov $__NR_socketcall, %eax
mov $SYS_CONNECT, %ebx
mov %esp, %ecx
int $0x80
# syscall(SYS_write, socket, hellostr, strlen(hellostr))
mov $__NR_write, %eax
mov (%esp), %ebx # socket-param = sys_connect_args.fd
mov $hellostr, %ecx # Put the offset of hello in ecx
mov $helloLen, %edx # helloLen is a constant, so we don't need to say
# mov edx,[helloLen] to get it's actual value
int $0x80 # Call the kernel (syscall num in %eax)
# restore stack
add $12, %esp
mov $__NR_exit, %eax
xor %ebx, %ebx # Exit with return code of 0 (no error)
int $0x80
編集:最初の段落を拡張して、他の2つの考えられるエラーに言及し、私にとって機能する32ビット(x86)のサンプルを追加しました。