Jump to content

Problema em gerar executável no Windows - PoC Aprendendo Assembly


Paulo Ferr
 Share

Recommended Posts

Olá,

Estou estudando Assembly no Windows pelo livro Aprendendo Assembly e para gerar um aqruivo objeto em NASM eu envio este comando:

nasm assembly.asm -f win64

o que gera um arquivo assembly.obj. Entretanto não consigo linkar com o main.o do arquivo C para gerar o executável final. Envio o print da mensagem de erro para tentar obter alguma ajuda.

 

print.png

Link to comment
Share on other sites

  • 4 months later...
Em 30/09/2021 em 13:48, Paulo Ferr disse:

Olá,

Estou estudando Assembly no Windows pelo livro Aprendendo Assembly e para gerar um aqruivo objeto em NASM eu envio este comando:

nasm assembly.asm -f win64

o que gera um arquivo assembly.obj. Entretanto não consigo linkar com o main.o do arquivo C para gerar o executável final. Envio o print da mensagem de erro para tentar obter alguma ajuda.

 

print.png

Conseguiu resolver o problema? também estou passando por ele..

 

Link to comment
Share on other sites

3 horas atrás, Fernando Mercês disse:

Envia o código também, pra gente dar uma olhada. 😉

 

Olá Fernando, o código que utilizei foi o do próprio tutorial:

bits 64

global assembly
assembly:
  mov eax, 777
  ret

O objeto é criado, mas não dá pra linkar com o main.o; pesquisei sober o error e, se entendi corretamente, o problema seria no arquivo assembly, a sua estrutura.

Link to comment
Share on other sites

  • Administrators

Olha, eu não tenho certeza, mas acho que o NASM requer símbolos globais começando com underscore. De qualquer forma, como você tá usando o gcc, acho que ele vai buscar a main. Então tenta aí:

bits 64

global main

main:
  mov eax, 777
  ret

Ou tenta com _main ao invés de main (altera nos dois lugares).

Boa sorte!

Link to comment
Share on other sites

3 horas atrás, Fernando Mercês disse:

Ah, você pode tentar linkar com o ld também:

ld -o assembly assembly.obj

 

Eu não estava conseguindo fazer a montagem e executar o arquivo Fonte Assembler na minha máquina, então eu fiz um simples programinha em C, que soma 2 variáveis e coloca numa terceira variável, depois apresenta na tela o resultado. 

Com o programa pronto, executei o seguinte comando: gcc -S -m32 main.c  e gerei um arquivo main.s.

Depois fiz: gcc -o main_asm -m32 main.s que gerou um main_asm.exe (executavel) e funcionou !!!

Porém ... o arquivo teste.s, ao abri-lo, notei que o formato está diferente do NASM, está no GAS, incluindo umas diretivas do CFI que não compreendo bem

 😞 

Programa teste.s:

    .file    "main.c"
    .def    ___main;    .scl    2;    .type    32;    .endef
    .section .rdata,"dr"
LC0:
    .ascii "Resultado: %d\12\0"
    .text
    .globl    _main
    .def    _main;    .scl    2;    .type    32;    .endef
_main:
LFB10:
    .cfi_startproc
    pushl    %ebp
    .cfi_def_cfa_offset 8
    .cfi_offset 5, -8
    movl    %esp, %ebp
    .cfi_def_cfa_register 5
    andl    $-16, %esp
    subl    $32, %esp
    call    ___main
    movl    $5, 28(%esp)
    movl    $3, 24(%esp)
    movl    28(%esp), %edx
    movl    24(%esp), %eax
    addl    %edx, %eax
    movl    %eax, 20(%esp)
    movl    20(%esp), %eax
    movl    %eax, 4(%esp)
    movl    $LC0, (%esp)
    call    _printf
    movl    $0, %eax
    leave
    .cfi_restore 5
    .cfi_def_cfa 4, 4
    ret
    .cfi_endproc
LFE10:
    .ident    "GCC: (MinGW.org GCC-6.3.0-1) 6.3.0"
    .def    _printf;    .scl    2;    .type    32;    .endef

 

 

Minha dúvida está em como fazer a sintaxe do NASM funcionar ao fazer o processo de montagem e, como tirar as diretivas do CFI pela sintaxe GAS.

PS1: O NASM foi instalado corretamente, consigo ver a versão pelo CMD, bem como ver as instruções do comando usando nasm -h.

PS2: Como modifiquei o programa original, não faço uso de função externa, tenho somente um arquivo e por isso não fiz processo de linkar ainda.

Link to comment
Share on other sites

  • Administrators
3 horas atrás, Thailsson Baumstark disse:

Minha dúvida está em como fazer a sintaxe do NASM funcionar

Não acho que dê. Que eu saiba, o NASM não suporta a sintaxe da AT&T usada pelo GAS. Eu insistiria no seu exemplo anterior com o ld mesmo. 😉

Abraço.

Link to comment
Share on other sites

Em 04/02/2022 em 22:02, Fernando Mercês disse:

