неправильные данные в памяти

нашел ошибку в коде и очень странно что она есть. я указал на нее с помощью < --. дело в том, что я указал переменной sizeof_s 4 байта размер и число 16, что равно структуре sockaddr_in. но если в коде написать в той строке так mov edx, [sizeof_s] то запишется почему то перевернутый адрес порта, но почему? вот код.

;DEFAULT REL
global main
extern printf
extern inet_aton
extern perror
extern connect

section .text

shellcode:
    mov rax, 59
    mov rdi, [path]
    mov rsi, 0
    mov rdx, 0
    syscall

exploit:
    mov rax, 1
    mov rdi, [sock]
    lea rsi, [shellcode]
    mov rdx, [size_of_shellcode]
    syscall
    ret
main:
;------ получаем сокет -------
    xor rsi, rsi
    xor rdi, rdi
    xor rdx, rdx
    mov rdx, 0
    mov si, [SOCK_STREAM]
    mov di, [PF_INET]
    mov rax, 41
    syscall
    mov [sock], eax
    cmp rax, 0
    jg continue_socket
    xor rax, rax
    lea rdi, [cant_socket]
    syscall
    jmp exit
;---- заполнить структуру ----
continue_socket:
    xor rax, rax
    mov ax, [PF_INET]
    mov [s + sockaddr_in.family], ax
    mov ax, [server_port]
    xchg al, ah
    mov [s + sockaddr_in.port], ax
    xor rax, rax
    lea rdi, [host]
    xor rsi, rsi
    lea esi, [s + sockaddr_in.s_addr]
    call inet_aton
    cmp rax, 0
    jg continue_fill
    lea rdi, [cant_fill]
    call perror
    jmp exit
;------- подключение --------
continue_fill:
    xor rax, rax
    mov [s + sockaddr_in.data], rax
    xor rsi, rsi
    xor rdi, rdi
    xor rdx, rdx
    mov edx, 16        ; < ---------- вот здесь я присваивал [sizeof_s]
    lea rsi, [s]
    mov edi, [sock]
    xor rax, rax
    call connect
    cmp rax, 0
    je continue_connect
    lea rdi, [cant_connect]
    call perror
    jmp exit
continue_connect:
;---- написать сообщение ----
    xor rax, rax
    mov rdi, 1
    call exploit
;---- выход из программы ----
exit:
    mov rax, 60
    syscall
    ret


section .data
struc sockaddr_in
    .family  resw  1
    .port    resw  1
    .s_addr  resd  1
    .data    resb  8
endstruc
cant_socket   db    'Не удалось получить сокет', 0xa, 0x0
cant_fill     db    'Не удалось преобразовать ip', 0x0
cant_connect  db    'Невозможно подключиться', 0x0

host          db    '127.0.0.1', 0x0
path          dq    '/bin/sh'
size          dd    $ - path
sock          dd    0
s             istruc sockaddr_in 
sizeof_s      dd    16
server_port   dw    8020

PF_INET       dw    2
SOCK_STREAM   dw    1

size_of_shellcode dd exploit - shellcode

вот для компиляции.

all:
        nasm -f elf64 bf.asm -o bf.o
        gcc -no-pie bf.o -o test
#       ld -b elf64-x86-64 bf.o inet.o -lc -o test


Ответы (1 шт):

Автор решения: insolor

Скомпилировал код из вопроса и посмотрел под дизассемблером, оказалось, что метки s и sizeof_s совпадают в памяти. Нормально структура создается, если использовать такой код:

s istruc sockaddr_in
    at sockaddr_in.family, dw 0
    at sockaddr_in.port,   dw 0
    at sockaddr_in.s_addr, dd 0
    at sockaddr_in.data,   db 0
iend
sizeof_s      dd    16

Документация: ISTRUC, AT иIEND: Объявление экземпляров структур

Я предполагаю, что nasm считает, что все что идет ниже s istruc sockaddr_in - это часть этой структуры. Почему при этом не ругается на отсутствующий iend - не понятно. Но может так разработчиками задумано. Но в любом случае это объясняет, почему из sizeof_s читается порт - в первое поле структуры перед этим его и записали, а первое поле структуры у вас пересекается с s_size.

→ Ссылка