目录

前言 1.1

可执行文件格式概览 1.2

通用内容 1.3

常见格式 1.4

COFF 1.4.1

PE 1.4.2

ELF 1.4.3

Mach-O 1.4.4

相关工具 1.5

file 1.5.1

LIEF 1.5.2

LIEF用法举例 1.5.2.1

Mach-O 1.5.2.1.1

Android 1.5.2.1.2

OAT 1.5.2.1.2.1

ELF 1.5.2.1.3

libtacker.so 1.5.2.1.3.1

子教程 1.6

附录 1.7

参考资料 1.7.1

前言

可执行文件格式

最新版本：v0.8.3

更新时间：20231007

简介

介绍常用的可执行文件格式，先是概览；然后是通用内容；接着介绍常见格式，包括早期通用的COFF、Windows的PE、Linux/Android的ELF、macOS/iOS的Mach-O，以及相关的工具，比如查看格式的file，和解析格式的LIEF，且给出具体用法实例，包括解析Mach-O、解析Android的OAT、解析ELF；以及相关子教程。

源码+浏览+下载

本书的各种源码、在线浏览地址、多种格式文件下载如下：

HonKit源码

crifan/executable_file_format: 可执行文件格式

如何使用此HonKit源码去生成发布为电子书

详见：crifan/honkit_template: demo how to use crifan honkit template and demo

在线浏览

可执行文件格式 book.crifan.org

可执行文件格式 crifan.github.io

离线下载阅读

可执行文件格式 PDF

可执行文件格式 ePub

可执行文件格式 Mobi

版权和用途说明

此电子书教程的全部内容，如无特别说明，均为本人原创。其中部分内容参考自网络，均已备注了出处。如发现有侵权，请通过邮箱联系我 admin 艾特 crifan.com，我会尽快删除。谢谢合作。

各种技术类教程，仅作为学习和研究使用。请勿用于任何非法用途。如有非法用途，均与本人无关。

鸣谢

感谢我的老婆陈雪的包容理解和悉心照料，才使得我crifan有更多精力去专注技术专研和整理归纳出这些电子书和技术教程，特此鸣谢。

其他

作者的其他电子书

本人crifan还写了其他150+本电子书教程，感兴趣可移步至：

crifan/crifan_ebook_readme: Crifan的电子书的使用说明

关于作者

关于作者更多介绍，详见：

关于CrifanLi李茂 – 在路上

crifan.org，使用署名4.0国际(CC BY 4.0)协议发布 all right reserved，powered by Gitbook最后更新： 2023-10-07 23:42:14

可执行文件格式概览

可执行文件格式概览

可执行文件格式，常见的有很多种。

此处只至少其中相对常见的：

背景知识

文件后缀和格式

文件后缀和格式

库文件

动态库文件

Win: .dll

Linux/Android: .so

相关：目标文件：.o

Mac: .dylib

静态库文件

Win: .lib

Linux: .a

Mac: .a

可执行文件

Win:.exe

Linux/Android: 无后缀

Mac:.app 或 无后缀

可执行文件格式和文件后缀

可执行文件格式和文件后缀

可执行文件格式发展历史关系图

离线查看

在线浏览

可执行文件格式发展历史关系图| ProcessOn免费在线作图

概述

早期的：a.out、通用的COFF

目前主流的：

Win：PE

相关文件：.exe可执行文件、.dll动态库

Linux和Android：ELF

相关文件：无后缀可执行文件、.so动态库、.o目标文件

macOS/iOS：Mach-O

相关文件：无后缀可执行文件、.dylib动态库、.o目标文件

详解

早期的

Microsoft

MZ：DOS中的.exe

MZ=Mark Zbikowski：MS-DOS主要开发者之一

UNIX系统

最早的

a.out

=assembler output

后来通用的

COFF

目前主流的

Microsoft系的：PE

常见系统：Windows

常见后缀：.exe

相关的：动态链接库的.dll

Linux系的：ELF

常见系统：Linux各个发行版（Ubuntu、CentOS等）、（基于Linux改造的）Android

常见后缀：无

相关的：动态链接库的.so、目标文件的.o

Apple系的：Mach-O

常见系统：macOS/iOS/watchOS/tvOS

常见后缀：无

相关的：动态链接库的.dylib

crifan.org，使用署名4.0国际(CC BY 4.0)协议发布 all right reserved，powered by Gitbook最后更新： 2023-09-19 22:55:59

通用内容

通用内容

核心点和通用点

不同可执行文件格式的内部，最核心的是：

编译和链接的过程

涉及到编译器和链接器

如何生成代码？

把生成的代码和数据，放到什么地方？

运行时如何加载这些代码和数据？

才能确保程序能正常执行

不用文件格式的通用内容

各种的

Segment段

代码段

.text

数据段

.data

等等

section区

.bss

.data

.rodata

等等

函数调用逻辑

When a program wants to call a function, it actually does following flow:

1.It made a jump to relevant entry in PLT (Procedure Linkage Table)

2.In PLT, there is another jump to an address mentioned in related entry in GOT (Global Offset Table)

3.If this is the first the function is called, follow step #4. If this isn't, follow step #5.

4.The related GOT entry contains an address that points back to next instruction in PLT. Program will jump to this address and then calls the dynamic linker to resolve the function's address. If the function is found, its address is put in related GOT entry and then the function itself is executed.

So, another time the function is called, GOT already holds its address and PLT can jump directly to the address. This procedure is called lazy binding; all external symbols are not resolved until the time it is really needed (in this case, when a function is called). Jump to step #6

5.Jump to the address mentioned in GOT. It is the address of the function thus PLT is no longer used

6.Execution of the function is finished. Jump back to the next instruction in the main program.

-》

