GOT overwrite对策 – Full-RELRO

  • GOT可以重写会产生问题

    • Full-RELRO使其只读

    • 这里整个section被设置为只读属性(只能在二进制启动时初始化写入),Full-RELRO (RELocation Read-Only)
    • 编译选项: gcc -Wl,-z,relro,-z,now

NX+ASLR+Full-RELRO绕过1 –ret2dl_runtime_resolve

NX+ASLR+Full-RELRO绕过2 – _IO_jump_t overwrite

其他的 – libc/ld specific ptr

  • libc.so或者ld.so的bss中,有一些有趣的函数指针
    • libc_bss+0x08(x86)/0x10(x64):_dl_runtime_resolve@got.plt
    • libc_bss+0x30(x86)/0x38(x64):__tls_get_addr@got.plt
    • ld_bss+0x838(x86)/0xf68(x64):_dl_rtld_lock_recursive
    • ld_bss+0x83c(x86)/0xf70(x64):_dl_rtld_unlock_recursive
    • (以上数据为Ubuntu 14.04 latest中的偏移)
  • 还与一个函数指针表(指针的指针)
    • (x86) libc.so正上方mapped+0x914处的匿名函数指针表
    • (x64) ld.so正下方mapped+0x6f0处的匿名函数指针表
    • __GI___call_tls_dtors调用的函数表
    • (以上数据为Ubuntu 14.04 latest中的偏移)
    • Ubuntu16.04中许多已经受到保护,但仍有部分可用
  • 如果覆盖这些,exit()时将会自动调用
    • 更改为shellcode地址,将会被执行
  • 可以覆盖任意内存,但不能直接控制EIP/RIP的困难情况
    • 尝试利用之前的地址强行控制EIP/RIP
    • 之后从DROP开始的stack pivot可以做任何事情
    • 实际应用这种情况不多

library地址相关

  • 即使在ASLR下,x86的library地址也是很低的熵
    • 具体来说,只有256种模式(8比特)
      • 可以通过brute force来集中正确的libc_base
      • mmap, vdso, pie时的.text也是同样程度的熵
    • x64种,熵足够高(28比特),暴力方式几乎不可能
  • x86/x64种,library与某些区域的相对距离是固定的
    • library A与library B
    • library A与mapped
    • library A与0x21000以上size的malloc地址
    • library A与经过PIE的.text
      • 泄露相关地址后,就能够计算出其他地址
      • offset需要预先在相同版本ASLR环境下确认
      • 需要注意的是,heap,vdso,stack之间的距离不是固定值