Não acho que dê. Que eu saiba, o NASM não suporta a sintaxe da AT&T usada pelo GAS. Eu insistiria no seu exemplo anterior com o ld mesmo. 😉

Abraço.

Consegui resolver o problema, muito obrigado Fernando 🙂

Poderia me ajudar só com mais uma dúvida ?

Estou trabalhando com a sintaxe AT&T e tenho esses dados que imprime um simples "Hello word!" :

    .file    "hello.c"
    .def    ___main;    .scl    2;    .type    32;    .endef
    .section .rdata,"dr"
LC0:
    .ascii "Hello World!\0"
    .text
    .globl    _main
    .def    _main;    .scl    2;    .type    32;    .endef
_main:
    pushl    %ebp
    movl    %esp, %ebp
    andl    $-16, %esp
    subl    $16, %esp
    call    ___main
    movl    $LC0, (%esp)
    call    _printf
    movl    $0, %eax
    leave
    ret
    .ident    "GCC: (MinGW.org GCC-6.3.0-1) 6.3.0"
    .def    _printf;    .scl    2;    .type    32;    .endef

Estou estudando a movimentação na stack, mas não entendo essa chamada recursiva do próprio main.

Onde está em negrito, são referencia para o mesmo Main, neste caso _main ou __main é diferente de _main?

Link to comment
Share on other sites

Em 06/02/2022 em 11:39, Fernando Mercês disse:

É outro label sim, porque tem dois underscores. Mas não vejo onde ele está sendo definido. Talvez esteja vazio? Como fica no binário depois de assemblado?

Abraço!

Nunca gerei um binário antes, procurei na internet e achei esse código: xxd -b hello.o | less, porém removi o less e concatenei num arquivo dessa forma forma:

xxd -b hello.o > binario.txt  

logo abaixo deixei o arquivo binário, mas não consegui identificar os labels referidos anteriormente, nem se o __main esta de fato executando algo...

 

binario.txt

Link to comment
Share on other sites

  • Administrators

Opa, quando a gente fala "binário" é em referência ao arquivo executável (ou biblioteca), mas não precisa dar a saída em sistema binário de numeração não. 😉

Na verdade a melhor saída pra ver isso é com um disassembler, então você pode ou anexar o arquivo aqui (hello.o) ou postar a saída do seguinte comando:

$ objdump -d hello.o

Valeu!

Link to comment
Share on other sites

1 hora atrás, Fernando Mercês disse:

Opa, quando a gente fala "binário" é em referência ao arquivo executável (ou biblioteca), mas não precisa dar a saída em sistema binário de numeração não. 😉

Na verdade a melhor saída pra ver isso é com um disassembler, então você pode ou anexar o arquivo aqui (hello.o) ou postar a saída do seguinte comando:

$ objdump -d hello.o

Valeu!

Estava lendo sobre engenharia reversa e percebi que entendi errado XD, deixo abaixo o txt com o formato adequado. Muito mais legivel kkkk. Um está com sintaxe NASM e outro GAS, mas são o mesmo "Hello world". Obrigado por mencionar o Disassembler.

Achei o __Main, ele não é uma função vazia, porém ele armazena segmento de dado (407028) em eax e depois faz um test eax, eax. Ainda está obscuro para mim essas "movimentações" e manipulação da memória 😆

Esqueci de avisar que estou no Windows, porém estou usando o Git Bash e manipulando os arquivos como se fosse Linux, foi o jeito que achei para seguir o tutorial.

 Livro excelente sobre Assembly 😎

binario.txt binario2.txt

Link to comment
Share on other sites

  • Administrators

O fato de você estar compilando com gcc no Windows pelo Git Bash faz com que várias coisas sejam adicionadas no binário final, por conta do MinGW (Minimalist GNU for Windows). Fica mais complicado aprender assim. Eu recomendaria usar nasm e ld somente, de preferência num Linux virtual, ou via WSL2.

Outra opção é usar ferramentas nativas para Windows. Aí recomendaria o fasm.

Mas o livro é muito bom mesmo, então segui-lo como o autor propõe é a melhor recomendação, creio. 🙂

Abraço.

Link to comment
Share on other sites

 

Em 10/02/2022 em 10:37, Fernando Mercês disse:

O fato de você estar compilando com gcc no Windows pelo Git Bash faz com que várias coisas sejam adicionadas no binário final, por conta do MinGW (Minimalist GNU for Windows). Fica mais complicado aprender assim. Eu recomendaria usar nasm e ld somente, de preferência num Linux virtual, ou via WSL2.

Outra opção é usar ferramentas nativas para Windows. Aí recomendaria o fasm.

Mas o livro é muito bom mesmo, então segui-lo como o autor propõe é a melhor recomendação, creio. 🙂

Abraço.

Agradeço muito pelo apoio e as dicas, certamente me ajudaram muito. Irei montar uma maquina virtual e analisar os resultados posteriormente 😄

  • Curtir 1
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...