Linux 二进制分析-Linux环境和工具(chapter 1)

目录

1. Linux工具

1.1 gdb调试器

1.2 binutils工具箱

1.3 hexdump

1.4 strace

1.5 ltrace

2. 设备和文件

2.1 /proc/${pid}/maps

2.2 /proc/kcore

2.3 /boot/System.map

2.4 /boot/kallsyms

2.5 /proc/iomem

2.6 ECFS(extended core file snapshot,扩展核心文件快照)

3. 链接器

3.1 LD_PRELOAD环境变量

3.2 LD_SHOW_AUXV环境变量

3.3 链接器脚本


Linux下二进制文件遵循一个统一的格式布局规范,这个二进制规范使得二进制在不同系统中可以拷贝、共享和运行,以及支持跨平台的交叉编译。二进制文件规范的制定,考虑了不同的硬件平台、各类操作系统和编译器的支持。实际上,有了该规范,才会产生操作系统内核的实现支持,才会有编译器的编译、链接器的链接、动态加载的支持。

二进制分析,是信息安全行业逆向工程的技术。在本系列文章中,我将根据参考一系列教材,介绍Linux下二进制相关的知识、实践相关的二进制分析工具。同时,从安全的角度,给出各类针对二进制进行漏洞、病毒的恶意攻击方法和防御方法,包括但不限于:二进制保护、进程追踪方法、病毒技术、二进制取证分析等等。

本系列文章将耗费接近半年的时间来完成,并在随后的时间里,继续添加一系列实践类的篇章。技术文章创作不易,希望对自己和读者都有所收益。欢迎关注和收藏,记得一键四连(关注、评论、点赞、收藏)

1. Linux工具

1.1 gdb调试器

调试工具,不详述。做C/C++开发的小伙伴,都比较熟悉它。基于ptrace实现,实际有更多使用功能。后文会介绍到。

1.2 binutils工具箱

  • objdump

objdump可以对ELF二进制进行解析(反编译)的工具,对未被篡改过的二进制文件能进行信息dump。显示二进制中的相关信息。objdump依赖于ELF的Section Header,因此无法进行控制流分析,且如果没有正确的ELF Section Header,objdump无法正常工作。

ELF二进制中的Section,将在后面的章节根据设计规范详细介绍。

常使用的功能如下:

#include <stdio.h>
#include <stdlib.h>

int main()
{
        printf("hello binar\n");
}
# gcc -o a a.c

1) 查看二进制中的所有符号(静态和动态符号表)

# objdump -tT a

2) 显示二进制中的Sections(header)

# objdump -h a

 

3)显示二进制中特定section的信息

配合-S可以尽可能显示源代码。

# objdump -j .data -s a

4) 显示二进制中所有section的数据或代码

# objdump -D a

5) 显示二进制中可执行代码section的部分

# objdump -d a
  • objcopy

objcopy是公认的正统分析和修改ELF二进制的工具,支持将.elf格式文件转换为.hex文件,支持将二进制转换成目标文件(.o文件)。用来分析和修改任意类型的ELF目标文件,可修改,也可将ELF Section复制到ELF二进制中。例如:将一个ELF目标文件复制到另一个文件中使用如下命令:

objcopy --only-section=.data <infile> <outfile>

1) 生成ELF二进制

# dd if=/dev/urandom of=foo.bin bs=1K count=1 oflag=direct
# objcopy -I binary -O elf64-x86-64 foo.bin foo.o
# objdump -h foo.o

foo.o:     file format elf64-little

Sections:
Idx Name          Size      VMA               LMA               File off  Algn
  0 .data         00000400  0000000000000000  0000000000000000  00000040  2**0
                  CONTENTS, ALLOC, LOAD, DATA
 # objdump -j .data -s foo.o > foo2.bin

Usage: objcopy [option(s)] in-file [out-file]

支持的目标有: elf64-x86-64 elf32-i386 elf32-iamcu elf32-x86-64 a.out-i386-linux pei-i386 pei-x86-64 elf64-l1om elf64-k1om elf64-little elf64-big elf32-little elf32-big pe-x86-64 pe-bigobj-x86-64 pe-i386 plugin srec symbolsrec verilog tekhex binary ihex

选项:

