stack细节

想要知道详细信息,可以写一段什么都不做的代码,例如这样:

1
2
3
4
$ cat test.c 
void main(void){
}
$ gcc test.c -o test

编译,gdb运行,查看内存状态

  • main的返回地址
  • __libc_start_main()所使用的stack
  • argv[ ] 实体
  • envp[ ] 实体
  • ELF Auxiliary Vectors
  • argv[]或者envp[]之类所使用的字符串本身(一直到结尾)

最终,一个完整的stack状态如图:

  • argv

    • 产生错误时可能泄漏部分信息
    • 这一点exploit时用的较多
  • ELF Auxiliary Vectors

    • http://articles.manugarg.com/aboutelfauxiliaryvectors

    • 主要是从内核传递各种值的表

    • 极少数情况下,可以用作反调试

    • 可以使用LD_SHOW_AUXV查看其中的值

    • 但是ELF Auxiliary Vectors很少用于exploit

      1. vdso_base或者ld_base的leak
      2. AT_RANDOM(指向地址),在没有到达canary路径时可用

argv[0] leak

如果满足以下条件,则可能产生通用内存泄漏

  1. 存在Stack Canary保护(很常见)
    • 利用了canary被破坏后调用的__stack_chk_fail()
    • 如果stack上有8字节或者更多的数组,则通常会出现
  2. 没有开启PIE(Position-Independent Executables)(很常见)
    • 也就是说,默认编译的二进制文件(高版本gcc默认启用PIE了)
  3. canary保护的函数有足够的栈溢出空间(CTF中很常见)
    • 允许空字符的溢出问题
  4. 本地权限提升类型或者xintd类型(CVTF中很常见)
    • 可以获取到glibc给出的错误信息

如果满足这些条件,则可以泄漏任意( 指定地址)内存

  • 但是需要注意,leak之后进程会结束
  • 也就是说不能用于常规ASLR环境下