1.跳转到PLT=Procedure Linkage Table中的对应入口

2.PLT中还有另外一个跳转，跳转到GOT=Global Offset Table中相关的入口

3.如果函数找到了被调用了，则继续步骤4，否则继续步骤5

GOT入口中包括了一个地址，指向了PLT中的下一个指令

程序会调到转该指令，谈话调用动态链接器去继续函数地址。

如果函数找到了，则该函数地址被放到GOT入口中，然后函数自己被执行

如果下一次函数被执行时，GOT中已有其地址，所以PLT可以直接跳转到对应地址

此过程叫做懒绑定lazy binding

所有外部符号都不会去解析，直到去真正要执行之前，需要解析，才去解析

5.跳转到GOT中提到的函数的地址。所以就不用PLT了。

执行函数，直到结束。跳转会主程序中的下一个指令。

crifan.org，使用署名4.0国际(CC BY 4.0)协议发布 all right reserved，powered by Gitbook最后更新： 2023-10-02 17:23:02

常见格式

常见格式

此处介绍常见的可执行文件格式：

早期通用的：COFF

目前主流的：

Win的：PE

Linux/Android的：ELF

macOS/iOS的：Mach-O

crifan.org，使用署名4.0国际(CC BY 4.0)协议发布 all right reserved，powered by Gitbook最后更新： 2023-09-19 21:57:52

COFF

COFF

COFF=Common Object File Format=通用对象文件格式

crifan.org，使用署名4.0国际(CC BY 4.0)协议发布 all right reserved，powered by Gitbook最后更新： 2023-09-19 21:58:21

PE

PE

PE=Portable Executable

crifan.org，使用署名4.0国际(CC BY 4.0)协议发布 all right reserved，powered by Gitbook最后更新： 2023-09-19 22:54:27

ELF

ELF

ELF=Executable and Linking Format=可执行和链接格式

按类型分

Relocatable File=可重定位文件

A relocatable file holds code and data suitable for linking with other object files to create an executable or a shared object file.

Executable File=可执行文件

An executable file holds a program suitable for execution

Shared Object File=共享对象文件

A shared object file holds code and data suitable for linking in two contexts. First, the link editor may process it with other relocatable and shared object files to create another object file.

Second, the dynamic linker combines it with an executable file and other shared objects to create a process image

ELF格式概览

图

详见子教程

可执行文件格式：ELF

crifan.org，使用署名4.0国际(CC BY 4.0)协议发布 all right reserved，powered by Gitbook最后更新： 2023-10-04 15:17:20

Mach-O

Mach-O

Mach-O = Mach Object

Mach-O是Mac和iOS等Apple平台中的可执行文件格式

详见子教程

可执行文件格式：Mach-O

crifan.org，使用署名4.0国际(CC BY 4.0)协议发布 all right reserved，powered by Gitbook最后更新： 2023-10-07 23:41:47

相关工具

相关工具

crifan.org，使用署名4.0国际(CC BY 4.0)协议发布 all right reserved，powered by Gitbook最后更新： 2023-09-19 22:00:06

file

file

file

是个命令行工具，可以在Linux/Android和macOS/iOS中查看文件的格式

举例

Mac

rsync

➜  bin pwd
/usr/local/Cellar/rsync/3.2.7_1/bin

➜  bin file rsync
rsync: Mach-O 64-bit executable x86_64

readelf

➜  ~ file /opt/homebrew/opt/binutils/bin/readelf
/opt/homebrew/opt/binutils/bin/readelf: Mach-O 64-bit executable arm64

python64.dylib

➜  plugins pwd
/Applications/IDA Pro 7.0/ida.app/Contents/MacOS/plugins
➜  plugins ll
total 33776
...
-rw-r--r--@  1 crifan  admin   113K  9 14  2017 python.dylib
-rw-r--r--@  1 crifan  admin   113K  9 14  2017 python64.dylib
...

➜  plugins file python64.dylib
python64.dylib: Mach-O 64-bit dynamically linked shared library x86_64

FAT格式

FAT格式的rsync

➜  ~ which rsync
/usr/bin/rsync
➜  ~ file /usr/bin/rsync
/usr/bin/rsync: Mach-O universal binary with 2 architectures: [x86_64:Mach-O 64-bit executable x86_64] [arm64e:Mach-O 64-bit executable arm64e]
/usr/bin/rsync (for architecture x86_64):    Mach-O 64-bit executable x86_64
/usr/bin/rsync (for architecture arm64e):    Mach-O 64-bit executable arm64e

更多例子详见：

FAT举例 · 可执行文件格式：Mach-O (crifan.org)

crifan.org，使用署名4.0国际(CC BY 4.0)协议发布 all right reserved，powered by Gitbook最后更新： 2023-10-07 23:40:46

LIEF

LIEF

LIEF

介绍：用于查看和解析（ELF/MachO/PE/Android等）各种通用的可执行文件格式的库

一句话描述：Library to Instrument Executable Formats

支持格式

ELF

PE

MachO

Android

DEX

OAT

ART

VDEX

主页

LIEF

图

文档

Welcome to LIEF’s documentation! — LIEF Documentation

下载

LIEF

安装

Mac

pip install lief

crifan.org，使用署名4.0国际(CC BY 4.0)协议发布 all right reserved，powered by Gitbook最后更新： 2023-10-04 15:25:15

LIEF用法举例

LIEF用法举例

crifan.org，使用署名4.0国际(CC BY 4.0)协议发布 all right reserved，powered by Gitbook最后更新： 2023-10-04 15:39:24

Mach-O

LIEF解析Mach-O

从Mach-O中解析__text、__data等section的内容：

import lief

