关于ELF符号表一次随想的记录

只是一次简单的记录

最近遇到一个情况,测试的二进制文件中没有使用system函数,但是有使用execl函数,我可以通过内存泄漏的洞来读取到execl函数的地址,然后获取到libc的基地址。

但是我不想使用execl函数来利用,太麻烦了,我想使用system函数来进行利用。一般情况下,如果已知libc版本,就能直接用偏移计算system地址了。

但是我考虑到,如果不知道libc版本怎么办,假设在一个不知道libc版本的情况下。我怎么获取到system函数的地址呢?

然后我想到了ELF的符号表,是不是能通过符号表来获取到相应函数的偏移。因为能读取任意内存,并且知道libc的基地址。

  1. 通过ELF头部获取到section信息:
1
2
3
4
1. section_offset = u64(elf_header[0x28:0x30])  section offset
2. section_header_size = u16(elf_header[0x3a:0x3c])
3. section_number = u16(elf_header[0x3c:0x3e])
4. section_mem = data[section_offset: section_offset + section_number * section_header_size]
  1. 然后读取section_mem的内容,获取DNYSYMSTRTAB两个块的信息:
1
2
3
4
5
6
7
8
9
5. for x in range(0, section_number * section_header_size, section_header_size):
tmp_mem = section_mem[x: x+section_header_size]
if tmp_mem[4:8] == b"\x0b\x00\x00\x00": # DYNSYM
dynsym_offset = u64(tmp_mem[0x10:0x18])
dynsym_size = u64(tmp_mem[0x20:0x28])
if tmp_mem[4:8] == b"\x03\x00\x00\x00": # STRTAB
strtab_offset = u64(tmp_mem[0x10:0x18])
strtab_size = u64(tmp_mem[0x20:0x28])
break
  1. 读取DNYSYMSTRTAB块的数据:
1
2
6. dynsym_mem = data[dynsym_offset:dynsym_offset+dynsym_size]
7. strtab_mem = data[strtab_offset:strtab_offset+strtab_size]
  1. 搜索相应的符号
1
2
3
4
5
6
7
8. for x in range(0, dynsym_size, 0x18):
tmp_dynsym = dynsym_mem[x:x+0x18]
st_name = u32(tmp_dynsym[:4])
name = strtab_mem[st_name:].strip(b"\x00").split(b"\x00")[0]
if name == b"system":
offset = u64(tmp_dynsym[0x8:0x10])
break

但是在实际测试的时候发现,除了运行程序本身符号表块能读,其他lib库的符号表都是不可读不可写不可执行的。权限不够,🤷‍♂️。

文章目录