├── .editorconfig ├── README.md ├── readelf ├── __init__.py └── readelf.py ├── setup.py ├── LICENSE └── .gitignore /.editorconfig: -------------------------------------------------------------------------------- 1 | # http://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | indent_style = tab 6 | indent_size = 4 7 | end_of_line = lf 8 | charset = utf-8 9 | trim_trailing_whitespace = true 10 | insert_final_newline = true 11 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [ELF]: https://refspecs.linuxfoundation.org/ 2 | 3 | readelf 4 | ======= 5 | One Python File To Parse ELF for learning 6 | 7 | Purpose 8 | ======= 9 | 10 | It's used to learning [ELF] whcich is writed on One Python File. 11 | 12 | 13 | TODO 14 | ======= 15 | * Relocatable File 16 | 17 | 18 | Author 19 | ======= 20 | detailyang (detailyang@gmail.com) 21 | -------------------------------------------------------------------------------- /readelf/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # @Author: detailyang 3 | # @Date: 2016-12-13 17:47:41 4 | # @Last Modified by: detailyang 5 | # @Last Modified time: 2016-12-13 17:54:10 6 | 7 | 8 | import sys 9 | 10 | from readelf import readelf 11 | 12 | def entry(): 13 | if len(sys.argv) != 2: 14 | print("Usage: readelf /path/to/file") 15 | sys.exit(1) 16 | 17 | with open(sys.argv[1], 'r') as elf: 18 | readelf(elf) 19 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | # @Author: BingWu Yang 2 | # @Date: 2016-09-20T20:27:36+08:00 3 | # @Email: detailyang@gmail.com 4 | # @Last modified by: detailyang 5 | # @Last modified time: 2016-09-20T15:23:48+08:00 6 | # @License: The MIT License (MIT) 7 | 8 | 9 | from setuptools import setup, find_packages 10 | 11 | 12 | setup( 13 | name='readelf', 14 | version='0.1.0', 15 | keywords=('elf'), 16 | description='One Python File To Parse ELF For Learning ELF', 17 | license='MIT License', 18 | install_requires=[ 19 | ], 20 | entry_points={ 21 | 'console_scripts': [ 22 | 'readelf=readelf:entry', 23 | ], 24 | }, 25 | author='detailyang', 26 | author_email='detailyang@gmail.com', 27 | 28 | packages=find_packages(), 29 | platforms='any', 30 | ) 31 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016 detailyang 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Created by https://www.gitignore.io/api/python 2 | 3 | ### Python ### 4 | # Byte-compiled / optimized / DLL files 5 | __pycache__/ 6 | *.py[cod] 7 | *$py.class 8 | 9 | # C extensions 10 | *.so 11 | 12 | # Distribution / packaging 13 | .Python 14 | env/ 15 | build/ 16 | develop-eggs/ 17 | dist/ 18 | downloads/ 19 | eggs/ 20 | .eggs/ 21 | lib/ 22 | lib64/ 23 | parts/ 24 | sdist/ 25 | var/ 26 | *.egg-info/ 27 | .installed.cfg 28 | *.egg 29 | 30 | # PyInstaller 31 | # Usually these files are written by a python script from a template 32 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 33 | *.manifest 34 | *.spec 35 | 36 | # Installer logs 37 | pip-log.txt 38 | pip-delete-this-directory.txt 39 | 40 | # Unit test / coverage reports 41 | htmlcov/ 42 | .tox/ 43 | .coverage 44 | .coverage.* 45 | .cache 46 | nosetests.xml 47 | coverage.xml 48 | *,cover 49 | .hypothesis/ 50 | 51 | # Translations 52 | *.mo 53 | *.pot 54 | 55 | # Django stuff: 56 | *.log 57 | local_settings.py 58 | 59 | # Flask stuff: 60 | instance/ 61 | .webassets-cache 62 | 63 | # Scrapy stuff: 64 | .scrapy 65 | 66 | # Sphinx documentation 67 | docs/_build/ 68 | 69 | # PyBuilder 70 | target/ 71 | 72 | # IPython Notebook 73 | .ipynb_checkpoints 74 | 75 | # pyenv 76 | .python-version 77 | 78 | # celery beat schedule file 79 | celerybeat-schedule 80 | 81 | # dotenv 82 | .env 83 | 84 | # Spyder project settings 85 | .spyderproject 86 | 87 | # Rope project settings 88 | .ropeproject 89 | -------------------------------------------------------------------------------- /readelf/readelf.py: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env python 2 | #-*-coding: utf-8 -*- 3 | 4 | import sys 5 | import struct 6 | 7 | 8 | class ELFError(Exception): 9 | pass 10 | 11 | 12 | SHF_WRITE = 0x1 13 | SHF_ALLOC = 0x2 14 | SHF_EXECINSTR = 0x4 15 | SHF_MASKPROC = 0xF0000000 16 | 17 | 18 | TAG = { 19 | 0:"NULL", 20 | 1:"NEEDED", 21 | 2:"PLTRELSZ", 22 | 3:"PLTGOT", 23 | 4:"HASH", 24 | 5:"STRTAB", 25 | 6:"SYMTAB", 26 | 7:"RELA", 27 | 8:"RELASZ", 28 | 9:"RELAENT", 29 | 10:"STRSZ", 30 | 11:"SYMENT", 31 | 12:"INIT", 32 | 13:"FINI", 33 | 14:"SONAME", 34 | 15:"RPATH", 35 | 16:"SYMBOLIC", 36 | 17:"REL", 37 | 18:"RELSZ", 38 | 19:"RELENT", 39 | 20:"PLTREL", 40 | 21:"DEBUG", 41 | 22:"TEXTREL", 42 | 23:"JMPREL", 43 | 24:"BIND_NOW", 44 | 25:"INIT_ARRAY", 45 | 26:"FINI_ARRAY", 46 | 27:"INIT_ARRAYSZ", 47 | 28:"FINI_ARRAYSZ", 48 | 29:"RUNPATH", 49 | 30:"FLAGS", 50 | 32:"ENCODING", 51 | 32:"PREINIT_ARRAY", 52 | 33:"PREINIT_ARRAYSZ", 53 | 34:"MAXPOSTAGS", 54 | 0x6000000d:"LOOS", 55 | 0x6000000d:"SUNW_AUXILIARY", 56 | 0x6000000e:"SUNW_RTLDINF", 57 | 0x6000000e:"SUNW_FILTER", 58 | 0x60000010:"SUNW_CAP", 59 | 0x60000011:"SUNW_SYMTAB", 60 | 0x60000012:"SUNW_SYMSZ", 61 | 0x60000013:"SUNW_ENCODING", 62 | 0x60000013:"SUNW_SORTENT", 63 | 0x60000014:"SUNW_SYMSORT", 64 | 0x60000015:"SUNW_SYMSORTSZ", 65 | 0x60000016:"SUNW_TLSSORT", 66 | 0x60000017:"SUNW_TLSSORTSZ", 67 | 0x60000018:"SUNW_CAPINFO", 68 | 0x60000019:"SUNW_STRPAD", 69 | 0x6000001a:"SUNW_CAPCHAIN", 70 | 0x6000001b:"SUNW_LDMACH", 71 | 0x6000001d:"SUNW_CAPCHAINENT", 72 | 0x6000001f:"SUNW_CAPCHAINSZ", 73 | 0x6ffff000:"HIOS", 74 | 0x6ffffd00:"VALRNGLO", 75 | 0x6ffffdf8:"CHECKSUM", 76 | 0x6ffffdf9:"PLTPADSZ", 77 | 0x6ffffdfa:"MOVEENT", 78 | 0x6ffffdfb:"MOVESZ", 79 | 0x6ffffdfd:"POSFLAG_1", 80 | 0x6ffffdfe:"SYMINSZ", 81 | 0x6ffffdff:"SYMINENT", 82 | 0x6ffffdff:"VALRNGHI", 83 | 0x6ffffe00:"ADDRRNGLO", 84 | 0x6ffffefa:"CONFIG", 85 | 0x6ffffefb:"DEPAUDIT", 86 | 0x6ffffefc:"AUDIT", 87 | 0x6ffffefd:"PLTPAD", 88 | 0x6ffffefe:"MOVETAB", 89 | 0x6ffffeff:"SYMINFO", 90 | 0x6ffffeff:"ADDRRNGHI", 91 | 0x6ffffff9:"RELACOUNT", 92 | 0x6ffffffa:"RELCOUNT", 93 | 0x6ffffffb:"FLAGS_1", 94 | 0x6ffffffc:"VERDEF", 95 | 0x6ffffffd:"VERDEFNUM", 96 | 0x6ffffffe:"VERNEED", 97 | 0x6fffffff:"VERNEEDNUM", 98 | 0x70000000:"LOPROC", 99 | 0x70000001:"SPARC_REGISTER", 100 | 0x7ffffffd:"AUXILIARY", 101 | 0x7ffffffe:"USED", 102 | 0x7fffffff:"FILTER", 103 | 0x7fffffff:"HIPROC", 104 | } 105 | 106 | 107 | PT_FLAGS = { 108 | 0: "None", 109 | 1: "E", 110 | 2: "W", 111 | 3: "WE", 112 | 4: "R", 113 | 5: "RE", 114 | 6: "RW", 115 | 7: "RWE" 116 | } 117 | 118 | 119 | PT_TYPE = { 120 | 0: "NULL", 121 | 1: "LOAD", 122 | 2: "DYNAMIC", 123 | 3: "INTERP", 124 | 4: "NOTE", 125 | 5: "SHLIB", 126 | 6: "PHDR", 127 | 7: "TLS", 128 | 0x70000000: "LOPROC", 129 | 0x7fffffff: "HPROC" 130 | } 131 | 132 | 133 | STT_TYPE = { 134 | 0: 'NOTYPE', 135 | 1: 'OBJECT', 136 | 2: 'FUNC', 137 | 3: 'SECTION', 138 | 4: 'FILE', 139 | 5: 'COMMON', 140 | 6: 'TLS', 141 | 10: 'LOOS', 142 | 12: 'HIOS', 143 | 13: 'LOPROC', 144 | 15: 'HIPROC' 145 | } 146 | 147 | 148 | STB_BIND = { 149 | 0: 'LOCAL', 150 | 1: 'GLOBAL', 151 | 2: 'WEAK', 152 | 13: 'LOPROC', 153 | 15: 'HIPROC' 154 | } 155 | 156 | 157 | STV_VISIBILITY = { 158 | 0: 'DEFAULT', 159 | 1: 'INTERNAL', 160 | 2: 'HIDDEN', 161 | 3: 'PROTECTED' 162 | } 163 | 164 | 165 | SH_TYPE = { 166 | 0:"NULL", 167 | 1:"PROGBITS", 168 | 2:"SYMTAB", 169 | 3:"STRTAB", 170 | 4:"RELA", 171 | 5:"HASH", 172 | 6:"DYNAMIC", 173 | 7:"NOTE", 174 | 8:"NOBITS", 175 | 9:"REL", 176 | 10:"SHLIB", 177 | 11:"DYNSYM", 178 | 14:"INIT_ARRAY", 179 | 15:"FINI_ARRAY", 180 | 16:"PREINIT_ARRAY", 181 | 17:"GROUP", 182 | 18:"SYMTAB_SHNDX", 183 | 0x60000000:"LOOS", 184 | 0x6fffffff:"HIOS", 185 | 0x70000000:"LOPROC", 186 | 0x7fffffff:"HIPROC", 187 | 0x80000000:"LOUSER", 188 | 0xffffffff:"HIUSER", 189 | } 190 | 191 | 192 | EI_MACHINE = { 193 | 0:"No machine", 194 | 1:"AT&T WE 32100", 195 | 2:"SPARC", 196 | 3:"Intel 80386", 197 | 4:"Motorola 68000", 198 | 5:"Motorola 88000", 199 | 6:"Intel MCU", 200 | 7:"Intel 80860", 201 | 8:"MIPS I Architecture", 202 | 9:"IBM System/370 Processor", 203 | 10:"MIPS RS3000 Little-endian", 204 | 11-14:"Reserved for future use", 205 | 15:"Hewlett-Packard PA-RISC", 206 | 16:"Reserved for future use", 207 | 17:"Fujitsu VPP500", 208 | 18:"Enhanced instruction set SPARC", 209 | 19:"Intel 80960", 210 | 20:"PowerPC", 211 | 21:"64-bit PowerPC", 212 | 22:"IBM System/390 Processor", 213 | 23:"IBM SPU/SPC", 214 | 24-35:"Reserved for future use", 215 | 36:"NEC V800", 216 | 37:"Fujitsu FR20", 217 | 38:"TRW RH-32", 218 | 39:"Motorola RCE", 219 | 40:"ARM 32-bit architecture (AARCH32)", 220 | 41:"Digital Alpha", 221 | 42:"Hitachi SH", 222 | 43:"SPARC Version 9", 223 | 44:"Siemens TriCore embedded processor", 224 | 45:"Argonaut RISC Core, Argonaut Technologies Inc.", 225 | 46:"Hitachi H8/300", 226 | 47:"Hitachi H8/300H", 227 | 48:"Hitachi H8S", 228 | 49:"Hitachi H8/500", 229 | 50:"Intel IA-64 processor architecture", 230 | 51:"Stanford MIPS-X", 231 | 52:"Motorola ColdFire", 232 | 53:"Motorola M68HC12", 233 | 54:"Fujitsu MMA Multimedia Accelerator", 234 | 55:"Siemens PCP", 235 | 56:"Sony nCPU embedded RISC processor", 236 | 57:"Denso NDR1 microprocessor", 237 | 58:"Motorola Star*Core processor", 238 | 59:"Toyota ME16 processor", 239 | 60:"STMicroelectronics ST100 processor", 240 | 61:"Advanced Logic Corp. TinyJ embedded processor family", 241 | 62:"AMD x86-64 architecture", 242 | 63:"Sony DSP Processor", 243 | 64:"Digital Equipment Corp. PDP-10", 244 | 65:"Digital Equipment Corp. PDP-11", 245 | 66:"Siemens FX66 microcontroller", 246 | 67:"STMicroelectronics ST9+ 8/16 bit microcontroller", 247 | 68:"STMicroelectronics ST7 8-bit microcontroller", 248 | 69:"Motorola MC68HC16 Microcontroller", 249 | 70:"Motorola MC68HC11 Microcontroller", 250 | 71:"Motorola MC68HC08 Microcontroller", 251 | 72:"Motorola MC68HC05 Microcontroller", 252 | 73:"Silicon Graphics SVx", 253 | 74:"STMicroelectronics ST19 8-bit microcontroller", 254 | 75:"Digital VAX", 255 | 76:"Axis Communications 32-bit embedded processor", 256 | 77:"Infineon Technologies 32-bit embedded processor", 257 | 78:"Element 14 64-bit DSP Processor", 258 | 79:"LSI Logic 16-bit DSP Processor", 259 | 80:"Donald Knuth's educational 64-bit processor", 260 | 81:"Harvard University machine-independent object files", 261 | 82:"SiTera Prism", 262 | 83:"Atmel AVR 8-bit microcontroller", 263 | 84:"Fujitsu FR30", 264 | 85:"Mitsubishi D10V", 265 | 86:"Mitsubishi D30V", 266 | 87:"NEC v850", 267 | 88:"Mitsubishi M32R", 268 | 89:"Matsushita MN10300", 269 | 90:"Matsushita MN10200", 270 | 91:"picoJava", 271 | 92:"OpenRISC 32-bit embedded processor", 272 | 93:"ARC International ARCompact processor (old spelling/synonym: EM_ARC_A5)", 273 | 94:"Tensilica Xtensa Architecture", 274 | 95:"Alphamosaic VideoCore processor", 275 | 96:"Thompson Multimedia General Purpose Processor", 276 | 97:"National Semiconductor 32000 series", 277 | 98:"Tenor Network TPC processor", 278 | 99:"Trebia SNP 1000 processor", 279 | 100:"STMicroelectronics (www.st.com) ST200 microcontroller", 280 | 101:"Ubicom IP2xxx microcontroller family", 281 | 102:"MAX Processor", 282 | 103:"National Semiconductor CompactRISC microprocessor", 283 | 104:"Fujitsu F2MC16", 284 | 105:"Texas Instruments embedded microcontroller msp430", 285 | 106:"Analog Devices Blackfin (DSP) processor", 286 | 107:"S1C33 Family of Seiko Epson processors", 287 | 108:"Sharp embedded microprocessor", 288 | 109:"Arca RISC Microprocessor", 289 | 110:"Microprocessor series from PKU-Unity Ltd. and MPRC of Peking University", 290 | 111:"eXcess: 16/32/64-bit configurable embedded CPU", 291 | 112:"Icera Semiconductor Inc. Deep Execution Processor", 292 | 113:"Altera Nios II soft-core processor", 293 | 114:"National Semiconductor CompactRISC CRX microprocessor", 294 | 115:"Motorola XGATE embedded processor", 295 | 116:"Infineon C16x/XC16x processor", 296 | 117:"Renesas M16C series microprocessors", 297 | 118:"Microchip Technology dsPIC30F Digital Signal Controller", 298 | 119:"Freescale Communication Engine RISC core", 299 | 120:"Renesas M32C series microprocessors", 300 | 121-130:"Reserved for future use", 301 | 131:"Altium TSK3000 core", 302 | 132:"Freescale RS08 embedded processor", 303 | 133:"Analog Devices SHARC family of 32-bit DSP processors", 304 | 134:"Cyan Technology eCOG2 microprocessor", 305 | 135:"Sunplus S+core7 RISC processor", 306 | 136:"New Japan Radio (NJR) 24-bit DSP Processor", 307 | 137:"Broadcom VideoCore III processor", 308 | 138:"RISC processor for Lattice FPGA architecture", 309 | 139:"Seiko Epson C17 family", 310 | 140:"The Texas Instruments TMS320C6000 DSP family", 311 | 141:"The Texas Instruments TMS320C2000 DSP family", 312 | 142:"The Texas Instruments TMS320C55x DSP family", 313 | 143:"Texas Instruments Application Specific RISC Processor, 32bit fetch", 314 | 144:"Texas Instruments Programmable Realtime Unit", 315 | 145-159:"Reserved for future use", 316 | 160:"", 317 | 145-159:"Reserved for future use", 318 | 160:"STMicroelectronics 64bit VLIW Data Signal Processor", 319 | 161:"Cypress M8C microprocessor", 320 | 162:"Renesas R32C series microprocessors", 321 | 163:"NXP Semiconductors TriMedia architecture family", 322 | 164:"QUALCOMM DSP6 Processor", 323 | 165:"Intel 8051 and variants", 324 | 166:"STMicroelectronics STxP7x family of configurable and extensible RISC processors", 325 | 167:"Andes Technology compact code size embedded RISC processor family", 326 | 168:"Cyan Technology eCOG1X family", 327 | 168:"Cyan Technology eCOG1X family", 328 | 169:"Dallas Semiconductor MAXQ30 Core Micro-controllers", 329 | 170:"New Japan Radio (NJR) 16-bit DSP Processor", 330 | 171:"M2000 Reconfigurable RISC Microprocessor", 331 | 172:"Cray Inc. NV2 vector architecture", 332 | 173:"Renesas RX family", 333 | 174:"Imagination Technologies META processor architecture", 334 | 175:"MCST Elbrus general purpose hardware architecture", 335 | 176:"Cyan Technology eCOG16 family", 336 | 177:"National Semiconductor CompactRISC CR16 16-bit microprocessor", 337 | 178:"Freescale Extended Time Processing Unit", 338 | 179:"Infineon Technologies SLE9X core", 339 | 180:"Intel L10M", 340 | 181:"Intel K10M", 341 | 182:"Reserved for future Intel use", 342 | 183:"ARM 64-bit architecture (AARCH64)", 343 | 184:"Reserved for future ARM use", 344 | 185:"Atmel Corporation 32-bit microprocessor family", 345 | 186:"STMicroeletronics STM8 8-bit microcontroller", 346 | 187:"Tilera TILE64 multicore architecture family", 347 | 188:"Tilera TILEPro multicore architecture family", 348 | 189:"Xilinx MicroBlaze 32-bit RISC soft processor core", 349 | 190:"NVIDIA CUDA architecture", 350 | 191:"Tilera TILE-Gx multicore architecture family", 351 | 192:"CloudShield architecture family", 352 | 193:"KIPO-KAIST Core-A 1st generation processor family", 353 | 194:"KIPO-KAIST Core-A 2nd generation processor family", 354 | 195:"Synopsys ARCompact V2", 355 | 196:"Open8 8-bit RISC soft processor core", 356 | 197:"Renesas RL78 family", 357 | 198:"Broadcom VideoCore V processor", 358 | 199:"Renesas 78KOR family", 359 | 200:"Freescale 56800EX Digital Signal Controller (DSC)", 360 | 201:"Beyond BA1 CPU architecture", 361 | 202:"Beyond BA2 CPU architecture", 362 | 203:"XMOS xCORE processor family", 363 | 204:"Microchip 8-bit PIC(r) family", 364 | 205:"Reserved by Intel", 365 | 206:"Reserved by Intel", 366 | 207:"Reserved by Intel", 367 | 208:"Reserved by Intel", 368 | 209:"Reserved by Intel", 369 | 210:"KM211 KM32 32-bit processor", 370 | 211:"KM211 KMX32 32-bit processor", 371 | 212:"KM211 KMX16 16-bit processor", 372 | 213:"KM211 KMX8 8-bit processor", 373 | 214:"KM211 KVARC processor", 374 | 215:"Paneve CDP architecture family", 375 | 216:"Cognitive Smart Memory Processor", 376 | 217:"Bluechip Systems CoolEngine", 377 | 218:"Nanoradio Optimized RISC", 378 | 219:"CSR Kalimba architecture family", 379 | 220:"Zilog Z80", 380 | 221:"Controls and Data Services VISIUMcore processor", 381 | 222:"FTDI Chip FT32 high performance 32-bit RISC architecture", 382 | 223:"Moxie processor family", 383 | 224:"AMD GPU architecture", 384 | 243:"RISC-V", 385 | } 386 | 387 | 388 | def ELF_ST_BIND(i): 389 | return ((i) >> 4) 390 | 391 | 392 | def ELF_ST_TYPE(i): 393 | return ((i)&0x0f) 394 | 395 | 396 | def ELF_ST_INFO(b, t): 397 | return ((b)<<4 + ((t)&0x0f)) 398 | 399 | 400 | def ELF_ST_VISIBILITY(i): 401 | return ((i)&0x3) 402 | 403 | 404 | def readelf(elf): 405 | ''' 406 | #define EI_NIDENT 16 407 | typedef struct{ 408 | unsigned char e_ident[EI_NIDENT]; 409 | Elf32_Half e_type; 410 | Elf32_Half e_machine; 411 | Elf32_Word e_version; 412 | Elf32_Addr e_entry; 413 | Elf32_Off e_phoff; 414 | Elf32_Off e_shoff; 415 | Elf32_Word e_flags; 416 | Elf32_Half e_ehsize; 417 | Elf32_Half e_phentsize; 418 | Elf32_Half e_phnum; 419 | Elf32_Half e_shentsize; 420 | Elf32_Half e_shnum; 421 | Elf32_Half e_shstrndx; 422 | }Elf32_Ehdr; 423 | ''' 424 | e_type = e_class = 'dummpy' 425 | 426 | ei_ident = struct.unpack('16B', elf.read(16)) 427 | ei_mag0, ei_mag1,ei_mag2, ei_mag3, ei_class, ei_data, ei_version, ei_pad = ei_ident[:8] 428 | ei_nident = ei_ident[8:] 429 | if ei_mag0 != 0x7F and ei_mag1 != ord('E') and ei_mag2 != ord('L') and ei_mag3 != ord('F'): 430 | raise ELFError 431 | if ei_class == 0: 432 | raise ELFError('Invalid class') 433 | elif ei_class == 1: 434 | e_class = '32-bit objects' 435 | elif ei_class == 2: 436 | e_class = '64-bit objects' 437 | 438 | if ei_data == 0: 439 | raise ELFError('Invalid data encoding') 440 | elif ei_data == 1: 441 | e_data = 'ELFDATA2LSB' 442 | elif ei_data == 2: 443 | e_data = 'ELFDATA2MSB' 444 | 445 | ei_type = struct.unpack('H', elf.read(2))[0] 446 | if ei_type == 0: 447 | e_type = 'No file type' 448 | elif ei_type == 1: 449 | e_type = 'Relocatable file' 450 | elif ei_type == 2: 451 | e_type = 'Executable file' 452 | elif ei_type == 3: 453 | e_type = 'Shared object file' 454 | elif ei_type == 4: 455 | e_type = 'Core file' 456 | elif ei_type == 0xff00: 457 | e_type = 'Processor-specific' 458 | elif ei_type == 0xffff: 459 | e_type = 'Processor-specific' 460 | 461 | ei_machine = struct.unpack('H', elf.read(2))[0] 462 | if ei_machine in EI_MACHINE: 463 | e_machine = EI_MACHINE[ei_machine] 464 | else: 465 | e_machine = 'Unknow machine' 466 | 467 | ei_version = struct.unpack('I', elf.read(4))[0] 468 | if ei_version == 0: 469 | e_version = 'illegal version' 470 | else: 471 | e_version = str(ei_version) 472 | 473 | if ei_class == 1: 474 | ei_entry = struct.unpack('I', elf.read(4))[0] 475 | e_entry = ei_entry 476 | e_phoff, e_shoff, e_flags, e_ehsize, e_phentsize, e_phnum, e_shentsize, e_shnum, e_shstrndx = struct.unpack('IIIHHHHHH', elf.read(24)) 477 | else: 478 | ei_entry = struct.unpack('Q', elf.read(8))[0] 479 | e_entry = ei_entry 480 | e_phoff, e_shoff, e_flags, e_ehsize, e_phentsize, e_phnum, e_shentsize, e_shnum, e_shstrndx = struct.unpack('QQIHHHHHH', elf.read(32)) 481 | print("ELF Header:") 482 | print("Magic: %02x %02x %02x %02x %02x %02x %02x %02x" %(ei_mag0, ei_mag1, ei_mag2, ei_mag3, ei_class, ei_data, ei_version, ei_pad)) 483 | print("Class: %s" %(e_class)) 484 | print("Data: %s" %(e_data)) 485 | print("Type: %s" %(e_type)) 486 | print("Machine: %s" %(e_machine)) 487 | print("Version: %s" %(e_version)) 488 | print("Entry point address: 0x%x" %(e_entry)); 489 | print("Start of program headers: %d (bytes into file)" % e_phoff) 490 | print("Start of section headers: %d (bytes into file)" % e_shoff) 491 | print("Flags: 0x%02x" % e_flags) 492 | print("Size of this header: %d (bytes)" % e_ehsize) 493 | print("Size of program header: %d (bytes)" % e_phentsize) 494 | print("Number of program headers: %d" % e_shnum) 495 | print("Size of section headers: %d (bytes)" % e_shentsize) 496 | print("Number of section headers: %d" % e_shnum) 497 | print("Section header string table index: %d" % e_shstrndx) 498 | 499 | 500 | elf.seek(e_shoff + e_shentsize * e_shstrndx) 501 | if ei_class == 1: 502 | sh_name, sh_type, sh_flags, sh_addr, sh_offset, sh_size, sh_link, sh_info, sh_addralign, sh_entsize = struct.unpack('IIIHHIIIII', elf.read(48)) 503 | else: 504 | sh_name, sh_type, sh_flags, sh_addr, sh_offset, sh_size, sh_link, sh_info, sh_addralign, sh_entsize = struct.unpack('IIQQQQIIQQ', elf.read(64)) 505 | 506 | elf.seek(sh_offset) 507 | str_section = elf.read(sh_size) 508 | 509 | string_table = {} 510 | lastnull = 0 511 | for i, s in enumerate(str_section): 512 | if s == '\0': 513 | string_table[lastnull] = str_section[lastnull:i] 514 | lastnull = i + 1 515 | print("") 516 | print("Program Headers:") 517 | print("%10s 0x%10s 0x%14s 0x%14s 0x%10s 0x%10s %010s" %("Type", "Offset", "VirtAddr", "PhysAddr", "FileSiz", "MemSiz", "Flags")) 518 | 519 | 520 | e_shinterpndx = -1 521 | for i in range(0, e_phnum): 522 | elf.seek(e_phoff + e_phentsize * i) 523 | 524 | 525 | if ei_class == 1: 526 | p_type, p_offset, p_vaddr, p_paddr, p_filesz, p_memsz, p_flags, p_align = strcut.unpack('IIIIIIII', elf.read(32)) 527 | else: 528 | p_type, p_flags, p_offset, p_vaddr, p_paddr, p_filesz, p_memsz, p_align = struct.unpack('IIQQQQQQ', elf.read(56)) 529 | 530 | 531 | #INTERP 532 | if p_type == 3: 533 | e_shinterpndx = i 534 | 535 | 536 | print("%10s 0x%08x 0x%014x 0x%014x 0x%010x 0x%010x %010s" %( PT_TYPE[p_type] if p_type in PT_TYPE else p_type,p_offset, p_vaddr, p_paddr, p_filesz, p_memsz, PT_FLAGS[p_flags])) 537 | 538 | if e_shinterpndx >= 0: 539 | elf.seek(e_phoff + e_phentsize * e_shinterpndx) 540 | if ei_class == 1: 541 | p_type, p_offset, p_vaddr, p_paddr, p_filesz, p_memsz, p_flags, p_align = strcut.unpack('IIIIIIII', elf.read(32)) 542 | else: 543 | p_type, p_flags, p_offset, p_vaddr, p_paddr, p_filesz, p_memsz, p_align = struct.unpack('IIQQQQQQ', elf.read(56)) 544 | elf.seek(p_offset) 545 | interp = elf.read(p_filesz) 546 | print("") 547 | print("Interp:") 548 | print(interp) 549 | 550 | e_shsymndx = -1 551 | e_shstrndx = -1 552 | e_shdynsym = -1 553 | e_shdynstr = -1 554 | e_shdynamic = -1 555 | 556 | print("") 557 | print("Section Headers:") 558 | print("[NR] %20s%10s%15s%10s%8s%8s%5s%5s%5s%6s" % ("Name", "Type", "Address", "Offset", "Size", "EntSize", "Flag", "Link", "Info", "Align")) 559 | for i in range(0, e_shnum): 560 | elf.seek(e_shoff + e_shentsize * i) 561 | 562 | if ei_class == 1: 563 | sh_name, sh_type, sh_flags, sh_addr, sh_offset, sh_size, sh_link, sh_info, sh_addralign, sh_entsize = struct.unpack('IIIHHIIIII', elf.read(48)) 564 | else: 565 | sh_name, sh_type, sh_flags, sh_addr, sh_offset, sh_size, sh_link, sh_info, sh_addralign, sh_entsize = struct.unpack('IIQQQQIIQQ', elf.read(64)) 566 | 567 | f = "" 568 | if sh_flags & SHF_WRITE: 569 | f += "W" 570 | if sh_flags & SHF_ALLOC: 571 | f += "A" 572 | if sh_flags & SHF_EXECINSTR: 573 | f += "X" 574 | if sh_flags & SHF_MASKPROC: 575 | f += "M" 576 | 577 | if sh_name in string_table: 578 | print("[%02d]%20s%15s%10x%10d%8d%8d%5s%5s%5s%6s" % (i, string_table[sh_name], SH_TYPE[sh_type] if sh_type in SH_TYPE else sh_type, sh_addr, sh_offset, sh_size, sh_entsize, f, sh_link, sh_info, sh_addralign)) 579 | 580 | if string_table[sh_name] == '.symtab': 581 | e_shsymndx = i 582 | 583 | if string_table[sh_name] == '.strtab': 584 | e_shstrndx = i 585 | 586 | if string_table[sh_name] == '.dynsym': 587 | e_shdynsym = i 588 | 589 | if string_table[sh_name] == '.dynstr': 590 | e_shdynstr = i 591 | 592 | if string_table[sh_name] == '.dynamic': 593 | e_shdynamic = i 594 | 595 | else: 596 | print("[%02d]%20s%15s%10x%10d%8d%8d%5s%5s%5s%6s" % (i, sh_name, SH_TYPE[sh_type] if sh_type in SH_TYPE else sh_type, sh_addr, sh_offset, sh_size, sh_entsize, f, sh_link, sh_info, sh_addralign)) 597 | 598 | 599 | if e_shdynsym >= 0 and e_shdynstr >= 0: 600 | elf.seek(e_shoff + e_shentsize * e_shdynstr) 601 | if ei_class == 1: 602 | sh_name, sh_type, sh_flags, sh_addr, sh_offset, sh_size, sh_link, sh_info, sh_addralign, sh_entsize = struct.unpack('IIIHHIIIII', elf.read(48)) 603 | else: 604 | sh_name, sh_type, sh_flags, sh_addr, sh_offset, sh_size, sh_link, sh_info, sh_addralign, sh_entsize = struct.unpack('IIQQQQIIQQ', elf.read(64)) 605 | 606 | elf.seek(sh_offset) 607 | dynsym_section = elf.read(sh_size) 608 | dynsymbol_table = {} 609 | lastnull = 0 610 | for i, s in enumerate(dynsym_section): 611 | if s == '\0': 612 | dynsymbol_table[lastnull] = dynsym_section[lastnull:i] 613 | lastnull = i + 1 614 | 615 | elf.seek(e_shoff + e_shentsize * e_shdynsym) 616 | 617 | if ei_class == 1: 618 | sh_name, sh_type, sh_flags, sh_addr, sh_offset, sh_size, sh_link, sh_info, sh_addralign, sh_entsize = struct.unpack('IIIHHIIIII', elf.read(48)) 619 | else: 620 | sh_name, sh_type, sh_flags, sh_addr, sh_offset, sh_size, sh_link, sh_info, sh_addralign, sh_entsize = struct.unpack('IIQQQQIIQQ', elf.read(64)) 621 | 622 | elf.seek(sh_offset) 623 | dynsym_section = elf.read(sh_size) 624 | 625 | print("") 626 | if ei_class == 1: 627 | print("Symbol table '.dynsym' contains %d entries:" % (sh_size / 16)) 628 | else: 629 | print("Symbol table '.dynsym' contains %d entries:" % (sh_size / 24)) 630 | print("%04s%10s%10s%10s%10s%10s%10s%30s" %("Num", "Value", "Size", "Type", "Bind", "Vis", "Ndx", "Name")) 631 | 632 | for i in range(0, sh_size / 24): 633 | if ei_class == 1: 634 | st_name, st_info, st_other, st_shndx, st_value, st_size = struct.unpack('IIIBBH', dynsym_section[i*16:(i+1)*16]) 635 | else: 636 | st_name, st_info, st_other, st_shndx, st_value, st_size = struct.unpack('IBBHQQ', dynsym_section[i*24:(i+1)*24]) 637 | 638 | if st_name in dynsymbol_table: 639 | print("%04d%10d%10d%10s%10s%10s%10d%30s" %(i, st_value, st_size, STT_TYPE[ELF_ST_TYPE(st_info)], 640 | STB_BIND[ELF_ST_BIND(st_info)], STV_VISIBILITY[ELF_ST_VISIBILITY(st_other)], st_shndx, dynsymbol_table[st_name],)) 641 | else: 642 | print("%04d%10d%10d%10s%10s%10s%10d%30d" %(i, st_value, st_size, STT_TYPE[ELF_ST_TYPE(st_info)], 643 | STB_BIND[ELF_ST_BIND(st_info)], STV_VISIBILITY[ELF_ST_VISIBILITY(st_other)], st_shndx, st_name,)) 644 | 645 | 646 | if e_shsymndx >= 0 and e_shstrndx >= 0: 647 | elf.seek(e_shoff + e_shentsize * e_shstrndx) 648 | if ei_class == 1: 649 | sh_name, sh_type, sh_flags, sh_addr, sh_offset, sh_size, sh_link, sh_info, sh_addralign, sh_entsize = struct.unpack('IIIHHIIIII', elf.read(48)) 650 | else: 651 | sh_name, sh_type, sh_flags, sh_addr, sh_offset, sh_size, sh_link, sh_info, sh_addralign, sh_entsize = struct.unpack('IIQQQQIIQQ', elf.read(64)) 652 | 653 | elf.seek(sh_offset) 654 | sym_section = elf.read(sh_size) 655 | lastnull = 0 656 | symbol_table = {} 657 | for i, s in enumerate(sym_section): 658 | if s == '\0': 659 | symbol_table[lastnull] = sym_section[lastnull:i] 660 | lastnull = i + 1 661 | 662 | elf.seek(e_shoff + e_shentsize * e_shsymndx) 663 | 664 | if ei_class == 1: 665 | sh_name, sh_type, sh_flags, sh_addr, sh_offset, sh_size, sh_link, sh_info, sh_addralign, sh_entsize = struct.unpack('IIIHHIIIII', elf.read(48)) 666 | else: 667 | sh_name, sh_type, sh_flags, sh_addr, sh_offset, sh_size, sh_link, sh_info, sh_addralign, sh_entsize = struct.unpack('IIQQQQIIQQ', elf.read(64)) 668 | 669 | elf.seek(sh_offset) 670 | sym_section = elf.read(sh_size) 671 | 672 | print("") 673 | if ei_class == 1: 674 | print("Symbol table '.symtab' contains %d entries:" % (sh_size / 16)) 675 | else: 676 | print("Symbol table '.symtab' contains %d entries:" % (sh_size / 24)) 677 | print("%04s%10s%10s%10s%10s%10s%10s%30s" %("Num", "Value", "Size", "Type", "Bind", "Vis", "Ndx", "Name")) 678 | 679 | for i in range(0, sh_size / 24): 680 | if ei_class == 1: 681 | st_name, st_info, st_other, st_shndx, st_value, st_size = struct.unpack('IIIBBH', sym_section[i*16:(i+1)*16]) 682 | else: 683 | st_name, st_info, st_other, st_shndx, st_value, st_size = struct.unpack('IBBHQQ', sym_section[i*24:(i+1)*24]) 684 | 685 | if st_name in symbol_table: 686 | print("%04d%10d%10d%10s%10s%10s%10d%30s" %(i, st_value, st_size, STT_TYPE[ELF_ST_TYPE(st_info)], 687 | STB_BIND[ELF_ST_BIND(st_info)], STV_VISIBILITY[ELF_ST_VISIBILITY(st_other)], st_shndx, symbol_table[st_name],)) 688 | else: 689 | print("%04d%10d%10d%10s%10s%10s%10d%30d" %(i, st_value, st_size, STT_TYPE[ELF_ST_TYPE(st_info)], 690 | STB_BIND[ELF_ST_BIND(st_info)], STV_VISIBILITY[ELF_ST_VISIBILITY(st_other)], st_shndx, st_name,)) 691 | 692 | if e_shdynamic >= 0: 693 | elf.seek(e_shoff + e_shentsize * e_shdynamic) 694 | if ei_class == 1: 695 | sh_name, sh_type, sh_flags, sh_addr, sh_offset, sh_size, sh_link, sh_info, sh_addralign, sh_entsize = struct.unpack('IIIHHIIIII', elf.read(48)) 696 | else: 697 | sh_name, sh_type, sh_flags, sh_addr, sh_offset, sh_size, sh_link, sh_info, sh_addralign, sh_entsize = struct.unpack('IIQQQQIIQQ', elf.read(64)) 698 | 699 | elf.seek(sh_offset) 700 | dynamic_section = elf.read(sh_size) 701 | print('') 702 | print('Dynamic section:') 703 | print('%20s %20s %20s' %("Tag", "Type", "Name/Value")) 704 | if ei_class == 1: 705 | pass 706 | else: 707 | for i in range(0, sh_size/16): 708 | elf.seek(sh_offset + i * 16) 709 | d_tag, d_un = struct.unpack('QQ', elf.read(16)) 710 | if d_tag in TAG: 711 | if d_tag == 1 or d_tag == 15: 712 | print('0x%018x %20s %20s' %(d_tag, TAG[d_tag], dynsymbol_table[d_un])) 713 | else: 714 | print('0x%018x %20s %20s' %(d_tag, TAG[d_tag], d_un)) 715 | else: 716 | if d_tag == 1 or d_tag == 15: 717 | print('0x%018x %20s %20s' %(d_tag, d_tag, dynsymbol_table[d_un])) 718 | else: 719 | print('0x%018x %20s %20s' %(d_tag, d_tag, d_un)) 720 | 721 | return 722 | 723 | 724 | if __name__ == '__main__': 725 | if len(sys.argv) != 2: 726 | print("Usage: readelf /path/to/file") 727 | sys.exit(1) 728 | 729 | with open(sys.argv[1], 'r') as elf: 730 | readelf(elf) 731 | 732 | --------------------------------------------------------------------------------