# --- Extract __text and __data section content from the binary ---
binary = lief.parse("uncrackable.arm64")
text_section = binary.get_section("__text")
text_content = text_section.content

data_section = binary.get_section("__data")
data_content = data_section.content

crifan.org，使用署名4.0国际(CC BY 4.0)协议发布 all right reserved，powered by Gitbook最后更新： 2023-10-04 16:56:15

Android

Android

此处举例说明，如何用LIEF去解析Android的相关格式。

crifan.org，使用署名4.0国际(CC BY 4.0)协议发布 all right reserved，powered by Gitbook最后更新： 2023-10-04 16:58:38

OAT

LIEF解析Android的OAT

此处用例子说明，如何用LIEF解析Android的OAT格式文件：

代码：

import lief

oat = lief.parse("SomeOAT")
for s in oat.dynamic_symbols:
  print(s)

输出：

oatdata                       OBJECT    GLOBAL    1000      1262000
oatexec                       OBJECT    GLOBAL    1263000   10d4060
oatlastword                   OBJECT    GLOBAL    233705c   4
oatbss                        OBJECT    GLOBAL    2338000   f5050
oatbsslastword                OBJECT    GLOBAL    242d04c   4

crifan.org，使用署名4.0国际(CC BY 4.0)协议发布 all right reserved，powered by Gitbook最后更新： 2023-10-04 16:59:20

ELF

LIEF解析ELF

crifan.org，使用署名4.0国际(CC BY 4.0)协议发布 all right reserved，powered by Gitbook最后更新： 2023-10-04 16:59:42

libtacker.so

LIEF修改ELF的libtacker.so

此处举例说明LIEF的用法：

用LIEF解析修改ELF格式的so库文件：libtacker.so

基本用法：打印解析后对象的信息

代码：

import lief

libtackerObj = lief.parse('modifyElf/input/libtacker_arm64_v8a.so')
print("libtackerObj=", libtackerObj)

输出：

➜  libtacker_so python modifyElf/modifyLibtackerSo.py
intputElfFile= modifyElf/input/libtacker_armeabi_v7a.so
inputFileName= libtacker_armeabi_v7a.so
pureFileName=%s, fileExt=%s ('libtacker_armeabi_v7a', '.so')
Loaded file:  modifyElf/input/libtacker_armeabi_v7a.so
libtackerElf= 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:                     0xb9c8
Program header offset:           0x34
Section header offset:           815008
Processor Flag:                  83886592 SOFT_FLOAT EABI_VER5
Header size:                     52
Size of program header:          32
Number of program header:        9
Size of section header:          40
Number of section headers:       27
Section Name Table idx:          26

Sections
========
                    NULL           0         0         0         0
.note.android.ident NOTE           154       98        154       1.09412   ALLOC                         LOAD NOTE
.note.gnu.build-id  NOTE           1ec       24        1ec       4.13606   ALLOC                         LOAD NOTE
.dynsym             DYNSYM         210       6d0       210       3.54702   ALLOC                         LOAD
.gnu.version        HIOS           8e0       da        8e0       1.48975   ALLOC                         LOAD
.gnu.version_r      GNU_VERNEED    9bc       40        9bc       2.16157   ALLOC                         LOAD
.gnu.hash           GNU_HASH       9fc       1ec       9fc       6.3602    ALLOC                         LOAD
.hash               HASH           be8       370       be8       1.38896   ALLOC                         LOAD
.dynstr             STRTAB         f58       b8f       f58       4.66594   ALLOC                         LOAD
.rel.dyn            REL            1ae8      2dd0      1ae8      3.36673   ALLOC                         LOAD
.ARM.exidx          ARM_EXIDX      48b8      1ad8      48b8      5.18866   ALLOC LINK_ORDER              LOAD ARM_UNWIND
.rel.plt            REL            6390      120       6390      3.54485   ALLOC INFO_LINK               LOAD
.ARM.extab          PROGBITS       64b0      334c      64b0      4.80098   ALLOC                         LOAD
.rodata             PROGBITS       97fc      21c7      97fc      5.26982   ALLOC MERGE STRINGS           LOAD
.text               PROGBITS       b9c8      b72c4     b9c8      6.55022   ALLOC EXECINSTR               LOAD
.plt                PROGBITS       c2c90     260       c2c90     3.78829   ALLOC EXECINSTR               LOAD
.data.rel.ro        PROGBITS       c3ef0     1790      c2ef0     4.42226   WRITE ALLOC                   LOAD GNU_RELRO
.fini_array         FINI_ARRAY     c5680     8         c4680     1.75      WRITE ALLOC                   LOAD GNU_RELRO
.init_array         INIT_ARRAY     c5688     114       c4688     -0        WRITE ALLOC                   LOAD GNU_RELRO
.dynamic            DYNAMIC        c579c     e8        c479c     3.17459   WRITE ALLOC                   LOAD DYNAMIC GNU_RELRO
.got                PROGBITS       c5884     70        c4884     3.63662   WRITE ALLOC                   LOAD GNU_RELRO
.got.plt            PROGBITS       c58f4     9c        c48f4     1.98777   WRITE ALLOC                   LOAD GNU_RELRO
.data               PROGBITS       c6990     2410      c4990     7.22773   WRITE ALLOC                   LOAD
.bss                NOBITS         c8da0     22d       c6da0     5.11609   WRITE ALLOC                   LOAD
.comment            PROGBITS       0         c6        c6da0     5.05236   MERGE STRINGS
.ARM.attributes     ARM_ATTRIBUTES 0         3c        c6e66     4.587
.shstrtab           STRTAB         0         fe        c6ea2     4.2632

Segments
========
PHDR              r--       34        34        34        120       120       4

LOAD              r-x       0         0         0         c2ef0     c2ef0     1000
Sections in this segment :
    .note.android.ident
    .note.gnu.build-id
    .dynsym
    .gnu.version
    .gnu.version_r
    .gnu.hash
    .hash
    .dynstr
    .rel.dyn
    .ARM.exidx
    .rel.plt
    .ARM.extab
    .rodata
    .text
    .plt

LOAD              rw-       c2ef0     c3ef0     c3ef0     1aa0      1aa0      1000
Sections in this segment :
    .data.rel.ro
    .fini_array
    .init_array
    .dynamic
    .got
    .got.plt

LOAD              rw-       c4990     c6990     c6990     2410      263d      1000
Sections in this segment :
    .data
    .bss

DYNAMIC           rw-       c479c     c579c     c579c     e8        e8        4
Sections in this segment :
    .dynamic

GNU_RELRO         r--       c2ef0     c3ef0     c3ef0     1aa0      2110      1
Sections in this segment :
    .data.rel.ro
    .fini_array
    .init_array
    .dynamic
    .got
    .got.plt

GNU_STACK         rw-       0         0         0         0         0         0

NOTE              r--       154       154       154       bc        bc        4
Sections in this segment :
    .note.android.ident
    .note.gnu.build-id

ARM_UNWIND        r--       48b8      48b8      48b8      1ad8      1ad8      4
Sections in this segment :
    .ARM.exidx

Dynamic entries
===============
NEEDED              b71       liblog.so
NEEDED              b7b       libm.so
NEEDED              b5b       libdl.so
NEEDED              b69       libc.so
SONAME              b83       libforce.so
FLAGS               8          BIND_NOW
FLAGS_1             1          NOW
REL                 1ae8
RELSZ               2dd0
RELENT              8
RELCOUNT            573
JMPREL              6390
PLTRELSZ            120
PLTGOT              c58f4
PLTREL              11
SYMTAB              210
SYMENT              10
STRTAB              f58
STRSZ               b8f
GNU_HASH            9fc
HASH                be8
INIT_ARRAY          c5688     [0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0]
INIT_ARRAYSZ        114
FINI_ARRAY          c5680     [0xb9dc, 0xb9c8]
FINI_ARRAYSZ        8
VERSYM              8e0
VERNEED             9bc
VERNEEDNUM          2
NULL                0

Dynamic symbols
===============
                              NOTYPE    LOCAL     0         0         * Local *
__cxa_finalize                FUNC      GLOBAL    0         0         LIBC      (2)
__cxa_atexit                  FUNC      GLOBAL    0         0         LIBC      (2)
__android_log_print           FUNC      GLOBAL    0         0         * Global *
__stack_chk_fail              FUNC      GLOBAL    0         0         LIBC      (2)
__stack_chk_guard             OBJECT    GLOBAL    0         0         LIBC      (2)
__strncpy_chk2                FUNC      GLOBAL    0         0         LIBC      (2)
strncpy                       FUNC      GLOBAL    0         0         LIBC      (2)
strncat                       FUNC      GLOBAL    0         0         LIBC      (2)
pthread_self                  FUNC      GLOBAL    0         0         LIBC      (2)
malloc                        FUNC      GLOBAL    0         0         LIBC      (2)
free                          FUNC      GLOBAL    0         0         LIBC      (2)
posix_memalign                FUNC      GLOBAL    0         0         LIBC      (2)
abort                         FUNC      GLOBAL    0         0         LIBC      (2)
vfprintf                      FUNC      GLOBAL    0         0         LIBC      (2)
fputc                         FUNC      GLOBAL    0         0         LIBC      (2)
vasprintf                     FUNC      GLOBAL    0         0         LIBC      (2)
__assert2                     FUNC      GLOBAL    0         0         LIBC      (2)
__sF                          OBJECT    GLOBAL    0         0         LIBC      (2)
strlen                        FUNC      GLOBAL    0         0         LIBC      (2)
realloc                       FUNC      GLOBAL    0         0         LIBC      (2)
__strlen_chk                  FUNC      GLOBAL    0         0         LIBC      (2)
memchr                        FUNC      GLOBAL    0         0         LIBC      (2)
__vsnprintf_chk               FUNC      GLOBAL    0         0         LIBC      (2)
pthread_mutex_lock            FUNC      GLOBAL    0         0         LIBC      (2)
calloc                        FUNC      GLOBAL    0         0         LIBC      (2)
pthread_mutex_unlock          FUNC      GLOBAL    0         0         LIBC      (2)
strcmp                        FUNC      GLOBAL    0         0         LIBC      (2)
pthread_getspecific           FUNC      GLOBAL    0         0         LIBC      (2)
memset                        FUNC      GLOBAL    0         0         LIBC      (2)
pthread_once                  FUNC      GLOBAL    0         0         LIBC      (2)
pthread_setspecific           FUNC      GLOBAL    0         0         LIBC      (2)
memcpy                        FUNC      GLOBAL    0         0         LIBC      (2)
pthread_key_delete            FUNC      GLOBAL    0         0         LIBC      (2)
pthread_key_create            FUNC      GLOBAL    0         0         LIBC      (2)
memmove                       FUNC      GLOBAL    0         0         LIBC      (2)
fprintf                       FUNC      GLOBAL    0         0         LIBC      (2)
fflush                        FUNC      GLOBAL    0         0         LIBC      (2)
dl_unwind_find_exidx          FUNC      GLOBAL    0         0         LIBC      (3)
.datadiv_decode8345671930506918460FUNC      GLOBAL    28ec9     2384      * Global *
.datadiv_decode17898716361002246085FUNC      GLOBAL    69a59     eee       * Global *
...
.datadiv_decode18430821605022316503FUNC      GLOBAL    9c47d     1044      * Global *
JNI_OnLoad                    FUNC      GLOBAL    b2bcd     48c       * Global *
.datadiv_decode9810505568447265400FUNC      GLOBAL    18c81     33e8      * Global *
...
.datadiv_decode3623259086264565478FUNC      GLOBAL    89201     8e6       * Global *

