elfファイルの説明と分析

1.最初にAndroid64ビットを010エディターにドラッグします

ここに画像の説明を挿入
4つの構造体があり、これらの構造体の見方を確認できます。ここでは、elf_header、program_header_table、section_header_tableに焦点を当てます。

  1. elf_headerは、elfファイルのヘッダーファイルであり、ここでいくつかのフィールドの意味を説明するためのさまざまな情報をカバーしています。実際、010エディター
    コメントの英字を確認することで、各フィールドの意味を理解できます
 1.16个字节是elf标识
 2. 2个字节.dynsym表示该节区包含了要动态连接的符号
3.e_mechine表示arm版本
4.e_version表示文件版本
5.表示so的开始地址一般为0x000000
6.program_header_offset,程序头位移 52 段头表
7.section_header_offset,节区位移    节头表
8.elf header size elf头的大小
9.paogram_header_entry_size 每个paramitem的大小
10.number of program_header_entries program的个数
11.section_header_size 节的个数
12.numver_of_section_header_entry_size, 每个节的大小
13.e_shtrndx_string_table_index, shtrndx在setion的index
  1. では、program_headerとsection_headerは何をするのでしょうか?
这又要说elf的两种视图
1.program视图 段视图, 执行视频
2.section视图 节视图,ida视图,加载so的时候会把节变为段
  1. では、セクションはセクション(セクション)をプログラム(セクション)としてどのようにロードしますか?
分三步
1.装载
2.分配数据块
3.连接 (重点)

おそらくそれらの間の関係を明らかにし、次にelfファイル分析の書き方を明らかにしました

  1. まず、elfのヘッダーフィールドを読み取ります
import mmap  # 将一个文件或者其它对象映射到进程的地址空间
import struct

endian_prefix = ""

def is_elf(f):
    magic_code = f.read(4).decode()
    if magic_code.find("ELF") == -1:
        raise ValueError("not a valid elf file")


def get_ei_data(mm):
    # 判断大小端
    ei_data = struct.unpack("<B", mm.read(1))[0]
    # 其他没啥用
    endian_prefix = '<' if ei_data == 1 else '>'
    return endian_prefix

# elf头
class ElfHeader:
    e_type = ""
    e_machine = ""
    e_version = ""
    e_entry = ""
    e_phoff = ""
    e_shoff = ""
    e_flags = ""
    e_ehsize = ""
    e_phentsize = ""
    e_phnum = ""
    e_shentsize = ""
    e_shnum = ""
    e_shtrndx = ""


def read_elf_header(f):
    is_elf(f)
    global endian_prefix
    endian_prefix = get_ei_data(f)
    f.seek(16)
    ElfHeader.e_type = unpack_data("H", 2, f)
    ElfHeader.e_machine = unpack_data("H", 2, f)
    ElfHeader.e_version = unpack_data("I", 4, f)
    ElfHeader.e_entry = unpack_data("I", 4, f)
    ElfHeader.e_phoff = unpack_data("I", 4, f)
    ElfHeader.e_shoff = unpack_data("I", 4, f)
    ElfHeader.e_flags = unpack_data("I", 4, f)
    ElfHeader.e_ehsize = unpack_data("H", 2, f)
    ElfHeader.e_phentsize = unpack_data("H", 2, f)
    ElfHeader.e_phnum = unpack_data("H", 2, f)
    ElfHeader.e_shentsize = unpack_data("H", 2, f)
    ElfHeader.e_shnum = unpack_data("H", 2, f)
    ElfHeader.e_shtrndx = unpack_data("H", 2, f)


def main(so_path):
    with open(so_path, "r+b") as f:
        with mmap.mmap(f.fileno(), 0) as mm:
            mm = mm
            read_elf_header(mm)    
  1. プログラムデータの読み取り
def read_data(f, off, size):
    print("off", off)
    f.seek(off)
    return b''.join([t[0] for t in struct.iter_unpack('<s', f.read(size))])


def unpack_data(data_type, size, f):
    return struct.unpack(endian_prefix + data_type, f.read(size))[0]


def read_program_header_table(f, off, size):
    """
    读取程序视图
    :param f:
    :param off:
    :param size:
    :return:
    """
    f.seek(off)
    for _ in range(size):
        info = ProgramInfo()
        info.p_type = unpack_data("I", 4, f)
        info.p_elf_begin = unpack_data("I", 4, f)
        info.p_var_addr = unpack_data("I", 4, f)
        info.p_p_addr = unpack_data("I", 4, f)
        info.p_seg_length = unpack_data("I", 4, f)
        info.p_memsz = unpack_data("I", 4, f)
        info.p_flag = unpack_data("I", 4, f)
        info.p_align = unpack_data("I", 4, f)
        current = f.tell()
        data = read_data(f, info.p_elf_begin, info.p_seg_length)
        info.data = data
        f.seek(current)
  1. セクションデータの読み取り
def read_section_header(f, off, size):
    """
    节区视图
    :param f:
    :param off:
    :param size:
    :return:
    """
    f.seek(off)
    for _ in range(size):
        info = SectionInfo()
        info.s_name = unpack_data("I", 4, f)
        info.p_elf_begin = unpack_data("I", 4, f)
        info.s_type = unpack_data("I", 4, f)
        info.s_flag = unpack_data("I", 4, f)
        info.s_addr = unpack_data("I", 4, f)
        info.s_size = unpack_data("I", 4, f)
        info.s_link = unpack_data("I", 4, f)
        info.s_info = unpack_data("I", 4, f)
        info.s_addr_align = unpack_data("I", 4, f)
        info.s_ent_size = unpack_data("I", 4, f)
        current = f.tell()
        char_data = read_data(f, info.s_addr, info.s_size)
        print("char_data", char_data.decode('utf-8', errors='ignore'))
        f.seek(current)

注意

1.字段的大小怎么看,可以根据010editor里的size字段去看
2.需要注意大端小端的数据怎么去取

おすすめ

転載: blog.csdn.net/esabeny/article/details/112288146