При обращении к полю структуры пишет 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 шт):
В примере в документации показано, что имена полей нужно объявлять с точкой в начале:
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. В этом варианте синтаксиса точки перед именами ставить не нужно, они проставятся автоматически при разворачивании макросов.