使用 C 创建可重定位的 elf 二进制文件,无需 libelf 或任何其他库
所以我尝试用 c 创建一个可重定位的 elf 二进制文件。我不想使用库或类似的东西。我已经编写了一些代码。这是我一直在阅读的资源:https://refspecs.linuxfoundation。 org/elf/gabi4+/ch4.eheader.html 。我的精灵标题看起来是正确的。当涉及到节和节标题时,我只是遇到错误。 这是我的主要代码
#include <stdio.h>
#include <stdlib.h>
#include "elf.h"
const unsigned char strtab[] = {
'\0',
'.', 's', 'h', 's', 't', 'r', 't', 'a', 'b', '\0',
'.', 's', 't', 'r', 't', 'a', 'b', '\0',
'.', 'd', 'a', 't', 'a', '\0',
'.', 't', 'e', 'x', 't', '\0',
};
int strtab_size = sizeof(strtab);
int strtab_index = 1;
int section_n = 2;
Elf32_Shdr * create_shdr(){
Elf32_Shdr * header = calloc(sizeof(Elf32_Shdr), 1);
if (header == NULL){
return NULL;
}
return header;
}
Elf32_Ehdr * create_ehdr(){
Elf32_Ehdr * header = calloc(sizeof(Elf32_Ehdr), 1);
if (header == NULL){
return NULL;
}
header->e_ident[EI_MAG0] = 0x7f;
header->e_ident[EI_MAG1] = 'E';
header->e_ident[EI_MAG2] = 'L';
header->e_ident[EI_MAG3] = 'F';
// set the object to 32 bit
header->e_ident[EI_CLASS] = ELFCLASS32;
header->e_ident[EI_DATA] = ELFDATA2LSB;
// set the file version
header->e_ident[EI_VERSION] = EV_CURRENT;
// set sysv abi
header->e_ident[EI_OSABI] = ELFOSABI_SYSV;
header->e_ident[EI_ABIVERSION] = ELFOSABI_NONE;
header->e_ident[EI_PAD] = 0; // needs to be changed
header->e_shentsize = sizeof(Elf32_Shdr);
// we default to relocatable
header->e_type = ET_REL;
header->e_machine = EM_X86;
header->e_version = EV_CURRENT;
header->e_ehsize = sizeof(Elf32_Ehdr);
header->e_phentsize = sizeof(Elf32_Phdr);
header->e_phnum = 0;
return header;
}
int main()
{
FILE * fout;
Elf32_Ehdr *elf_header;
Elf32_Shdr *NULL_Section; // this should all be null
Elf32_Shdr *strtab_Section;
printf("%d\n", strtab_size);
fout = fopen("output.elf", "wb");
if (fout == NULL){
printf("Failed to open output.elf\n");
return 1;
}
if ((elf_header = create_ehdr()) == NULL){
printf("Failed to create new header\n");
return 1;
}
if ((NULL_Section = create_shdr()) == NULL){
printf("Failed to create new section header\n");
return 1;
}
if ((strtab_Section = create_shdr()) == NULL){
printf("Failed to create new section header\n");
return 1;
}
elf_header->e_shstrndx = strtab_index; // Point to the shstrtab section
elf_header->e_shnum = section_n;
elf_header->e_shoff = sizeof(Elf32_Ehdr)-1;
strtab_Section->sh_type = SHT_STRTAB;
strtab_Section->sh_offset = ((sizeof(Elf32_Shdr))*1)+sizeof(Elf32_Ehdr);
strtab_Section->sh_addr = 80;
//strtab_Section->sh_addralign = 1;
strtab_Section->sh_size = strtab_size;
fwrite(elf_header, sizeof(Elf32_Ehdr), 1, fout);
fwrite(NULL_Section, sizeof(Elf32_Shdr), 1, fout);
fwrite(strtab_Section, sizeof(Elf32_Shdr), 1, fout);
fwrite(strtab, strtab_size, 1, fout);
return 0;
}
我的 elf.h 文件是
#pragma once
enum EI{
EI_MAG0 = 0,
EI_MAG1,
EI_MAG2,
EI_MAG3,
EI_CLASS,
EI_DATA,
EI_VERSION,
EI_OSABI,
EI_ABIVERSION,
EI_PAD,
};
#define ELFOSABI_NONE 0 //No extensions or unspecified
#define ELFOSABI_HPUX 1 //Hewlett-Packard HP-UX
#define ELFOSABI_NETBSD 2 //NetBSD
#define ELFOSABI_LINUX 3 //Linux
#define ELFOSABI_SOLARIS 6 //Sun Solaris
#define ELFOSABI_AIX 7 //AIX
#define ELFOSABI_IRIX 8 //IRIX
#define ELFOSABI_FREEBSD 9 //FreeBSD
#define ELFOSABI_TRU64 10 //Compaq TRU64 UNIX
#define ELFOSABI_MODESTO 11 //Novell Modesto
#define ELFOSABI_OPENBSD 12 //Open BSD
#define ELFOSABI_OPENVMS 13 //Open VMS
#define ELFOSABI_NSK 14 //Hewlett-Packard Non-Stop Kernel
#define SHF_WRITE 0x1
#define SHF_ALLOC 0x2
#define SHF_EXECINSTR 0x4
#define SHF_MERGE 0x10
#define SHF_STRINGS 0x20
#define SHF_INFO_LINK 0x40
#define SHF_LINK_ORDER 0x80
#define SHF_OS_NONCONFORMING 0x100
#define SHF_GROUP 0x200
#define SHF_TLS 0x400
#define SHF_MASKOS 0x0ff00000
#define SHF_MASKPROC 0xf0000000
#define ELFCLASSNONE 0
#define ELFCLASS32 1
#define ELFCLASS64 2
#define ELFDATANONE 0
#define ELFDATA2LSB 1
#define ELFDATA2MSB 2
#define ELFOSABI_SYSV 0
#define ELFOSABI_HPUX 1
#define ELFOSABI_STANDALONE 255
#define ET_NONE 0
#define ET_REL 1 // relocatable file
#define ET_EXEC 2 // executable file
#define ET_DYN 3 // shared object file
#define ET_CORE 4 // core file
#define ET_LOOS 0xfe00 // operating system-specific
#define ET_HIOS 0xfeff // operating system specific
#define ET_LOPROC 0xff00 // processor-specific
#define ET_HIPROC 0xffff // processor-specific
#define SHT_NULL 0
#define SHT_PROGBITS 1
#define SHT_SYMTAB 2
#define SHT_STRTAB 3
#define SHT_RELA 4
#define SHT_HASH 5
#define SHT_DYNAMIC 6
#define SHT_NOTE 7
#define SHT_NOBITS 8
#define SHT_REL 9
#define SHT_SHLIB 10
#define SHT_DYNSYM 11
#define SHT_INIT_ARRAY 14
#define SHT_FINI_ARRAY 15
#define SHT_PREINIT_ARRAY 16
#define SHT_GROUP 17
#define SHT_SYMTAB_SHNDX 18
#define SHT_LOOS 0x60000000
#define SHT_HIOS 0x6fffffff
#define SHT_LOPROC 0x70000000
#define SHT_HIPROC 0x7fffffff
#define SHT_LOUSER 0x80000000
#define SHT_HIUSER 0xffffffff
#define EM_X86 0x03
#define EM_AMD_X86_64 0x3E
#define EV_NONE 0
#define EV_CURRENT 1
#define EI_NIDENT 16
typedef unsigned int Elf32_Addr;
typedef unsigned short Elf32_Half;
typedef unsigned int Elf32_Off;
typedef signed int Elf32_Sword;
typedef unsigned int Elf32_Word;
typedef struct{ // elf file header
unsigned char e_ident[EI_NIDENT];
Elf32_Half e_type;
Elf32_Half e_machine;
Elf32_Word e_version;
Elf32_Addr e_entry;
Elf32_Off e_phoff;
Elf32_Off e_shoff;
Elf32_Word e_flags;
Elf32_Half e_ehsize;
Elf32_Half e_phentsize;
Elf32_Half e_phnum;
Elf32_Half e_shentsize;
Elf32_Half e_shnum;
Elf32_Half e_shstrndx;
} Elf32_Ehdr;
typedef struct { // program header
Elf32_Word p_type;
Elf32_Off p_offset;
Elf32_Addr p_vaddr;
Elf32_Addr p_paddr;
Elf32_Word p_filesz;
Elf32_Word p_memsz;
Elf32_Word p_flags;
Elf32_Word p_align;
} Elf32_Phdr;
typedef struct{ // section header
Elf32_Word sh_name;
Elf32_Word sh_type;
Elf32_Word sh_flags;
Elf32_Addr sh_addr;
Elf32_Off sh_offset;
Elf32_Word sh_size;
Elf32_Word sh_link;
Elf32_Word sh_info;
Elf32_Word sh_addralign;
Elf32_Word sh_entsize;
} Elf32_Shdr;
我一直在测试我的二进制文件是否与 readelf 都正确。这是使用命令 readelf --section-headers output.elf 时的当前输出:
There are 2 section headers, starting at offset 0x33:
readelf: Error: Reading 7936 bytes extends past end of file for string table
Section Headers:
[Nr] Name Type Addr Off Size ES Flg Lk Inf Al
[ 0] <no-strings> NULL 00000000 000000 000000 00 0 0 0
readelf: Warning: Size of section 1 is larger than the entire file!
[ 1] <no-strings> 00000300: <unkn 00005000 005c00 001f00 00 0 0 0
Key to Flags:
W (write), A (alloc), X (execute), M (merge), S (strings), I (info),
L (link order), O (extra OS processing required), G (group), T (TLS),
C (compressed), x (unknown), o (OS specific), E (exclude),
D (mbind), p (processor specific)
readelf: Error: Reading 7936 bytes extends past end of file for string table
readelf: Error: Reading 7936 bytes extends past end of file for string table
readelf: Error: Reading 7936 bytes extends past end of file for string table
readelf: Error: Reading 7936 bytes extends past end of file for string table
readelf: Error: Reading 7936 bytes extends past end of file for string table
NULL 节头的偏移量似乎一切都很好,所以我认为这不是问题所在。标题的大小是正确的,所以我不认为是这样。我真的很困惑为什么这会给我带来错误。有人看到我做错了什么吗? 如果您需要更多信息,请发表评论,我会添加您需要的任何内容。
更新: 这是我对代码所做的更改
elf_header->e_shstrndx = strtab_index; // Point to the shstrtab section
elf_header->e_shnum = section_n;
elf_header->e_shoff = sizeof(Elf32_Ehdr);
strtab_Section->sh_type = SHT_STRTAB;
strtab_Section->sh_offset = ((sizeof(Elf32_Shdr))*1)+sizeof(Elf32_Ehdr);
strtab_Section->sh_addr = sizeof(Elf32_Shdr)*2;
strtab_Section->sh_addralign = 1;
strtab_Section->sh_size = sizeof(*strtab_Section) + strtab_size;
So im trying to create a relocatable elf binary with c. I don't want to use and libraries or anything like that. I have some code already that i have been writing. This has been the resource i have been reading: https://refspecs.linuxfoundation.org/elf/gabi4+/ch4.eheader.html . i have got the elf headers looking correct. Im just getting errors when it comes to sections and section headers.
This is my main code
#include <stdio.h>
#include <stdlib.h>
#include "elf.h"
const unsigned char strtab[] = {
'\0',
'.', 's', 'h', 's', 't', 'r', 't', 'a', 'b', '\0',
'.', 's', 't', 'r', 't', 'a', 'b', '\0',
'.', 'd', 'a', 't', 'a', '\0',
'.', 't', 'e', 'x', 't', '\0',
};
int strtab_size = sizeof(strtab);
int strtab_index = 1;
int section_n = 2;
Elf32_Shdr * create_shdr(){
Elf32_Shdr * header = calloc(sizeof(Elf32_Shdr), 1);
if (header == NULL){
return NULL;
}
return header;
}
Elf32_Ehdr * create_ehdr(){
Elf32_Ehdr * header = calloc(sizeof(Elf32_Ehdr), 1);
if (header == NULL){
return NULL;
}
header->e_ident[EI_MAG0] = 0x7f;
header->e_ident[EI_MAG1] = 'E';
header->e_ident[EI_MAG2] = 'L';
header->e_ident[EI_MAG3] = 'F';
// set the object to 32 bit
header->e_ident[EI_CLASS] = ELFCLASS32;
header->e_ident[EI_DATA] = ELFDATA2LSB;
// set the file version
header->e_ident[EI_VERSION] = EV_CURRENT;
// set sysv abi
header->e_ident[EI_OSABI] = ELFOSABI_SYSV;
header->e_ident[EI_ABIVERSION] = ELFOSABI_NONE;
header->e_ident[EI_PAD] = 0; // needs to be changed
header->e_shentsize = sizeof(Elf32_Shdr);
// we default to relocatable
header->e_type = ET_REL;
header->e_machine = EM_X86;
header->e_version = EV_CURRENT;
header->e_ehsize = sizeof(Elf32_Ehdr);
header->e_phentsize = sizeof(Elf32_Phdr);
header->e_phnum = 0;
return header;
}
int main()
{
FILE * fout;
Elf32_Ehdr *elf_header;
Elf32_Shdr *NULL_Section; // this should all be null
Elf32_Shdr *strtab_Section;
printf("%d\n", strtab_size);
fout = fopen("output.elf", "wb");
if (fout == NULL){
printf("Failed to open output.elf\n");
return 1;
}
if ((elf_header = create_ehdr()) == NULL){
printf("Failed to create new header\n");
return 1;
}
if ((NULL_Section = create_shdr()) == NULL){
printf("Failed to create new section header\n");
return 1;
}
if ((strtab_Section = create_shdr()) == NULL){
printf("Failed to create new section header\n");
return 1;
}
elf_header->e_shstrndx = strtab_index; // Point to the shstrtab section
elf_header->e_shnum = section_n;
elf_header->e_shoff = sizeof(Elf32_Ehdr)-1;
strtab_Section->sh_type = SHT_STRTAB;
strtab_Section->sh_offset = ((sizeof(Elf32_Shdr))*1)+sizeof(Elf32_Ehdr);
strtab_Section->sh_addr = 80;
//strtab_Section->sh_addralign = 1;
strtab_Section->sh_size = strtab_size;
fwrite(elf_header, sizeof(Elf32_Ehdr), 1, fout);
fwrite(NULL_Section, sizeof(Elf32_Shdr), 1, fout);
fwrite(strtab_Section, sizeof(Elf32_Shdr), 1, fout);
fwrite(strtab, strtab_size, 1, fout);
return 0;
}
My elf.h file is
#pragma once
enum EI{
EI_MAG0 = 0,
EI_MAG1,
EI_MAG2,
EI_MAG3,
EI_CLASS,
EI_DATA,
EI_VERSION,
EI_OSABI,
EI_ABIVERSION,
EI_PAD,
};
#define ELFOSABI_NONE 0 //No extensions or unspecified
#define ELFOSABI_HPUX 1 //Hewlett-Packard HP-UX
#define ELFOSABI_NETBSD 2 //NetBSD
#define ELFOSABI_LINUX 3 //Linux
#define ELFOSABI_SOLARIS 6 //Sun Solaris
#define ELFOSABI_AIX 7 //AIX
#define ELFOSABI_IRIX 8 //IRIX
#define ELFOSABI_FREEBSD 9 //FreeBSD
#define ELFOSABI_TRU64 10 //Compaq TRU64 UNIX
#define ELFOSABI_MODESTO 11 //Novell Modesto
#define ELFOSABI_OPENBSD 12 //Open BSD
#define ELFOSABI_OPENVMS 13 //Open VMS
#define ELFOSABI_NSK 14 //Hewlett-Packard Non-Stop Kernel
#define SHF_WRITE 0x1
#define SHF_ALLOC 0x2
#define SHF_EXECINSTR 0x4
#define SHF_MERGE 0x10
#define SHF_STRINGS 0x20
#define SHF_INFO_LINK 0x40
#define SHF_LINK_ORDER 0x80
#define SHF_OS_NONCONFORMING 0x100
#define SHF_GROUP 0x200
#define SHF_TLS 0x400
#define SHF_MASKOS 0x0ff00000
#define SHF_MASKPROC 0xf0000000
#define ELFCLASSNONE 0
#define ELFCLASS32 1
#define ELFCLASS64 2
#define ELFDATANONE 0
#define ELFDATA2LSB 1
#define ELFDATA2MSB 2
#define ELFOSABI_SYSV 0
#define ELFOSABI_HPUX 1
#define ELFOSABI_STANDALONE 255
#define ET_NONE 0
#define ET_REL 1 // relocatable file
#define ET_EXEC 2 // executable file
#define ET_DYN 3 // shared object file
#define ET_CORE 4 // core file
#define ET_LOOS 0xfe00 // operating system-specific
#define ET_HIOS 0xfeff // operating system specific
#define ET_LOPROC 0xff00 // processor-specific
#define ET_HIPROC 0xffff // processor-specific
#define SHT_NULL 0
#define SHT_PROGBITS 1
#define SHT_SYMTAB 2
#define SHT_STRTAB 3
#define SHT_RELA 4
#define SHT_HASH 5
#define SHT_DYNAMIC 6
#define SHT_NOTE 7
#define SHT_NOBITS 8
#define SHT_REL 9
#define SHT_SHLIB 10
#define SHT_DYNSYM 11
#define SHT_INIT_ARRAY 14
#define SHT_FINI_ARRAY 15
#define SHT_PREINIT_ARRAY 16
#define SHT_GROUP 17
#define SHT_SYMTAB_SHNDX 18
#define SHT_LOOS 0x60000000
#define SHT_HIOS 0x6fffffff
#define SHT_LOPROC 0x70000000
#define SHT_HIPROC 0x7fffffff
#define SHT_LOUSER 0x80000000
#define SHT_HIUSER 0xffffffff
#define EM_X86 0x03
#define EM_AMD_X86_64 0x3E
#define EV_NONE 0
#define EV_CURRENT 1
#define EI_NIDENT 16
typedef unsigned int Elf32_Addr;
typedef unsigned short Elf32_Half;
typedef unsigned int Elf32_Off;
typedef signed int Elf32_Sword;
typedef unsigned int Elf32_Word;
typedef struct{ // elf file header
unsigned char e_ident[EI_NIDENT];
Elf32_Half e_type;
Elf32_Half e_machine;
Elf32_Word e_version;
Elf32_Addr e_entry;
Elf32_Off e_phoff;
Elf32_Off e_shoff;
Elf32_Word e_flags;
Elf32_Half e_ehsize;
Elf32_Half e_phentsize;
Elf32_Half e_phnum;
Elf32_Half e_shentsize;
Elf32_Half e_shnum;
Elf32_Half e_shstrndx;
} Elf32_Ehdr;
typedef struct { // program header
Elf32_Word p_type;
Elf32_Off p_offset;
Elf32_Addr p_vaddr;
Elf32_Addr p_paddr;
Elf32_Word p_filesz;
Elf32_Word p_memsz;
Elf32_Word p_flags;
Elf32_Word p_align;
} Elf32_Phdr;
typedef struct{ // section header
Elf32_Word sh_name;
Elf32_Word sh_type;
Elf32_Word sh_flags;
Elf32_Addr sh_addr;
Elf32_Off sh_offset;
Elf32_Word sh_size;
Elf32_Word sh_link;
Elf32_Word sh_info;
Elf32_Word sh_addralign;
Elf32_Word sh_entsize;
} Elf32_Shdr;
I have been testing if my binaries are all correct with readelf. This is the current output when using the command readelf --section-headers output.elf
:
There are 2 section headers, starting at offset 0x33:
readelf: Error: Reading 7936 bytes extends past end of file for string table
Section Headers:
[Nr] Name Type Addr Off Size ES Flg Lk Inf Al
[ 0] <no-strings> NULL 00000000 000000 000000 00 0 0 0
readelf: Warning: Size of section 1 is larger than the entire file!
[ 1] <no-strings> 00000300: <unkn 00005000 005c00 001f00 00 0 0 0
Key to Flags:
W (write), A (alloc), X (execute), M (merge), S (strings), I (info),
L (link order), O (extra OS processing required), G (group), T (TLS),
C (compressed), x (unknown), o (OS specific), E (exclude),
D (mbind), p (processor specific)
readelf: Error: Reading 7936 bytes extends past end of file for string table
readelf: Error: Reading 7936 bytes extends past end of file for string table
readelf: Error: Reading 7936 bytes extends past end of file for string table
readelf: Error: Reading 7936 bytes extends past end of file for string table
readelf: Error: Reading 7936 bytes extends past end of file for string table
The offset to the NULL section header seems all good, so i don't think it is that problem. The size of the headers are correct, so i don't think its that. Im really puzzled why this is giving me errors. Does anyone see anything im doing incorrectly?
If you need more info please put a comment and i will add anything you need.
Update:
this are the changes i have made to my code
elf_header->e_shstrndx = strtab_index; // Point to the shstrtab section
elf_header->e_shnum = section_n;
elf_header->e_shoff = sizeof(Elf32_Ehdr);
strtab_Section->sh_type = SHT_STRTAB;
strtab_Section->sh_offset = ((sizeof(Elf32_Shdr))*1)+sizeof(Elf32_Ehdr);
strtab_Section->sh_addr = sizeof(Elf32_Shdr)*2;
strtab_Section->sh_addralign = 1;
strtab_Section->sh_size = sizeof(*strtab_Section) + strtab_size;
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我不这么认为:
节标题的开头显然是假的。从这一行删除伪造的
-1
:生成一个看起来更好的
output.elf
二进制文件:更新:
为此,您需要设置
strtab_Section->sh_name = 1;
并将其sh_offset
设置为((sizeof(Elf32_Shdr))*2)+sizeof( Elf32_Ehdr)
(您有两个部分,而不是一个)。按原样,
.sh_name == 0
,对应于空字符串。通过上述更改,我得到:I don't think so:
The start of section headers is obviously bogus. Removing bogus
-1
from this line:produces an
output.elf
binary which looks better:Update:
For that, you need to set
strtab_Section->sh_name = 1;
and set itssh_offset
to((sizeof(Elf32_Shdr))*2)+sizeof(Elf32_Ehdr)
(you have two sections, not one).As-is,
.sh_name == 0
, which corresponds to empty string. With above change, I get: