AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / user-11588863

pikafan_8080's questions

Martin Hope
pikafan_8080
Asked: 2023-10-06 20:16:12 +0800 CST

Como usar o GNU Assembler (GAS) para criar um arquivo ELF escrito à mão a partir do arquivo .s correspondente

  • 7

Introdução

Estou tentando aprender sobre ELFArquivos e também experimentar um pouco com eles. Atualmente, estou seguindo o tutorial aqui , que trata de criar um pequeno ELFarquivo de 32 bits que sai apenas com o código 42. Este tutorial usa NASMe ldpara criar os ELFarquivos. No entanto, eu gostaria de usar o GNU Assembler (GAS)para criar um arquivo de 64 bits ELF(e não de 32 bits), pois estou familiarizado com ele (mas não sou um especialista em usá-lo!)

No momento, estou preso na parte do tutorial em que eles começam a criar ELFarquivos do zero - o que envolve escrever ELFo cabeçalho e os cabeçalhos do programa. Como os arquivos de 32 e 64 bits ELFdiferem ligeiramente (por exemplo, em termos de tamanho do cabeçalho ELF), minha versão do .sarquivo está abaixo:

.intel_syntax noprefix
ehdr:
        .byte 0x7F
        .byte 0x45 # E
        .byte 0x4c # L
        .byte 0x46 # F
        .byte 0x02 # 64 bit ; CLASS
        .byte 0x01 # lsb ; DATA
        .byte 0x01 # ; VERSION
        .byte 0x00 # None/Sytem V ; OS ABI
        .8byte 0x0 # ABI VERSION + PADDING

        .2byte 0x02 # ET_EXEC ; E_TYPE
        .2byte 0x3E # AMD64 ; E_MACHINE
        .4byte 0x01 # 1 ; E_VERSION
        .8byte _start # ; E_ENTRY
        .8byte phdr - ehdr # offset into program header ; E_PHOFF
        .8byte 0x00 # offset into section header ; E_SHOFF
        .4byte 0x00 # flag ; E_FLAGS
        .2byte ehdrsize # ELF header size ; E_EHSIZE
        .2byte phdrsize # Program header size ; E_PHSIZE
        .2byte 0x01 # Number of program headers ; E_PHNUM
        .2byte 0x00 # Section header size ; E_SHENTSIZE
        .2byte 0x00 # Number of section headers ; E_SHNUM
        .2byte 0x00 # Section header string table index ; E_SHSTRNDX

DECLARE_ELF_HEADER_SIZE:
.set ehdrsize,  DECLARE_ELF_HEADER_SIZE - ehdr

phdr:
        .4byte 0x01 # PT_LOAD ; P_TYPE
        .4byte 0x00 # located at offset 0??? ; P_OFFSET
        .8byte ehdr # ; P_VADDR
        .8byte ehdr # ; P_PADDR
        .8byte filesize # ; P_FILESIZE
        .8byte filesize # ; P_MEMSZ
        .8byte 5 # R-X ; P_FLAGS
        .8byte 0x1000 # P_ALIGN

DECLARE_PHEADER_SIZE:
.set phdrsize, DECLARE_PHEADER_SIZE - phdr

_start:
        mov eax, 60
        mov edi, 42
        syscall

DECLARE_FILE_SIZE:
.set filesize, DECLARE_FILE_SIZE - ehdr

Mais informações sobre cabeçalhos de arquivos ELF podem ser encontradas observando o código-fonte correspondente aqui . Como ainda estou aprendendo sobre ELFarquivos, o código acima pode estar incorreto (avise-me caso encontre alguma falha!)

Problema

Supondo que o código acima esteja correto, gostaria de converter o .sarquivo acima em um ELFarquivo. Para isso, o tutorial utiliza o comando:

$ nasm -f bin -o a.out tiny.asm

No entanto, não consigo descobrir qual comando correspondente devo usar com o GAS para criar o ELFarquivo correspondente, e esse é o problema que estou enfrentando.

O que eu tentei...

Eu tentei várias abordagens. Vou listá-los abaixo:

  1. Há uma pergunta semelhante no SO, que pode ser encontrada aqui . Esta abordagem usa os 2 comandos a seguir para obter o arquivo ELF correspondente:
$ as --64 -o test.o test.s 
$ ld -Ttext 200000 --oformat binary -o test.bin test.o

Executando os mesmos comandos para o .sarquivo que escrevi, recebo um arquivo ELF, junto com o seguinte aviso :

ld: warning: cannot find entry symbol _start; defaulting to 0000000000200000

A execução do arquivo ELF gerado obtém uma falha de segmentação e sai com o código 139. O ELFcabeçalho do arquivo gerado está abaixo (obtido executando readelf -h <output ELF file>):

