1# coding=utf-8
2# Copyright 2018 Sascha Schirra
3#
4# Redistribution and use in source and binary forms, with or without
5# modification, are permitted provided that the following conditions are met:
6#
7# 1. Redistributions of source code must retain the above copyright notice, this
8# list of conditions and the following disclaimer.
9#
10# 2. Redistributions in binary form must reproduce the above copyright notice,
11# this list of conditions and the following disclaimer in the documentation
12# and/or other materials provided with the distribution.
13#
14# 3. Neither the name of the copyright holder nor the names of its contributors
15# may be used to endorse or promote products derived from this software without
16# specific prior written permission.
17#
18# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" A ND
19# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
22# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
25# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
26# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
29
30from .enum import Enum
31from .binary import *
32
33####################### Constants ############################
34
35class ET(Enum):
36    NONE = 0x0
37    REL = 0x1
38    EXEC = 0x2
39    DYN = 0x3
40    CORE = 0x4
41    LOOS = 0xfe00
42    HIOS = 0xfeff
43    LOPROC = 0xff00
44    HIPROC = 0xffff
45
46
47class EM(Enum):
48    NONE = 0  # No machine
49    M32 = 1  # AT&T WE 32100
50    SPARC = 2  # SPARC
51    INTEL_386 = 3  # Intel 80386
52    MOTOROLA_68k = 4  # Motorola 68000
53    MOTOROLA_88K = 5  # Motorola 88000
54    INTEL_80860 = 7  # Intel 80860
55    MIPS = 8  # MIPS RS3000
56    S370 = 9
57    MIPS_RS3_LE = 10
58
59    PARISC = 15
60    VPP500 = 17
61    SPARC32PLUS = 18
62    INTEL_80960 = 19
63    PPC = 20
64    PPC64 = 21
65    S390 = 22
66
67    V800 = 36
68    FR20 = 37
69    RH32 = 38
70    RCE = 39
71    ARM = 40
72    FAKE_ALPHA = 41
73    SH = 42
74    SPARCV9 = 43
75    TRICORE = 44
76    ARC = 45
77    H8_300 = 46
78    H8_300H = 47
79    H8S = 48
80    H8_500 = 49
81    IA_64 = 50
82    MIPS_X = 51
83    COLDFIRE = 52
84    MOTOROLA_68HC12 = 53
85    MMA = 54
86    PCP = 55
87    NCPU = 56
88    NDR1 = 57
89    STARCORE = 58
90    ME16 = 59
91    ST100 = 60
92    TINYJ = 61
93    X86_64 = 62
94    FX66 = 66
95    ST9PLUS = 67
96    ST7 = 68
97    MOTOROLA_68HC16 = 69
98    MOTOROLA_68HC11 = 70
99    MOTOROLA_68HC08 = 71
100    MOTOROLA_68HC05 = 72
101    SVX = 73
102    ST19 = 74
103    VAX = 75
104    CRIS = 76
105    JAVELIN = 77
106    FIREPATH = 78
107    ZSP = 79
108    MMIX = 80
109    HUANY = 81
110    PRISM = 82
111    AVR = 83
112    FR30 = 84
113    D10V = 85
114    D30V = 86
115    V850 = 87
116    M32R = 88
117    MN10300 = 89
118    MN10200 = 90
119    PJ = 91
120    OPENRISC = 92
121    ARC_A5 = 93
122    XTENSA = 94
123    NUM = 95
124    ARM64 = 183
125
126
127class EI(Enum):
128    MAG0 = 0x0
129    MAG1 = 0x1
130    MAG2 = 0x2
131    MAG3 = 0x3
132    CLASS = 0x4
133    DATA = 0x5
134    VERSION = 0x6
135    OSABI = 0x7
136    ABIVERSION = 0x8
137    PAD = 0x9
138    NIDENT = 0xf
139
140
141class ELFOSABI(Enum):
142    SYSV = 0
143    HPUX = 1
144    STANDALONE = 255
145
146
147class ELFCLASS(Enum):
148    NONE = 0
149    BITS_32 = 1
150    BITS_64 = 2
151
152
153class ELFDATA(Enum):
154    NONE = 0
155    LSB = 1
156    MSB = 2
157
158
159class SHN(Enum):
160    UNDEF = 0
161    LOPROC = 0xff00
162    HIPROC = 0xff1f
163    LOOS = 0xff20
164    HIOS = 0xff3f
165    ABS = 0xfff1
166    COMMON = 0xfff2
167    HIRESERVE = 0xffff
168
169class SHF(Enum):
170    WRITE = 0x1
171    ALLOC = 0x2
172    EXECINSTR = 0x4
173    MASKPROC = 0xf0000000
174
175
176class SHT(Enum):
177    NULL = 0x0
178    PROGBITS = 0x1
179    SYMTAB = 0x2
180    STRTAB = 0x3
181    RELA = 0x4
182    HASH = 0x5
183    DYNAMIC = 0x6
184    NOTE = 0x7
185    NOBITS = 0x8
186    REL = 0x9
187    SHLIB = 0xa
188    DYNSYM = 0xb
189    INIT_ARRAY = 0xe
190    FINI_ARRAY = 0xf
191    PREINIT_ARRAY = 0x10
192    GROUP = 0x11
193    SYMTAB_SHNDX = 0x12
194    NUM = 0x13
195    LOOS = 0x60000000
196    GNU_HASH = 0x6ffffff6
197    GNU_LIBLIST = 0x6ffffff7
198    CHECKSUM = 0x6ffffff8
199    LOSUNW = 0x6ffffffa
200    SUNW_COMDAT = 0x6ffffffb
201    SUNW_syminfo = 0x6ffffffc
202    GNU_verdef = 0x6ffffffd
203    GNU_verneed = 0x6ffffffe
204    HIOS = 0x6fffffff
205    LOPROC = 0x70000000
206    HIPROC = 0x7fffffff
207    LOUSER = 0x80000000
208    HIUSER = 0x8fffffff
209
210
211class STT(Enum):
212    NOTYPE = 0
213    OBJECT = 1
214    FUNC = 2
215    SECTION = 3
216    FILE = 4
217    COMMON = 5
218    TLS = 6
219    NUM = 7
220    LOOS = 10
221    HIOS = 12
222    LOPROC = 13
223    HIPROC = 15
224
225
226class STB(Enum):
227
228    LOCAL = 0
229    GLOBAL = 1
230    WEAK = 2
231    NUM = 3
232    LOOS = 10
233    HIOS = 12
234    LOPROC = 13
235    HIPROC = 15
236
237class STV(Enum):
238    DEFAULT = 0
239    INTERNAL = 1
240    HIDDEN = 2
241    PROTECTED = 3
242    EXPORTED = 4
243    SINGLETON = 5
244    ELIMINATE = 6
245
246
247
248class PT(Enum):
249    NULL = 0
250    LOAD = 1
251    DYNAMIC = 2
252    INTERP = 3
253    NOTE = 4
254    SHLIB = 5
255    PHDR = 6
256    TLS = 7
257    NUM = 8
258    LOPROC = 0x70000000
259    HIPROC = 0x7fffffff
260
261    GNU_EH_FRAME = 0x6474e550
262    GNU_STACK = 0x6474e551
263    GNU_RELRO = 0x6474e552
264
265
266class R_386(Enum):
267    NONE = 0
268    R_32 = 1
269    PC32 = 2
270    GOT32 = 3
271    PLT32 = 4
272    COPY = 5
273    GLOB_DAT = 6
274    JMP_SLOT = 7
275    RELATIVE = 8
276    GOTOFF = 9
277    GOTPC = 10
278
279    TLS_TPOFF = 14
280    TLS_IE = 15
281    TLS_GOTIE = 16
282    TLS_LE = 17
283    TLS_GD = 18
284    TLS_LDM = 19
285    R16 = 20
286    PC16 = 21
287    R8 = 22
288    PC8 = 23
289    TLS_GD_32 = 24
290    TLS_GD_PUSH = 25
291    TLS_GD_CALL = 26
292    TLS_GD_POP = 27
293    TLS_LDM_32 = 28
294    TLS_LDM_PUSH = 29
295    TLS_LDM_CALL = 30
296    TLS_LDM_POP = 31
297    TLS_LDO_32 = 32
298    TLS_IE_32 = 33
299    TLS_LE_32 = 34
300    TLS_DTPMOD32 = 35
301    TLS_DTPOFF32 = 36
302    TLS_TPOFF32 = 37
303    NUM = 38
304
305
306class PF(Enum):
307
308    READ = 4
309    WRITE = 2
310    EXEC = 1
311
312    def shortString(self, perm):
313        toReturn = ''
314        toReturn += 'R' if perm & int(self.READ) > 0 else ' '
315        toReturn += 'W' if perm & int(self.WRITE) > 0 else ' '
316        toReturn += 'E' if perm & int(self.EXEC) > 0 else ' '
317
318        return toReturn
319
320class DT(Enum):
321    NULL = 0
322    NEEDED = 1
323    PLTRELSZ = 2
324    PLTGOT = 3
325    HASH = 4
326    STRTAB = 5
327    SYMTAB = 6
328    RELA = 7
329    RELASZ = 8
330    RELAENT = 9
331    STRSZ = 10
332    SYMENT = 11
333    INIT = 12
334    FINI = 13
335    SONAME = 14
336    RPATH = 15
337    SYMBOLIC = 16
338    REL = 17
339    RELSZ = 18
340    RELENT = 19
341    PLTREL = 20
342    DEBUG = 21
343    TEXTREL = 22
344    JMPREL = 23
345    BIND_NOW = 24
346    INIT_ARRAY = 25
347    FINI_ARRAY = 26
348    INIT_ARRAYSZ = 27
349    FINI_ARRAYSZ = 28
350    RUNPATH = 29
351    FLAGS = 30
352    ENCODING = 31
353    PREINIT_ARRAY = 32
354    PREINIT_ARRAYSZ = 33
355    MAXPOSTAGS = 34
356    LOOS = 0x6000000d
357    #SUNW_AUXILIARY = 0x6000000d
358    SUNW_RTLDINF = 0x6000000e
359    #SUNW_FILTER = 0x6000000e
360    SUNW_CAP = 0x60000010
361    SUNW_SYMTAB = 0x60000011
362    SUNW_SYMSZ = 0x60000012
363    SUNW_ENCODING = 0x60000013
364    #SUNW_SORTENT = 0x60000013
365    SUNW_SYMSORT = 0x60000014
366    SUNW_SYMSORTSZ = 0x60000015
367    SUNW_TLSSORT = 0x60000016
368    SUNW_TLSSORTSZ = 0x60000017
369    SUNW_CAPINFO = 0x60000018
370    SUNW_STRPAD = 0x60000019
371    SUNW_CAPCHAIN = 0x6000001a
372    SUNW_LDMACH = 0x6000001b
373    SUNW_CAPCHAINENT = 0x6000001d
374    SUNW_CAPCHAINSZ = 0x6000001f
375    HIOS = 0x6ffff000
376    VALRNGLO = 0x6ffffd00
377    CHECKSUM = 0x6ffffdf8
378    PLTPADSZ = 0x6ffffdf9
379    MOVEENT = 0x6ffffdfa
380    MOVESZ = 0x6ffffdfb
381    POSFLAG_1 = 0x6ffffdfd
382    SYMINSZ = 0x6ffffdfe
383    SYMINENT = 0x6ffffdff
384    #VALRNGHI = 0x6ffffdff
385    ADDRRNGLO = 0x6ffffe00
386    GNU_HASH = 0x6ffffef5
387    TLSDESC_PLT = 0x6ffffef6
388    TLSDESC_GOT  = 0x6ffffef7
389    GNU_CONFLICT = 0x6ffffef8
390    GNU_LIBLIST = 0x6ffffef9
391    CONFIG = 0x6ffffefa
392    DEPAUDIT = 0x6ffffefb
393    AUDIT = 0x6ffffefc
394    PLTPAD = 0x6ffffefd
395    MOVETAB = 0x6ffffefe
396    SYMINFO = 0x6ffffeff
397    #ADDRRNGHI = 0x6ffffeff
398    VERSYM = 0x6ffffff0
399    RELACOUNT = 0x6ffffff9
400    RELCOUNT = 0x6ffffffa
401    FLAGS_1 = 0x6ffffffb
402    VERDEF = 0x6ffffffc
403    VERDEFNUM = 0x6ffffffd
404    VERNEED = 0x6ffffffe
405    VERNEEDNUM = 0x6fffffff
406    LOPROC = 0x70000000
407    SPARC_REGISTER = 0x70000001
408    AUXILIARY = 0x7ffffffd
409    USED = 0x7ffffffe
410    #FILTER = 0x7fffffff
411    HIPROC = 0x7fffffff
412
413########################### LSB 32 BIT Structures ###########################
414
415LSB_32_R_SYM = lambda i: i >> 8
416LSB_32_R_TYPE = lambda i: i & 0xff
417
418
419class LSB_32_EHDR(LittleEndianStructure):
420    _fields_ = [('e_ident', c_ubyte * 16),
421                ('e_type', c_ushort),
422                ('e_machine', c_ushort),
423                ('e_version', c_uint),
424                ('e_entry', c_uint),
425                ('e_phoff', c_uint),
426                ('e_shoff', c_uint),
427                ('e_flags', c_uint),
428                ('e_ehsize', c_ushort),
429                ('e_phentsize', c_ushort),
430                ('e_phnum', c_ushort),
431                ('e_shentsize', c_ushort),
432                ('e_shnum', c_ushort),
433                ('e_shstrndx', c_ushort)]
434
435
436class LSB_32_SHDR(LittleEndianStructure):
437    _fields_ = [('sh_name', c_uint),
438                ('sh_type', c_uint),
439                ('sh_flags', c_uint),
440                ('sh_addr', c_uint),
441                ('sh_offset', c_uint),
442                ('sh_size', c_uint),
443                ('sh_link', c_uint),
444                ('sh_info', c_uint),
445                ('sh_addralign', c_uint),
446                ('sh_entsize', c_uint)
447                ]
448
449
450class LSB_32_SYM(LittleEndianStructure):
451    _fields_ = [('st_name', c_uint),
452                ('st_value', c_uint),
453                ('st_size', c_uint),
454                ('st_info', c_ubyte),
455                ('st_other', c_ubyte),
456                ('st_shndx', c_ushort)
457                ]
458
459
460class LSB_32_REL(LittleEndianStructure):
461    _fields_ = [('r_offset', c_uint),
462                ('r_info', c_uint)]
463
464
465class LSB_32_RELA(LittleEndianStructure):
466    _fields_ = [('r_offset', c_uint),
467                ('r_info', c_uint),
468                ('r_addend', c_int)
469                ]
470
471
472class LSB_32_PHDR(LittleEndianStructure):
473    _fields_ = [('p_type', c_uint),
474                ('p_offset', c_uint),
475                ('p_vaddr', c_uint),
476                ('p_paddr', c_uint),
477                ('p_filesz', c_uint),
478                ('p_memsz', c_uint),
479                ('p_flags', c_uint),
480                ('p_align', c_uint)
481                ]
482
483class LSB_32_DYN(LittleEndianStructure):
484    _fields_ = [('d_tag', c_uint),
485                ('d_un', c_uint)
486                ]
487
488class LSB_32():
489    PHDR = LSB_32_PHDR
490    EHDR = LSB_32_EHDR
491    SHDR = LSB_32_SHDR
492    REL = LSB_32_REL
493    RELA = LSB_32_RELA
494    SYM = LSB_32_SYM
495    DYN = LSB_32_DYN
496    R_SYM = staticmethod(LSB_32_R_SYM)
497    R_TYPE = staticmethod(LSB_32_R_TYPE)
498
499########################### MSB 32 BIT Structures ###########################
500
501MSB_32_R_SYM = lambda i: i >> 8
502MSB_32_R_TYPE = lambda i: i & 0xff
503
504
505class MSB_32_EHDR(BigEndianStructure):
506    _fields_ = [('e_ident', c_ubyte * 16),
507                ('e_type', c_ushort),
508                ('e_machine', c_ushort),
509                ('e_version', c_uint),
510                ('e_entry', c_uint),
511                ('e_phoff', c_uint),
512                ('e_shoff', c_uint),
513                ('e_flags', c_uint),
514                ('e_ehsize', c_ushort),
515                ('e_phentsize', c_ushort),
516                ('e_phnum', c_ushort),
517                ('e_shentsize', c_ushort),
518                ('e_shnum', c_ushort),
519                ('e_shstrndx', c_ushort)]
520
521
522class MSB_32_SHDR(BigEndianStructure):
523    _fields_ = [('sh_name', c_uint),
524                ('sh_type', c_uint),
525                ('sh_flags', c_uint),
526                ('sh_addr', c_uint),
527                ('sh_offset', c_uint),
528                ('sh_size', c_uint),
529                ('sh_link', c_uint),
530                ('sh_info', c_uint),
531                ('sh_addralign', c_uint),
532                ('sh_entsize', c_uint)
533                ]
534
535
536class MSB_32_SYM(BigEndianStructure):
537    _fields_ = [('st_name', c_uint),
538                ('st_value', c_uint),
539                ('st_size', c_uint),
540                ('st_info', c_ubyte),
541                ('st_other', c_ubyte),
542                ('st_shndx', c_ushort)
543                ]
544
545
546class MSB_32_REL(BigEndianStructure):
547    _fields_ = [('r_offset', c_uint),
548                ('r_info', c_uint)]
549
550
551class MSB_32_RELA(BigEndianStructure):
552    _fields_ = [('r_offset', c_uint),
553                ('r_info', c_uint),
554                ('r_addend', c_int)
555                ]
556
557
558class MSB_32_PHDR(BigEndianStructure):
559    _fields_ = [('p_type', c_uint),
560                ('p_offset', c_uint),
561                ('p_vaddr', c_uint),
562                ('p_paddr', c_uint),
563                ('p_filesz', c_uint),
564                ('p_memsz', c_uint),
565                ('p_flags', c_uint),
566                ('p_align', c_uint)
567                ]
568
569class MSB_32_DYN(BigEndianStructure):
570    _fields_ = [('d_tag', c_uint),
571                ('d_un', c_uint)
572                ]
573
574class MSB_32():
575    PHDR = MSB_32_PHDR
576    EHDR = MSB_32_EHDR
577    SHDR = MSB_32_SHDR
578    REL = MSB_32_REL
579    RELA = MSB_32_RELA
580    SYM = MSB_32_SYM
581    DYN = MSB_32_DYN
582    R_SYM = staticmethod(MSB_32_R_SYM)
583    R_TYPE = staticmethod(MSB_32_R_TYPE)
584
585########################### 64 BIT Types ###########################
586
587Elf64_Addr = c_ulonglong
588Elf64_Off = c_ulonglong
589Elf64_Half = c_ushort
590Elf64_Word = c_uint
591Elf64_Sword = c_int
592Elf64_Xword = c_ulonglong
593Elf64_Sxword = c_longlong
594uchar = c_ubyte
595
596########################### LSB 64 BIT Structures ###########################
597
598LSB_64_R_SYM = lambda i: i >> 32
599LSB_64_R_TYPE = lambda i: i & 0xffffffff
600
601
602class LSB_64_EHDR(LittleEndianStructure):
603    _fields_ = [('e_ident', uchar * 16),
604                ('e_type', Elf64_Half),
605                ('e_machine', Elf64_Half),
606                ('e_version', Elf64_Word),
607                ('e_entry', Elf64_Addr),
608                ('e_phoff', Elf64_Off),
609                ('e_shoff', Elf64_Off),
610                ('e_flags', Elf64_Word),
611                ('e_ehsize', Elf64_Half),
612                ('e_phentsize', Elf64_Half),
613                ('e_phnum', Elf64_Half),
614                ('e_shentsize', Elf64_Half),
615                ('e_shnum', Elf64_Half),
616                ('e_shstrndx', Elf64_Half)
617                ]
618
619
620class LSB_64_SHDR(LittleEndianStructure):
621    _fields_ = [('sh_name', Elf64_Word),
622                ('sh_type', Elf64_Word),
623                ('sh_flags', Elf64_Xword),
624                ('sh_addr', Elf64_Addr),
625                ('sh_offset', Elf64_Off),
626                ('sh_size', Elf64_Xword),
627                ('sh_link', Elf64_Word),
628                ('sh_info', Elf64_Word),
629                ('sh_addralign', Elf64_Xword),
630                ('sh_entsize', Elf64_Xword)
631                ]
632
633
634class LSB_64_SYM(LittleEndianStructure):
635    _fields_ = [('st_name', Elf64_Word),
636                ('st_info', uchar),
637                ('st_other', uchar),
638                ('st_shndx', Elf64_Half),
639                ('st_value', Elf64_Addr),
640                ('st_size', Elf64_Xword)
641                ]
642
643
644class LSB_64_REL(LittleEndianStructure):
645    _fields_ = [('r_offset', Elf64_Addr),
646                ('r_info', Elf64_Xword)]
647
648
649class LSB_64_RELA(LittleEndianStructure):
650    _fields_ = [('r_offset', Elf64_Addr),
651                ('r_info', Elf64_Xword),
652                ('r_addend', Elf64_Sxword)
653                ]
654
655
656class LSB_64_PHDR(LittleEndianStructure):
657    _fields_ = [('p_type', Elf64_Word),
658                ('p_flags', Elf64_Word),
659                ('p_offset', Elf64_Off),
660                ('p_vaddr', Elf64_Addr),
661                ('p_paddr', Elf64_Addr),
662                ('p_filesz', Elf64_Xword),
663                ('p_memsz', Elf64_Xword),
664                ('p_align', Elf64_Xword)
665                ]
666
667class LSB_64_DYN(LittleEndianStructure):
668    _fields_ = [('d_tag', Elf64_Xword),
669                ('d_un', Elf64_Xword)
670                ]
671
672class LSB_64():
673    PHDR = LSB_64_PHDR
674    EHDR = LSB_64_EHDR
675    SHDR = LSB_64_SHDR
676    REL = LSB_64_REL
677    RELA = LSB_64_RELA
678    SYM = LSB_64_SYM
679    DYN = LSB_64_DYN
680    R_SYM = staticmethod(LSB_64_R_SYM)
681    R_TYPE = staticmethod(LSB_64_R_TYPE)
682
683########################### MSB 64 BIT Structures ###########################
684
685MSB_64_R_SYM = lambda i: i >> 32
686MSB_64_R_TYPE = lambda i: i & 0xffffffff
687
688
689class MSB_64_EHDR(BigEndianStructure):
690    _fields_ = [('e_ident', uchar * 16),
691                ('e_type', Elf64_Half),
692                ('e_machine', Elf64_Half),
693                ('e_version', Elf64_Word),
694                ('e_entry', Elf64_Addr),
695                ('e_phoff', Elf64_Off),
696                ('e_shoff', Elf64_Off),
697                ('e_flags', Elf64_Word),
698                ('e_ehsize', Elf64_Half),
699                ('e_phentsize', Elf64_Half),
700                ('e_phnum', Elf64_Half),
701                ('e_shentsize', Elf64_Half),
702                ('e_shnum', Elf64_Half),
703                ('e_shstrndx', Elf64_Half)
704                ]
705
706
707class MSB_64_SHDR(BigEndianStructure):
708    _fields_ = [('sh_name', Elf64_Word),
709                ('sh_type', Elf64_Word),
710                ('sh_flags', Elf64_Xword),
711                ('sh_addr', Elf64_Addr),
712                ('sh_offset', Elf64_Off),
713                ('sh_size', Elf64_Xword),
714                ('sh_link', Elf64_Word),
715                ('sh_info', Elf64_Word),
716                ('sh_addralign', Elf64_Xword),
717                ('sh_entsize', Elf64_Xword)
718                ]
719
720
721class MSB_64_SYM(BigEndianStructure):
722    _fields_ = [('st_name', Elf64_Word),
723                ('st_info', uchar),
724                ('st_other', uchar),
725                ('st_shndx', Elf64_Half),
726                ('st_value', Elf64_Addr),
727                ('st_size', Elf64_Xword)
728                ]
729
730
731class MSB_64_REL(BigEndianStructure):
732    _fields_ = [('r_offset', Elf64_Addr),
733                ('r_info', Elf64_Xword)]
734
735
736class MSB_64_RELA(BigEndianStructure):
737    _fields_ = [('r_offset', Elf64_Addr),
738                ('r_info', Elf64_Xword),
739                ('r_addend', Elf64_Sxword)
740                ]
741
742
743class MSB_64_PHDR(BigEndianStructure):
744    _fields_ = [('p_type', Elf64_Word),
745                ('p_flags', Elf64_Word),
746                ('p_offset', Elf64_Off),
747                ('p_vaddr', Elf64_Addr),
748                ('p_paddr', Elf64_Addr),
749                ('p_filesz', Elf64_Xword),
750                ('p_memsz', Elf64_Xword),
751                ('p_align', Elf64_Xword)
752                ]
753
754class MSB_64_DYN(BigEndianStructure):
755    _fields_ = [('d_tag', Elf64_Xword),
756                ('d_un', Elf64_Xword)
757                ]
758
759class MSB_64():
760    PHDR = MSB_64_PHDR
761    EHDR = MSB_64_EHDR
762    SHDR = MSB_64_SHDR
763    REL = MSB_64_REL
764    RELA = MSB_64_RELA
765    SYM = MSB_64_SYM
766    DYN = MSB_64_DYN
767    R_SYM = staticmethod(MSB_64_R_SYM)
768    R_TYPE = staticmethod(MSB_64_R_TYPE)
769
770################################ ELF File Implementation #########################################
771
772class EhdrData(Container):
773    """
774    header = SectionHeader
775    """
776
777class ShdrData(Container):
778
779    """
780    header = SectionHeader
781    name = string (section name)
782    bytes = bytearray (section bytes)
783    raw = c_ubyte_array
784
785    .dynamic
786    content = List of DYN entries
787
788    .rel & .rela
789    relocations = list of REL or RELA
790
791    .dynsym & .symtab
792    symbols = list of SYM entries
793    """
794
795
796class PhdrData(Container):
797
798    """
799    type = Programm Header Type
800    header = ProgrammHeader
801    bytes = bytearray (section bytes)
802    raw = c_ubyte_array
803    vaddr = virtual address (int)
804    offset = offset
805    """
806
807
808class SymbolData(Container):
809
810    """
811    header = Symbol
812    name = string
813    type = int
814    bind = bind
815    """
816
817
818class RelocationData(Container):
819
820    """
821    header = RelocationStruct
822    symbol = SymbolData
823    type = type of relocation
824    """
825
826class DynamicData(Container):
827    """
828    header = DYN
829    tag = value of class DT
830
831    """
832
833##################### ELF Class ##############################
834
835class ELF(Binary):
836
837    def __init__(self, fileName, fileContent=None):
838        super(ELF, self).__init__(fileName, fileContent)
839
840        self.__classes = self._getSuitableClasses(self._bytes)
841        if not self.__classes:
842            raise BinaryError('Bad architecture')
843
844        self.__elfHeader = self._parseElfHeader(self._bytes)
845        self.__segments = self._parseSegments(self._bytes, self.elfHeader)
846        self.__sections = self._parseSections(self._bytes, self.elfHeader)
847        self._parseSymbols(self.sections)
848        self._parseDynamic(self.sections)
849        self._parseRelocations(self.sections)
850
851    @property
852    def _classes(self):
853        return self.__classes
854
855
856    @property
857    def elfHeader(self):
858        return self.__elfHeader
859
860
861    @property
862    def sections(self):
863        return list(self.__sections)
864
865    @property
866    def segments(self):
867        return list(self.__segments)
868
869    @property
870    def programHeaders(self):
871        return list(self.__segments)
872
873    @property
874    def entryPoint(self):
875        return self.elfHeader.header.e_entry
876
877    @property
878    def imageBase(self):
879        return self.segments[0].header.p_vaddr - self.segments[0].header.p_offset if len(self.segments) > 0 else 0
880
881    def _getSuitableClasses(self, data):
882        """Returns the class which holds the suitable classes for the loaded file"""
883        classes = None
884        if data[EI.CLASS] == ELFCLASS.BITS_32:
885            if data[EI.DATA] == ELFDATA.LSB:
886                classes = LSB_32
887            elif data[EI.DATA] == ELFDATA.MSB:
888                classes = MSB_32
889
890        elif data[EI.CLASS] == ELFCLASS.BITS_64:
891            if data[EI.DATA] == ELFDATA.LSB:
892                classes = LSB_64
893            elif data[EI.DATA] == ELFDATA.MSB:
894                classes = MSB_64
895
896        return classes
897
898    def _parseElfHeader(self, data):
899        """Returns the elf header"""
900        ehdr = self.__classes.EHDR.from_buffer(data)
901        return EhdrData(header=ehdr)
902
903    def _parseSegments(self, data, elfHeader):
904        """Return a list of segments"""
905        offset = elfHeader.header.e_phoff
906        segments = []
907        for i in range(elfHeader.header.e_phnum):
908            phdr = self.__classes.PHDR.from_buffer(data, offset)
909            segment_bytes = (c_ubyte * phdr.p_filesz).from_buffer(data, phdr.p_offset)
910
911            phdrData = PhdrData(header=phdr, raw=segment_bytes, bytes=bytearray(segment_bytes), type=PT[phdr.p_type], vaddr=phdr.p_vaddr, offset=phdr.p_offset)
912            segments.append(phdrData)
913
914            offset += elfHeader.header.e_phentsize
915
916        return segments
917
918    def _parseSections(self, data, elfHeader):
919        """Returns a list of sections"""
920        offset = elfHeader.header.e_shoff
921        shdrs = []
922        for i in range(elfHeader.header.e_shnum):
923            shdr = self.__classes.SHDR.from_buffer(data, offset)
924            section_bytes = None
925            ba_section_bytes = None
926            if shdr.sh_type != SHT.NOBITS:
927                section_bytes = (c_ubyte * shdr.sh_size).from_buffer(data, shdr.sh_offset)
928                ba_section_bytes = bytearray(section_bytes)
929            shdrs.append(ShdrData(name=None,header=shdr, raw=section_bytes, bytes=ba_section_bytes))
930            offset += elfHeader.header.e_shentsize
931
932        if elfHeader.header.e_shstrndx != SHN.UNDEF:
933            strtab = shdrs[elfHeader.header.e_shstrndx]
934            strtab_offset = strtab.header.sh_offset
935
936            for section in shdrs:
937                section.name = get_str(strtab.raw, section.header.sh_name)
938
939        return shdrs
940
941    def _parseSymbols(self, sections):
942        """Sets a list of symbols in each DYNSYM and SYMTAB section"""
943        for section in sections:
944            strtab = sections[section.header.sh_link]
945            if section.header.sh_type in (int(SHT.DYNSYM), int(SHT.SYMTAB)):
946                section.symbols = self.__parseSymbolEntriesForSection(section, strtab)
947
948
949    def __parseSymbolEntriesForSection(self, section, strtab):
950        entries = []
951        offset = 0
952        bytes_p = cast(pointer(section.raw), c_void_p)
953        sym_size = sizeof(self.__classes.SYM)
954
955        for i in range(int(section.header.sh_size / sym_size)):
956            entry = self.__classes.SYM.from_buffer(section.raw, offset)
957            name = get_str(strtab.raw, entry.st_name)
958            sym_data = SymbolData(header=entry, name=name, type=entry.st_info & 0xf, bind=entry.st_info >> 4)
959            entries.append(sym_data)
960
961            offset += sym_size
962
963        return entries
964
965    def _parseRelocations(self, sections):
966        """Parses the relocations and add those to the section"""
967        for section in sections:
968            if section.header.sh_link != SHN.UNDEF and section.header.sh_type in (SHT.REL, SHT.RELA):
969                symbols = sections[section.header.sh_link].symbols
970                relocations = self.__parseRelocationEntries(section, symbols)
971                section.relocations = relocations
972
973    def __parseRelocationEntries(self, section, symbols):
974        struct = self.__classes.REL if section.header.sh_type == SHT.REL else self.__classes.RELA
975        struct_size = sizeof(struct)
976        offset = 0
977        entries = []
978
979        for i in range(int(section.header.sh_size / struct_size)):
980            entry = struct.from_buffer(section.raw, offset)
981            sym = symbols[self.__classes.R_SYM(entry.r_info)]
982            reloc_entry = RelocationData(header=entry, symbol=sym, type=self.__classes.R_TYPE(entry.r_info))
983            entries.append(reloc_entry)
984            offset += sizeof(struct)
985
986        return entries
987
988    def _parseDynamic(self, sections):
989
990        dyn_size = sizeof(self._classes.DYN)
991
992        for section in sections:
993            offset = 0
994            dyns = []
995            if section.header.sh_type == SHT.DYNAMIC:
996                for i in range(int(len(section.bytes) / dyn_size)):
997                    dyn = self._classes.DYN.from_buffer(section.raw, offset)
998                    dyns.append(DynamicData(header=dyn, tag=DT[dyn.d_tag]))
999                    if dyn.d_tag == DT.NULL:
1000                        break
1001                    offset += dyn_size
1002                section.content = dyns
1003                self._parseDynamicTags(dyns, sections)
1004
1005    def _parseDynamicTags(self, dyns, sections):
1006
1007        for dyn in dyns:
1008            if dyn.header.d_tag == DT.NEEDED:
1009                self.__parseDynamicTagNeeded(dyn, dyns, sections)
1010
1011
1012    def __parseDynamicTagNeeded(self, dyn, dyns, sections):
1013        dyn_strtab = None
1014        for d in dyns:
1015            if d.header.d_tag == DT.STRTAB:
1016                dyn_strtab = d
1017
1018        if not dyn_strtab:
1019            return
1020
1021        for section in sections:
1022            if section.header.sh_addr == dyn_strtab.header.d_un:
1023                dyn.val = get_str(section.raw, dyn.header.d_un)
1024                break
1025
1026    @classmethod
1027    def isSupportedContent(cls, fileContent):
1028        """Returns if the files are valid for this filetype"""
1029        return bytearray(fileContent)[:4] == b'\x7fELF'
1030