LIEF
LIEF copied to clipboard
Support patching libraries without relying on sections
Is your feature request related to a problem? Please describe. This is a duplicate report of the issue encountered in #378. Opening a ticket to track progress
I tried to use LIEF in python to add Frida to an armeabi-v7a Android lib. It seems to work but when I save the file using the write() function, the shared library is not added to the created file.
LIEF fails because the library misses some sections like .text
, .dynsym
, ... LIEF is able to parse libraries with such layout but it can't be rebuilt or modified.
How to reproduce libcronet.61.0.3163.128.so.zip
Original lib:
l = lief.parse('libcronet.61.0.3163.128.so')
>>> print(l)
Header
======
Magic: 7f 45 4c 46
Class CLASS32
Endianness: LSB
Version: CURRENT
OS/ABI: SYSTEMV
ABI Version: 0
Machine type: ARM
File type: DYNAMIC
Object file version: CURRENT
Entry Point: 0x0
Program header offset: 0x52
Section header offset: 2781536
Processor Flag 83886592 SOFT_FLOAT EABI_VER5
Header size: 52
Size of program header : 32
Number of program header: 8
Size of section header: 40
Number of section headers: 4
Section Name Table idx: 3
Sections
========
NULL 0 0 0 -0
.dynstr STRTAB 1418 bb7 1418 4.44089 ALLOC LOAD
.dynamic DYNAMIC 2a659c 118 2a559c 2.43791 WRITE ALLOC LOAD DYNAMIC GNU_RELRO
.shstrtab STRTAB 0 103 2a705c 3.53617
Segments
========
PHDR r-- 34 34 34 100 100 4
LOAD r-x 0 0 0 2994fe 2994fe 1000
Sections in this segment :
.dynstr
LOAD rw- 299790 29a790 29a790 d7f0 115b1 1000
Sections in this segment :
.dynamic
DYNAMIC rw- 2a559c 2a659c 2a659c 118 118 4
Sections in this segment :
.dynamic
NULL --- 0 0 0 0 0 0
GNU_STACK rw- 0 0 0 0 0 0
ARM_UNWIND r-- 1f4d10 1f4d10 1f4d10 1cfd0 1cfd0 4
GNU_RELRO rw- 299790 29a790 29a790 c870 c870 10
Sections in this segment :
.dynamic
Dynamic entries
===============
PLTGOT 2a6ce4
PLTRELSZ 620
JMPREL 160f8
PLTREL 11
REL 2b78
RELSZ 13580
RELENT 8
RELCOUNT 26aa
SYMTAB 158
SYMENT 10
STRTAB 1418
STRSZ bb7
HASH 1fd0
NEEDED 51 libc.so
NEEDED 200 libdl.so
NEEDED e2 libm.so
NEEDED bad liblog.so
SONAME 59 libcronet.61.0.3163.128.so
FINI_ARRAY 2a6590 [0x17080, 0x0]
FINI_ARRAYSZ 8
INIT_ARRAY 2a6598 [0x0]
INIT_ARRAYSZ 4
FLAGS 8 BIND_NOW
FLAGS_1 1 NOW
NULL 0
VERDEF 2afc
VERDEFNUM 1
NULL 0
NULL 0
NULL 0
NULL 0
NULL 0
NULL 0
NULL 0
NULL 0
...
After adding Frida:
>>> l.add_library('libgadget.so')
<_pylief.ELF.DynamicEntryLibrary object at 0x1094080f0>
>>> print(l)
Header
======
Magic: 7f 45 4c 46
Class CLASS32
Endianness: LSB
Version: CURRENT
OS/ABI: SYSTEMV
ABI Version: 0
Machine type: ARM
File type: DYNAMIC
Object file version: CURRENT
Entry Point: 0x0
Program header offset: 0x52
Section header offset: 2781536
Processor Flag 83886592 SOFT_FLOAT EABI_VER5
Header size: 52
Size of program header : 32
Number of program header: 8
Size of section header: 40
Number of section headers: 4
Section Name Table idx: 3
Sections
========
NULL 0 0 0 -0
.dynstr STRTAB 1418 bb7 1418 4.44089 ALLOC LOAD
.dynamic DYNAMIC 2a659c 118 2a559c 2.43791 WRITE ALLOC LOAD DYNAMIC GNU_RELRO
.shstrtab STRTAB 0 103 2a705c 3.53617
Segments
========
PHDR r-- 34 34 34 100 100 4
LOAD r-x 0 0 0 2994fe 2994fe 1000
Sections in this segment :
.dynstr
LOAD rw- 299790 29a790 29a790 d7f0 115b1 1000
Sections in this segment :
.dynamic
DYNAMIC rw- 2a559c 2a659c 2a659c 118 118 4
Sections in this segment :
.dynamic
NULL --- 0 0 0 0 0 0
GNU_STACK rw- 0 0 0 0 0 0
ARM_UNWIND r-- 1f4d10 1f4d10 1f4d10 1cfd0 1cfd0 4
GNU_RELRO rw- 299790 29a790 29a790 c870 c870 10
Sections in this segment :
.dynamic
Dynamic entries
===============
PLTGOT 2a6ce4
PLTRELSZ 620
JMPREL 160f8
PLTREL 11
REL 2b78
RELSZ 13580
RELENT 8
RELCOUNT 26aa
SYMTAB 158
SYMENT 10
STRTAB 1418
STRSZ bb7
HASH 1fd0
NEEDED 0 libgadget.so
NEEDED 51 libc.so
NEEDED 200 libdl.so
NEEDED e2 libm.so
NEEDED bad liblog.so
SONAME 59 libcronet.61.0.3163.128.so
FINI_ARRAY 2a6590 [0x17080, 0x0]
FINI_ARRAYSZ 8
INIT_ARRAY 2a6598 [0x0]
INIT_ARRAYSZ 4
FLAGS 8 BIND_NOW
FLAGS_1 1 NOW
NULL 0
VERDEF 2afc
VERDEFNUM 1
NULL 0
NULL 0
NULL 0
NULL 0
NULL 0
NULL 0
NULL 0
NULL 0
....
>>> l.write('libcronet.61.0.3163.128.injected.so')
Reading back patched file:
>>> l = lief.parse('libcronet.61.0.3163.128.injected.so')
>>> print(l)
Header
======
Magic: 7f 45 4c 46
Class CLASS32
Endianness: LSB
Version: CURRENT
OS/ABI: SYSTEMV
ABI Version: 0
Machine type: ARM
File type: DYNAMIC
Object file version: CURRENT
Entry Point: 0x0
Program header offset: 0x52
Section header offset: 2781536
Processor Flag 83886592 SOFT_FLOAT EABI_VER5
Header size: 52
Size of program header : 32
Number of program header: 8
Size of section header: 40
Number of section headers: 4
Section Name Table idx: 3
Sections
========
NULL 0 0 0 -0
.dynstr STRTAB 1418 bb7 1418 4.44089 ALLOC LOAD
.dynamic DYNAMIC 2a659c 118 2a559c 2.43791 WRITE ALLOC LOAD DYNAMIC GNU_RELRO
.shstrtab STRTAB 0 1c 2a705c 3.65505
Segments
========
PHDR r-- 34 34 34 100 100 4
LOAD r-x 0 0 0 2994fe 2994fe 1000
Sections in this segment :
.dynstr
LOAD rw- 299790 29a790 29a790 d7f0 115b1 1000
Sections in this segment :
.dynamic
DYNAMIC rw- 2a559c 2a659c 2a659c 118 118 4
Sections in this segment :
.dynamic
NULL --- 0 0 0 0 0 0
GNU_STACK rw- 0 0 0 0 0 0
ARM_UNWIND r-- 1f4d10 1f4d10 1f4d10 1cfd0 1cfd0 4
GNU_RELRO rw- 299790 29a790 29a790 c870 c870 10
Sections in this segment :
.dynamic
Dynamic entries
===============
PLTGOT 2a6ce4
PLTRELSZ 620
JMPREL 160f8
PLTREL 11
REL 2b78
RELSZ 13580
RELENT 8
RELCOUNT 26aa
SYMTAB 158
SYMENT 10
STRTAB 1418
STRSZ bb7
HASH 1fd0
NEEDED 51 libc.so
NEEDED 200 libdl.so
NEEDED e2 libm.so
NEEDED bad liblog.so
SONAME 59 libcronet.61.0.3163.128.so
FINI_ARRAY 2a6590 [0x17080, 0x0]
FINI_ARRAYSZ 8
INIT_ARRAY 2a6598 [0x0]
INIT_ARRAYSZ 4
FLAGS 8 BIND_NOW
FLAGS_1 1 NOW
NULL 0
VERDEF 2afc
VERDEFNUM 1
NULL 0
NULL 0
NULL 0
NULL 0
NULL 0
NULL 0
NULL 0
NULL 0