Static symbols
==============

Symbol versions
===============
* Local *
LIBC(2)
LIBC(2)
* Global *
LIBC(2)
LIBC(2)
...
LIBC(2)
LIBC(3)
* Global *
...
* Global *

Symbol versions definition
==========================

Symbol version requirement
==========================
1 libdl.so
1 libc.so

Dynamic relocations
===================
c3ef0     RELATIVE  32  0         0         DYNAMIC
c3ef4     RELATIVE  32  0         0         DYNAMIC
c3ef8     RELATIVE  32  0         0         DYNAMIC
...
c8d9c     RELATIVE  32  0         0         DYNAMIC
c5884     GLOB_DAT  32  0         5         DYNAMIC   __stack_chk_guard
c58a8     GLOB_DAT  32  0         12        DYNAMIC   __sF
c56ac     ABS32     32  0         27        DYNAMIC   .datadiv_decode8345671930506918460
c56fc     ABS32     32  0         28        DYNAMIC   .datadiv_decode17898716361002246085
c573c     ABS32     32  0         29        DYNAMIC   .datadiv_decode1857239248186750646
...
c5738     ABS32     32  0         6c        DYNAMIC   .datadiv_decode3623259086264565478

.plt.got relocations
====================
c5900     JUMP_SLOT 32  0         1         PLTGOT    __cxa_finalize
c5904     JUMP_SLOT 32  0         2         PLTGOT    __cxa_atexit
c5908     JUMP_SLOT 32  0         3         PLTGOT    __android_log_print
c590c     JUMP_SLOT 32  0         4         PLTGOT    __stack_chk_fail
c5910     JUMP_SLOT 32  0         6         PLTGOT    __strncpy_chk2
c5914     JUMP_SLOT 32  0         7         PLTGOT    strncpy
c5918     JUMP_SLOT 32  0         8         PLTGOT    strncat
c591c     JUMP_SLOT 32  0         9         PLTGOT    pthread_self
c5920     JUMP_SLOT 32  0         a         PLTGOT    malloc
c5924     JUMP_SLOT 32  0         b         PLTGOT    free
c5928     JUMP_SLOT 32  0         c         PLTGOT    posix_memalign
c592c     JUMP_SLOT 32  0         d         PLTGOT    abort
c5930     JUMP_SLOT 32  0         e         PLTGOT    vfprintf
c5934     JUMP_SLOT 32  0         f         PLTGOT    fputc
c5938     JUMP_SLOT 32  0         10        PLTGOT    vasprintf
c593c     JUMP_SLOT 32  0         11        PLTGOT    __assert2
c5940     JUMP_SLOT 32  0         13        PLTGOT    strlen
c5944     JUMP_SLOT 32  0         14        PLTGOT    realloc
c5948     JUMP_SLOT 32  0         15        PLTGOT    __strlen_chk
c594c     JUMP_SLOT 32  0         16        PLTGOT    memchr
c5950     JUMP_SLOT 32  0         17        PLTGOT    __vsnprintf_chk
c5954     JUMP_SLOT 32  0         18        PLTGOT    pthread_mutex_lock
c5958     JUMP_SLOT 32  0         19        PLTGOT    calloc
c595c     JUMP_SLOT 32  0         1a        PLTGOT    pthread_mutex_unlock
c5960     JUMP_SLOT 32  0         1b        PLTGOT    strcmp
c5964     JUMP_SLOT 32  0         1c        PLTGOT    pthread_getspecific
c5968     JUMP_SLOT 32  0         1d        PLTGOT    memset
c596c     JUMP_SLOT 32  0         1e        PLTGOT    pthread_once
c5970     JUMP_SLOT 32  0         1f        PLTGOT    pthread_setspecific
c5974     JUMP_SLOT 32  0         20        PLTGOT    memcpy
c5978     JUMP_SLOT 32  0         21        PLTGOT    pthread_key_delete
c597c     JUMP_SLOT 32  0         22        PLTGOT    pthread_key_create
c5980     JUMP_SLOT 32  0         23        PLTGOT    memmove
c5984     JUMP_SLOT 32  0         24        PLTGOT    fprintf
c5988     JUMP_SLOT 32  0         25        PLTGOT    fflush
c598c     JUMP_SLOT 32  0         26        PLTGOT    dl_unwind_find_exidx

Notes
=====
Note #0
-------
Name:                            Android
Type:                            ABI_TAG
Description:                     [15 00 00 00 72 32 34 00 00 00 00 00 00 00 00 00 ...]

Note #1
-------
Name:                            GNU
Type:                            BUILD_ID
Description:                     [fa 8a 30 55 6b db 44 9a 4a 2f 1f 83 46 6d 93 44 ...]
ID Hash:                         fa8a30556bdb449a4a2f1f83466d9344fdef3fb5

GNU Hash Table
==============
0x6000022d2e80

SYSV Hash Table
===============
0x600001381b40

复杂用法：修改.comment内容为随机乱码

代码：

modifyElf/modifyLibtackerSo.py

# Function: mofidy libtacker so (arm64_v8a, armeabi_v7a) comments section content the output to new one
# Author: Crifan Li
# Update: 20230912

import os
import random
import string
import lief

################################################################################
# input & config
################################################################################

# intputElfFile = "modifyElf/input/libtacker_arm64_v8a.so"
intputElfFile = "modifyElf/input/libtacker_armeabi_v7a.so"
print("intputElfFile=", intputElfFile)

outputFoler = "modifyElf/output"

TotalRandomTime = 40
OutputSuffixStartNum = 20

################################################################################
# generate output file name
################################################################################

inputFileName = os.path.basename(intputElfFile)
print("inputFileName=", inputFileName)
pureFileName, fileExt = os.path.splitext(inputFileName)
print("pureFileName=%s, fileExt=%s", (pureFileName, fileExt)) # pureFileName=%s, fileExt=%s ('libtacker_arm64_v8a', '.so')

################################################################################
# Main
################################################################################

libtackerElf = lief.parse(intputElfFile)
print("Loaded file: ", intputElfFile)
# print("libtackerElf=", libtackerElf)
print("header=", libtackerElf.header)
print("imported_functions=", libtackerElf.imported_functions)
print("exported_functions=", libtackerElf.exported_functions)

for section in libtackerElf.sections:
  print("-"*20) # section's name
  print("name=", section.name) # section's name
  print("size=", section.size) # section's size
  contentLen = len(section.content)
  print("contentLen=", contentLen) # Should match the previous print

commentSection = libtackerElf.get_section(".comment")

print("\n\n")

print("+++ Start total %d round overwrite .comment section content with random char" % TotalRandomTime)

ContentCharNum = commentSection.size
print("ContentCharNum=", ContentCharNum)

RamdonCharRange = string.ascii_letters + string.digits
print("RamdonCharRange=", RamdonCharRange)

for curRandomTimeIdx in range(TotalRandomTime):
  curRandomTime = curRandomTimeIdx + 1
  print("%s Random Time [%d] %s" % ("-"*30, curRandomTime, "-"*30))

  # randomCharList = random.sample(RamdonCharRange, 198)

  randomCharList = []
  for randomCharIdx in range(ContentCharNum):
    curRandomChar = random.choice(RamdonCharRange)
    randomCharList.append(curRandomChar)
  print("randomCharList=", randomCharList)

  # randomCharBytes = bytes(randomCharList)
  randomStr = "".join(randomCharList)
  print("randomStr=", randomStr)
  randomCharBytes = bytes(randomStr, "utf-8")
  print("randomCharBytes=", randomCharBytes)
  newContentBytes = randomCharBytes

  print("before: commentSection.content=", commentSection.content)

  # num0 = 0x30
  # print("commentSection contentType=", type(commentSection.content))
  # newContentBytes = bytes([num0] * commentSection.size)

  newContentMemoryView = memoryview(newContentBytes)
  # print("newContentMemoryView type=", type(newContentMemoryView))
  commentSection.content = newContentMemoryView
  print("after: commentSection.content=", commentSection.content)

  # outputElfFile = "modifyElf/output/libtacker_arm64_v8a_changedComment.so"
  # outputElfFile = "modifyElf/output/libtacker_arm64_v8a_changedComment_%d.so" % curRandomTime
  suffixNum = OutputSuffixStartNum + curRandomTime
  outputFileName = "%s_changedComment_%d%s" % (pureFileName, suffixNum, fileExt)
  outputElfFile = os.path.join(outputFoler, outputFileName)

  libtackerElf.write(outputElfFile)
  print("Saved to", outputElfFile)

输出log日志

Loaded file:  modifyElf/input/libtacker_arm64_v8a.so
header= Magic:                           7f 45 4c 46
Class:                           CLASS64
Endianness:                      LSB
Version:                         CURRENT
OS/ABI:                          SYSTEMV
ABI Version:                     0
Machine type:                    AARCH64
File type:                       DYNAMIC
Object file version:             CURRENT
Entry Point:                     0x1a5c0
Program header offset:           0x40
Section header offset:           848344
Processor Flag:                  0
Header size:                     64
Size of program header:          56
Number of program header:        9
Size of section header:          64
Number of section headers:       27
Section Name Table idx:          26

