{
	"id": "566ba2de-9599-4873-a91d-0f0753710ffc",
	"created_at": "2026-04-06T00:22:07.058677Z",
	"updated_at": "2026-04-10T03:30:33.433902Z",
	"deleted_at": null,
	"sha1_hash": "805eba8373a6806c8d0e4cb54d49bbf14005df19",
	"title": "Executable and Linkable Format 101. Part 2: Symbols",
	"llm_title": "",
	"authors": "",
	"file_creation_date": "0001-01-01T00:00:00Z",
	"file_modification_date": "0001-01-01T00:00:00Z",
	"file_size": 88754,
	"plain_text": "Executable and Linkable Format 101. Part 2: Symbols\r\nBy Ignacio Sanmillan\r\nPublished: 2018-02-07 · Archived: 2026-04-05 19:35:24 UTC\r\nIn our previous post, we focused on understanding the relationship between sections and segments, which serve as\r\nthe foundation for understanding the ELF file format. However, we will soon discover that we have ignored some\r\ndegree of detail for the sake of simplicity.\r\nIn the next couple of posts, we will focus on explaining the details behind Symbols and Relocations, which play a\r\nfundamental role in understanding the ELF file format in greater depth.\r\nDefining Symbols\r\nIn the development process of a program, we often use names to refer toa objects in our code, such as functions or\r\nvariables that are used all throughout the program. This information is what is known as the program’s symbolic\r\ninformation. Symbolic references in machine code get translated into offsets and addresses on the compilation\r\nprocess.\r\nHowever, compilers are not limited to machine code generation; they also export symbolic information from\r\nsource code. Symbolic information is exported in order to improve the interpretation of the generated machine\r\ncode. The ELF file format has a means to hold this symbolic information and provides an interface for local and\r\nexternal ELF objects to access it.\r\nA wide range of tools interact with symbols to enforce their functionality. One example of these tools are Linkers.\r\nLinkers usually interact with a Symbol Table in order to match/reference/modify a given symbol inside an ELF\r\nobject at linktime. Without Symbols, Linkers would not work, since they won’t know which relocations must take\r\nplace, and therefore would not have a mechanism to match a given symbolic reference to its corresponding value.\r\nAnother example of tools that heavily depend on symbolic information are Debuggers. Without Symbols, the\r\nprocess of Debugging can become considerably harder or even worthless, especially for projects with massive\r\ncode bases such as the Linux Kernel. Debugging without symbols implies that one has no ability to identify\r\nfunctions or variables by name among other impediments. This would considerably reduce the features afforded\r\nby debuggers.\r\nInterestingly, Malware also interacts with symbol tables as an anti-analysis mechanism. Symbol Tables can appear\r\nto be completely removed from the binary as an attempt to harden the analysis process, or in other cases their\r\nString Table entries may be swapped so that symbols will be miss-interpreted. (We’ll cover malware anti-analysis\r\ntechniques in coming posts.)\r\nELF Symbol structure\r\nIn the ELF file format, each Symbol is represented as an instance of an Elfxx_Sym structure inside a given Symbol\r\nTable.\r\nhttps://www.intezer.com/blog/malware-analysis/executable-linkable-format-101-part-2-symbols/\r\nPage 1 of 5\n\nThe Elements of this structure include:\r\nst_name: index in string table of symbol name. If this field is not initialized, then the symbol doesn’t have a\r\nname\r\nst_info: contains symbol bind and type attributes. Binding attributes determine the linkage visibility and\r\nbehavior when a given symbol is referenced by an external object. The most common symbol binds are the\r\nfollowing:\r\nSTB_LOCAL: Symbol is not visible outside the ELF object containing the symbol definition.\r\nSTB_GLOBAL: Symbol is visible to all object files.\r\nSTB_WEAK: Representing global symbols, but their definition can be overridden.\r\nThe most common symbol types are the following:\r\nSTT_NOTYPE: symbol type is not specified\r\nSTT_OBJECT: symbol is a data object (variable).\r\nSTT_FUNC: symbol is a code object (function).\r\nSTT_SECTION: symbol is a section.\r\nIn order to retrieve these fields, a set of bitmasks are used. These bitmasks include:\r\nELF64_ST_BIND(info)    ((info) \u003e\u003e 4)\r\nELF64_ST_TYPE(info)    ((info) \u0026 0xf)\r\nst_other: information about symbol visibility. Symbol visibility defines how a given symbol may be\r\naccessed once the symbol has become part of an executable or shared object. Some common symbol\r\nvisibilities are the following:\r\nSTV_DEFAULT: for default visibility symbols, its attribute is specified by the symbol’s binding\r\ntype.\r\nSTV_PROTECTED: symbol is visible by other objects, but cannot be preempted.\r\nSTV_HIDDEN: symbol is not visible to other objects.\r\nhttps://www.intezer.com/blog/malware-analysis/executable-linkable-format-101-part-2-symbols/\r\nPage 2 of 5\n\nSTV_INTERNAL: symbol visibility is reserved.\r\nThe major difference between symbol visibility and symbol binding is that the former is enforced on the host\r\nobject of a given symbol and applies to any external object referencing it. Symbol binding, on the other hand, is\r\nspecified by an external object referencing the symbol and is enforced at link-time. In other words, object binding\r\ndepends on the object referencing the symbol, while symbol visibility depends on how the object containing the\r\nsymbol was compiled.\r\nThe only relevant contents of this field are its three last significant bits. Other bit fields do not contain specific\r\nmeaning. In order to retrieve visibility information, the following macro is used:\r\nELF64_ST_VISIBILITY(o)    ((o) \u0026 0x3)\r\nst_shndx: Every symbol entry within the Symbol Table is associated with a section. This value specifies the\r\nsection index within the Section Header Table associated with the given symbol. Common values for\r\nsection type field include:\r\nSHT_UNDEF: section is not present in current object. This value is typically set in symbols that\r\nhave been imported from external objects.\r\nSHT_PROGBITS: section is defined in current object.\r\nSHT_SYMTAB, SHT_DYNSYM: Symbol Table (.symtab, .dynsym).\r\nSHT_STRTAB, SHT_DYNSTR:  String Table (.strtab, .dynstr).\r\nSHT_REL: Relocation Table without explicit addends (.rel.dyn, .rel.plt).\r\nSHT_RELA: Relocation Table with explicit addends (.rela.dyn, .rela.plt).\r\nSHT_HASH: Hash Table for dynamic symbol resolution (.gnu.hash)\r\nSHT_DYNAMIC: section holding Dynamic Linking information (.dynamic)\r\nSHT_NOBITS: section takes no space in disk (.bss).\r\nst_value: This field specifies the symbol value for a given Symbol Table entry. The interpretation of this\r\nfield can vary depending on the object type.\r\nFor ET_REL files st_value holds a section offset. The section in which this offset resides is specified\r\non its st_shndx field.\r\nFor ET_EXEC / ET_DYN files, st_value holds a virtual address. If this field contains a value of 0\r\nand the symbol’s section pointed by st_shndx has a sh_type field of type SHT_UNDEF, the symbol\r\nis an imported relocation, and its value will be resolved at runtime by the RTLD (ld.so).\r\nst_size: Field containing symbol’s size.\r\nSymbol and String Tables\r\nA single ELF object may contain a maximum of two Symbol Tables. These are .symtab and .dynsym. The\r\ndifference between these two instances involves the number and type of symbols they contain. We refer .symtab as\r\nthe binary’s global Symbol Table, containing all symbol references in the current object. The section .strtab is the\r\nString Table of .symtab Symbol Table. String Tables store null-terminated strings used to reference objects from a\r\ndifferent section. Each String Table contains the exact number of entries as its corresponding Symbol Table. This\r\nhttps://www.intezer.com/blog/malware-analysis/executable-linkable-format-101-part-2-symbols/\r\nPage 3 of 5\n\nentails that each string entry at a given index in .strtab corresponds to an Elfxx_Sym entry at the same index in\r\n.symtab.\r\nOn the other hand, we have .dynsym Symbol Table. This Symbol Table only holds symbols needed for Dynamic\r\nLinking. (We’ll cover Dynamic Linking extensively in future posts.) As an overview, when developing an\r\napplication, sometimes we’d want to use symbols that don’t reside within the context of our program but are\r\ninstead defined in external objects such as libraries (Shared Objects). Dynamic Linking is the process where the\r\nlinker tries to dynamically bind those external symbols at runtime in order for them to be referenced safely within\r\nthe context of a program.\r\nIf a given binary has been stripped (.symtab/.strtab have been removed) and this same binary has been compiled\r\nso that a subset of its symbols will be dynamically linked, this subset of symbols can be recovered by parsing\r\n.dynsym table located at DT_SYMTAB entry within PT_DYNAMIC segment. For dynamically linked executables,\r\n.dynsym will not be removed even if target binary has been stripped, since it is needed at runtime by the RTLD in\r\nthe process of Dynamic Linking.\r\nAs with .symtab, .dynsym has its own string table called .dynstr. All the relationships previously covered between\r\n.symtab and .strtab also apply between .dynsym and .dynstr. The following diagram illustrates the concepts of\r\nSymbols and String tables that we’ve just discussed:\r\nIn this diagram, we see an example representation of various data structures from a binary containing the symbol\r\n_IO_stdin_used. This symbol is represented as the second Elf32_Sym instance in .dynsym Symbol Table. Note that\r\nhttps://www.intezer.com/blog/malware-analysis/executable-linkable-format-101-part-2-symbols/\r\nPage 4 of 5\n\n.dynsym is a section represented as an Elf32_Shdr structure, and the index of its String Table within the Section\r\nHeader Table can be retrieved by its Elf32_Shdr’s sh_link field.\r\nMoreover, This symbol resides within the .rodata section as shown by its Elf32_Sym st_shndx field, which denotes\r\nthe fourth Elf32_Shdr instance within the Section Header Table. This Elf32_Shdr instance’s sh_name field points\r\nto the second null terminated string within the Section Header String Table, which is the ‘.rodata’ string.\r\nFurthermore, we can obtain _IO_stdin_used‘s attributes based on its Elf32_Sym instance. We can see that it is of\r\ntype OBJECT, and its binding is of type GLOBAL. Therefore, we can assume this symbol is a Global variable.\r\nNote that the st_value field may lead to misconceptions since it contains a virtual address denoting the symbol’s\r\nlocation within its correspondent section, but not the actual value of the Symbol.\r\nSummary\r\nWe’ve covered the intricacies of Symbol handling within the ELF file format. We now have an understanding of\r\nwhat symbols are and their different uses. We have also covered the different types of Symbol Tables and how\r\nthey correlate to different String Tables. In the next post, we will dive into ELF Relocations and the Dynamic\r\nLinking process.\r\nSource: https://www.intezer.com/blog/malware-analysis/executable-linkable-format-101-part-2-symbols/\r\nhttps://www.intezer.com/blog/malware-analysis/executable-linkable-format-101-part-2-symbols/\r\nPage 5 of 5",
	"extraction_quality": 1,
	"language": "EN",
	"sources": [
		"MITRE"
	],
	"references": [
		"https://www.intezer.com/blog/malware-analysis/executable-linkable-format-101-part-2-symbols/"
	],
	"report_names": [
		"executable-linkable-format-101-part-2-symbols"
	],
	"threat_actors": [
		{
			"id": "75108fc1-7f6a-450e-b024-10284f3f62bb",
			"created_at": "2024-11-01T02:00:52.756877Z",
			"updated_at": "2026-04-10T02:00:05.273746Z",
			"deleted_at": null,
			"main_name": "Play",
			"aliases": null,
			"source_name": "MITRE:Play",
			"tools": [
				"Nltest",
				"AdFind",
				"PsExec",
				"Wevtutil",
				"Cobalt Strike",
				"Playcrypt",
				"Mimikatz"
			],
			"source_id": "MITRE",
			"reports": null
		}
	],
	"ts_created_at": 1775434927,
	"ts_updated_at": 1775791833,
	"ts_creation_date": 0,
	"ts_modification_date": 0,
	"files": {
		"pdf": "https://archive.orkl.eu/805eba8373a6806c8d0e4cb54d49bbf14005df19.pdf",
		"text": "https://archive.orkl.eu/805eba8373a6806c8d0e4cb54d49bbf14005df19.txt",
		"img": "https://archive.orkl.eu/805eba8373a6806c8d0e4cb54d49bbf14005df19.jpg"
	}
}