-I --input-target <bfdname> Assume input file is in format <bfdname>

-O --output-target <bfdname> Create an output file in format <bfdname>

 

上述命令将二进制文件foo.bin,转换为foo.o的目标文件。可以看到foo.bin内容与foo.o的.data section的内容是一致的。 默认情况下,二进制数据放在目标文件的.data Section下。 可以通过--rename-section选项,更改到其它Section。如下:

# objcopy -I binary -O elf64-x86-64 \
     --rename-section .data=.rodata,alloc,load,readonly foo.bin foo2.o
# objdump -h foo2.o

foo2.o:     file format elf64-little

Sections:
Idx Name          Size      VMA               LMA               File off  Algn
  0 .rodata       00000400  0000000000000000  0000000000000000  00000040  2**0
                  CONTENTS, ALLOC, LOAD, READONLY, DATA

2)通过添加Section嵌入数据到二进制对象中

例如,有如下的目标对象:

# echo 'int main() { puts("Hello world\n"); }' | gcc -x c - -c -o hello.o

通过objdump把foo.bin的二进制添加到.mydata的Section中,并编译成可执行文件:

# objcopy --add-section .mydata=foo.bin \
    --set-section-flags .mydata=noload,readonly hello.o hello2.o
#  gcc hello2.o -o hello
# ./hello
Hello world
# objdump -h hello | grep data
 15 .rodata       00000011  00000000000006e0  00000000000006e0  000006e0  2**2
 22 .data         00000010  0000000000201000  0000000000201000  00001000  2**3
 25 .mydata       00000400  0000000000000000  0000000000000000  00001039  2**0

通过 objdump -sj .mydata hello命令可以看到二进制内容与foo.bin完全一致。

QA: objcopy --only-section=.mydata -O binary hello2.o hello.bin

  • readelf

readelf是用来解析ELF二进制文件的强大工具。在进行二进制分析(黑客攻击)时,与objcopy一样,是一个利器,可以收集目标文件相关的所有特定于ELF的数据,为后续的反编译准备信息。常用如下:

1)查询ELF文件头

# readelf -h hello
ELF Header:
  Magic:   7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00
  Class:                             ELF64
  Data:                              2's complement, little endian
  Version:                           1 (current)
  OS/ABI:                            UNIX - System V
  ABI Version:                       0
  Type:                              DYN (Shared object file)
  Machine:                           Advanced Micro Devices X86-64
  Version:                           0x1
  Entry point address:               0x530
  Start of program headers:          64 (bytes into file)
  Start of section headers:          7496 (bytes into file)
  Flags:                             0x0
  Size of this header:               64 (bytes)
  Size of program headers:           56 (bytes)
  Number of program headers:         9
  Size of section headers:           64 (bytes)
  Number of section headers:         30
  Section header string table index: 29

2)查询ELF符号表

 3) 查询ELF二进制程序头

# readelf -l hello

Elf file type is DYN (Shared object file)
Entry point 0x530
There are 9 program headers, starting at offset 64

Program Headers:
  Type           Offset             VirtAddr           PhysAddr
                 FileSiz            MemSiz              Flags  Align
  PHDR           0x0000000000000040 0x0000000000000040 0x0000000000000040
                 0x00000000000001f8 0x00000000000001f8  R      0x8
  INTERP         0x0000000000000238 0x0000000000000238 0x0000000000000238
                 0x000000000000001c 0x000000000000001c  R      0x1
      [Requesting program interpreter: /lib64/ld-linux-x86-64.so.2]
  LOAD           0x0000000000000000 0x0000000000000000 0x0000000000000000
                 0x0000000000000838 0x0000000000000838  R E    0x200000
  LOAD           0x0000000000000db8 0x0000000000200db8 0x0000000000200db8
                 0x0000000000000258 0x0000000000000260  RW     0x200000
  DYNAMIC        0x0000000000000dc8 0x0000000000200dc8 0x0000000000200dc8
                 0x00000000000001f0 0x00000000000001f0  RW     0x8
  NOTE           0x0000000000000254 0x0000000000000254 0x0000000000000254
                 0x0000000000000044 0x0000000000000044  R      0x4
  GNU_EH_FRAME   0x00000000000006f4 0x00000000000006f4 0x00000000000006f4
                 0x000000000000003c 0x000000000000003c  R      0x4
  GNU_STACK      0x0000000000000000 0x0000000000000000 0x0000000000000000
                 0x0000000000000000 0x0000000000000000  RW     0x10
  GNU_RELRO      0x0000000000000db8 0x0000000000200db8 0x0000000000200db8
                 0x0000000000000248 0x0000000000000248  R      0x1

 Section to Segment mapping:
  Segment Sections...
   00
   01     .interp
   02     .interp .note.ABI-tag .note.gnu.build-id .gnu.hash .dynsym .dynstr .gnu.version .gnu.version_r .rela.dyn .rela.plt .init .plt .plt.got .text .fini .rodata .eh_frame_hdr .eh_frame
   03     .init_array .fini_array .dynamic .got .data .bss
   04     .dynamic
   05     .note.ABI-tag .note.gnu.build-id
   06     .eh_frame_hdr
   07
   08     .init_array .fini_array .dynamic .got

4) -S查询Section headers表

5)-d查询动态Section部分

6)-r查询可重定位入口

7) -e查询ELF文件Header数据(等同于-l -h -S)

1.3 hexdump

hexdump将文件看作二进制,并以十六进制dump显示。

该工具主要能调整dump的位置,以及显示的格式。

# hexdump -h
hexdump: invalid option -- 'h'
usage: hexdump [-bcCdovx] [-e fmt] [-f fmt_file] [-n length]
               [-s skip] [file ...]
       hd      [-bcdovx]  [-e fmt] [-f fmt_file] [-n length]
               [-s skip] [file ...]

1.4 strace

strace是系统调用的追踪工具,基于ptrace实现。strace在一个循环中使用PTRACE_SYSCALL来显示运行程序中所使用到的系统调用。在调试二进制运行,可以收集二进制运行机制。

1)追踪命令执行过程中的系统调用

例如,追踪ls命令:

 2) 追踪特定进程系统调用

# strace -p 12100 -o 12100.strace

1.5 ltrace

ltrace(library trace)是一个库追踪的工具,比较简洁。可以用来解析共享库,即一个程序的链接信息,并打印出用到的库函数。

 

2. 设备和文件

2.1 /proc/${pid}/maps

该文件可以输出进程的映像,展现每个内存映射。内容包括:可执行文件、共享库、栈、堆、VDSO等信息。可以用这些信息快速解析一个进程的地址空间的分布情况。后文详细介绍。

2.2 /proc/kcore

Linux内核的动态核心文件,是以ELF核心文件的形式展示的原生内存转储,gdb可以对/proc/kcore来对内核进行调试和分析。第9章节将详细介绍。

2.3 /boot/System.map

该文件存在于几乎所有的Linux发行版中,包含了整个内核的所有符号。对内核黑客来说,非常重要。

2.4 /boot/kallsyms

与System.map类似,但区别是kallsyms是内核所属的/proc的一个入口,可动态更新。安装了新的LKM(Linux Kernel Module)之后,符号会自动添加到kallsyms中。其中包含了内核中的绝大多数的符号,通过配置内核编译选项CONFIG_KALLSYMS_ALL甚至可以包含内核中的全部符号。

2.5 /proc/iomem

Linux系统中,固定分配给设备以及内核代码段、数据段等的系统物理内存 地址。可以查看内核的code/text段、data段和bss段的地址范围如下:

# cat /proc/iomem | grep Kernel
  ea8400000-ea9200e30 : Kernel code
  ea9200e31-eaa051cff : Kernel data
  eaa321000-eaa7fffff : Kernel bss

2.6 ECFS(extended core file snapshot,扩展核心文件快照)

Extended Core File Snapshot(ECFS),是一项特殊的核心转储技术,专门为进程映像设计的高级取证分析。该软件代码参考:https://github.com/elfmaster/ecf

第8章节将详细介绍ECFS及其使用方法,可以用它进行高级内存取证分析。

3. 链接器

动态链接/加载,是在程序链接、运行过程中的基本功能。在Linux中,有许多可以代替动态链接的方法,可以被黑客利用,从而攻击或分析运行中的应用程序。下面给出两种方法,后文会详细给出操作实践:

3.1 LD_PRELOAD环境变量

该环境变量可以设置一个指定库的路径,运行时动态链接时可以比其它库有更高的链接优先级。这就允许预加载库中的函数和符号,能够覆盖掉后续链接库中的函数和符号。利用它的技术,可以通过重定向共享库函数来进行运行时修复,或者绕过反调试代码,以及用作用户级的rootkit。

3.2 LD_SHOW_AUXV环境变量

该环境变量能够通知程序加载器来展示程序运行时的辅助向量。辅助向量是放在程序栈(通过内核的ELF常规加载方式)上的信息,其附带了传递给动态链接器的程序相关的特定信息。这些信息对于反编译和调试来说非常有用。例如,想要获取进程映像VDSO页的内存地址,就需要查询AT_SYSINFO。

第2章节将介绍辅助向量,如下带有LD_SHOW_AUXV辅助向量的例子:

# LD_SHOW_AUXV=1 whoami
AT_SYSINFO_EHDR: 0x7ffd7af17000
AT_HWCAP:        bfebfbff
AT_PAGESZ:       4096
AT_CLKTCK:       100
AT_PHDR:         0x5615bf740040
AT_PHENT:        56
AT_PHNUM:        9
AT_BASE:         0x7f4338e2a000
AT_FLAGS:        0x0
AT_ENTRY:        0x5615bf741a10
AT_UID:          0
AT_EUID:         0
AT_GID:          0
AT_EGID:         0
AT_SECURE:       0
AT_RANDOM:       0x7ffd7ae83239
AT_HWCAP2:       0x0
AT_EXECFN:       /usr/bin/whoami
AT_PLATFORM:     x86_64
root

3.3 链接器脚本

链接器脚本的使用,可以极大提高分析的能力。**链接器脚本是由链接器linker进行解释,把程序划分成相应的节、内存和符号。默认的连机器脚本可以使用ld --verbose查看

ld链接程序有自己解释的一套语言,当有文件输入时,如可重定位的目标文件、共享库或头文件,ld链接器会用自己的语言来决定输出文件(如可执行文件)的组织方式。

例如:如果输出的是一个ELF可执行文件,链接器脚本能够决定该输出文件的布局,以及每个段中包含哪些Sections。

再如:.bss Section总是存放在data段的尾部,这也是由链接器脚本决定的。

对于编译链接过程的深入了解是很重要的,gcc依赖于链接器和其它程序来完成编译任务,在某些情况下,能够控制可执行文件的布局相当重要(制作病毒)。ld命令语言是一门非常深入的语言,非常值得学习和深究。

同时,在对可执行文件进行反编译时,普通段地址或者文件的其它部分有时会被修改,这就表明引入了一个自定义的链接器脚本。gcc通过使用-T选项来指定链接器脚本。 第5章节将详细介绍相应的链接器脚本的使用实践。

关于作者:

犇叔,浙江大学计算机科学与技术专业,研究生毕业,而立有余。先后在华为、阿里巴巴和字节跳动,从事技术研发工作,资深研发专家。主要研究领域包括虚拟化、分布式技术和存储系统(包括CPU与计算、GPU异构计算、分布式块存储、分布式数据库等领域)、高性能RDMA网络协议和数据中心应用、Linux内核等方向。

专业方向爱好:数学、科学技术应用

关注犇叔,期望为您带来更多科研领域的知识和产业应用。

内容坚持原创,坚持干货有料。坚持长期创作,关注犇叔不迷路

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
### 回答1: 《Linux二进制分析》是一本介绍分析Linux二进制文件的PDF文档。本书的目的是帮助读者了解Linux系统中二进制文件的结构和内容,以及如何进行分析和调试。这本书按照逻辑顺序分为多个章节,每个章节探讨了不同的主题。 第一章介绍了二进制文件的基础知识,包括二进制文件的类型、结构和常见的文件格式。通过学习这些基础知识,读者可以对Linux二进制文件有一个整体的了解。 第二章讨论了在Linux系统中进行二进制文件分析工具和技术。这部分内容涵盖了命令行工具、调试器和反汇编器的使用方法,以及一些常见的二进制文件分析技术。 第三章以一个实际的案例为例,介绍了如何通过分析二进制文件来理解程序的功能和行为。这个案例涉及了静态分析和动态分析的技术,读者可以通过跟随案例学习如何应用这些技术。 第四章包含了一些高级的二进制文件分析技术,如符号动态执行、模糊测试和漏洞挖掘等。这些技术需要一定的专业知识和经验,但对于希望深入了解Linux二进制文件分析的读者来说,是非常有用的。 总的来说,这本《Linux二进制分析》PDF为读者提供了系统而全面的关于Linux二进制文件分析的知识。无论是初学者还是有经验的分析师,都可以从中获得有价值的信息和技巧。 ### 回答2: 《Linux二进制分析PDF》是一本介绍Linux二进制分析的电子书籍。通过对该书的阅读和学习,可以了解Linux操作系统中二进制文件的结构、特性和功能。 首先,该书会详细介绍Linux二进制文件的基本概念和核心组成部分。包括ELF(Executable and Linkable Format)格式的介绍,这是Linux系统中常见的二进制文件格式。通过了解ELF格式,可以深入理解可执行文件、共享库和目标文件的结构和功能。 其次,该书会介绍ELF文件的各个节(section)和段(segment)。节是ELF文件中存储数据和代码的逻辑块,而段是指逻辑上相关的节的集合。了解节和段的细节对于进行二进制分析非常重要,可以帮助我们理解程序的内部结构和运行机制。 此外,该书还会介绍动态链接(Dynamic Linking)和装载器(Loader)。动态链接是Linux中的一种链接方式,通过将共享库与可执行文件动态地链接在一起,提高了代码的复用性和运行效率。装载器是Linux系统中负责将可执行文件加载到内存并执行的组件。了解动态链接和装载器的工作原理,可以帮助我们理解程序运行的整个过程。 最后,该书还会介绍一些常见的二进制分析工具和技术。例如,调试器(Debugger)可以帮助我们追踪程序的执行过程和查找bug。反汇编器(Disassembler)可以将二进制文件转换为可读的汇编代码。逆向工程技术可以帮助我们分析和修改二进制文件中的代码。 总之,《Linux二进制分析PDF》是一本系统介绍Linux二进制分析的书籍,通过阅读和学习这本书,我们可以了解Linux二进制文件的结构、特性和功能,以及进行二进制分析的常见工具和技术。这对于提高我们对Linux操作系统的理解和应用开发能力非常有帮助。 ### 回答3: "Linux二进制分析PDF" 是指一本关于Linux操作系统二进制分析的书籍或电子文档。 Linux二进制分析是指对Linux操作系统中的二进制文件进行深入研究和分析的过程。这些二进制文件包括可执行文件、库文件、驱动程序和内核等。通过对这些文件逐个解析和分析,我们可以更好地理解它们的结构和功能,并且能够更好地进行调试、优化和开发工作。 "Linux二进制分析PDF" 这本书提供了关于如何进行Linux二进制分析的详细指导和实践经验。它可能包括以下方面的内容: 1. 二进制文件的格式:介绍二进制文件的基本结构和格式,如ELF(Executable and Linkable Format)等。讲解二进制文件中的各个段(section)和节(segment),以及文件头(header)和节头(section header)等信息。 2. 动态链接与装载:详细解释Linux中的动态链接和动态装载机制,如何解析和加载共享库,并将它们链接到可执行文件中。 3. 符号表与调试信息:讲解二进制文件中的符号表和调试信息,包括函数和变量的符号名、地址和类型等。以及如何利用这些信息进行调试和反汇编工作。 4. 反汇编和反编译:介绍如何将二进制文件转换成汇编代码,并进行反编译,还可以讲解一些常用的反汇编和反编译工具和技术。 5. 内核分析:讲解如何对Linux内核进行二进制分析和调试,包括内核模块、系统调用和驱动程序等。 通过学习和掌握这本书的内容,读者可以更深入地了解Linux系统的底层实现和机制,并且可以开展更高级、更复杂的开发和调试工作。当然,理解和运用这些知识需要具备一定的编程和计算机系统知识基础。希望这本"Linux二进制分析PDF"对想要深入学习Linux系统内部工作原理的读者有所帮助。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

敩科炼技堂

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值