imported_functions= [<lief._lief.Function object at 0x104876f70>, <lief._lief.Function object at 0x104877230>, <lief._lief.Function object at 0x104877370>, <lief._lief.Function object at 0x1048772f0>, <lief._lief.Function object at 0x1048a99b0>, <lief._lief.Function object at 0x104967230>, <lief._lief.Function object at 0x1049668f0>, <lief._lief.Function object at 0x10487cc30>, <lief._lief.Function object at 0x10487cbb0>, <lief._lief.Function object at 0x10487cc70>, <lief._lief.Function object at 0x10487ccf0>, <lief._lief.Function object at 0x10487ccb0>, <lief._lief.Function object at 0x10497a7f0>, <lief._lief.Function object at 0x104a45bf0>, <lief._lief.Function object at 0x104a47c30>, <lief._lief.Function object at 0x104a474b0>, <lief._lief.Function object at 0x104a44470>, <lief._lief.Function object at 0x1049fd8b0>, <lief._lief.Function object at 0x1049fcab0>, <lief._lief.Function object at 0x104a7d6f0>, <lief._lief.Function object at 0x104a7ffb0>, <lief._lief.Function object at 0x104a7fbf0>, <lief._lief.Function object at 0x104a7fb70>, <lief._lief.Function object at 0x104a7ebb0>, <lief._lief.Function object at 0x104a7f5b0>, <lief._lief.Function object at 0x104a7efb0>, <lief._lief.Function object at 0x104a7c7f0>, <lief._lief.Function object at 0x1048e16b0>, <lief._lief.Function object at 0x1048e21f0>, <lief._lief.Function object at 0x10492bd70>, <lief._lief.Function object at 0x104929cf0>, <lief._lief.Function object at 0x104a14430>, <lief._lief.Function object at 0x104a166f0>, <lief._lief.Function object at 0x1049d86f0>, <lief._lief.Function object at 0x1049db6f0>, <lief._lief.Function object at 0x10495c6f0>, <lief._lief.Function object at 0x10495f1f0>, <lief._lief.Function object at 0x10495ebb0>, <lief._lief.Function object at 0x104a218b0>, <lief._lief.Function object at 0x104a211f0>, <lief._lief.Function object at 0x1048f98f0>, <lief._lief.Function object at 0x1049c20b0>, <lief._lief.Function object at 0x1048cfeb0>, <lief._lief.Function object at 0x104890370>, <lief._lief.Function object at 0x104890f70>, <lief._lief.Function object at 0x104a0f030>]
exported_functions= [<lief._lief.Function object at 0x104876f70>, <lief._lief.Function object at 0x104877230>, <lief._lief.Function object at 0x104877370>, <lief._lief.Function object at 0x1048772f0>, <lief._lief.Function object at 0x1048a99b0>, <lief._lief.Function object at 0x104967230>, <lief._lief.Function object at 0x1049668f0>, <lief._lief.Function object at 0x10487cc30>, <lief._lief.Function object at 0x10487cbb0>, <lief._lief.Function object at 0x10487cc70>, <lief._lief.Function object at 0x10487ccf0>, <lief._lief.Function object at 0x10487ccb0>, <lief._lief.Function object at 0x10497a7f0>, <lief._lief.Function object at 0x104a45bf0>, <lief._lief.Function object at 0x104a47c30>, <lief._lief.Function object at 0x104a474b0>, <lief._lief.Function object at 0x104a44470>, <lief._lief.Function object at 0x1049fd8b0>, <lief._lief.Function object at 0x1049fcab0>, <lief._lief.Function object at 0x104a7d6f0>, <lief._lief.Function object at 0x104a7ffb0>, <lief._lief.Function object at 0x104a7fbf0>, <lief._lief.Function object at 0x104a7fb70>, <lief._lief.Function object at 0x104a7ebb0>, <lief._lief.Function object at 0x104a7f5b0>, <lief._lief.Function object at 0x104a7efb0>, <lief._lief.Function object at 0x104a7c7f0>, <lief._lief.Function object at 0x1048e16b0>, <lief._lief.Function object at 0x1048e21f0>, <lief._lief.Function object at 0x10492bd70>, <lief._lief.Function object at 0x104929cf0>, <lief._lief.Function object at 0x104a14430>, <lief._lief.Function object at 0x104a166f0>, <lief._lief.Function object at 0x1049d86f0>, <lief._lief.Function object at 0x1049db6f0>, <lief._lief.Function object at 0x10495c6f0>, <lief._lief.Function object at 0x10495f1f0>, <lief._lief.Function object at 0x10495ebb0>, <lief._lief.Function object at 0x104a218b0>, <lief._lief.Function object at 0x104a211f0>, <lief._lief.Function object at 0x1048f98f0>, <lief._lief.Function object at 0x1049c20b0>, <lief._lief.Function object at 0x1048cfeb0>, <lief._lief.Function object at 0x104890370>, <lief._lief.Function object at 0x104890f70>, <lief._lief.Function object at 0x104a0f030>, <lief._lief.Function object at 0x104a0db30>, <lief._lief.Function object at 0x104896770>, <lief._lief.Function object at 0x1049144b0>, <lief._lief.Function object at 0x1048e5530>, <lief._lief.Function object at 0x1048ac730>, <lief._lief.Function object at 0x1049a4ef0>, <lief._lief.Function object at 0x1049a5670>, <lief._lief.Function object at 0x10488b1b0>, <lief._lief.Function object at 0x104993570>, <lief._lief.Function object at 0x104993fb0>, <lief._lief.Function object at 0x104992f30>, <lief._lief.Function object at 0x104a900f0>, <lief._lief.Function object at 0x104a90130>, <lief._lief.Function object at 0x104a90170>, <lief._lief.Function object at 0x104a901b0>, <lief._lief.Function object at 0x104a901f0>, <lief._lief.Function object at 0x104a90230>, <lief._lief.Function object at 0x104a90270>, <lief._lief.Function object at 0x104a902b0>, <lief._lief.Function object at 0x104a902f0>, <lief._lief.Function object at 0x104a90330>, <lief._lief.Function object at 0x104a90370>, <lief._lief.Function object at 0x104a903b0>, <lief._lief.Function object at 0x104a903f0>]
--------------------
name=
size= 0
contentLen= 0
--------------------
name= .note.android.ident
size= 152
contentLen= 152
--------------------
name= .note.gnu.build-id
size= 36
contentLen= 36
--------------------
name= .dynsym
size= 2832
contentLen= 2832
--------------------
name= .gnu.version
size= 236
contentLen= 236
--------------------
name= .gnu.version_r
size= 64
contentLen= 64
--------------------
name= .gnu.hash
size= 492
contentLen= 492
--------------------
name= .hash
size= 952
contentLen= 952
--------------------
name= .dynstr
size= 3097
contentLen= 3097
--------------------
name= .rela.dyn
size= 34896
contentLen= 34896
--------------------
name= .rela.plt
size= 1104
contentLen= 1104
--------------------
name= .gcc_except_table
size= 6496
contentLen= 6496
--------------------
name= .rodata
size= 13364
contentLen= 13364
--------------------
name= .eh_frame_hdr
size= 7612
contentLen= 7612
--------------------
name= .eh_frame
size= 36052
contentLen= 36052
--------------------
name= .text
size= 715872
contentLen= 715872
--------------------
name= .plt
size= 768
contentLen= 768
--------------------
name= .data.rel.ro
size= 11960
contentLen= 11960
--------------------
name= .fini_array
size= 16
contentLen= 16
--------------------
name= .init_array
size= 560
contentLen= 560
--------------------
name= .dynamic
size= 464
contentLen= 464
--------------------
name= .got
size= 192
contentLen= 192
--------------------
name= .got.plt
size= 392
contentLen= 392
--------------------
name= .data
size= 9688
contentLen= 9688
--------------------
name= .bss
size= 2768
contentLen= 0
--------------------
name= .comment
size= 198
contentLen= 198
--------------------
name= .shstrtab
size= 260
contentLen= 260
before: commentSection.content= <memory at 0x1049b5480>
commentSection contentType= <class 'memoryview'>
newContentMemoryView type= <class 'memoryview'>
after: commentSection.content= <memory at 0x1049b5540>
Saved to modifyElf/output/libtacker_arm64_v8a_changedComment.so

输出文件：（一次性的批量的多个）修改后的ELF文件：

修改前后的内容对比

.comment修改前：

Contents of section .comment:
0000 4c696e6b 65723a20 4c4c4420 31342e30  Linker: LLD 14.0
0010 2e310063 6c616e67 20766572 73696f6e  .1.clang version
0020 2031342e 302e3000 416e6472 6f696420   14.0.0.Android
0030 28383037 35313738 2c206261 73656420  (8075178, based
0040 6f6e2072 34333731 31326229 20636c61  on r437112b) cla
0050 6e672076 65727369 6f6e2031 342e302e  ng version 14.0.
0060 31202868 74747073 3a2f2f61 6e64726f  1 (https://andro
0070 69642e67 6f6f676c 65736f75 7263652e  id.googlesource.
0080 636f6d2f 746f6f6c 63686169 6e2f6c6c  com/toolchain/ll
0090 766d2d70 726f6a65 63742038 36373133  vm-project 86713
00a0 34386238 31623935 66633630 33353035  48b81b95fc603505
00b0 64666338 38316234 35313033 62656531  dfc881b45103bee1
00c0 37333129 0000                        731)..

.comment修改后：

Contents of section .comment:
0000 62464a30 35487661 384a3768 42435237  bFJ05Hva8J7hBCR7
0010 76426449 59784743 524e4d54 33744c42  vBdIYxGCRNMT3tLB
0020 304d664d 36615353 39493555 7943464d  0MfM6aSS9I5UyCFM
0030 63566348 41376b76 67427050 4b4d4f35  cVcHA7kvgBpPKMO5
0040 38503143 72734d73 636e476b 6f684932  8P1CrsMscnGkohI2
0050 4561616e 72376c30 6861466c 53667858  Eaanr7l0haFlSfxX
0060 6f66684b 3646594a 43656154 77656849  ofhK6FYJCeaTwehI
0070 71766167 67653570 45627946 576b4c45  qvagge5pEbyFWkLE
0080 4a747759 4c6f474a 38554d74 71717749  JtwYLoGJ8UMtqqwI
0090 37534a4b 7a526547 396d687a 3464544a  7SJKzReG9mhz4dTJ
00a0 67787276 6843555a 59596332 50336836  gxrvhCUZYYc2P3h6
00b0 615a3362 786c4444 526e7370 66556f54  aZ3bxlDDRnspfUoT
00c0 746e4573 3152                        tnEs1R

crifan.org，使用署名4.0国际(CC BY 4.0)协议发布 all right reserved，powered by Gitbook最后更新： 2023-10-04 17:00:10

子教程

子教程

此处列出相关子教程：

可执行文件格式

可执行文件格式：ELF

可执行文件格式：Mach-O

crifan.org，使用署名4.0国际(CC BY 4.0)协议发布 all right reserved，powered by Gitbook最后更新： 2023-10-04 15:18:44

附录

附录

下面列出相关参考资料。

crifan.org，使用署名4.0国际(CC BY 4.0)协议发布 all right reserved，powered by Gitbook最后更新： 2023-09-19 21:13:04

参考资料

参考资料

【已解决】给已有libtacker.so去改动信息

【已解决】用LIEF去修改ELF的so中的部分信息

【整理】Mach-O格式分析工具：LIEF

【整理】安卓相关：OTA格式

【已解决】新Mac M2 Max中如何安装x86_64版本rsync

Comparison of executable file formats - Wikipedia

DOS MZ executable - Wikipedia

a.out - Wikipedia

Portable Executable - Wikipedia

COFF - Wikipedia

Tool Interface Standard (TIS) Executable and Linking Format (ELF) Specification Version 1.2

Creating and using static libraries in Linux ~ codingfreak

Better understanding Linux secondary dependencies solving with examples

动态库与静态库的区别（linux vs windows vs mac）51CTO博客动态库和静态库的区别

C/C++ 动态库(dll)与静态库(lib)c++编译出来的lib库和c库有什么区别一叶知秋@qqy的博客-CSDN博客

以.a(a为后缀)的文件类型是啥鸭？.a是什么文件子燕若水的博客-CSDN博客

静态库的格式there is no dynamic section in this file广敏的博客-CSDN博客

静态库的管理与文件格式分析 - 知乎

静态库（.a）和共享库（.so）的文件格式差异？

Welcome to LIEF’s documentation! — LIEF Documentation (lief-project.github.io)

Installation and Integration — LIEF Documentation (lief-project.github.io)

Tutorials — LIEF Documentation (lief-project.github.io)

03 - Play with ELF symbols — LIEF Documentation (lief-project.github.io)

10 - Android formats — LIEF Documentation (archive.is)

Hiding Behind ART - Black Hat 2015

Dalvik and ART

OAT internal structures

crifan.org，使用署名4.0国际(CC BY 4.0)协议发布 all right reserved，powered by Gitbook最后更新： 2023-10-04 16:49:55