ELF Header:
  Magic:   7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00
  Class:                             ELF64
  Data:                              2's complement, little endian
  Version:                           1 (current)
  OS/ABI:                            UNIX - System V
  ABI Version:                       0
  Type:                              EXEC (Executable file)
  Machine:                           Advanced Micro Devices X86-64
  Version:                           0x1
  Entry point address:               0x200078
  Start of program headers:          64 (bytes into file)
  Start of section headers:          0 (bytes into file)
  Flags:                             0x0
  Size of this header:               64 (bytes)
  Size of program headers:           56 (bytes)
  Number of program headers:         1
  Size of section headers:           0 (bytes)
  Number of section headers:         0
  Section header string table index: 0
readelf: Error: the segment's file size is larger than its memory size

Acredito que a falha de segmentação está acontecendo porque Entry Point addressprovavelmente está incorreta (isso também foi sugerido ldna mensagem de erro).

  1. Nesta abordagem, modifiquei os comandos:
$ as --64 -o test.o test.s 
$ ld -Ttext 200000 --oformat binary -o test.bin test.o

para

$ as --64 -o test.o test.s (same as before) 
$ ld -nmagic -s test.o (changed)

Isso também cria um arquivo ELF, mas novamente com o seguinte aviso :

ld: warning: cannot find entry symbol _start; defaulting to 0000000000400078

E isso novamente sugere que teremos uma falha de segmentação, o que é de fato o caso do novo ELFarquivo. O cabeçalho ELF para este arquivo é:

ELF Header:
  Magic:   7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00
  Class:                             ELF64
  Data:                              2's complement, little endian
  Version:                           1 (current)
  OS/ABI:                            UNIX - System V
  ABI Version:                       0
  Type:                              EXEC (Executable file)
  Machine:                           Advanced Micro Devices X86-64
  Version:                           0x1
  Entry point address:               0x400078
  Start of program headers:          64 (bytes into file)
  Start of section headers:          0 (bytes into file)
  Flags:                             0x0
  Size of this header:               64 (bytes)
  Size of program headers:           56 (bytes)
  Number of program headers:         1
  Size of section headers:           64 (bytes)
  Number of section headers:         0
  Section header string table index: 0

Sem sorte!

  1. A partir dos avisos dados por ld, parece que podemos querer adicionar .global _startnosso .sarquivo. Abaixo está o novo .sarquivo que também contém esta linha:
.intel_syntax noprefix
.global _start   # Added here
ehdr:
        .byte 0x7F
        .byte 0x45 # E
        .byte 0x4c # L
        .byte 0x46 # F
        .byte 0x02 # 64 bit ; CLASS
        .byte 0x01 # lsb ; DATA
        .byte 0x01 # ; VERSION
        .byte 0x00 # None/Sytem V ; OS ABI
        .8byte 0x0 # ABI VERSION + PADDING

        .2byte 0x02 # ET_EXEC ; E_TYPE
        .2byte 0x3E # AMD64 ; E_MACHINE
        .4byte 0x01 # 1 ; E_VERSION
        .8byte _start # ; E_ENTRY
        .8byte phdr - ehdr # offset into program header ; E_PHOFF
        .8byte 0x00 # offset into section header ; E_SHOFF
        .4byte 0x00 # flag ; E_FLAGS
        .2byte ehdrsize # ELF header size ; E_EHSIZE
        .2byte phdrsize # Program header size ; E_PHSIZE
        .2byte 0x01 # Number of program headers ; E_PHNUM
        .2byte 0x00 # Section header size ; E_SHENTSIZE
        .2byte 0x00 # Number of section headers ; E_SHNUM
        .2byte 0x00 # Section header string table index ; E_SHSTRNDX

DECLARE_ELF_HEADER_SIZE:
.set ehdrsize,  DECLARE_ELF_HEADER_SIZE - ehdr

phdr:
        .4byte 0x01 # PT_LOAD ; P_TYPE
        .4byte 0x00 # located at offset 0??? ; P_OFFSET
        .8byte ehdr # ; P_VADDR
        .8byte ehdr # ; P_PADDR
        .8byte filesize # ; P_FILESIZE
        .8byte filesize # ; P_MEMSZ
        .8byte 5 # R-X ; P_FLAGS
        .8byte 0x1000 # P_ALIGN

DECLARE_PHEADER_SIZE:
.set phdrsize, DECLARE_PHEADER_SIZE - phdr

_start:
        mov eax, 60
        mov edi, 42
        syscall

DECLARE_FILE_SIZE:
.set filesize, DECLARE_FILE_SIZE - ehdr

Novamente, criamos o arquivo ELF para o código acima usando:

$ as --64 -o test.o test.s 
$ ld -nmagic -s test.o 

Desta vez, não recebemos nenhum erro e o arquivo ELF faz o que deveria fazer (ou seja, sai com o código 42). O cabeçalho ELF para este arquivo é:

ELF Header:
  Magic:   7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00
  Class:                             ELF64
  Data:                              2's complement, little endian
  Version:                           1 (current)
  OS/ABI:                            UNIX - System V
  ABI Version:                       0
  Type:                              EXEC (Executable file)
  Machine:                           Advanced Micro Devices X86-64
  Version:                           0x1
  Entry point address:               0x4000f0
  Start of program headers:          64 (bytes into file)
  Start of section headers:          0 (bytes into file)
  Flags:                             0x0
  Size of this header:               64 (bytes)
  Size of program headers:           56 (bytes)
  Number of program headers:         1
  Size of section headers:           64 (bytes)
  Number of section headers:         0
  Section header string table index: 0

Problema resolvido, né?

Infelizmente, acho que não. Aprofundando-se um pouco mais no binário, revela-se que ele não usa o cabeçalho manuscrito ELFque havíamos escrito no .sarquivo:

gef➤  search-pattern 'ELF'
[+] Searching 'ELF' in memory
[+] In '/home/VM/Desktop/Experiments/ELF/a.out'(0x400000-0x401000), permission=r-x
  0x400001 - 0x400004  →   "ELF[...]"
  0x400079 - 0x40007c  →   "ELF[...]"

Ops, parece que ld(ou as, não tenho certeza!) criou seu próprio ELFcabeçalho (como é evidente pelo fato de que existem 2 locais contendo a string ELF. Pelo que entendi, a ELFstring at 0x400001é aquela que foi contribuída por ld( ou as), e aquele em 0x400079era o que eu incluí no .sarquivo.

No entanto, isso vai contra o propósito de escrever um arquivo ELF do zero, incluindo o ELFcabeçalho e os cabeçalhos do programa! Também tenho certeza de que esse problema está presente nas abordagens 1 e 2 que listei antes, mas como elas saíram com uma falha de segmentação, não destaquei esse problema nessas abordagens.

Agora, estou sem ideias sobre o que fazer, então agradeceria muito qualquer ajuda para construir o ELFarquivo corretamente!

Muito obrigado!

assembly
  • 1 respostas
  • 30 Views

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    Reformatar números, inserindo separadores em posições fixas

    • 6 respostas
  • Marko Smith

    Por que os conceitos do C++20 causam erros de restrição cíclica, enquanto o SFINAE antigo não?

    • 2 respostas
  • Marko Smith

    Problema com extensão desinstalada automaticamente do VScode (tema Material)

    • 2 respostas
  • Marko Smith

    Vue 3: Erro na criação "Identificador esperado, mas encontrado 'import'" [duplicado]

    • 1 respostas
  • Marko Smith

    Qual é o propósito de `enum class` com um tipo subjacente especificado, mas sem enumeradores?

    • 1 respostas
  • Marko Smith

    Como faço para corrigir um erro MODULE_NOT_FOUND para um módulo que não importei manualmente?

    • 6 respostas
  • Marko Smith

    `(expression, lvalue) = rvalue` é uma atribuição válida em C ou C++? Por que alguns compiladores aceitam/rejeitam isso?

    • 3 respostas
  • Marko Smith

    Um programa vazio que não faz nada em C++ precisa de um heap de 204 KB, mas não em C

    • 1 respostas
  • Marko Smith

    PowerBI atualmente quebrado com BigQuery: problema de driver Simba com atualização do Windows

    • 2 respostas
  • Marko Smith

    AdMob: MobileAds.initialize() - "java.lang.Integer não pode ser convertido em java.lang.String" para alguns dispositivos

    • 1 respostas
  • Martin Hope
    Fantastic Mr Fox Somente o tipo copiável não é aceito na implementação std::vector do MSVC 2025-04-23 06:40:49 +0800 CST
  • Martin Hope
    Howard Hinnant Encontre o próximo dia da semana usando o cronógrafo 2025-04-21 08:30:25 +0800 CST
  • Martin Hope
    Fedor O inicializador de membro do construtor pode incluir a inicialização de outro membro? 2025-04-15 01:01:44 +0800 CST
  • Martin Hope
    Petr Filipský Por que os conceitos do C++20 causam erros de restrição cíclica, enquanto o SFINAE antigo não? 2025-03-23 21:39:40 +0800 CST
  • Martin Hope
    Catskul O C++20 mudou para permitir a conversão de `type(&)[N]` de matriz de limites conhecidos para `type(&)[]` de matriz de limites desconhecidos? 2025-03-04 06:57:53 +0800 CST
  • Martin Hope
    Stefan Pochmann Como/por que {2,3,10} e {x,3,10} com x=2 são ordenados de forma diferente? 2025-01-13 23:24:07 +0800 CST
  • Martin Hope
    Chad Feller O ponto e vírgula agora é opcional em condicionais bash com [[ .. ]] na versão 5.2? 2024-10-21 05:50:33 +0800 CST
  • Martin Hope
    Wrench Por que um traço duplo (--) faz com que esta cláusula MariaDB seja avaliada como verdadeira? 2024-05-05 13:37:20 +0800 CST
  • Martin Hope
    Waket Zheng Por que `dict(id=1, **{'id': 2})` às vezes gera `KeyError: 'id'` em vez de um TypeError? 2024-05-04 14:19:19 +0800 CST
  • Martin Hope
    user924 AdMob: MobileAds.initialize() - "java.lang.Integer não pode ser convertido em java.lang.String" para alguns dispositivos 2024-03-20 03:12:31 +0800 CST

Hot tag

python javascript c++ c# java typescript sql reactjs html

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve