При обращении к полю структуры пишет undefined symbol

пробую написать мелкую программку, но не пойму как со структурами работать. в документации нашел только как вот так объявлять структуру. но когда я для windows писал, там по другому структура определялась. но здесь определяется вроде тоже нормально, но я не пойму как получить доступ к её полям. вот код.

format ELF64 executable 3

entry start

struc sockaddr_in
{
        port    dw  0
        in_addr dd  0
}

segment readable executable
shellcode:

start:
;------ получаем сокет -------
        mov rdx, 0
        mov rsi, [SOCK_STREAM]
        mov rdi, [PF_INET]
        mov rax, 41
        syscall
        mov [sock], rax
;---- заполнить структуру ----
        mov ax, [server_port]
        xchg al, ah
        mov [s.port], ax
        ret

segment readable writable

path          dq    '/bin/sh'
size          dd    $ - path
sock          dq    0
s             sockaddr_in
server_port   dw    8020

PF_INET       dq    2
SOCK_STREAM   dq    1

sd dd start - shellcode

ошибка здесь mov [s.port], ax


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

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

В примере в документации показано, что имена полей нужно объявлять с точкой в начале:

Here is the sample of structure macroinstruction:

struc point x,y
 {
    .x dw x
    .y dw y
 }

Это нужно для того, чтобы метки полей структуры были локальными ("дочерними") по отношению к основной метке (в вашем случае - метка s), а не новыми глобальными метками (фактически в вашем коде нет метки s.port, но есть глобальная метка port). Подробнее о локальных метках - см. предпоследний абзац в разделе Constants and labels.

Соответственно, ваша структура должна выглядеть так:

struc sockaddr_in
{
        .port    dw  0
        .in_addr dd  0
}

После этого изменения ваш код успешно компилируется.


Как это работает:

Структура - это по сути макрос: в месте использования структуры вставляется тело самой структуры. Т.е., когда вы пишете:

struc sockaddr_in
{
        port    dw  0
        in_addr dd  0
}

; ...

s             sockaddr_in

Это превращается в такой код:

s:
port    dw  0
in_addr dd  0

Т.е. тут получается просто три глобальных метки. Поля такой структуры будут доступны просто по именам port и in_addr. Но если вы попытаетесь создать несколько структур, то будет конфликт имен (error: symbol already defined), из-за того что будет попытка создать несколько глобальных меток с одинаковым названием.

Если же добавить точки в начало имен полей, то после подстановки будет получаться такой код:

s:
.port    dw  0
.in_addr dd  0

И поля структуры будут доступны по именам s.port и s.in_addr.


Есть, конечно, другой синтаксис структур, реализованный через макросы (см. Windows programming headers - Structures):

  struct POINT
    x dd ?
    y dd ?
  ends

но для его работы нужно подключать файл INCLUDE/MACRO/STRUCT.INC из пакета flat assembler для Windows. В этом варианте синтаксиса точки перед именами ставить не нужно, они проставятся автоматически при разворачивании макросов.

→ Ссылка